使用 JSqlParser 在 SQL 查询中查找标记的位置
Find token's position in an SQL query using JSqlParser
我正在尝试使用 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 - 某些特定已解析标记的节点信息,但不是全部。使用以下代码截取:
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 字符串中的绝对位置和范围。
这 "limitation" 来自 JSqlParsers 功能驱动开发和对生成所有 AST 节点的巨大性能影响。此外,一些 AST 节点是 linked with JSQlParsers parsers objects like Column, Table, etc. 这还没有完成自动使用 JavaCC,但必须在语法定义中完成。
起初我提到了一个打过补丁的JSqlParser。这确实很容易通过修改 pom.xml 和设置
<nodeDefaultVoid>true</nodeDefaultVoid>
变为 错误 。然后为所有产品生成 AST 节点。但是你会看到,它会产生一棵巨大的树,即使是你简单的陈述。
如果您需要此信息用于某些特定的产品,例如您的 EqualTo 对象,这可以通过 JSqlParser (github) 的功能请求集成。
为什么是这两种树?
JSqlParser 中的解析树和抽象语法树是有区别的。对于从 ASTNodeAccessImpl 扩展的对象,两者之间有一个 link。交付的解析树对象是对 sql 的已解析部分的更实用的方法。例如,您可以将 Table 对象设置为 Column 对象以引用此 table 中的列。使用 AST 方法,这将导致构建更多节点来构建点、标识符等。
AST 节点具有您需要的信息,即标记在原始 sql 文本中的确切位置。如果你查看一个 Function 对象,你可以使用方法 getASTNode 来获取相应的 AST - 节点以获得你的 sql。但正如我所写,这仅针对少数解析树对象实现。如果您需要特定的节点来获取此信息,我会很乐意为它扩展 JSqlParser,但请记住,获取所有这些节点会对性能和内存产生巨大影响。
我正在尝试使用 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 - 某些特定已解析标记的节点信息,但不是全部。使用以下代码截取:
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 字符串中的绝对位置和范围。
这 "limitation" 来自 JSqlParsers 功能驱动开发和对生成所有 AST 节点的巨大性能影响。此外,一些 AST 节点是 linked with JSQlParsers parsers objects like Column, Table, etc. 这还没有完成自动使用 JavaCC,但必须在语法定义中完成。
起初我提到了一个打过补丁的JSqlParser。这确实很容易通过修改 pom.xml 和设置
<nodeDefaultVoid>true</nodeDefaultVoid>
变为 错误 。然后为所有产品生成 AST 节点。但是你会看到,它会产生一棵巨大的树,即使是你简单的陈述。
如果您需要此信息用于某些特定的产品,例如您的 EqualTo 对象,这可以通过 JSqlParser (github) 的功能请求集成。
为什么是这两种树?
JSqlParser 中的解析树和抽象语法树是有区别的。对于从 ASTNodeAccessImpl 扩展的对象,两者之间有一个 link。交付的解析树对象是对 sql 的已解析部分的更实用的方法。例如,您可以将 Table 对象设置为 Column 对象以引用此 table 中的列。使用 AST 方法,这将导致构建更多节点来构建点、标识符等。
AST 节点具有您需要的信息,即标记在原始 sql 文本中的确切位置。如果你查看一个 Function 对象,你可以使用方法 getASTNode 来获取相应的 AST - 节点以获得你的 sql。但正如我所写,这仅针对少数解析树对象实现。如果您需要特定的节点来获取此信息,我会很乐意为它扩展 JSqlParser,但请记住,获取所有这些节点会对性能和内存产生巨大影响。