goo blog サービス終了のお知らせ 

ひしだまの変更履歴

ひしだまHPの更新履歴。
主にTRPGリプレイの元ネタ集、プログラミング技術メモと自作ソフト、好きなゲームや音楽です。

SQL to AsakusaFW:join(CoGroup)

2019-12-12 00:00:00 | PG(分散処理)

Asakusa Framework Advent Calendar 2019の12日目、SQLをAsakusaFWに変換するポイントについてです。

SELECT文のFROM句ではテーブルを結合できます。
これはAsakusaFWではCoGroup演算子で実現できます。

AsakusaFWでは基本的にCoGroupを使わずに他の演算子を使った方が良いとされていますが、SQLのJOINに関してはCoGroupにしておくのが無難だと思います。
というのは、JOINではキーによる結合結果として複数レコード出力されることがあり、AsakusaFWで結合時に複数レコード出力できるのはCoGroupだけだからです。

ONで「=」によってキー同士を比較しているカラムは、CoGroupの結合キーとして使用できます。
そしてCoGroupの本体では、2つの入力を二重ループで処理します。
INNER JOINの場合、双方に存在しているレコードを出力するだけなので簡単ですが、
LEFT JOINの場合は、左側に存在しない場合は右側を出力するので、そういった処理が必要となります。


SQL to AsakusaFW:WHERE(2)

2019-12-11 00:00:00 | PG(分散処理)

Asakusa Framework Advent Calendar 2019の11日目、SQLをAsakusaFWに変換するポイントについてです。

SELECT・UPDATEやDELETE文のWHERE条件は、基本的にBranch演算子で実現できます
基本的にと言うのは、入力レコードのみで判断できるものを指しています。
そして、そうでないものとは、別レコードとの結合を必要とするもの、すなわちSQLのexistsやin-selectです。
col in (select c from t)という形式はexists (select 1 from t where c = col)に置き換えられるので、実質同じです。

そして、existsはMasterCheck演算子で実現することが出来ます。
ただし、null同士の比較がありうるのであれば、そのままでは出来ません。一番簡単な解決策は、マスター側のnullデータを事前に別の値に更新しておくことでしょうか。そうすればnullとその値の比較はマッチしないので、SQLと同じ結果になります。

あと、existsのwhereに等値「=」以外の比較がある場合は、MasterSelectionで実現できると思います。


SQL to AsakusaFW:WHERE(1)

2019-12-10 00:00:00 | PG(分散処理)

Asakusa Framework Advent Calendar 2019の10日目、SQLをAsakusaFWに変換するポイントについてです。

SELECT・UPDATEやDELETE文のWHERE条件は、基本的にBranch演算子で実現できます。
SELECTの場合は条件を満たしたものだけ抽出、DELETEは逆に条件を満たしたものは出力しない。UPDATEは条件を満たしたものだけ更新し、満たさなかったものと後で合流(core.confluent演算子)します。

ここで重要なのは、NULLの扱いです。
SQLではNULLとの比較演算の結果はUNKNOWNとなり、UNKNOWNはFALSE扱いです。
例えば等値演算「a=b」の場合、AsakusaFWのオペレーターではa.equals(b)となるわけですが、aもbもNULLの場合、SQLはUNKNOWNすなわちFALSEになるのに対し、AsakusaFWではtrue(null同士なので等しい)になります。
(aかbのどちらかのみがNULLの場合は、SQLの「a=b」はUNKNOWNでFALSE扱いとなり、AsakusaFWでは単純に不一致でfalseとなるので、結果は一致します)
なので、AsakusaFWではSQL用の演算を行うユーティリティーを作り、それを呼び出すようにした方が良いと思います。

それでもさらに問題があって、それは否定演算NOTです。
SQLでは「NOT(a=b)」に対してaかbがNULLの場合、「NOT UNKNWON」→「UNKOWN」→「FALSE扱い」となります。なので、AsakusaFWに変換するときはNOTは要注意。単純にJavaの否定演算子「!」を使えばいいというわけにはいきません。
このSQLの「3値Boolean」をJavaで厳密に扱うなら、専用のクラスを作るべきかもしれません…。


SQL to AsakusaFW:with

2019-12-09 00:00:00 | PG(分散処理)

Asakusa Framework Advent Calendar 2019の9日目、SQLをAsakusaFWに変換するポイントについてです。

SQLのwith句(共通表式や共通テーブル式と呼ばれる)は、そのSQL文でしか使わないローカルなビューのようなものです。
したがって、withをAsakusaFWに変換するのはビューと同様です。

ところが、withには、再帰的な共通表式という使い方があります。これは、自分自身を再帰的に参照する自己参照の機能らしいです。
AsakusaFWでは、こういった不定回数繰り返す処理は実現できません。
(再帰的な共通表式なんて、今回調べるまで知りもしなかったし、見たこともないのですが^^;)


SQL to AsakusaFW:ビュー

2019-12-08 00:00:00 | PG(分散処理)

Asakusa Framework Advent Calendar 2019の8日目、SQLをAsakusaFWに変換するポイントについてです。

RDBのビューをAsakusaFWで使うには、2通りの方法が考えられます。
ひとつは、テーブルと同じように、RDBのビューのデータをそのまま読み込むという方法です。
もうひとつは、ビューを作るのに必要なテーブルのデータを読み込み、Asakusaアプリケーション上でビューを構築する方法です。

前者の方法は、「AsakusaFWに変換する」という意味では何もしなくてよいので、楽ですねw

後者の方法は、つまりCREATE VIEWをAsakusaFWで実現するということですが、これはINSERT-SELECTとほとんど同じです。
もし複数のAsakusaバッチがあって、前のバッチでビューを構成するテーブルのデータが更新されるのであれば、この方法を使うしかないでしょう。(でなければ、一旦RDBに反映してからビューとして読み込むことになってしまい、とても無駄な感じがします)
あるいは、そもそもビューを作るSELECTが重いのであれば、Asakusaアプリケーション上でビューを構成する方が実行速度は速くなるかもしれません。


自分では使ったことがありませんが、ビューには更新可能ビューというものがあります。
更新可能ビューに対してUPDATEを行うと、ビューを構成している元のテーブルが更新されるというものです。

さすがにこれをAsakusaFWで実現するのは大変だと思います^^;