2021SC@SDUSC
我负责的PostgreSQL代码部分:查询的编译与执行
此篇博客分析内容:语义分析
上篇博客我分析了查询分析的词法分析和语法分析,我们可以知道经过词法分析和语法分析我们可以得到一个用SelectStmt结构体存储的分析树,由流程分析图可以得知我们还需经过语法分析才可以得到查询树。
语义分析:语义分析阶段会检查命令中是否有不符合语义规定的成分,检查命令是否可以正确执行。
语义分析阶段主要负责语义分析的是analyze.c文件中的parse_analyze函数。parse_analyze函数会根据分析树生成一个对应的查询树,然后再由后面的查询重写模块对这一查询树进行进一步的修改,将查询树改写成查询树链表。在parse_analyze函数中会根据命令类型分成七种情况处理:
语义分析中涉及的重要结构体:
Query:用于存储查询树,是查询分析的最终输出结果
ParseState:ParseState:用于记录语义分析的中间信息
struct ParseState
{
struct ParseState *parentParseState; //如果当前是一个子查询的话,这个字段指向其外层查询
const char *p_sourcetext; //原始sql命令,只用于报告语法分析出错的位置
List *p_rtable; //查询涉及的表--范围表
List *p_joinexprs; //连接表达式
List *p_joinlist; //连接项
List *p_namespace; //表名字集合,用于检查表名冲突
bool p_lateral_active; //是否有关联引用
List *p_ctenamespace;//公共表达式的名字集合
List *p_future_ctes; //不在p_ctenamespace中的公共表达式
CommonTableExpr *p_parent_cte; /* this query's containing CTE */
Relation p_target_relation; //目标表
RangeTblEntry *p_target_rangetblentry; /* target rel's RTE */
bool p_is_insert; //是否为insert语句
List *p_windowdefs; //window子句的原始定义形式
ParseExprKind p_expr_kind; //参数的类型
int p_next_resno;
List *p_multiassign_exprs;
List *p_locking_clause; //locking子句
bool p_locked_from_parent;
bool p_resolve_unknowns; //还未解决的类型
QueryEnvironment *p_queryEnv;
bool p_hasAggs;//是否有聚集函数
bool p_hasWindowFuncs;//是否有窗口函数
bool p_hasTargetSRFs;//是否有SRF
bool p_hasSubLinks;//是否有子链接
bool p_hasModifyingCTE;//是否修改CTE
Node *p_last_srf;
/*
* Optional hook functions for parser callbacks. These are null unless
* set up by the caller of make_parsestate.
*/
PreParseColumnRefHook p_pre_columnref_hook;
PostParseColumnRefHook p_post_columnref_hook;
ParseParamRefHook p_paramref_hook;
CoerceParamHook p_coerce_param_hook;
void *p_ref_hook_state; /* common passthrough link for above */
};
typedef struct Query
{
NodeTag type;//节点类型,T_Query
CmdType commandType; //命令类型
QuerySource querySource; //是原始查询还是来自规则的查询
uint64 queryId; /* query identifier (can be set by plugins) */
bool canSetTag;
//查询重写时用到,如果该query是由原始查询转换而来则此字段为假;如果query是由查询重写或查询规划时新增加的则此字段为真
Node *utilityStmt;//定义游标或者不可优化的查询语句
int resultRelation; //结果关系
bool hasAggs;//目标子句或者having子句中是否有聚集函数
bool hasWindowFuncs; //目标属性中是否有窗口函数
bool hasTargetSRFs; /* has set-returning functions in tlist *