Antlr4之简单的sql查询解析demo
Posted 你是小KS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Antlr4之简单的sql查询解析demo相关的知识,希望对你有一定的参考价值。
当前版本:jdk1.8
、antlr4.8
1. 声明
当前内容主要为测试和使用Antlr4,并设计简单的SQL查询解析(本人解析IoTDB源码中发现其中使用了Antlr4来实现对sql执行的解析)
1. 首先下载antlr4.8对g4文件的编译包,官方antlr-4.8-complete.jar
2. 编写sql解析的g4文件
grammar SqlBase;
singleStatement : statement EOF ;
statement : 'SELECT' selectElements fromClause ;
fromClause : 'FROM' tableName ;
selectElements : ID ;
tableName : ID ;
ID : [a-zA-Z]+ ;
WS : [ \\r\\n\\t]+ -> skip ;
语法简述:
- grammar SqlBase; 表示定义解析的语法名称为SqlBase
- singleStatement : statement EOF ;表示我们只会使用这个语法标记解析全部文本
- ID : [a-zA-Z]+ ; 表示匹配的为英文字母的语法
- WS : [ \\r\\n\\t]+ -> skip ; 表示使用跳过空白的部分
这里其实就是解析:SELECT XXX FROM XXX的这种简单的sql语法
将上述文件使用记事本保存并修改为SqlBase.g4即可
3. 开始使用antlr生成对应的java文件
将SqlBase.g4文件放到刚才下载的complete.jar一起
然后执行命令:java -jar antlr-4.8-complete.jar SqlBase.g4
这样就得到了生成的文件:
4. 开始编写代码并解析得到执行sql的内容
对于简单的查询sql这里只需要得到查询的字段和查询的表名称即可
将上述生成的文件导入到项目中,并导入maven依赖即可
解析代码如下:
/**
*
* @author hy
* @createTime 2022-06-12 14:10:29
* @description 测试并使用当前的antlr来对sql进行解析
*
*/
public class SqlGrammaParseTest
public static void main(String[] args)
String sql = "SELECT name FROM users";
CharStream stream = CharStreams.fromString(sql);
SqlBaseLexer lexer1 = new SqlBaseLexer(stream);
CommonTokenStream tokens1 = new CommonTokenStream(lexer1);
SqlBaseParser parser1 = new SqlBaseParser(tokens1);
parser1.getInterpreter().setPredictionMode(PredictionMode.SLL);
parser1.removeErrorListeners(); // 移除所有错误的监听
// parser1.addErrorListener();
ParseTree tree = null;
try
tree = parser1.singleStatement(); // STAGE 1
catch (Exception ex)
ex.printStackTrace();
SimpleSqlTreeVisitor simpleSqlTreeVisitor = new SimpleSqlTreeVisitor();
if (tree != null)
SelectSql selectSql = simpleSqlTreeVisitor.visit(tree);
System.out.println(selectSql);
if (!selectSql.isQuery())
throw new RuntimeException("当前执行的sql不是查询!");
System.out.print(selectSql.startToken);
System.out.print(" " + selectSql.fields.stream().collect(Collectors.joining(",")));
if (selectSql.from)
System.out.print(" FROM");
System.out.print(" " + selectSql.tableName);
System.out.println();
private static class SelectSql
private String startToken;
private boolean from;
private List<String> fields;
private String tableName;
public boolean isQuery()
return "SELECT".equalsIgnoreCase(startToken);
private static class SimpleSqlTreeVisitor implements ParseTreeVisitor<SelectSql>
SelectSql selectSql;
SimpleSqlTreeVisitor()
selectSql = new SelectSql();
selectSql.fields = new ArrayList<>();
@Override
public SelectSql visit(ParseTree tree)
int childCount = tree.getChildCount();
for (int i = 0; i < childCount; i++)
ParseTree child = tree.getChild(i);
if (child instanceof StatementContext)
StatementContext statementContext = (StatementContext) child;
System.out.println("statementContext");
handlerWithStatement(statementContext);
return selectSql;
private void handlerWithStatement(StatementContext statementContext)
int childCount = statementContext.getChildCount(); // 必定以select开头
int i = 0;
for (; i < childCount; i++)
ParseTree child = statementContext.getChild(i);
if (child instanceof SelectElementsContext)
System.out.println("SelectElementsContext");
selectSql.fields.add(child.getText());// 这里应该是有多个
else if (child instanceof SqlBaseParser.FromClauseContext)
System.out.println("FromClauseContext");
selectSql.tableName = child.getChild(1).getText();
selectSql.from = true;
else if (child instanceof TerminalNode)
selectSql.startToken = child.getText(); // 这个就是SELECT
// System.out.println("TerminalNode==>" + terminalNode);
@Override
public SelectSql visitChildren(RuleNode node)
// TODO Auto-generated method stub
return null;
@Override
public SelectSql visitTerminal(TerminalNode node)
// TODO Auto-generated method stub
return null;
@Override
public SelectSql visitErrorNode(ErrorNode node)
// TODO Auto-generated method stub
return null;
注意这里的解析方式实际上就是和自己定义的g4文件有关系,是按照树的样式来解的
得到的结果:
发现手动解析语法还是要手动判断的
5. 总结
- 对于antlr4的使用是需要对g4的文件格式必须了解,要会编写对应的文件
- antlr4对于解析语法还是比较简单的
- 对于将解析的语法转换为实体类还是比较麻烦的(还是要根据对应的g4格式来解析)
以上是关于Antlr4之简单的sql查询解析demo的主要内容,如果未能解决你的问题,请参考以下文章