openGauss 内核:SQL 解析过程分析

本文分享自华为云社区《 openGauss内核分析(三):SQL解析》,作者:Gauss 松鼠会。
在传统数据库中 SQL 引擎一般指对用户输入的 SQL 语句进行解析、优化的软件模块。
SQL 的解析过程主要分为:
• 词法分析:将用户输入的 SQL 语句拆解成单词(Token)序列,并识别出关键字、标识、常量等。
• 语法分析:分析器对词法分析器解析出来的单词(Token)序列在语法上是否满足 SQL 语法规则。
• 语义分析:语义分析是 SQL 解析过程的一个逻辑阶段,主要任务是在语法正确的基础上进行上下文有关性质的审查,在 SQL 解析过程中该阶段完成表名、操作符、类型等元素的合法性判断,同时检测语义上的二义性。
openGauss 在 pg_parse_query 中调用 raw_parser 函数对用户输入的 SQL 命令进行词法分析和语法分析,生成语法树添加到链表 parsetree_list 中。完成语法分析后,对于 parsetree_list 中的每一颗语法树 parsetree,会调用 parse_**yze 函数进行语义分析,根据 SQL 命令的不同,执行对应的入口函数,最终生成查询树。

词法分析
openGauss 使用 flex 工具进行词法分析。flex 工具通过对已经定义好的词法文件进行编译,生成词法分析的代码。词法文件是 scan.l,它根据 SQL 语言标准对 SQL 语言中的关键字、标识符、操作符、常量、终结符进行了定义和识别。在 kwlist.h 中定义了大量的关键字,按照字母的顺序排列,方便在查找关键字时通过二分法进行查找。在 scan.l 中处理"标识符"时,会到关键字列表中进行匹配,如果一个标识符匹配到关键字,则认为是关键字,否则才是标识符,即关键字优先.以“select a, b from item”为例说明词法分析结果。

语法分析
openGauss 中定义了 bison 工具能够识别的语法文件 gram.y,根据 SQL 语言的不同定义了一系列表达 Statement 的结构体(这些结构体通常以 Stmt 作为命名后缀),用来保存语法分析结果。以 SELECT 查询为例,它对应的 Statement 结构体如下。
这个结构体可以看作一个多叉树,每个叶子节点都表达了 SELECT 查询语句中的一个语法结构,对应到 gram.y 中,它会有一个 SelectStmt。代码如下:

从 simple_select 语法分析结构可以看出,一条简单的查询语句由以下子句组成:去除行重复的 distinctClause、目标属性 targetList、SELECT INTO 子句 intoClause、FROM 子句 fromClause、WHERE 子句 whereClause、GROUP BY BY 子句 groupClause、HAVING 子句 havingClause、窗口子句窗口 Clause 和 plan_hint 子句。在成功匹配 simple_select 语法结构后,将会创建一个 Statement 结构体,将各个子句进行相应的赋值。对 simple_select 而言,目标属性、FROM 子句、WHERE 子句是最重要的组成部分。SelectStmt 与其他结构体的关系如下:

下面以“select a, b from item”为例说明简单 select 语句的解析过程,函数 exec_simple_query 调用 pg_parse_query 执行解析,解析树中只有一个元素。

List 中的节点类型为 T_SelectStmt。
查看 SelectStmt 结构体,targetList 和 fromClause 非空。
查看 SelectStmt 的 targetlist,有两个 ResTarget。
查看 SelectStmt 的 fromClause,有一个 RangeVar。
综合以上分析可以得到语法树结构。

语义分析
在完成词法分析和语法分析后,parse_Ana lyze 函数会根据语法树的类型,调用 transformSelectStmt 将 parseTree 改写为查询树。

得到的查询树结构如下:

完成词法、语法和语义分析后,SQL 解析过程完成,SQL 引擎开始执行查询优化,在下一期中再具体分析。
版权声明: 本文为 InfoQ 作者【华为云开发者联盟】的原创文章。
原文链接:【http://xie.infoq.cn/article/1c4be4053b77073a504405040】。文章转载请联系作者。
评论