我过去做过几次类似的事情。一些更大的事情浮现在脑海中。
- where 子句是最难搞定的。如果你把事情分成我所说的“表达式”和“谓词”,它会更容易。
- 表达式 - 列引用、参数、文字、函数、聚合(计数/总和)
- 谓词 - 比较,如,之间,在,为空(谓词有表达式作为子项,例如 expr1 = expr2。然后你也有复合词,如和/或/不。
- 可以想象,整个 where 子句是一棵树,其根部有一个谓词,下面可能还有子谓词,最终在叶子处以表达式结束。
- 要构建 HQL,您需要遍历模型(通常是深度优先)。我使用了一个访问者,因为我出于其他原因需要走我的模型,但如果您没有多种用途,您可以将渲染代码直接构建到模型中。
例如,如果你有
"where upper(column1) = :param1 AND ( column2 is null OR column3 between :param2 and param3)"
然后树是
根
- 和
- 平等的
- 功能(上)
- 列参考(column1)
- 参数(param1)
- 或者
- 一片空白
- 列参考(column2)
- 之间
- 列参考(column3)
- 参数(param2)
- 参数(param3)
然后,您首先遍历树深度,并在返回的路上合并 HQL 的渲染位。例如,上层函数会期望渲染一段子 HQL,然后生成
"upper( " + childHql + " )"
并将其传递给它的父母。像 Between 这样的东西需要三个子 HQL 片段。
然后,您可以在 select/group by/order by 子句中重新使用表达式模型
如果您愿意,您可以通过仅存储选择和查询构造扫描之前的聚合来跳过存储组。如果有一个或多个,则只需将所有非聚合选择表达式复制到 group by。
From 子句只是表引用 + 零个或多个连接子句的列表。每个连接子句都有一个类型(内/左/右)和一个表引用。表引用是表名 + 可选别名。
另外,如果您想要解析查询语言(或其他任何东西),那么我强烈推荐ANTLR。学习曲线非常陡峭,但有很多示例语法可供查看。
HTH。