Java 查找令牌';使用JSqlParser在SQL查询中的位置

Java 查找令牌';使用JSqlParser在SQL查询中的位置,java,jsqlparser,Java,Jsqlparser,我试图用JSqlParser在SQL查询中查找SQL对象(令牌?)的位置(行就足够了) 例如,在查询中: SELECT a FROM table WHERE a = 1 AND b = 2 AND c = 3 当看到表达式b=2时,我想知道它在第4行。或者,当查看SelectItem“a”时,我想知道它在第1行 没有在文档中或对象本身中看到任何关于其位置的信息。 如果这在目前还不可能实现,请您提出一个好的方法,让我自己添加此功能(性能方面最简单、最快速)。如果没有经过修

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

例如,在查询中:

SELECT a
FROM table
WHERE a = 1 AND
      b = 2 AND
      c = 3
当看到表达式b=2时,我想知道它在第4行。或者,当查看SelectItem“a”时,我想知道它在第1行

没有在文档中或对象本身中看到任何关于其位置的信息。
如果这在目前还不可能实现,请您提出一个好的方法,让我自己添加此功能(性能方面最简单、最快速)。

如果没有经过修补的JSqlParser版本,您就不能。目前,JSqlParser V1.2-SNAPSHOT确实为您提供了一些特定解析令牌的AST节点信息,但不是所有令牌的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>
true
。然后为所有产品生成AST节点。但你会看到,它会导致一棵大树,即使是你的简单陈述

如果您需要一些特定产品(如EqualTo对象)的此信息,可以通过JSqlParser(github)的功能请求集成此信息

为什么是这两种树?

JSqlParser中的解析树和抽象语法树之间存在差异。对于从ASTNodeAccessImpl扩展而来的对象,这两者之间存在链接。交付的解析树对象是sql解析部分的一种更实用的方法。例如,您可以将对象设置为对象,以引用此表中的列。使用AST方法将导致构造更多节点来构造点、标识符等


AST节点具有您需要的信息,即令牌在原始sql文本中的确切位置。如果查看函数对象,可以使用方法getASTNode获取相应的AST节点,以获取sql中的确切位置。但正如我所写的,这只针对少数解析树对象实现。如果您需要特定的节点来获取此信息,我很乐意为此扩展JSqlParser,但请记住,获取所有这些节点会对性能和内存产生巨大影响。

感谢您提供的信息。这是一个完全不同的位置对象树?在我的用例中,这实际上没有多大意义,因为我的目标是跟踪已解析语句中的对象(使用JSqlParser的常规对象)并获取它们的位置。例如,如果我在树中找到一个函数名Foo,我还想得到它在原始查询中的位置。你能给我指出正确的方向吗?因为我不想为了得到位置而解析一个全新的节点树(我也不理解对象和节点树之间的关系)。谢谢你提供的信息。您提到,此功能目前仅针对少数解析树对象实现。有没有简单的方法可以为任何对象添加此功能?我需要它用于许多类型(例如:函数、表、列、InExpression、EqualTo、ExistsExpression、LikeExpression、StringValue等)。我知道这可能会导致性能下降,但如果我可以配置需要定位信息的类型,那就最好了。我很高兴知道一些关于如何实现它的指导,即使是我自己,因为它对我来说非常重要。首先,JSqlParser对象类必须从ASTNodeAccessImpl进行扩展,其次必须使用linkAST在语法中链接它,就像在函数生成中一样。谢谢!我试着看看当前的实现——如何在Maven中获得v1.2快照?另外,我应该在哪里添加nodeDefaultVoid配置?你能举个例子吗?只有你自己构建jsqlparser,你才能改变这个。实际的主分支头是1.2-Snapshot。查看pom.xml。可以在sonatype maven repo中引用jar。