如果没有 JSqlParser 的修补版本,则不能。目前,JSqlParser V1.2-SNAPSHOT 确实为您提供了一些特定已解析令牌的 AST - 节点信息,但并非全部。使用以下代码截断:
public static void main(String[] args) throws JSQLParserException {
String sql = "SELECT a\n"
+ "FROM table\n"
+ "WHERE a = 1 AND\n"
+ " b = 2 AND\n"
+ " c = 3";
SimpleNode node = (SimpleNode) CCJSqlParserUtil.parseAST(sql);
node.jjtAccept(new CCJSqlParserDefaultVisitor() {
@Override
public Object visit(SimpleNode node, Object data) {
System.out.println(node.toString() + " firstToken=" + node.jjtGetFirstToken().image
+ " line=" + node.jjtGetFirstToken().beginLine);
return super.visit(node, data);
}
}, null);
}
您可以获得有关所有已保存 AST 节点的信息。探索 SimpleNode 的界面,您还可以了解令牌在源 sql 字符串中的绝对位置和范围。
这种“限制”来自 JSqlParsers 功能驱动的开发以及对生成所有 AST 节点的巨大性能影响。此外,一些 AST 节点与 JSQlParsers 解析对象(如Column、Table等)链接,这不是使用 JavaCC 自动完成的,而是必须在语法定义中完成。
起初我提到了一个修补过的 JSqlParser。这确实很容易通过修改pom.xml和设置
<nodeDefaultVoid>true</nodeDefaultVoid>
为假。然后为所有产品生成 AST 节点。但是您会看到,即使对于您的简单语句,它也会生成一棵巨大的树。
如果您需要此信息用于某些特定产品(例如EqualTo对象),可以通过 JSqlParser (github) 的功能请求来集成。
为什么是那两种树?
JSqlParser 中的解析树和抽象语法树是有区别的。对于从ASTNodeAccessImpl扩展的对象,这两者之间存在联系。交付的解析树对象是分析 sql 部分的更实用的方法。例如,您可以将Table对象设置为Column对象以引用该表中的列。使用 AST 方法,这将导致构建更多节点来构建点、标识符等。
AST 节点具有您需要的信息,即令牌在原始 sql 文本中的确切位置。如果您查看Function对象,您可以使用方法getASTNode来获取相应的 AST - 节点以获取 sql 中的确切位置。但正如我所写,这仅适用于少数解析树对象。如果您需要特定的节点来获取此信息,我将很乐意为其扩展 JSqlParser,但请记住,获取所有这些节点会对性能和内存产生巨大影响。