ひしだまの変更履歴

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

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では、こういった不定回数繰り返す処理は実現できません。
(再帰的な共通表式なんて、今回調べるまで知りもしなかったし、見たこともないのですが^^;)

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Java 十六進浮動小数点リテラル

2019-12-08 12:10:54 | PG(Java)

Asakusa Frameworkのアドベントカレンダーはこつこつ書いていて、ついでにJava Advent Calendar 2019に空きがあるから書こうかなーと思ったけど今見たら全部埋まっていたので、カレンダーではないけれど書くだけ書いておきます。

メソッドの戻り値の配列の書き方とか、昔から知ってたけど書きそびれていたので良いネタではあるけど、今回は十六進浮動小数点リテラルについてです。


ちょっと前に浮動小数点のNaNについて話題になったことがあって、そのときにjava.lang.Doubleのソースを見ていたら、MAX_VALUEの定義が「0x1.fffffffffffffP+1023」になっていて、「Eは知ってるけどPって何だ?」と思ったのがきっかけです。

これは、SigSasakiさんによると十六進浮動小数点数というものらしいです。
Javaの浮動小数点はIEEE754の規約に従っていますが、十六進浮動小数点数もそれに含まれているようです。
浮動小数点数は内部では二進数で保持されるので、二進数(表記上は十六進数)で表した方が確実な場合があるのかもしれません。ちょうどMAX_VALUEがそんな感じですし。

でもJava言語仕様を見ても、Pを使った書き方は載ってないんですよね…。
と思ったら、Java8のJLSには載ってました^^;

歴代のjava.lang.Doubleを見てみると、JDK1.5のMAX_VALUEは「1.7976931348623157e+308; // 0x1.fffffffffffffP+1023」であり、Pを使った書き方になったのはJDK1.6からのようです。
でも実際に自分でPを使ってコンパイルしてみると、JDK1.4ではエラー、JDK1.5では通りました。

どの言語仕様(JLS)で追加されたのか確認したい…と思ったのですが、現在公開されているJLSで最も古いものはJava6なので、JDK1.5や1.4は確認できませんでしたorz
しかし色々ググってみたところ、JDK1.5のjava.mathの機能拡張に「16進数の浮動小数のサポート」というトピックがあるのを見つけたので、JDK1.5で追加されたという事で間違いないと思います。

自分が浮動小数点リテラルの書き方を勉強したのはJLS3の頃ですし、JDK1.5が出て注目されていたときも、誰も十六進浮動小数点リテラルには言及していなかったと思います。
そりゃ知らなくても無理は無し!w

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

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で実現するのは大変だと思います^^;

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

SQL to AsakusaFW:INSERT

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

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

SQLのINSERT文は、VALUESを使う構文とSELECTを使う構文があります。

まずINSERT-SELECTですが、これはSELECTした結果をINTOで示されたテーブルに入れるものなので、SELECT文をAsakusaFWに変換するのと同様(出力先データモデルが違うだけ)です。

一方、INSERT-VALUESは入力が何も無い状態からデータを出力することになりますが、AsakusaFWでは入力が無い場合の処理を記述することは出来ません。
core.empty演算子は空のデータを出力しますが、それと似て1レコードだけ出力するcore.oneみたいな演算子が欲しいなーと思っているのですが^^;)
ただ、ダミーで1レコードだけ存在しているファイルをジョブフローの入力とし、それをExtract演算子に渡せば、Extract演算子は自由に複数レコード出力することが出来るので、INSERT-VALUESを実現できます。


それと、テーブル定義のデフォルト値の仕組みはAsakusaFWには無いので、VALUESで指定されていない項目に対するデフォルト値は自分でセットする必要があります。
これは簡単だから特に問題ないのですが、問題は、IDの自動採番の仕組みです。

AsakusaFWは分散して処理するので、全体を通して一意になる値を採番することは出来ません。
処理を行うサーバーのホスト名やUUIDなんかを組み合わせれば一意にすることは出来ますが、RDBの自動採番はほぼ数値なので、直接的な代替にはなりませんよね…。
なので、Oracle用ですが、そこだけJDBC接続してOracleのシーケンスで採番するユーティリティーを作ってみました。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

SQL to AsakusaFW:DELETE

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

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

SQLのDELETE文を考えてみましょう。
WHERE条件が無いDELETE文の場合、全件削除となります。AsakusaFWでは、入力データをcore.stop演算子に渡し、core.empty演算子で空データを出力するのが良さそうです。
というか、ただ単に何もしないということなので、わざわざAsakusaバッチにする必要は全く無いですね(爆)

WHERE条件が有るDELETE文の場合、Branch演算子で条件分岐し、削除する側をcore.stop演算子に渡すことになるでしょう。


ひとつ問題となるのは、RDBへの反映方法です。
たいていのRDBを扱うAsakusaバッチの場合、出力結果をRDBに反映することになると思います。

INSERTやUPDATEの場合は出力したデータをテーブルに反映(上書き)すればいいですが、DELETEではそういうわけにいきません。RDB上の既存データと比較して存在チェックをし、無いものを実際にDELETEすることになりそうですが、面倒ですよね…。

削除したデータをcore.stop演算子に渡すのではなく削除済みデータとして出力しておけば、そのプライマリキーを元に(AsakusaFW以外のツールで)DELETE文を発行するという方法が使えます。こちらの方が幾分簡単な気がします。

なお、AsakusaFWのWindGate JDBCを使っている場合は、RDBへの反映はTRUNCATE(全件削除)+全件INSERTなので、DELETEだからと言っても特別な考慮をする必要はありません。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする