博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL在何处处理 sql查询之三十
阅读量:6806 次
发布时间:2019-06-26

本文共 4240 字,大约阅读时间需要 14 分钟。

接前面,继续分析:

PortalStrategyChoosePortalStrategy(List *stmts){    int            nSetTag;    ListCell   *lc;    /*     * PORTAL_ONE_SELECT and PORTAL_UTIL_SELECT need only consider the     * single-statement case, since there are no rewrite rules that can add     * auxiliary queries to a SELECT or a utility command. PORTAL_ONE_MOD_WITH     * likewise allows only one top-level statement.     */    if (list_length(stmts) == 1)    {        Node       *stmt = (Node *) linitial(stmts);        if (IsA(stmt, Query))        {            Query       *query = (Query *) stmt;            ...        }        else if (IsA(stmt, PlannedStmt))        {           ...        }        else        {           ...        }    }    /*     * PORTAL_ONE_RETURNING has to allow auxiliary queries added by rewrite.     * Choose PORTAL_ONE_RETURNING if there is exactly one canSetTag query and     * it has a RETURNING list.     */    nSetTag = 0;    foreach(lc, stmts)    {       ...    }    if (nSetTag == 1)        return PORTAL_ONE_RETURNING;    /* Else, it's the general case... */    return PORTAL_MULTI_QUERY;}

对  if (IsA(stmt, Query)) 进行分析:

#define IsA(nodeptr,_type_)        (nodeTag(nodeptr) == T_##_type_)
#define nodeTag(nodeptr)        (((const Node*)(nodeptr))->type)

 从上面看到,就是 获得计划树的Head, 把它转为 Node类型指针。

然后看看它的 type是否是 T_Query

经过实际测试,满足条件的是: else if (IsA(stmt, PlannedStmt)),

也就是说 Node指针所指向Node结构的 type是 T_PlannedStmt。

typedef struct Node{    NodeTag        type;} Node;
typedef struct List{    NodeTag        type;            /* T_List, T_IntList, or T_OidList */    int            length;    ListCell   *head;    ListCell   *tail;} List;struct ListCell{    union    {        void       *ptr_value;        int            int_value;        Oid            oid_value;    }            data;    ListCell   *next;};

 可以说, List 的头是一个Node,内有Nodetag说明其为何种类型:

#define lfirst(lc)                 ((lc)->data.ptr_value)#define linitial(l)                lfirst(list_head(l))static inline ListCell *list_head(const List *l){    return l ? l->head : NULL;}

 stmt再被强制转为 PlannedStmt:

* ---------------- *        PlannedStmt node * * The output of the planner is a Plan tree headed by a PlannedStmt node. * PlannedStmt holds the "one time" information needed by the executor. * ---------------- */typedef struct PlannedStmt{    NodeTag        type;    CmdType        commandType;    /* select|insert|update|delete */    uint32        queryId;        /* query identifier (copied from Query) */    bool        hasReturning;    /* is it insert|update|delete RETURNING? */    bool        hasModifyingCTE;    /* has insert|update|delete in WITH? */    bool        canSetTag;        /* do I set the command result tag? */    bool        transientPlan;    /* redo plan when TransactionXmin changes? */    struct Plan *planTree;        /* tree of Plan nodes */    List       *rtable;            /* list of RangeTblEntry nodes */    /* rtable indexes of target relations for INSERT/UPDATE/DELETE */    List       *resultRelations;    /* integer list of RT indexes, or NIL */    Node       *utilityStmt;    /* non-null if this is DECLARE CURSOR */    List       *subplans;        /* Plan trees for SubPlan expressions */    Bitmapset  *rewindPlanIDs;    /* indices of subplans that require REWIND */    List       *rowMarks;        /* a list of PlanRowMark's */    List       *relationOids;    /* OIDs of relations the plan depends on */    List       *invalItems;        /* other dependencies, as PlanInvalItems */    int            nParamExec;        /* number of PARAM_EXEC Params used */} PlannedStmt;

由此,再来重点看 elseif (IsA(stmt, PlannedStmt)) 判断分支:

else if (IsA(stmt, PlannedStmt))        {            fprintf(stderr,"It is a PlannedStmt... by process %d\n",getpid());            PlannedStmt *pstmt = (PlannedStmt *) stmt;            if (pstmt->canSetTag)            {                                if (pstmt->commandType == CMD_SELECT &&                    pstmt->utilityStmt == NULL)                {                    if (pstmt->hasModifyingCTE)                        return PORTAL_ONE_MOD_WITH;                    else                        return PORTAL_ONE_SELECT;                }            }        }

根据实际运行 select * from tst01 语句,可以得知返回 PORTAL_ONE_SELECT 类型。

转载地址:http://qhvwl.baihongyu.com/

你可能感兴趣的文章
pika开源:替代WebPack的全新JS构建工具
查看>>
借助Unity AR Foundation构建跨平台AR应用
查看>>
GitHub 重磅更新:无限私有仓库免费使用
查看>>
Russ Miles:被忽略的架构师和混沌工程
查看>>
研究人员发现:基于文本的AI模型容易受到改述攻击
查看>>
了解这12个概念,让你的JavaScript水平更上一层楼
查看>>
学习Kubernetes 和容器技术体系的最佳方法
查看>>
微软亚洲研究院等提出CNN训练新方法RePr,准确率显著提升
查看>>
GitHub预测2018年开源项目趋势
查看>>
QCon北京2015:移动开发最佳实践专题前瞻
查看>>
滴滴开源支撑业务代码重构工具Rdebug
查看>>
Java多线程编程那些事:volatile解惑
查看>>
苏宁11.11:苏宁易购移动端的架构优化实践
查看>>
Node.js v7 Beta版引入citgm
查看>>
《NoSQL For Mere Mortals》书评与作者问答录
查看>>
Core Animation基础
查看>>
InfoQ趋势报告:架构和设计领域技术演变详解
查看>>
【译文】Nodejs官方文档(Part 3 断言测试)
查看>>
无服务器计算的黑暗面:程序移植没那么容易
查看>>
小米松果电子拆分成立大鱼半导体,专注IoT芯片研发
查看>>