引入
parser所在目录:/src/common/backend/parser。本篇对于parser下各模块的功能分配以及查询解析主流程进行简要分析概括。
parser结构及各模块功能
Parser
======
This directory does more than tokenize and parse SQL queries. It also creates Query structures for the various complex queries that are passed to the optimizer and then executor.
/*
* 本目录不仅能够将SQL查询分解成token并解析SQL查询语句,还为各种
* 复杂查询创建查询结构并传递给optimizer优化器以及executor执行器。
*/
parser.cpp things start here
// 解析主程序
scan.l break query into tokens
// 词法分析,将查询分解成token
scansup.cpp handle escapes in input strings
// 处理查询语句中的转义符
kwlookup.cpp turn keywords into specific tokens
// 将关键字转化为其对应的token
keywords.cpp table of standard keywords (passed to kwlookup.c)
// 标准关键词列表
gram.y parse the tokens and produce a "raw" parse tree
// 语法分析,解析tokens并产生原始解析树
analyze.cpp top level of parse analysis for optimizable queries
// 分析查询语义
parse_agg.cpp handle aggregates, like SUM(col1), AVG(col2), ...
// 处理聚合函数,如SUM,AVG函数等
parse_clause.cpp handle clauses like WHERE, ORDER BY, GROUP BY, ...
// 处理where,order by等子句
parse_compatibility.cpp Handle A db compatibal syntax and feature support
// 处理数据库兼容语法和特性支持
parse_coerce.cpp handle coercing expressions to different data types
// 处理表达式数据类型的强制转换
parse_collate.cpp assign collation information in completed expressions
// 对完成表达式添加校对信息
parse_cte.cpp handle Common Table Expressions (WITH clauses)
// 处理公共表格表达式(with子句)
parse_expr.cpp handle expressions like col, col + 3, x = 3 or x = 4
// 处理简单表达式
parse_func.cpp handle functions, table.column and column identifiers
// 处理函数,表列以及列标识符
parse_node.cpp create nodes for various structures
// 对各种结构创建解析节点
parse_oper.cpp handle operators in expressions
// 处理表达式中的操作符
parse_param.cpp handle Params (for the cases used in the core backend)
// 处理核心后端的参数
parse_relation.cpp support routines for tables and column handling
// 支持表和列的关系处理程序
parse_target.cpp handle the result list of the query
// 处理查询解析的结果列表
parse_type.cpp support routines for data type handling
// 处理数据类型
parse_utilcmd.cpp parse analysis for utility commands (done at execution time)
// 处理实用命令的解析分析
parser主流程
查询解析大致分为三个步骤:词法解析、语法解析和语义解析,主流程大致如下:openGauss利用flex&bison工具生成原始解析器,查询语句先通过原始解析器完成词法解析和语法解析,生成原始语法树;再通过语义分析对语法树进行翻译和扩充,得到对应的查询树后交由executor执行查询任务。
词法和语法解析(原始解析)主函数:
/* parse.cpp */
/*
* raw_parser
* 原始解析器
* Given a query in string form, do lexical and grammatical analysis.
* 输入查询字符串,做词法和语法分析
* Returns a list of raw (un-analyzed) parse trees.
* 返回原始语法解析树列表
*/
List* raw_parser(const char* str, List** query_string_locationlist)
{
//…
/* initialize the flex scanner */
/* 初始化 flex scanner */
yyscanner = scanner_init(str, &yyextra.core_yy_extra, ScanKeywords, NumScanKeywords);
//…
/* initialize the bison parser */
/* 初始化 bison parser */
parser_init(&yyextra);
/* Parse! */
/* 解析! */
yyresult = base_yyparse(yyscanner);
/* Clean up (release memory) */
/* 清理释放内存*/
scanner_finish(yyscanner);
//…
return yyextra.parsetree;
}
查询语义解析主函数:
/* analyze.cpp */
/* 分析原始语法解析树,做语义分析并输出查询树 */
Query* parse_analyze(Node* parseTree, const char* sourceText, Oid* paramTypes, int numParams, bool isFirstNode, bool isCreateView)
{
// 中间结构变量和返回结果初始化
ParseState* pstate = make_parsestate(NULL);
Query* query = NULL;
//...
/* 将解析树转化为查询树 */
query = transformTopLevelStmt(pstate, parseTree, isFirstNode, isCreateView);
//...
/* 释放ParseState结构中间变量 */
free_parsestate(pstate);
//...
return query;
}