【发布时间】:2021-10-11 16:07:19
【问题描述】:
目标:在任何给定的 Clickhouse 语句中添加额外的 WHERE 子句。
我正在使用以下 Antlr 语法为词法分析器和解析器生成 Java 类。
词法分析
https://github.com/ClickHouse/ClickHouse/blob/master/utils/antlr/ClickHouseLexer.g4
解析器语法
https://github.com/ClickHouse/ClickHouse/blob/master/utils/antlr/ClickHouseParser.g4
问题:我无法弄清楚/理解如何与 Antlr 生成的生成类交互或创建适当的 POJO。
语句示例
String query = "INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')"
SQL 的目标(扩充代码)
String enrichedQuery = SqlParser.enrich(query);
System.out.println(enrichedQuery);
//Output
>> INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def') (WHERE X IN USERS)
我有以下 Java 主程序
public class Hello {
public static void main( String[] args) throws Exception{
String query = "INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')"
ClickhouseLexer = new ClickhouseLexer(new ANTLRInputStream(query));
CommonTokenStream tokens = new CommonTokenStream(lexer);
ClickHouseParser = new ClickHouseParser (tokens);
ParseTreeWalker walker = new ParseTreeWalker();
}
}
【问题讨论】:
-
首先,编写一个只解析输入字符串的驱动程序。将上述 main() 中的“HelloParser”替换为“ClickHouseParser”,将“HelloLexer”替换为“ClickHouseLexer”。测试一下,然后你就可以为你的目标修改解析器树了。
-
@kaby76 感谢您的留言。请参阅修改后的代码。我错误地用手卡住了我想要达到的目标的快速概要。此后已在您发送消息之前进行了更新
-
试试
var str = CharStreams.fromString(input); var lexer = new ClickHouseLexer(str); var tokens = new CommonTokenStream(lexer); var parser = new ClickHouseParser(tokens); var tree = parser.queryStmt();。但是解析器语法针对的是 C,而不是 Java。因此,您必须更改解析器语法:在顶部的options {...}之后添加@header { import java.util.Set; };std::set<std::string> attrs改为Set<String> attrs;attrs.count(改为attrs.contains(;attrs.insert(更改为attrs.add(。clauses类似。 -
有几种方法可以实现
where子句,但一个简单的解决方案是只编写一个树遍历器(可能您可以使用生成的 Antlr 语法侦听器)在每个叶子处输出原始代码,但是当您到达出现where的特定节点时,输出该代码。 -
由于子查询,不清楚您要添加哪个
where子句。仅用于顶级选择吗?这是否仅适用于 select 语句或其他可以有 where 子句的语句?
标签: java sql antlr4 clickhouse