機能 #11
openv3.1のivm機能実装
Added by keiji ono 9 months ago. Updated 3 months ago.
0%
Description
ivmはユーザの能動的なテーブル作成に使う
Updated by keiji ono 9 months ago
実現機能:
複数table選択→各tableからカラム選択→複数tableのカラムが選択されているなら1.普通にjetelina-api作成 2.ivm機能を使って新規table作成
複数tableが選択されているチェックはfunctionpane.js->containsMultiTables()
- 2の場合、ivmで使えないquery句をチェックすること→ivmの禁句リストはPgIVMController.jl->createIVMtable()のregulatedclauses変数が参考になる。これをconfigにしてもいいかなぁ..
- 1,2どちらもselect文だけの作成となる
- ivmの新規tableはそれとわかるようにtable listに追加される→ivm_<table1>_<table2>... とかする。長くなるかもしれないけど視認性を重視しよう。
- 2のweb-dbiは1のjeteilna-apiと見た目同じとする→js*とする
■js
- ivm table作成条件判定とサジェッション表示→functionpanel.js #1687でcontainsMultiTables()の判定処理をしているので、ここで全部やりきっていいかな
- ivm tableをtable listに表示(多分、現在のものでイケるとおもうけど要確認)
- ivm table削除(多分、現在のものでイケるとおもうけど要確認)
- ivm tableに対応する関連jetelina-api(insert/update/delete and select)をハイライト
- ivm table作成実行処理
- ivm tableをtable listに追加(多分、現在のものでイケるとおもうけど要確認)
- ivm table削除(多分、現在のものでイケるとおもうけど要確認)
- guide me更新
- Functions page更新 → ”create jetelina-api"にivmを追記
- Tips page更新 → 複数tableを使った場合、普通とivmの選択ができることを記述
- Example for the command.. page更新 → "create with ivm"
- v3.1リリース詳細表示
Updated by keiji ono 8 months ago
ちょっと想定外だったのが、checkIVMExistence()の実行タイミング。
Genie起動時にJTimer.TimerExecuterでやるのはDBDataControllerがまだ未設定でダメみたい。
table list取得時だと頻繁になるしなぁ。login時かなぁ。って感じ。
結局、login時に毎回checkIVM...()を実行することにする。
いつivmが実装されて、そして外されるかわからないので、誰かログインした時に毎回チェックでいいかなと。
parameter変更は"pg_ivm"でできるし、もし悪意をもってこの変数が変更されてもログイン毎にアップデートされるなら問題ないな。
PgDBController.jl chekUserExistence() #1122
try
・
・
finally
# checking ivm abailability in every login
# because who knows when ivm would be abailable, so check it every time when someone login to there
PgIVMController.checkIVMExistence(conn)
close_connection(conn)
end
Updated by keiji ono 8 months ago
configのpg_ivmは、ログイン直後にDBのabailableリストを取得しているので、そこで一緒に取得してログインユーザデータとして保持しよう。
loginして画面遷移する際に呼ばれる getdbsavailability -> GetDataController.getWorkingDBList()にpg_ivmパラメタを追加
#381
pgivm = j_config.JC["pg_ivm"]
・
df = DataFrame("postgres" => postgres, "pgivm" => pgivm, "mysql" => mysql, "redis" => redis, "mongodb" => mongodb)
これをjetelinalib.js getdata(o,t) t=5 でloginuser.pgivmに格納
#366
} else if (t == 5) {
・
・
// postgresql ivm function
if(v["pgivm"] !== null){
loginuser.pgivm = v["pgivm"];
}
これで以降の処理は loginuser.pgivmを見て判断できる。
logoutすればloginuserは空になるのでこれでOK。
parameter changeしたらloginuser.pgivmも更新することを忘れないように。
Updated by keiji ono 8 months ago
js*を作る時に「ivmを使いますか?」とか聞こうと思っていたけど、デフォルトivmを使って作成するってことでどうだろう?
sub queryにivm禁句があれば使わないで、イケそうなら自動的にivmを使うってことで。
ユーザにとってはivmを使うor使わないってのは然程意味を持たないだろうし、むしろ勝手にやってくれって感じだろうから。
なのでivm tableの表示もしないで今のまま普通にtableリストを表示し、普通にjsの関連tableをハイライトしてと。
ivm機能を完全にバックグラウンドにしてユーザには気取られなくてもいいんじゃね?って感じで。
どうしてもivmを使いたくないってときはパラメタをオフにしてもらえば、そのユーザではivmなしになる。他のユーザはどうせログインの時にパラメタが更新されるからOKだろう。pg_ivmパラメタは今の所「js create」でしか使ってないし。
- functionpanel.js #1687のcontainsMultiTables()判定の後にpostSelectedColumns("")を呼んでpost処理をしている
- postSelectedColuns(mode)ではmode="" or "pre"で、api作成 or テスト実行の判定をしている。引数modeはjsonに含まれてpostされる。post先はPostDataController.createApi()
- PostDataController.createApi()ではjson内のmodeを見て、mode="" -> "ok"としてapi作成とし、mode="pre"でテスト実行する。実行実態はDBDataController.createApiSelectSentence()
- DBDataController.createApiSelectSentence()では、configの"dbtype"(current database)を見て、postgres/mysql/mongoの各SQL句作成を依頼する。
- 依頼されたSQL句作成関数は(e.g. PgSQLSentenceManager.createApiSelectSentence())、mode!="pre"なら作成したSQL句をリストファイルに追記する。mode="pre"ならリストに追記せずにSQL句だけを返す
- 5で作成されたSQL句は4に戻され、mode="pre"なら各DB lib(e.g. PgDBController.doSelect())で実行されて、実行結果がユーザに返される。mode!="pre"ならapinoがユーザに返される。
注意点:
- post処理ではivmを使った場合はそれなりのメッセージを表示するようにしよう。
- ivmのtalbe名はjs*->jv*にしたものである
Updated by keiji ono 8 months ago
なにせ、js->jv対応ファイル"jsjvmatchingfile"があるから。
新規に作成しないといけないのは、jsがpostされた時にjsを実行するのかjvを実行するのか判断しないといけない部分。判断がつけば現状の関数を呼び出すことで最後までいける。
つまり、jsがpostされた時に対応ファイルを見にいかないといけない。まあこれはメモリ実行でやれるので実行速度には影響はなかろう。
処理の順番として、
- js post
- 対応ファイル"jsjvmatchingfile"参照
- 対応ファイルに当該jsが存在した場合、対応するjv名が実行対象のjv table名になる
- 3の場合、JetelinaSqllistを参照せずにすぐにPgIVMController.executeJVApi()を実行して終了
- 3で対応ファイルに当該jsが存在しない場合、JetelinaSqlListを参照して実行する「普通の」処理をして終了
- tableリストで"jv*"を選択した時にapiリストの該当"js*"がハイライトするのは要追加
- js->jv対応ファイルへの追記もこの.writeToList()で行う
- 1の判断でtable->api対応ファイルに記述する"table"を、オリジナルのtablename_arrを使うかjvのtableを使うかきめる
ふん。なんかこれでうまくいきそう。table->api対応ファイルさえできていればフロントでのハイライト処理のjavascriptは何も手を加えなくてもよさそう。
そもそものjs api作成も全部jlでやるから今回はjavascriptは変更なしでよさそう。
Updated by keiji ono 8 months ago
ロジックとして「複数tableを使用していたら...」の分岐を考えていたが、ユーザにivm or not ivmとするなら表面上のjs*は変わらないしtableにもivm tableを表示しないのだから、従来の「js vs jv比較」で「Speed(js) > Speed(jv)ならivm table作成しjs*コールでjv*を実行」がそのまま使える。
ivm table作成コストは高いのでこの方が、つまり「ivm化は必要ならやっときまっさ\(o)/」の方が絶対よかろう。
となると、ivm化はタイマーでやるよりは非同期並列の方がきっといい。
そういえば、ivm化のタイマー起動をどこでやるかでツマッていた気がする。非同期並列なら一挙解決かも。
- 並列 @async
- 並行 @spawn
2ではプロセスを複数立ち上げておいて空いているプロセスに処理を投げる。
複数プロセスが立ち上がっていると、処理が分散されてしまい、ログインした時にメモリに保持しているセッションデータの共有がされないため予想外のエラーが出る。
なので1で行こうとおもう。
Updated by keiji ono 8 months ago
- 複数tableを使用時にjsとjvの実行速度を比較する
- jvの方が実行速度が早いならivm化する
- jsの方が実行速度が早いならivm化しない
- ivm化すると、"jv*"のtableが作成される
- 〃 、JetelinaJvmnizedJsApiListに"js->jv"対応が追加される
- api listから"js*"を削除すると、JetelinaJvmni...ファイルに対応があれば一緒に削除される
- 〃 、 対応するivm tableがあれば一緒にdropされる
ここまでできた。
後は、js*実行時にjv*があればそちらを実行するpost処理だな。-> 'API test on Jetelina'で実行する分にはなんかいい感じ。テストページからの実行も試してみよう。
オリジナルtableに対するdata delete処理(jd*)ではjetelina_delete_flgの設定なので、これをivm tableにあらかじめぶっ込んでおかないといけない。
そしてivmで実行するselect文には必ず where jetelina_delete_flg=true"を加えておかないといけない。
Updated by keiji ono 8 months ago
作成されたjv table内のdataが、元のtableの当該データが更新されると消えてしまう事象が発生している。
と思ったら、where句の条件が崩れてしまうのでこうなるってことで正常だ。\(o)/
jv tableに対してji/juの各apiが正常に動作することを確認できた。
jdはjv tableのcreate時に無条件で対象となるtableのjetelina_delete_flg=0をwhere句に追加しよう。
いい感じ。終了だな。
OOps, jetelina_delete_flgはwhere句の前方に差し込まないと他の条件文(ex. order by)があった場合に変なsql文になってしまう。
ちょっと混乱している。jetelina_delete_flg=0のデータだけを扱うようにv3.0ではなっているが、
- test sql実行時にはjetelina_delete...はwhere句にはない createApiSelectSentence() --> PgDBController.doSelect()で実行
- js*実行時にはexecuteApi()->createExecutionSqlsentence()プログラム内で自動的に設定される --> PgDBController._executeApi()で実行
- ivm table作成時には2のような自動設定がないのでsql文にjetelina_del...を入れている createApiSelectSentence()._addJetelinaDeleteFlg2Subquery() --> PgIVMController.compareJsAndJv() --> createIVMtable()で実行
ちょっとこれを統一する必要があるな。
v3.0では、api作成時にはjetelina_delete_flgはsql句に含めず、実行時にsql文に追加している。->2
このため、api作成前のテスト実行ではjetelina_delete_flgは条件文には含まれない。 ->1
使用するtableの情報はcreateApiSelectSentence()の時点でわかっているのでテスト実行:doSelect()にjetelina...を反映することはできそう。
createExecu..()では登録されているapiの情報に頑張ってjetelina_delete_flgを追加しているが、createApis...()でもうjeteli_de...付きでapiとして登録してもいいんじゃね?
つまり、createApiSele...()でもうjetelina_de...の処理をしてしまえば、1も2も実行が統一されるとともに、2の時は余計な処理が不要になり登録されているapiのsql文を単に実行すればいいので処理速度も早くなりそう。
そうなれば3で_addJeteli..()の処理も不要になる。
さてさて、jetelina_del...をapiのsql文に含めることの不都合はなんだろうか?
11/17
jetelina_del..をsql文に含めることに特に不都合を感じないので、createApiSelectSentence()でもうjetelina_del..を付けたsub query文をつくってしまう。
api化した後の実行のcreateExecutionSqlSentence()ではapiリストのselect文とsub query文を結合したsql文を作成するだけにする。
Updated by keiji ono 8 months ago
ivm対象のjs apiを作成した時に、対処となるivm tableが大きいとJetelinaJvmnizedJsApiListの更新前に画面上のtable listが更新されるためtable listに対象ivm tableが表示されることがある。
これは、ivm処理と画面表示処理が非同期におこなわれているためで、同期にするとivm tableが大きいと画面表示が待たされることになる。
なので、これはこれで今はいいかなと思っている。
画面がリフレッシュされれば該当tableは表示されなくなるし。
一応、以下の部分のロジックは後々見直すことになるかもしれないのでメモメモ
PgIVMController.jl compareJsAndJv() #199辺り
if jsspeed[3] < jvspeed[3]
dropIVMtable(ivmapino)
ivmnized = "ivm table for $apino has not been created"
else
ApiSqlListManager.writeToMatchinglist(string(apino))
end
上で一度ivm tableを作成してjs vs jvの実行スピードを計測し、それぞれの平均速度jsspeed[3] vs jvspeed[3]を比較。
jvの方が”遅ければ”作成したivm tableを削除。jvの方が"早ければ"ivm tableはそのまま残してリストに記載する。
上記のcompareJsAndJv()がDBDataControlelr.jlで@asyncで呼ばれているからivm tableの作成に時間がかかるとどうしてもこうなるわな。
DBDataController.jl createApiSelectSentence() #571辺り
@async PgDBController.compareJsAndJv(pgret[2])
こうしておかないとユーザを待たしてしまうし。ねぇ。٩(๑´0`๑)۶
どうするかはもう一度v3.2で考えよう。
Updated by keiji ono 7 months ago
pg_ivm実装手順
ubuntu
- 実装されているpostgresのバージョン確認 psql> select version();
- demo siteはv16だったので、aptでレポジトリを探す sudo apt list | grep postgresql-server-dev*
- v16のdev libがあったのでインストールする sudo apt install postgresql-server-dev-16
- pg_ivmをgitから取得する git clone https://github.com/sraoss/pg_ivm.git
- cloneしたpg_ivmディレクトリで make実行 sudo make install
- postgresqlにpg_ivmが登録されたことを確認 psql> select * from pg_available_extensions where name = 'pg_ivm';
- pg_ivmを有効にする psql> create extension pg_ivm;
- しっかり入ったことを確認 psql> \dx pg_ivm; #
Updated by keiji ono 3 months ago
postgresqlインストールメモ
sudo apt update apt show postgresql -> ver16がレポジトリにあるのがわかる sudo apt install postgresql <- サックリ入る psql --version psql (PostgreSQL) 16.13 (Ubuntu 16.13-0ubuntu0.24.04.1) 素でインストールするとパスワードは未設定のままになっている。 現状のパスワードの確認 select rolname,rolpassword from pg_authid where rolname='postgres'; rolname | rolpassword | postgres| | <- 空になっている なのでパスワードを設定する alter role postgres with password 'postgres'; rolename | rolepassword | postgres | SCRAM-SHA-256$......| <- ハッシュされて設定される
pg_ivmいンストールメモ
gitから取得するのは#14と同じ。 make install時に"pg_configがないよ"と言われたらPG_CONFIGのパスを指定する。 2024/4/15現在のoptiprex ubuntu環境では/usr/local/....にあるので下記として実行する。 sudo make PG_CONFIG=/usr/local/pgsql/16.1/bin/pg_config install インストール成功後の確認方法は#14の通り
Updated by keiji ono 3 months ago
■超重要¶
postgresql 16.13
pg_ivm 1.7
julia 1.11.9
ubuntu 24.04.4 LTS
の環境で、create_immv()の扱いが変わった。
select create_immv('$ivmapino','$sql');
以前:
select pgivm.create_immv('$ivmapino','$sql');
------
よって、PgIVMController.jlの当該箇所が変更となった。他に影響はなし。
#124
# executesql::String = """select pgivm.create_immv('$ivmapino','$sql');"""
executesql::String = """select create_immv('$ivmapino','$sql');"""
Updated by keiji ono about 2 months ago
- Related to 作業 #30: ivmのバージョンによって呼び出し方が変わる added