私は、SQL を外部 DSL として Java に「内部化」することを目的としたjOOQと呼ばれるデータベース抽象化ライブラリーを開発および保守しています。この取り組みの目標は、最も一般的な RDBMS の可能なすべての SQL 構文要素をタイプ セーフに構築および実行できるようにすることです。jOOQ の内部 DSL はますます複雑になってきており、正式に把握したいと考えています。アイデアは、入力としてSQLのある種の正式な定義を持てるようにしたいということです。
select ::= subquery [ for-update-clause ]
subquery ::= SELECT [ { ALL | DISTINCT | UNIQUE } ] select-list
[ FROM table-reference ] ..
select-list ::= expression [ [ AS ] alias ] [, expression ... ]
expression ::= ...
alias ::= ...
table-reference ::= ...
入力は、XML またはその他の記述的なメタ言語で定義することもできます。その入力を取得したら、その入力から、Java で定義された構文をモデル化する一連の Java インターフェイスを生成したいと考えています。インターフェイスの例は次のとおりです。
// The first "step" of query creation is modelled with this interface
interface Select0 {
// The various SELECT keywords are modelled with methods
// returning the subsequent generated syntax-element
Select1 select(Expression...);
Select1 selectAll(Expression...);
Select1 selectDistinct(Expression...);
Select1 selectUnique(Expression...);
}
// The second "step" of query creation is optional, hence it
// inherits from the third "step"
interface Select1 extends Select2 {
// Here a FROM clause may be added optionally
Select2 from(TableReference...);
}
// To keep it simple, the third "step" is the last for this example
interface Select2 extends SelectEnd {
// WHERE, CONNECT BY, PIVOT, UNPIVOT, GROUP BY, HAVING, ORDER BY, etc...
}
上記のインターフェイスを使用すると、現在 jOOQ で既に許可されているように、Java で SQL クエリを作成できます。
create.select(ONE, TWO).from(TABLE)...
create.selectDistinct(ONE, TWO).from(TABLE)...
// etc...
また、特定のビルドの一部の構文要素を除外したいと思います。たとえば、MySQL 専用の jOOQ をビルドする場合、SQL MERGE ステートメントをサポートする必要はありません。
Java に DSL を正式に内部化および外部化するために、そのような一般的なアプローチを実装する既存のライブラリはありますか? それとも自分で巻くべきですか?