根据 <PostgreSQL 数据库内核分析>200和201页的说法,

ResTarget 应该指向 ColumnRef 。这是如何实现的呢?

target_list:                                target_el                { $$ = list_make1($1); }    | target_list ',' target_el                { $$ = lappend($1, $3); } ;                        target_el:    a_expr AS ColLabel                            {                $$ = makeNode(ResTarget);            $$->name = $3;            $$->indirection = NIL;            $$->val = (Node *)$1;            $$->location = @1;            }                /*                    * We support omitting AS only for column labels that aren't  * any known keyword.  There is an ambiguity against postfix* operators: is "a ! b" an infix expression, or a postfix * expression and a column label?  We prefer to resolve this * as an infix expression, which we accomplish by assigning  * IDENT a precedence higher than POSTFIXOP.                    */                    | a_expr IDENT                            {                $$ = makeNode(ResTarget);            $$->name = $2;            $$->indirection = NIL;            $$->val = (Node *)$1;            $$->location = @1;            }                | a_expr                            {                $$ = makeNode(ResTarget);            $$->name = NULL;            $$->indirection = NIL;            $$->val = (Node *)$1;            $$->location = @1; }                | '*'                    {                ColumnRef *n = makeNode(ColumnRef);            n->fields = list_make1(makeNode(A_Star));            n->location = @1;            $$ = makeNode(ResTarget);            $$->name = NULL;            $$->indirection = NIL;            $$->val = (Node *)n;            $$->location = @1;            }                ;                        

a_expr:     c_expr                            { $$ = $1; }                    | a_expr TYPECAST Typename                        { $$ = makeTypeCast($1, $3, @2); }                | a_expr COLLATE any_name                        {                    CollateClause *n = makeNode(CollateClause);                n->arg = $1;                n->collname = $3;                n->location = @2;                $$ = (Node *) n;                }...                    

c_expr:     columnref                               { $$ = $1; }| AexprConst                            { $$ = $1; }| PARAM opt_indirection                            {                        ParamRef *p = makeNode(ParamRef);                    p->number = $1;                    p->location = @1;                    if ($2)                    {                    A_Indirection *n = makeNode(A_Indirection);                n->arg = (Node *) p;                n->indirection = check_indirection($2, yyscanner);                $$ = (Node *) n;                }                    else                    $$ = (Node *) p;                }                        | '(' a_expr ')' opt_indirection                            {                        if ($4)                    {                    A_Indirection *n = makeNode(A_Indirection);                n->arg = $2;                n->indirection = check_indirection($4, yyscanner);                $$ = (Node *)n;                }                    else                    $$ = $2;                }                        | case_expr                            { $$ = $1; }                        | func_expr                            { $$ = $1; }                        | select_with_parens            %prec UMINUS                {                        SubLink *n = makeNode(SubLink);                    n->subLinkType = EXPR_SUBLINK;                    n->testexpr = NULL;                    n->operName = NIL;                    n->subselect = $1;                    n->location = @1;                    $$ = (Node *)n;                    }                        | EXISTS select_with_parens                            {                        SubLink *n = makeNode(SubLink);                    n->subLinkType = EXISTS_SUBLINK;                    n->testexpr = NULL;                    n->operName = NIL;                    n->subselect = $2;                    n->location = @1;                    $$ = (Node *)n;                    }                        | ARRAY select_with_parens                            {                        SubLink *n = makeNode(SubLink);                    n->subLinkType = ARRAY_SUBLINK;                    n->testexpr = NULL;                    n->operName = NIL;                    n->subselect = $2;                    n->location = @1;                    $$ = (Node *)n;                    }                        | ARRAY array_expr                            {                        A_ArrayExpr *n = (A_ArrayExpr *) $2;                    Assert(IsA(n, A_ArrayExpr));                    /* point outermost A_ArrayExpr to the ARRAY keyword */                    n->location = @1;                    $$ = (Node *)n;                    }                        | row                            {                        RowExpr *r = makeNode(RowExpr);                    r->args = $1;                    r->row_typeid = InvalidOid;    /* not analyzed yet */                r->location = @1;                    $$ = (Node *)r;                    }                        ;                                

这个时候,距离ColumnRef 就已经不远了。

然后挑选最简单的情况:

columnref:    ColId                                {                    $$ = makeColumnRef($1, NIL, @1, yyscanner);                }                    | ColId indirection                                {                    $$ = makeColumnRef($1, $2, @1, yyscanner);                }                    ;                                

查了一下, 原来 makeColumnRef 就在 gram.y 里面:

static Node *
makeColumnRef(char *colname, List *indirection, int location, core_yyscan_t yyscanner)
{                                                                /*                                                            * Generate a ColumnRef node, with an A_Indirection node added if there * is any subscripting in the specified indirection list.  However,* any field selection at the start of the indirection list must be * transposed into the "fields" part of the ColumnRef node. */                                                            ColumnRef  *c = makeNode(ColumnRef);                                                            int        nfields = 0;                                                    ListCell *l;                                                            c->location = location; foreach(l, indirection){                                                            if (IsA(lfirst(l), A_Indices)) {                                                        A_Indirection *i = makeNode(A_Indirection);if (nfields == 0)                                                    {                                                    /* easy case - all indirection goes to A_Indirection */ c->fields = list_make1(makeString(colname));                                                i->indirection = check_indirection(indirection, yyscanner);                                                }                                                    else                                                    {                                                    /* got to split the list in two */i->indirection = check_indirection(                    list_copy_tail(indirection, nfields),yyscanner);                indirection = list_truncate(indirection, nfields);                                                c->fields = lcons(makeString(colname), indirection);                                                }                                                    i->arg = (Node *) c;                                                    return (Node *) i;                                                    }                                                        else if (IsA(lfirst(l), A_Star))                                                        {                                                        /* We only allow '*' at the end of a ColumnRef */ if (lnext(l) != NULL)parser_yyerror("improper use of \"*\"");                                                }                                                        nfields++;                                                        }                                                            /* No subscripting, so all indirection gets added to field list */ c->fields = lcons(makeString(colname), indirection);                                                            return (Node *) c;
}                                                                 

这个

ColumnRef  *c = makeNode(ColumnRef);

c->fields = list_make1(makeString(colname)); 将 字段 赋予了 ColumnRef。

可以看出,语法分析是一层套着一层。而整个语法分析的目的,就是逐层地构建一个语法分析树形结构。

PostgreSQL 的 target_list分析(四)相关推荐

  1. PostgreSQL 的 target_list分析(一)

    首先看 lappend 00128 lappend(List *list, void *datum) 00129 { 00130 Assert(IsPointerList(list));00131 0 ...

  2. PostgreSQL 的 target_list分析(五)

    上文说到 ColumnRef 由于 a_expr 回溯到 c_expr. 其对应的 makeColumnRef 需要构建 ColumnRef 型Node, 看看 parsenodes.h: 00203 ...

  3. 手机自动化测试:Appium源码分析之跟踪代码分析四 1

    手机自动化测试:Appium源码分析之跟踪代码分析四 控制器模块 // Appium webserver controller methods // https://github.com/hugs/a ...

  4. PostgreSQL源码分析

    PostgreSQL源码结构 PostgreSQL的使用形态 PostgreSQL采用C/S(客户机/服务器)模式结构.应用层通过INET或者Unix Socket利用既定的协议与数据库服务器进行通信 ...

  5. ArcGIS网络分析之Silverlight客户端最近设施点分析(四)

    ArcGIS网络分析之Silverlight客户端最近设施点分析(四) 原文:ArcGIS网络分析之Silverlight客户端最近设施点分析(四) 在上一篇中说了如何实现最近路径分析,本篇将讨论如何 ...

  6. ABP源码分析四十七:ABP中的异常处理

    ABP源码分析四十七:ABP中的异常处理 参考文章: (1)ABP源码分析四十七:ABP中的异常处理 (2)https://www.cnblogs.com/1zhk/p/5538983.html (3 ...

  7. 【投屏】Scrcpy源码分析四(最终章 - Server篇)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  8. gSOAP 源码分析(四)

    gSOAP 源码分析(四) 2012-6-2 邵盛松 前言 本文主要说明gSOAP中对Client的认证分析 gSOAP中包含了HTTP基本认证,NTLM认证等,还可以自定义SOAP Heard实现认 ...

  9. 计算机教材与学情分析,四年级计算机教学计划范文(通用3篇)

    四年级计算机教学计划范文(通用3篇) 日子在弹指一挥间就毫无声息的流逝,我们将带着新的期许奔赴下一个挑战,是时候静下心来好好写写教学计划了.如何把教学计划写出新花样呢?下面是小编精心整理的四年级计算机 ...

最新文章

  1. 别再用 kill -9 了,这才是微服务上下线的正确姿势!
  2. R语言广义线性模型Logistic回归案例代码
  3. Tensorflow【实战Google深度学习框架】TensorFlow模型的保存与恢复加载
  4. Java线性池的使用方式以及核心运行原理
  5. 直接打开php非法请求
  6. hdp amabri mysql_MySQL数据库之Ambari 安装配置 MySql
  7. ToString:身份哈希码的十六进制表示形式
  8. python决策树算法_决策树算法及python实现
  9. 论文浅尝 | 用于低资源条件下知识图谱补全的关系对抗网络
  10. ftp网页服务器不允许匿名登录,我的FTP服务器不让匿名登陆,怎么办?
  11. windows 一键安装apache服务器 windows傻瓜式安装apache2 web服务器管理软件
  12. mysql练习_MySQL基础知识—习题练习
  13. 先少谈点人工智能好吗?
  14. luogu P3975 [TJOI2015]弦论 SAM
  15. 大数除法——超详细讲解
  16. 微信支付的软件架构也太特么牛逼了吧...
  17. SpringBoot2--Spring Security
  18. CJ20N - 项目定义屏幕增强(SMOD: CNEX0006)
  19. 学会这10招,让你的服装短视频带货率提升50%
  20. FIR滤波器学习设计笔记

热门文章

  1. 未能加载文件或程序集rsy3_abp vnext2.0之核心组件模块加载系统源码解析
  2. 计算机组成原理基于mips结构pdf,计算机组成原理_L12-MIPS系统结构-V1.pdf
  3. python项目部署到url_项目上线部署
  4. hough变换检测圆周_hough变换原理以及实现(转载)
  5. matlab中nsamp,matlab用于数字调制,几个函数的使用问题
  6. resultset需要关闭吗_旧电脑福音!关闭Windows这些没用的设置,电脑性能至少提升50%!...
  7. transient关键字的作用_ArrayList Vector (transient关键字)--JAVA成长之路
  8. 数据大屏产品介绍PPT_有这些图表美化工具,十分钟配出炫酷的数据可视化大屏...
  9. 使用C语言查看一个文件夹中所有文件及目录
  10. 《剑指offer》数组中只出现一次的数字