我试图在SQL查询中使用JSqlParser找到SQL对象(令牌?)的位置(行足够)。
例如,在查询中:
SELECT a
FROM table
WHERE a = 1 AND
b = 2 AND
c = 3
当看到表达式b = 2时,我希望能够知道它在第4行。或者,在查看SelectItem" a"时,我想知道它在第1行。
没有在文档中或在对象本身中看到有关其位置的任何内容。 如果目前无法做到这一点,请您建议我自己添加此功能的最佳方法(最简单,最快速的性能)。
答案 0 :(得分:1)
如果没有修补版本的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解析对象链接,如列,表等,这些对象不是使用JavaCC自动完成的,而是必须在语法定义中完成。
刚开始我提到了一个修补过的JSqlParser。通过修改 pom.xml 并设置
,确实很容易做到这一点<nodeDefaultVoid>true</nodeDefaultVoid>
到 false 。然后,对于所有产生,生成AST节点。但是你会看到,即使你的简单陈述,它也会产生一棵巨大的树。
如果您需要某些特定作品的信息,例如 EqualTo 对象,可以通过JSqlParser(github)的功能请求进行集成。
为什么这两种树?
JSqlParser中的解析树和抽象语法树之间存在差异。对于从 ASTNodeAccessImpl 扩展的对象,这两者之间存在链接。传递的解析树对象是一种更实用的方法来解析sql的解析部分。例如,您可以将表对象设置为列对象,以引用此表中的列。使用AST方法,这将导致构造更多节点以构造点,标识符等。
AST节点拥有您需要的信息,即原始sql文本中令牌的确切位置。如果查看 Function 对象,可以使用 getASTNode 方法获取相应的AST节点,以获取sql中的确切位置。但正如我所写,这仅适用于几个解析树对象。如果您需要特定的信息来获取此信息,我将很乐意为其扩展JSqlParser,但请记住,获取所有这些节点会产生巨大的性能和内存影响。