语义分析会根据分析树中的内容得到更有利于执行的数据, 例如: 根据表的名字得到OID,
根据属性名得到其属性号, 根据操作符的名字得到其对应的计算函数等.
exec_simple_query在从词法和语法分析模块获取了parsetree_list(分析树链表)之后,
会对其中每一棵分析树调用pg_analyze_and_rewrite进行语义分析和查询重写,而在其中负责语义分析的则是analyze.c文件中的parse_analyze函数.
parse_analyze会根据分析树生成一个对应的查询树,而查询重写模块则继续对这一查询树进行修改,
并且有可能会将这个查询树改写成一个包含多棵查询树的链表.
因此, pg_analyze_and_rewrite最终返回给exec_simple_query的将是一个查询树链表.
parse_analyze函数中的各个SQL语句命令(xxStmt)处理在parse_analyze函数中, 将根据命令类型分七种情况处理(参考函数transformStmt).
经过语义分析之后, 会生成查询树(Query结构).
其中select/insert/delete/update这四种情况所生成的查询树会经由查询重写和查询优化作进一步处理.
两个重要的结构体Query和ParseState该过程涉及两个重要的结构体: Query和ParseState.
Query(用于存储查询树)是查询分析的最终输出结果,
其中许多字段可以在分析树的相关结构体中找到对应项.
ParseState结构体则用于记录语义分析的中间信息.
parse_analyze处理中遇到的命令类型都有哪些概要分8种:
设置分析状态
Utility(建表,建索引等附件命令)
Explain (显示查询的执行计划)
Declarecursor (定义游标)
Select
Insert
Delete
Update
各个命令对应的主义分析函数 (列表说明) NodeTag值 语义分析函数T_InsertStmt transformInsertStmt
T_DeleteStmt transformDeleteStmt
T_UpdateStmt transformUpdateStmt
T_SelectStmt transformSelectStmt或transformValuesClause
T_DeclareCursorStmt transformDeclareCursorStmt (游标定义语句)
T_ExplainStmt transformExplainStmt (Explain语句)
其他 作为Utility类型处理, 直接在分析树上封装一个Query节点返回
简述transformSelectStmt函数的主要处理流程
transfromSelectStmt函数的作用是根据一个SelectStmt结构生成一个查询树(Query).
其主要流程如下:
创建一个新的Query节点, 设置其commandType字段为CMD_SELECT;
调用transformWithClause函数处理with子句;
调用transformFromClause函数处理from子句;
调用transfomrTargetList函数处理目标属性;
调用transformWhereClause函数处理where子句和having子句;
调用transformSortClause函数处理order by子句;
调用transformGroupClause函数处理group by子句;
调用transformDistinctClause函数或transformDistinctOnClause函数处理distinct.
调用transformLimitClause函数处理limit和offset.
处理INTO子句;
设置Query节点的其他标志(如hasAggs,hasSubLinks等字段);
返回Query节点.
由此可见,
对于SelectStmt的处理过程被分解成对其各个子句部分的处理,各子句的处理过程相对独立.
其他类型的分析树的语法分析过程与此大同小异.
5.3.1 规则系统 查询重写的核心是什么查询重写的核心是规则系统.
规则系统是什么规则系统是由一系列的规则组成的, 系统表pg_rewrite存储重写规则.
PG的查询执行 查询执行器的函数入口和查询编译一样吗查询执行器也是被函数exec_simple_query调用, 只是调用的顺序上查询编译在前,
查询执行器在后.