• PostgreSQL在何处处理 sql查询之三十二


    接前面,继续观察 PortalStart,其中有:

                    /*
                     * Create QueryDesc in portal's context; for the moment, set
                     * the destination to DestNone.
                     */
                   queryDesc = CreateQueryDesc((PlannedStmt *) linitial(portal->stmts),
                                                portal->sourceText,
                                                GetActiveSnapshot(),
                                                InvalidSnapshot,
                                                None_Receiver,
                                                params,
                                                0);

    CreateQueryDesc 的程序:

    /*
     * CreateQueryDesc
     */
    QueryDesc *
    CreateQueryDesc(PlannedStmt *plannedstmt,
                    const char *sourceText,
                    Snapshot snapshot,
                    Snapshot crosscheck_snapshot,
                    DestReceiver *dest,
                    ParamListInfo params,
                    int instrument_options)
    {
        QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
    
        qd->operation = plannedstmt->commandType;    /* operation */
        qd->plannedstmt = plannedstmt;        /* plan */
        qd->utilitystmt = plannedstmt->utilityStmt; /* in case DECLARE CURSOR */
        qd->sourceText = sourceText;    /* query text */
        qd->snapshot = RegisterSnapshot(snapshot);    /* snapshot */
        /* RI check snapshot */
        qd->crosscheck_snapshot = RegisterSnapshot(crosscheck_snapshot);
        qd->dest = dest;            /* output dest */
        qd->params = params;        /* parameter values passed into query */
        qd->instrument_options = instrument_options;        /* instrumentation
                                                             * wanted? */
    
        /* null these fields until set by ExecutorStart */
        qd->tupDesc = NULL;
        qd->estate = NULL;
        qd->planstate = NULL;
        qd->totaltime = NULL;
    
        return qd;
    }

    只是准备好了数据而已。

    再分析之下的一段:

                    /*
                     * Call ExecutorStart to prepare the plan for execution
                     */
                    ExecutorStart(queryDesc, myeflags);

    其定义为:

    /* ----------------------------------------------------------------
     *        ExecutorStart
     *
     *        This routine must be called at the beginning of any execution of any
     *        query plan
     *
     * Takes a QueryDesc previously created by CreateQueryDesc (which is separate
     * only because some places use QueryDescs for utility commands).  The tupDesc
     * field of the QueryDesc is filled in to describe the tuples that will be
     * returned, and the internal fields (estate and planstate) are set up.
     *
     * eflags contains flag bits as described in executor.h.
     *
     * NB: the CurrentMemoryContext when this is called will become the parent
     * of the per-query context used for this Executor invocation.
     *
     * We provide a function hook variable that lets loadable plugins
     * get control when ExecutorStart is called.  Such a plugin would
     * normally call standard_ExecutorStart().
     *
     * ----------------------------------------------------------------
     */
    void
    ExecutorStart(QueryDesc *queryDesc, int eflags)
    {
    
        if (ExecutorStart_hook)
            (*ExecutorStart_hook) (queryDesc, eflags);
        else
            standard_ExecutorStart(queryDesc, eflags);
    }
    
    void
    standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
    {
        ...
    
        /*
         * If non-read-only query, set the command ID to mark output tuples with
         */
        switch (queryDesc->operation)
        {
            case CMD_SELECT:
    
                /*
                 * SELECT FOR UPDATE/SHARE and modifying CTEs need to mark tuples
                 */
                if (queryDesc->plannedstmt->rowMarks != NIL ||
                    queryDesc->plannedstmt->hasModifyingCTE)
                    estate->es_output_cid = GetCurrentCommandId(true);
    
                /*
                 * A SELECT without modifying CTEs can't possibly queue triggers,
                 * so force skip-triggers mode. This is just a marginal efficiency
                 * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't
                 * all that expensive, but we might as well do it.
                 */
                if (!queryDesc->plannedstmt->hasModifyingCTE)
                    eflags |= EXEC_FLAG_SKIP_TRIGGERS;
                break;
    
            case CMD_INSERT:
            case CMD_DELETE:
            case CMD_UPDATE:
                estate->es_output_cid = GetCurrentCommandId(true);
                break;
    
            default:
                elog(ERROR, "unrecognized operation code: %d",
                     (int) queryDesc->operation);
                break;
        }
        ...
    }
  • 相关阅读:
    db.Exec和db.Query的区别
    golang两种get请求获取携带参数的方式
    gin实现中间件middleware
    gin操作session
    笔札-有触动的句子
    并发的基本概念
    售货员的难题
    传球游戏之最小总代价
    状压dp入门
    [COCI 2010] OGRADA
  • 原文地址:https://www.cnblogs.com/gaojian/p/3106363.html
Copyright © 2020-2023  润新知