使用JSqlParser

时间:2017-09-28 20:27:17

标签: java jsqlparser

我试图在SQL查询中使用JSqlParser找到SQL对象(令牌?)的位置(行足够)。

例如,在查询中:

SELECT a
FROM table
WHERE a = 1 AND
      b = 2 AND
      c = 3

当看到表达式b = 2时,我希望能够知道它在第4行。或者,在查看SelectItem" a"时,我想知道它在第1行。

没有在文档中或在对象本身中看到有关其位置的任何内容。 如果目前无法做到这一点,请您建议我自己添加此功能的最佳方法(最简单,最快速的性能)。

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,但请记住,获取所有这些节点会产生巨大的性能和内存影响。