我正在开发和维护一个名为jOOQ的数据库抽象库,它旨在将 SQL 作为外部 DSL “内部化”到 Java 中。这项工作的目标是允许类型安全地构造和执行最流行的 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...
}
有了上面的接口,就可以在 Java 中构造 SQL 查询,就像今天 jOOQ 已经允许做的那样:
create.select(ONE, TWO).from(TABLE)...
create.selectDistinct(ONE, TWO).from(TABLE)...
// etc...
另外,我想排除某些特定构建的一些语法元素。例如,当我为 MySQL 专门构建 jOOQ 时,不需要支持 SQL MERGE 语句。
是否有任何现有的库实现了这种通用方法,以便将 DSL 正式内部化和外部化到 Java?还是我应该自己滚动?