Java中外部DSL“内化”的工具

时间:2011-07-12 15:55:04

标签: java dsl dsl-tools

我正在开发和维护一个名为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?或者我应该自己滚动?

1 个答案:

答案 0 :(得分:1)

您真正想要做的是将通用SQL转换为内部API的调用。似乎是合理的。

要做到这一点,您需要一个“通用SQL”解析器,以及从该解析器生成代码的方法。通常你需要解析器来构建一个抽象语法树,你几乎需要一个符号表(这样你就知道什么是表名,什么是列名,以及这些列名是来自表A还是表B,所以某处您需要访问定义数据模型的SQL DDL ....这需要您再次解析SQL :)。

使用AST和符号表,您可以通过多种方式生成代码,但一种简单的方法是在遇到它们时将AST转换为转换结构。这不允许构建优化查询;这需要更复杂的代码生成,但如果您提供适当的API函数支持,我希望它足够了。

只需打印Java文本即可完成实际代码生成;如果你去ANTLR路线,你将不得不做这样的事情。另一种方法是将SQL代码片段(作为AST)逐字转换为Java代码片段(作为AST)。后一种方案为您提供了更多控制(如果它们是AST,您实际上可以对Java代码片段进行转换),如果正确完成,可以通过代码生成工具进行检查。

我们的DMS Software Reengineering Toolkit将是一个很好的基础。 DMS为构建翻译工具提供了一个生态系统,包括强大的解析器机制,符号表支持,表面语法模式导向的转换规则,并且具有通用SQL(SQL 2011,标准)作为可用的,经过测试的解析器,以及Java,用于代码生成方。