前置准备
SQL 解析语法模版
-
sql解析模版(mysql、hive、trino):
-
ck sql解析模版:
-
spark sql 解析模版:
idea 安装antlr4 插件
需要在IDEA中安装antlr4插件
新建Maven工程
新建Maven工程,导入maven 依赖
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.8-1</version>
</dependency>
</dependencies>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.8-1</version>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
<phase>none</phase>
</execution>
</executions>
<configuration>
<outputDirectory>src/main/java</outputDirectory>
<!--<listener>true</listener>-->
<visitor>true</visitor>
<!--<treatWarningsAsErrors>true</treatWarningsAsErrors>-->
</configuration>
</plugin>
</plugins>
idea 配置修改
问题原因:
这是因为生成的源文件有数万行,源文件过大导致 idea 拒绝编译过大的源文件。
解决方案:
如果 protoc 生成的 class 文件找不到,说明 protoc 文件没有没有正确编译。 可以调整 IDEA 的默认参数, 然后重启 IntelliJ IDEA 使得 IDE 能够正确找到 protoc 生成的 Java 类。
step1: 打开 Help -> Edit Custom Properties 菜单
step2: 增加一行: idea.max.intellisense.filesize=50000
step3: 重启 IDE
实现操作
将sql 语法解析模版放入 resource 文件夹
编译语法文件生成java语法解析类
生成文件
案例
获取一个SQL语句中的表名
public class GetTableNamesListener extends MySqlParserBaseListener {
private final Set<String> tableNameSet = new HashSet<String>();
@Override
public void enterTableSources(MySqlParser.TableSourcesContext ctx) {
List<MySqlParser.TableSourceContext> tableSourceContexts = ctx.getRuleContexts(MySqlParser.TableSourceContext.class);
for (MySqlParser.TableSourceContext tableSource : tableSourceContexts) {
//通过tableSourceItems获取表名
getTableNameByTableSourceItems(tableSource.getRuleContexts(MySqlParser.TableSourceItemContext.class));
//获取join部分
List<MySqlParser.OuterJoinContext> joinContexts = tableSource.getRuleContexts(MySqlParser.OuterJoinContext.class);
for (MySqlParser.OuterJoinContext joinContext : joinContexts) {
List<MySqlParser.TableSourceItemContext> tableSourceItemContexts = joinContext.getRuleContexts(MySqlParser.TableSourceItemContext.class);
getTableNameByTableSourceItems(tableSourceItemContexts);
}
}
}
private void getTableNameByTableSourceItems(List<MySqlParser.TableSourceItemContext> tableSourceItems) {
for (MySqlParser.TableSourceItemContext tableSourceItem : tableSourceItems) {
List<MySqlParser.TableNameContext> tableNameContexts = tableSourceItem.getRuleContexts(MySqlParser.TableNameContext.class);
for (MySqlParser.TableNameContext tableNameContext : tableNameContexts) {
tableNameSet.add(tableNameContext.getText());
}
}
}
public Set<String> getTableNameSet() {
return tableNameSet;
}
}
执行代码:
public static void main(String[] args) {
String sql = "SELECT t1.column1,t1.column2,t1.column3,t2.xy from tableC t1 left join tableA t2 on t1.id=t2.oid where t1.column1 = 1 and t2.yy=6";
System.out.println(sql);
MySqlLexer lexer = new MySqlLexer(CharStreams.fromString(sql.toUpperCase()));
MySqlParser parser = new MySqlParser(new CommonTokenStream(lexer));
//定义GetTableNamesListener
GetTableNamesListener listener = new GetTableNamesListener();
ParseTreeWalker.DEFAULT.walk(listener, parser.sqlStatements());
Set<String> tableNameSet = listener.getTableNameSet();
for (String tableName : tableNameSet) {
System.out.println(tableName);
}
}
返回结果:
SELECT t1.column1,t1.column2,t1.column3,t2.xy from tableC t1 left join tableA t2 on t1.id=t2.oid where t1.column1 = 1 and t2.yy=6
TABLEA
TABLEC