Project

General

Profile

Actions

機能 #1

open

v3.1に向けて v3.0の積み残し

Added by keiji ono about 1 year ago. Updated 9 months ago.

Status:
新規
Priority:
通常
Assignee:
-
Start date:
04/07/2025
Due date:
% Done:

0%

Estimated time:

Description

  1. api作成時のwhere句のチェック、”同じモノ”チェック
  2. incremental ciew maintenance対応
  3. セキュリティ強化:コンテンツ、プログラム変更、改ざん検知

要確認事項
jetelina_delete_flg=1のデータの自動削除
使われていないapiの自動削除 → 100日間アクセスがなければ自動的に削除する。90日目に通知する → "削除されるかもしれないapi”リスト表示 ← ファイル作成 apilifetime "apino,lifetime" アクセス解析のたびにアクセスがあったらlifetimeを100に戻す。アクセスがなかったらlifetimeをカウントダウンする。


Related issues 2 (2 open0 closed)

Related to 機能 #5: ivmの制限新規06/22/2025

Actions
Related to 機能 #11: v3.1のivm機能実装新規10/20/2025

Actions
Actions #1

Updated by keiji ono about 1 year ago

API作成時のwhere句チェック
  • table名が含まれているか
  • from句にあるtableのカラムであるか
  • 型はあっているか string -> "が必要

functionpanel.js checkGenelicInput()を別jsライブラリにして、込み入った処理を他に影響しないようにしてやる。
subquery.js

ムリムリムリ なので止めた (゚∀゚) 2025/4/28 もしいい手が見つかればリトライしてみる。

Actions #2

Updated by keiji ono about 1 year ago

3.セキュリティ強化:コンテンツ、プログラム変更、改ざん検知
保護すべきファイル
設定ファイル類
  • base.jdic -> initialize時のdate time
  • JetelinaConfig.cnf -> post処理による変更毎を基本とする
  • JetelinaSqlList -> 〃
対象ファイルの読み書きをする際に、
  1. 操作の前にファイルのタイムスタンプとDBに格納されているDataを比較する
  2. 1が問題なければ操作を実行する
  3. 書き込み操作なら、書き込み終了後にDBのdataを更新する
  4. 読み込み操作ならなにもしない
  5. 2で問題が発生した場合は操作を中断してオペレータに報告する
     ”いいから実行せい”となったら当該処理を実行する。実行したあとどうしようか。。。

プログラムファイルはどうしようかなぁ

この処理は新しいjlファイルで実行しよう。

Actions #3

Updated by keiji ono about 1 year ago

2.incremental view maintenance対応
"incremental matelialized view"という、データの実体を伴い且つ、元tableの更新も差分だけ自動で反映される機能があるらしい。
postgres/mysqlでは拡張機能で、oracleでは”トリガー"と呼ばれる標準機能みたいだ。
そこで、

  • 複数tableを使っていて且つ、実行回数が多い

SQL文をviewにする。view table名称はSQL番号(api no)の"js**_view"とする。

viewにしたら

  • view化後のSelect文が必要

viewにした後

  • create viewしたsqlを"jv**"としてSQLリストに登録する
  • 元のSQLとjv**を紐づける
  • 元のSQLにアクセスがあった場合、jv**と同じなら(バインディングが同じなら)jv**を実行する。違えば元SQLを実行する。
  • "jv**"はapiリストには載せない

ivmを使うには該当dbにextentionを追加する必要がある。

  ivmが利用できるかどうか調べる
   select * from pg_available_extensions where name = 'pg_ivm'
      の結果が帰ってきたら利用可能

 postgres=# select * from pg_available_extensions where name = 'pg_ivm';
    name  | default_version | installed_version |                  comment                   
  --------+-----------------+-------------------+--------------------------------------------
   pg_ivm | 1.7             | 1.7               | incremental view maintenance on PostgreSQL
  (1 行)

  extension追加
    create extension if not exists pg_ivm
 extension削除
   drop extension pg_ivm

Actions #4

Updated by keiji ono about 1 year ago

2.increment...をどう使うかだよなぁ。
sub queryに{}のパラメタがあるとそもそもviewが作れない。
履歴から一番多い{}パラメタをivm化するというのもなんだかなぁ。
subに{}が無く且つ、アクセス数が多いものを自動的にivm化するってのがいいのかなぁ。でもそれはユーザの意図に合うのだろうか?

ivmはシンプルなtableであることを前提としているらしいので、csvからtableを作成するjetelinaのコンセプトには合致している。
となると、tableのrelationはivmにおまかせという風にすればjetelinaとの整合性も良さげな感じがする。

ivmと同等の機能はoracle/mysqlではtriggerで実行している。これが問題。triggerはスクリプトを書かないといけなくて、しかもしばしばビジネスロジックになってしまう。
ivmは任意のsqlをview化するだけで更新可能にもしている点がちがう。つまり、欲しいデータのsqlを書いてそれがtable間で複雑な関係だったりする場合にはなんとも頼もしい機能になる。なにせ「勝手に」やってくれるから。
この点に注目してpostgreをoracle/mysqlと差別化して「jetelinaはrdbmsではpostgresを推しますよ」というのは戦略としてアリかもしれない。

実際のimvの使い方

e.g js7として
    select ftest3.ftest3_name,ftest2.ftest2_name,ftest3.ftest3_age,ftest2.ftest2_age from ftest3 as ftest3,ftest2 as ftest2 where test2.ftest2_ave < 0.3 and ftest3.ftest3_ave < 0.2
  なる複数tableを扱うSQLがあるとする

imv化するためにselect文としてcreate_immv()を実行する
 'js7' -> 'jv7' として対応をとっている
  select create_immv('jv7','select ftest3.ftest3_name,ftest2.ftest2_name,ftest3.ftest3_age,ftest2.ftest2_age from ftest3 as ftest3,ftest2 as ftest2 where  ftest2.ftest2_ave < 0.3 and ftest3.ftest3_ave < 0.2');
  
すると'jv7'というtableが新規に作成される(dropする場合は普通に drop table jv7)
postgres=# \dt
                   リレーション一覧
 スキーマ |        名前         |  タイプ  |  所有者  
----------+---------------------+----------+----------
 public   | ftest2              | テーブル | postgres
 public   | ftest3              | テーブル | postgres
 public   | jetelina_user_table | テーブル | postgres
 public   | jv7                 | テーブル | postgres    ← 新規に作成される

'jv7'の中を見てみると’js7'の実行結果がtableになっているのがわかる
postgres=# \d jv7
                          テーブル"public.jv7" 
     列      |      タイプ       | 照合順序 | Null 値を許容 | デフォルト 
-------------+-------------------+----------+---------------+------------
 ftest3_name | character varying |          |               | 
 ftest2_name | character varying |          |               | 
 ftest3_age  | integer           |          |               | 
 ftest2_age  | integer           |          |               | 

postgres=# select * from jv7;
 ftest3_name | ftest2_name | ftest3_age | ftest2_age 
-------------+-------------+------------+------------
 ZZZ         | ZZZ         |         10 |         10
 ZZZ         | YYY         |         10 |         20

ここでftest2 table上でftest2_nameを 'ZZZ' -> 'ZZZ1'にupdateしてみるとjv7 tableが更新されていることがわかる
postgres=# update ftest2 set ftest2_name='ZZZ1' where ftest2_jt_id=1;
UPDATE 1
postgres=# select * from ftest2 where ftest2_name='ZZZ1';
 ftest2_jt_id | ftest2_name | ftest2_sex | ftest2_age | ftest2_ave | jetelina_delete_flg 
--------------+-------------+------------+------------+------------+---------------------
            1 | ZZZ1        | m          |         10 |        0.1 |                   0
(1 行)

postgres=# select * from jv7;
 ftest3_name | ftest2_name | ftest3_age | ftest2_age 
-------------+-------------+------------+------------
 ZZZ         | YYY         |         10 |         20
 ZZZ         | ZZZ1        |         10 |         10    <- 'ZZZ1'になっている

さらに、ftest2 tableに新規データをinsertすると、js7の条件に合っていればjv7 tableに自動的に追加されている
postgres=# insert into ftest2 (ftest2_name,ftest2_sex,ftest2_age,ftest2_ave ,jetelina_delete_flg) values('KKK','m',20,0.2,0);
INSERT 0 1
postgres=# select * from ftest2;
 ftest2_jt_id | ftest2_name | ftest2_sex | ftest2_age | ftest2_ave | jetelina_delete_flg 
--------------+-------------+------------+------------+------------+---------------------
            2 | YYY         | f          |         20 |        0.2 |                   0
            3 | XXX         | m          |         30 |        0.3 |                   0
            1 | ZZZ1        | m          |         10 |        0.1 |                   0
            4 | KKK         | m          |         20 |        0.2 |                   0  <- 新規追加
(4 行)

postgres=# select * from jv7;
 ftest3_name | ftest2_name | ftest3_age | ftest2_age 
-------------+-------------+------------+------------
 ZZZ         | YYY         |         10 |         20
 ZZZ         | ZZZ1        |         10 |         10
 ZZZ         | KKK         |         10 |         20 <- 'KKK'は'..ave=0.2'なのでjs7のsubquery条件に合致するので自動的にjv7に追加されている
(3 行)

もちろん条件に合わないとjv7 tableには追加されない
postgres=# insert into ftest2 (ftest2_name,ftest2_sex,ftest2_age,ftest2_ave ,jetelina_delete_flg) values('GGG','m',20,0.4,0);
INSERT 0 1
postgres=# select * from ftest2;
 ftest2_jt_id | ftest2_name | ftest2_sex | ftest2_age | ftest2_ave | jetelina_delete_flg 
--------------+-------------+------------+------------+------------+---------------------
            2 | YYY         | f          |         20 |        0.2 |                   0
            3 | XXX         | m          |         30 |        0.3 |                   0
            1 | ZZZ1        | m          |         10 |        0.1 |                   0
            4 | KKK         | m          |         20 |        0.2 |                   0
            5 | GGG         | m          |         20 |        0.4 |                   0 <- 新規追加
(5 行)

postgres=# select * from jv7;
 ftest3_name | ftest2_name | ftest3_age | ftest2_age 
-------------+-------------+------------+------------
 ZZZ         | YYY         |         10 |         20
 ZZZ         | ZZZ1        |         10 |         10
 ZZZ         | KKK         |         10 |         20
(3 行)                               <- 'GGG'は'.._ave=0.4'でjs7のsubquery条件に合わないので追加されていない

もちろんftest2上でdeleteするとjv7上のデータも消える
postgres=# delete from ftest2 where ftest2_name='KKK';
DELETE 1
postgres=# select * from ftest2;
 ftest2_jt_id | ftest2_name | ftest2_sex | ftest2_age | ftest2_ave | jetelina_delete_flg 
--------------+-------------+------------+------------+------------+---------------------
            2 | YYY         | f          |         20 |        0.2 |                   0
            3 | XXX         | m          |         30 |        0.3 |                   0
            1 | ZZZ1        | m          |         10 |        0.1 |                   0
            5 | GGG         | m          |         20 |        0.4 |                   0
(4 行)

postgres=# select * from jv7;
 ftest3_name | ftest2_name | ftest3_age | ftest2_age 
-------------+-------------+------------+------------
 ZZZ         | YYY         |         10 |         20
 ZZZ         | ZZZ1        |         10 |         10
(2 行)

作成されたivmの実行queryを見るには
postgres=# select immvrelid, get_immv_def(immvrelid) from pg_ivm_immv;
* where句をつけて immvrelid='jv7'とかしても、それは効かない。:P

 immvrelid |                                                      get_immv_def                                                       
-----------+-------------------------------------------------------------------------------------------------------------------------
 jv7       |  SELECT ftest3.ftest3_name,                                                                                            +
           |     ftest2.ftest2_name,                                                                                                +
           |     ftest3.ftest3_age,                                                                                                 +
           |     ftest2.ftest2_age                                                                                                  +
           |    FROM ftest3 ftest3,                                                                                                 +
           |     ftest2 ftest2                                                                                                      +
           |   WHERE ((ftest2.ftest2_ave < (0.3)::double precision) AND (ftest3.ftest3_ave < (0.2)::double precision))
 36209     | 
 36261     | 
 36286     | 
 36312     | 
 36337     | 
 jv16      |  SELECT palt.palt_first_name,                                                                                          +
           |     people_1000.people_1000_first_name                                                                                 +
           |    FROM palt palt,                                                                                                     +
           |     people_1000 people_1000                                                                                            +
           |   WHERE ((palt.palt_jt_id < 100) AND ((100 < people_1000.people_1000_jt_id) AND (people_1000.people_1000_jt_id < 200)))

Actions #5

Updated by keiji ono about 1 year ago

imvのtableに格納されるjs*のSQLにjetelina_delete_flg=0であることを明示する必要がありそう
元tableでjetelina_delte_flg=1とdelete扱いされたときには、imvのtableの当該データも削除されるからOK

js* -> jv* 化
  1. 複数tableを使用しているsqlは原則jv*化する
  2. 試しにjs*の実行速度とjv*の実行速度を比較する
  3. js*の実行速度がjv*の実行速度よりも著しく遅い場合はjv*化優先候補となる
  4. js*の実際のアクセス数を見る
  5. js*のアクセス数が高いようならjv*化する
  6. jv*化したjs*はJetelinaSqlList上でjv*で表される
  7. api listの表示時にjv* -> js* と変換する
  8. js* apiが呼ばれて実行される際にはjs*とjv*のorを取って、存在する方のsqlを実行する
  9. api access count/exectute speed の各グラフもjs* -> jv* のapi名変更を行う
もしくは、5の時に、
  • js*/jv*対応ファイルを作成する
  • js実行時には常にこれを参照して対応するjvがあればそちらを実行する
  • jv実行時は単純に該当jvをselectすればいいだけなのでsqlは単純になる
  • jv実行時のjsonフォームをjsに合わせる必要がある
  • 6-9が不要になる

js*/jv*対応ファイルはJetelinaSqlList同様DataFrameにしてメモリに格納すればいいから比較のための処理速度はあまり気にならないかもしれないので、プログラミングを考えるとこっちのほうがよさそうだな。

Actions #6

Updated by keiji ono about 1 year ago

現状(v3.0)、PgTestDBController.jl、SQLAnalyzer.jlは利用されていない。
これらにはsqlのテスト実行と速度計測のための関数がある。
SQLA..はテスト用のtable作成/削除とかやってくれているので、これを上位プログラムとしてここからPgTest..を呼び出すことにしよう。
すでにSQLA..main()でタイマー機能があるからこれを使おう。
#5の1-5を実行するとして、
  1. 1はconfig/JetelinaTableApiRelationからpostgresで複数tableを使用しているjs*を抽出する -> collectIvmCandidateApis()
  2. PgIVM..を呼び出して2を実行する -> experimentalRun()
  3. jv化対象となるjs*を新規のファイルに記録しておく
  4. 定期実行(毎日一回とか)で4を見てjv化の判断をおこない、5まで実行する

これなら既存プログラムへの影響は軽微っぽい。

2025/6/3
js/jv対応表はconfig/JetelinaJvmnizedJsApiListに記録され、Df_JsJvListで運用される

Jetelina.InitApiSqlListManager.ApiSqlListManager.Df_JsJvList
2×2 DataFrame
 Row │ js       jv      
     │ String3  String3 
─────┼──────────────────
   1 │ js7      jv7
   2 │ js8      jv8

Df_JsJvListの作成・更新タイミングは
1.起動時にSQLAnalyzer.init()で初期実行される <- JetelinaJvmmize... file があれば。
2.   〃 定期的にmulti table利用のsqlを探って実行される
3.js*が削除された時に対応するjv*があれば実行する   <- 要実装 deleteJvApiFromMatchingList(), dropIVMtable()はもうあるから、いつ呼ぶかってこと

2025/6/1
2でivm tableを作成してその実行速度をfileに記録するところまでexperimentalRun()でやっていたが、それをやめて、SQLAnalyzer.executeIVMtest()はivm test runの平均実行速度を戻り値として取得し、これとivmにしないsqlの実行速度を比較して「ある程度」ivm効果が確認できるようならivm化することとしよう。これによってアクセス数云々というのは関係なくする。ivm効果が確認できないようならdropIVMtable()を呼び出してivm化をなかったことにする。
ivm化することにしたならjs/jv対応ファイルに追記すると。

2025/6/12
jv化するところまではOK.
次は、
  1. js作成時にjv化検討も行う(PgDBController.compareJsAndJv()実行) <-「js作成時にjvも」同時でなくてもいいよね。同時じゃないほうがいいか?
  2. api呼び出しでjvを呼び出し <- PgDBController.executeApi()に実装済 6/15
    5により、jv*のsqlがシンプルではなくなったのでjv*のsqlをどこかに格納しておく必要がでてきた
  3. api削除でjvを同時に削除 <- PostDataController.deleteApi()(実体はApiSqlListManager.delteApiFromList()), deleteTable()(実体はDBDataController.dropTable())でやれるかな <- 6/16 done
  4. Oops, table list にjv*が載っている。そりゃそうだjv*は普通のtableだから。表示しないようにちょっと工夫しないとな。 <- 6/17 done #7参照
  5. js*作成時のsqlにlimitやoffset句がある場合はjv*にも引き継がないといけないのでは?
    <= 現状でもjs*ではlimit/offsetが効く。これらの句はwhere句の後ろにあるといいらしい。さてjv*に反映だな。
    ivmは"HAVING, ORDER BY, LIMIT/OFFSET, UNION/INTERSECT/EXCEPT, DISTINCT ON"をサポートしていないらしい。なので、これらがsubquery句にあった場合は文字列を分離してjv*の実行文に後付してやるのか。メンドイな。
    SQL結合に使う句がある場合はivm化しないということにしよう。これらのclausesはivmのバージョンアップで変わる可能性があるから時々見直しが必要かも。
    clause ivm-nize
    having X
    order by
    limit
    offset
    union X
    intersect X
    except X
    distinct on X
    tablesample X
    values X
    for update X
    share X

これらのclauseを判別してivm tableを作成するかどうか決めるところまではPgIVMController.createIVMtable()で実装できた。問題は次、compareJsAndJv()でjs*とjv*の速度比較をして、よさげならjv*を使うことにするとしているが、sqlに変数'{...}'があると比較実行できない。もちろんclauseがあっても。
さて、どうしよう。

Actions #7

Updated by keiji ono about 1 year ago

  1. PgVMController.checkIVMExistence()の実行をGenie起動時に一度呼び出す
  2. table listにivmのtableが表示される <- ivmは”普通のtable”だからこうなる 6/17解決
    解決方法:
    quote:  PgDBController._getTableList()
            DataFrames.filter!(row -> row.tablename != "jetelina_user_table", df)
    
       →   DataFrames.filter!(row -> row.tablename != "jetelina_user_table" && row.tablename ∉ Df_JsJvList[!,:jv] , df)
                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    なんかjuliaっぽい:)
    

ivm未導入時にはconf内の"pg_ivm"はfalseになっている。
ivmを導入したら一度Geneiを再起動すると1でivmが認識されて"pg_ivm"がtrueになる。
以降、js*作成時にivm化が検討される。
では、ivm導入前に複数tableを使っているsqlはいつivm化が検討されるべきか?答えはSQLAnalyzer.collectIvmCandidateApis()が持っている。

10/29
ivm tableは非表示にすることにしたので元に戻す。ref. #11

Actions #8

Updated by keiji ono about 1 year ago

PgDBController.dropTable()のSQLに"if exists"を追加して、api削除時にivm tableも一緒に削除しようとした時に存在しなかったらスルーするようにする。

    drop table
    -> drop table if exists

MySqlでは今の所存在するtableだけが削除されるハズなので、こっちはそのままにしておく。

Actions #9

Updated by keiji ono about 1 year ago

Actions #10

Updated by keiji ono 12 months ago

ivm機能についてちょっと考え直している。

🔸従来の考え方
複数tableからivm talbを作成する事は実行速度の計測と実際の利用頻度から決めることにしていた。
この方式ではivmの機能と制限をそのまま受け入れて、view的な使い方をユーザが意識しないでやれるようにという方針。
この方式ではivm tableには一つのapiしかない。

🔹今考えていること
ivm tableは実態としてtableなんだからivmの制限とか気にしないでいきたい。
どのtbleを使って新し'talbe'を作るかはユーザの任意に任せ、jetelinaは作成されたivm talbeを新たなtableとして使う。
この方式ではivm tableには普通に複数のapiを作ることができる。但し、insert/delete/updateの処理は元のtableに対して行う。なので、元のtableのinsert/delete/update apiを組み合わせたsqlとしてあげればいい。
この方式では、従来の方式と違ってivm tableをユーザに意識的に作成させる。なので"ivm table作成"コマンドを用意してあげることになる。
つまりtable作成方法は2つになる

  • ファイルアップロード
  • ivm table作成コマンド実行

この方式ではivm table同士のさらなる組み合わせもできそうだけど、それはどうなんだろう?

Actions #11

Updated by keiji ono 10 months ago

ivmを使った機能について新しいアイデア

従来は「複数tableのselect文のパフォーマンスを見て、ivmを使った方がいいようなら自動的にそうする。ユーザはそれを知らなくてもいい」ということでやっていたが、むしろ「ユーザが意識して使う」というのはどうだろうか。
複数の「マスターテーブルから必要なデータを選択して新しいテーブルを作る」という方がユーザには理解しやすく受け入れやすいのではなかろうか。これを「バスケット方式」と呼ぶ。
マスターテーブルはcsvアップロードされたヤツになる。
  • dbiはselectのみ
  • insert/update/deleteのdbiは今まで通り
  • tableのリレーションなんか一目でわかると嬉しい
  • データ選択する際に表示するテーブルにはサンプルデータも表示してデータをイメージしやすくする。nullアリデータでも何か例が表示されるようならベスト
Actions #12

Updated by keiji ono 10 months ago

#11の方向でivm機能を追加していこうと思う。
これは当初のモノとは違ってくるのでbranchもv3.2として進める。当面は"-candidate"が付く。

Actions #13

Updated by keiji ono 9 months ago

"suggestion for api speed"の実行は、ログイン時に自動的にチェックされる。

jeteilnalib.js #1317
                    getAjaxData(scenario["analyzed-data-collect-url"][3]);    

それと、コマンド実行はここ

statspanel.js #192
        } else if (inScenarioChk(ut, 'stats-check-suggestion-cmd')) {
            // confirm the suggestion file existing
            getAjaxData(scenario["analyzed-data-collect-url"][7]);

このスピード比較機能は残しておいて、表示されるアイコンを変えよう。
対象画像: img/jetelina-concern.png

画像はalertにした。これを消すのは"general-thanks-cmd"、つまり"thank you"で消える。

jetelinalib.js #1562
                    changeChatGirlImage("chat");

Actions #14

Updated by keiji ono 9 months ago

公開repositoryを設定する。
git-jetelina/Jetelina

/ jetelina123

Actions #15

Updated by keiji ono 9 months ago

  • Related to 機能 #11: v3.1のivm機能実装 added
Actions

Also available in: Atom PDF