SQL解析器监听器
适用于 ❌ 开源版 ✅ Express 版 ✅ 专业版 ✅ 企业版
为了实现自定义的解析器行为,可以为你的 Configuration 提供一组自定义的 org.jooq.ParseListener
实现。
当前的 SPI 提供了 3 种类型的语法元素解析的钩子(另请参阅 解析器语法)
-
term
用于解析org.jooq.Field
表达式 -
predicate
用于解析org.jooq.Condition
表达式 -
tableFactor
用于解析org.jooq.Table
表达式
以及这两个生命周期事件
- 解析调用开始之前
- 解析调用结束之后
这个想法是,你提供给解析器的任何监听器实现都可以解析函数、顶级优先级运算符等,而无需处理所有较低级别的优先级运算符,例如 AND
、OR
、NOT
、+
、-
等。
例如,假设你想添加对逻辑 LOGICAL_XOR
运算符作为函数的支持
Query query = configuration .derive(ParseListener.onParseCondition(ctx -> { if (ctx.parseFunctionNameIf("LOGICAL_XOR")) { ctx.parse('('); Condition c1 = ctx.parseCondition(); ctx.parse(','); Condition c2 = ctx.parseCondition(); ctx.parse(')'); return c1.andNot(c2).or(c2.andNot(c1)); } // Let the parser take over if we don't know the token return null; }) .dsl() .parser() .parseQuery("select * from t where logical_xor(t.a = 1, t.b = 2)");
以上只是将便利函数 LOGICAL_XOR(c1, c2)
转换为其正式定义 c1 AND NOT c2 OR c2 AND NOT c1
。 但是我们可以做得更好。 如果某种方言具有原生 XOR
支持,为什么不支持它呢?
Query query = configuration .derive(ParseListener.onParseCondition(ctx -> { if (ctx.parseFunctionNameIf("LOGICAL_XOR")) { ctx.parse('('); Condition c1 = ctx.parseCondition(); ctx.parse(','); Condition c2 = ctx.parseCondition(); ctx.parse(')'); return CustomCondition.of(c -> { switch (c.family()) { case MARIADB: case MYSQL: c.visit(condition("{0} xor {1}", c1, c2)); break; default: c.visit(c1.andNot(c2).or(c2.andNot(c1))); break; } }); } // Let the parser take over if we don't know the token return null; })) .dsl() .parser() .parseQuery("select * from t where logical_xor(t.a = 1, t.b = 2)"); System.out.println(DSL.using(SQLDialect.MYSQL).render(query)); System.out.println(DSL.using(SQLDialect.ORACLE).render(query));
上面的输出现在是
-- MYSQL: select * from t where (t.a = 1 xor t.b = 2); -- ORACLE: select * from t where (t.a = 1 and not (t.b = 2)) or (t.b = 2 and not (t.a = 1));
反馈
你对此页面有任何反馈吗? 我们很乐意听到!