在之前的博客中我已经完成了对SQL parser的工作流程和词法解析方面知识的学习和总结,以及相关工具文件和SQL原始解析主流程函数等的解析工作。通过之前的学习,我将SQL parser原始解析模块(分为词法解析和语法解析)的文件调用关系总结如下图:
用户发出的查询请求在经过通信管理模块(postmaster)处理后会交由SQL引擎来对其进行解析、优化和重构等工作。首先SQL引擎中的解析模块(parser)负责原始查询语句的解析工作。
解析工作大概分为原始解析(分为词法和语法解析)和语义解析两个步骤。总结来讲,词法解析是从查询语句中识别出系统支持的关键字、标识符、运算符、终结符等,确定每个词固有的词性;而语法分析是根据SQL的标准定义语法规则,使用词法分析中产生的词去匹配语法规则,如果一个 SQL 语句能够匹配一个语法规则,则生成对应的抽象语法树(Abstract Syntax Tree,AST)。
简单地说,语法分析会根据词法分析获得的词(tokens)来匹配语法规则,最终生成一个抽象语法树。语法抽象树是用以表现编程语言语法结构的一种树状结构,它的每个结点都代表源代码中的一种结构或组成部分。例如,查询语句SELECT c_name FROM client WHERE c_age=37;对应的抽象语法树可以表示如下图:
语法解析正是在词法解析的基础上,对每一条SQL查询语句生成对应的抽象语法树;而生成的语法树又会通过语义解析模块对其进行扩充,这样就得到了最原始的查询树(Query Tree,QT)。得到查询树后,parser就完成了它的工作;而所得的查询树还会通过重写模块(rewriter)、查询优化(optimizer)等对其进行优化和重构,最终得到的优化后的查询树交由执行模块(executor)执行查询任务。
而在原始解析主流程函数raw_parser中我们可以得知,原始解析生成并返回的语法解析树蕴含在如下数据结构中(文件路径为/src/include/parser/gramparse.h)。结构base_yy_extra_type是与原始解析过程密切相关的。在raw_parser的每次执行过程中会创建一个base_yy_extra_type类型的变量,其成员变量包括core scanner所需的结构变量、函数base_yylex所需的结构变量(关于函数功能上一篇博客中有相关解析)以及存储原始解析所得语法树的List*类型变量。raw_parser执行完毕后,将其创建的base_yy_extra_type变量的parsetree指针返回。
/* gramparse.h */
typedef struct base_yy_extra_type {
/*
* Fields used by the core scanner.
*/
core_yy_extra_type core_yy_extra;
/*
* State variables for base_yylex().
*/
int lookahead_num; /* lookahead num. Currently can be:0,1,2 */
int lookahead_token[MAX_LOOKAHEAD_NUM]; /* token lookahead type */
core_YYSTYPE lookahead_yylval[MAX_LOOKAHEAD_NUM]; /* yylval for lookahead token */
YYLTYPE lookahead_yylloc[MAX_LOOKAHEAD_NUM]; /* yylloc for lookahead token */
/*
* State variables that belong to the grammar.
*/
List* parsetree; /* final parse result is delivered here */
} base_yy_extra_type;
在接下来的工作中,我会对语法解析模块的相关内容进行学习以及对语法分析相关的函数文件进行分析和注解。附与语法解析相关的文件列表。
文件路径 | 文件功能 |
---|---|
parse_agg.cpp | 处理聚合函数,如SUM,AVG函数等 |
parse_clause.cpp | 处理WHERE,ORDER BY等子句 |
parse_compatibility.cpp | 处理数据库兼容语法和特性支持 |
parse_coerce.cpp | 处理表达式数据类型的强制转换 |
parse_collate.cpp | 对完成表达式添加校对信息 |
parse_cte.cpp | 处理公共表格表达式(WITH 子句) |
parse_expr.cpp | 处理简单表达式 |
parse_func.cpp | 处理函数,表列以及列标识符 |
parse_node.cpp | 对各种结构创建解析节点 |
parse_oper.cpp | 处理表达式中的操作符 |
parse_param.cpp | 处理核心后端的参数 |
parse_relation.cpp | 支持表和列的关系处理程序 |
parse_target.cpp | 处理查询解析的结果列表 |
parse_type.cpp | 处理数据类型 |
parse_utilcmd.cpp | 处理实用命令的解析分析 |