从网上https://www.antlr.org/download.html下载antlr4-complete.jar或者在项目pom里引入antlr依赖也可.
找到MySQL语法:https://github.com/antlr/grammars-v4/tree/master/sql/mysql
按照
Oracle
文件夹里的说明https://github.com/mysql/mysql-workbench/tree/8.0/library/parsers/grammars, 根据生成命令生成的C++代码,如果把-Dlanguage改成Java,生成的代码中少了一些抽象类.
按照
Positive Technologies
文件夹https://github.com/antlr/grammars-v4/tree/master/sql/mysql/Positive-Technologies里的MySqlLexer.g4和MySqlParser.g4根据命令生成Java代码,命令如下:
java -jar ./antlr-4.8-complete.jar -Dlanguage=Java -listener -visitor -o ./mysql-parser -package com.mysql.parser MySqlLexer.g4 MySqlParser.g4
测试:
String sql = "select a.id from t_order a straight_join t_product b on a.productId = b.id".toUpperCase();
final MySqlLexer mySqlLexer = new MySqlLexer(CharStreams.fromString(sql));
final CommonTokenStream commonTokenStream = new CommonTokenStream(mySqlLexer);
final MySqlParser mySqlParser = new MySqlParser(commonTokenStream);
final MySqlParser.SelectStatementContext selectStatementContext = mySqlParser.selectStatement();
for (ParseTree child : selectStatementContext.children) {
System.out.println(child.getText());
}
// MySqlParserBaseVisitor mySqlParserBaseVisitor = new MySqlParserBaseVisitor();
// final Object o = mySqlParserBaseVisitor.visitSimpleSelect((MySqlParser.SimpleSelectContext) selectStatementContext);
解析后结果树相当深,同时Antlr没有实现Visitor,因此只能自己去实现Visitor了.
ShardingSphere也是基于Antlr实现,同时实现了Visitor,
final MySQLParser mySQLParser = new MySQLParser(new CommonTokenStream(new MySQLLexer(CharStreams.fromString(sql))));
final MySQLStatementParser.SelectContext select = mySQLParser.select();
final MySQLDMLVisitor mySQLDMLVisitor = new MySQLDMLVisitor();
final ASTNode astNode = mySQLDMLVisitor.visitSelect(select);
感觉ShardingSphere解析后的对象层次也深,不是太好用.
Antlr解析的效率有点慢.
另外JSqlParser也可以解析sql,但是只能解析标准sql,个人感觉解析后的对象用起来比较舒服.也支持Visitor模式. JSqlParser基于JavaCC实现.
阿里Druid也提供解析sql模块,效率不错,支持MySQL语法,看代码是硬编码解析,后续扩展可能是个问题.