如何实现一个SQL解析器( 二 )


SQL示例
如何实现一个SQL解析器

文章插图
SELECT name FROM tab WHERE id=1001;约定规则如下:
如何实现一个SQL解析器

文章插图
上表中,红色的内容通常表示终结符,它们一般是大写的关键字或者符号等,小写的内容是非终结符,一般用作规则的命名,比如字段、表名等 。具体AST数据结构如下图所示:
如何实现一个SQL解析器

文章插图
3.1.3 什么是语义解析?如何理解语义解析呢?语义解析我们可以这么来进行理解,语义分析的任务是对语法解析得到的抽象语法树进行有效的校验,比如字段、字段类型、函数、表等进行检查 。比如如下语句:
SQL示例
SELECT name FROM tab WHERE id=1001;
如何实现一个SQL解析器

文章插图
上述SQL语句,语义分析任务会做如下检查:
  • SQL语句中表名是否存在;
  • 字段name是否存在于表tab中;
  • WHERE条件中的id字段类型是否可以与1001进行比较操作 。
上述检查结束后,语义解析会生成对应的表达式供优化器去使用 。
四、 如何选择SQL解析器?在了解了解析器的核心知识点后,如何选择合适的SQL解析器来应用到我们的实际业务当中呢?下面,我们来对比一下主流的两种SQL解析器 。它们分别是ANTLR和Calcite 。
4.1 ANTLRANTLR是一款功能强大的语法分析器生成器,可以用来读取、处理、执行和转换结构化文本或者二进制文件 。在大数据的一些SQL框架里面有有广泛的应用,比如Hive的词法文件是ANTLR3写的,Presto词法文件也是ANTLR4实现的,SparkSQLambda词法文件也是用Presto的词法文件改写的,另外还有HBase的SQL工具Phoenix也是用ANTLR工具进行SQL解析的 。
使用ANTLR来实现一条SQL,执行或者实现的过程大致是这样的,实现词法文件(.g4),生成词法分析器和语法分析器,生成抽象语法树(也就是我常说的AST),然后再遍历抽象语法树,生成语义树,访问统计信息,优化器生成逻辑执行计划,再生成物理执行计划去执行 。
如何实现一个SQL解析器

文章插图
官网示例:
ANTLR表达式
assign : ID '=' expr ';' ;
如何实现一个SQL解析器

文章插图
解析器的代码类似于下面这样:
ANTLR解析器代码
如何实现一个SQL解析器

文章插图
void assign() {match(ID);match('=');expr();match(';');}4.1.1 ParserParser是用来识别语言的程序,其本身包含两个部分:词法分析器和语法分析器 。词法分析阶段主要解决的问题是关键字以及各种标识符,比如INT(类型关键字)和ID(变量标识符) 。语法分析主要是基于词法分析的结果,构造一颗语法分析数,流程大致如下:
如何实现一个SQL解析器

文章插图
因此,为了让词法分析和语法分析能够正常工作,在使用ANTLR4的时候,需要定义语法(Grammar) 。
我们可以把字符流(CharStream),转换成一棵语法分析树,字符流经过词法分析会变成Token流 。Token流再最终组装成一棵语法分析树,其中包含叶子节点(TerminalNode)和非叶子节点(RuleNode) 。具体语法分析树如下图所示:

经验总结扩展阅读