jOOQのDB方言変換機能を使ってみる

2019年7月1日

jOOQまとめがあるので参照されたい

jOOQではDSLを使ってSQLを表現するJavaオブジェクトを構築し、指定されたデータベースに対する実際のSQL文字列を生成する。

DSLを使い、各方言のSQLを生成させる

次は同じ意味のSQLを各方言で出力させる例だ。単純に「select * from a」の結果行の10行目から20行を取得する。

※なお、SQL文字列の取得だけで、実際のDB操作は行わないのでコネクションはnullで良いようだ。

    Arrays.stream(new SQLDialect[] { SQLDialect.MYSQL, SQLDialect.FIREBIRD, SQLDialect.DERBY }).forEach(d-> {
      DSLContext ctx = DSL.using((Connection)null, d);
      System.out.println(
          d + ":" + ctx.selectFrom(table("a")).limit(10, 20).getSQL(ParamType.INLINED));      
    });

出力結果は以下になる。

MYSQL:select * from a limit 20 offset 10
FIREBIRD:select * from a rows (10 + 1) to (10 + 20)
DERBY:select * from a offset 10 rows fetch next 20 rows only

このように、jOOQのDSLによるSQL表現を使うことにより、サポート済のDB用のSQL方言を出力させることができる。

※jOOQの有料バージョンでは、Oracle等の有料DB向けの出力ができる。

各方言のSQLを別方言に変換するウェブ

上はDSL表現からの方言出力だったのだが、方言文字列から別の方言文字列に変換する試みもされている。もちろん、試してみたところでは、これは完全ではない。「ある程度は」というところだ。実際に以下で試すことができる。

実際に前項で得られたFirebird用の文字列を入力してみるとエラーになってしまう(2019/6現在)。

ところが、Firebirdの以前の仕様を入力してみると、今度はうまく行っている。

各方言のSQLを別方言に変換するプログラム

前述のようにこの機能は完全ではないのだが、実際にプログラムでこれを行わせる方法としては以下だ。

ここでは、最初の10行を取得するFirebirdの古い仕様を入力としている。

    Arrays.stream(new SQLDialect[] { SQLDialect.MYSQL, SQLDialect.FIREBIRD, SQLDialect.DERBY }).forEach(d-> {
      DSLContext ctx = DSL.using((Connection)null, d);
      Query query = ctx.parser().parseQuery("select first 10 * from a");
      System.out.println(ctx.render(query));   
    });

結果は以下になる。

MYSQL:select * from a limit 10
FIREBIRD:select * from a rows (0 + 1) to (0 + 10)
DERBY:select * from a offset 0 rows fetch next 10 rows only

※ウェブ版では、入力方言を指定するコンボがついているが、プログラム上では入力方言を指定する方法は見つからなかった。出力方言のみを指定できる。