2021SC@SDUSC
目录
概述
我负责的PostgreSQL代码部分:查询的编译与执行
此篇博客分析内容:目标属性的语义分析
上篇博客,我分析了from子句的语义分析,大体了解了PostgreSQL是如何处理范围表以及表与表之间的连接,此片博客接着向下分析,在确定了范围表后,又该如何取得目标属性呢?
目标属性的语义分析
处理目标属性的入口函数是TransformTargetList函数,TransformTargetList函数通过调用函数TransformTargetEntry来处理分析树的目标属性中的每一项。对于目标属性中任何一项都会调用函数makeTargetentry创建TargetEntry结构体用来存储和组织。TransformTargetList函数返回p_target,而再通过查询语义分析的函数transformSelectStmt将直接把transformTargetList函数的返回值作为目标属性赋值给targetList字段
TransformTargetList函数
ResTarget结构体
typedef struct ResTarget
{
NodeTag type; //节点类型
char *name; //列名或者null
List *indirection; //目标列存储下标,域名,*或者NIL
Node *val; //要计算的表达式
int location; //token的位置,-1表示未知
} ResTarget;
transformTargetList函数是处理目标属性的入口函数,通过调用transformTargetEntry来处理目标属性。transformTargetList函数的参数由两个ParseState(在上上篇博客PostgreSQL–语义分析-ParseState分析过)和分析树的targetList字段指向的链表(在上上篇博客PostgreSQL–语义分析-Query分析过)
List *
transformTargetList(ParseState *pstate, List *targetlist,
ParseExprKind exprKind)
{
List *p_target = NIL;//准备空的链表p_target ,为了以后存储TargetEntry结构体
bool expand_star;//是否要展开查询表达式里包含的*(即是否把*对应的目标属性全部列出)
ListCell *o_target;//临时变量存储targetlist里面的每一个节点
//逐一取出targetlist里面的每一个节点
foreach(o_target, targetlist)
{
ResTarget *res = (ResTarget *) lfirst(o_target);//取出每个节点的RESTarget结构体
if (expand_star)//判断有无展开的*
{
//val字段:要计算的表达式
if (IsA(res->val, ColumnRef))//判断val字段中是否存储列名
{
ColumnRef *cref = (ColumnRef *) res->val;//从val字段中获取列名
if (IsA(llast(