zoukankan      html  css  js  c++  java
  • PostgreSQL在何处处理 sql查询之二十九

    接前面,继续分析 ChoosePortalStrategy:

    /*
     * ChoosePortalStrategy
     *        Select portal execution strategy given the intended statement list.
     *
     * The list elements can be Querys, PlannedStmts, or utility statements.
     * That's more general than portals need, but plancache.c uses this too.
     *
     * See the comments in portal.h.
     */
    PortalStrategy
    ChoosePortalStrategy(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;
    
                if (query->canSetTag)
                {
                    if (query->commandType == CMD_SELECT &&
                        query->utilityStmt == NULL)
                    {
                        if (query->hasModifyingCTE)
                            return PORTAL_ONE_MOD_WITH;
                        else
                            return PORTAL_ONE_SELECT;
                    }
                    if (query->commandType == CMD_UTILITY &&
                        query->utilityStmt != NULL)
                    {
                        if (UtilityReturnsTuples(query->utilityStmt))
                            return PORTAL_UTIL_SELECT;
                        /* it can't be ONE_RETURNING, so give up */
                        return PORTAL_MULTI_QUERY;
                    }
                }
            }
            else if (IsA(stmt, PlannedStmt))
            {
                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;
                    }
                }
            }
            else
            {
                /* must be a utility command; assume it's canSetTag */
                if (UtilityReturnsTuples(stmt))
                    return PORTAL_UTIL_SELECT;
                /* it can't be ONE_RETURNING, so give up */
                return PORTAL_MULTI_QUERY;
            }
        }
    
        /*
         * 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)
        {
            Node       *stmt = (Node *) lfirst(lc);
    
            if (IsA(stmt, Query))
            {
                Query       *query = (Query *) stmt;
    
                if (query->canSetTag)
                {
                    if (++nSetTag > 1)
                        return PORTAL_MULTI_QUERY;    /* no need to look further */
                    if (query->returningList == NIL)
                        return PORTAL_MULTI_QUERY;    /* no need to look further */
                }
            }
            else if (IsA(stmt, PlannedStmt))
            {
                PlannedStmt *pstmt = (PlannedStmt *) stmt;
    
                if (pstmt->canSetTag)
                {
                    if (++nSetTag > 1)
                        return PORTAL_MULTI_QUERY;    /* no need to look further */
                    if (!pstmt->hasReturning)
                        return PORTAL_MULTI_QUERY;    /* no need to look further */
                }
            }
            /* otherwise, utility command, assumed not canSetTag */
        }
        if (nSetTag == 1)
            return PORTAL_ONE_RETURNING;
    
        /* Else, it's the general case... */
        return PORTAL_MULTI_QUERY;
    }

    先展开第一段的判断:if (list_length(stmts) == 1)

    其实是:

    static inline int
    list_length(const List *l)
    {
        return l ? l->length : 0;
    }

    这里我作一个查询验证一下,

    select * from tst01 where id IN (select sid from tst02) or id IN (select sid from tst03);

    list_length(stmts) == 1 的条件满足。

    再看:

    #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;
    }

    所以呢,这句 :Node *stmt = (Node *) lfirst(lc); 就是拿到了 计划树的头,并且转换为 Node 指针。

  • 相关阅读:
    python学习-10 运算符1
    python学习-9 pycharm的安装
    python学习-8 用户有三次机会登陆
    python学习-7 条件语句 while循环 + 练习题
    python学习-6 猜拳小游戏
    python学习-5 python基础-2 条件语句(if的简单用法2---elif)
    python学习-4 python基础-2 条件语句(if的简单用法1)
    python学习-3 python基础-1基础知识和解释器
    RaspBerry--解决无法用 ssh 直接以 root 用户登录
    NetWork--HTTPS 原理解析<转>
  • 原文地址:https://www.cnblogs.com/gaojian/p/3105804.html
Copyright © 2011-2022 走看看