且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

PostgreSQL在何处处理 sql查询之九

更新时间:2022-09-14 15:21:21

调用关系:PortalRun -> PortalRunSelect -> ExecutorRun

ExecutorRun,实际上会去运行 standard_ExecutorRun ->ExecutePlan:

PostgreSQL在何处处理 sql查询之九
/* ----------------------------------------------------------------
 *        ExecutorRun
 *
 *        This is the main routine of the executor module. It accepts
 *        the query descriptor from the traffic cop and executes the
 *        query plan.
 *
 *        ExecutorStart must have been called already.
 *
 *        If direction is NoMovementScanDirection then nothing is done
 *        except to start up/shut down the destination.  Otherwise,
 *        we retrieve up to 'count' tuples in the specified direction.
 *
 *        Note: count = 0 is interpreted as no portal limit, i.e., run to
 *        completion.
 *
 *        There is no return value, but output tuples (if any) are sent to
 *        the destination receiver specified in the QueryDesc; and the number
 *        of tuples processed at the top level can be found in
 *        estate->es_processed.
 *
 *        We provide a function hook variable that lets loadable plugins
 *        get control when ExecutorRun is called.  Such a plugin would
 *        normally call standard_ExecutorRun().
 *
 * ----------------------------------------------------------------
 */
void
ExecutorRun(QueryDesc *queryDesc,
            ScanDirection direction, long count)
{
    if (ExecutorRun_hook)
        (*ExecutorRun_hook) (queryDesc, direction, count);
    else
        standard_ExecutorRun(queryDesc, direction, count);
}

void
standard_ExecutorRun(QueryDesc *queryDesc,
                     ScanDirection direction, long count)
{
    EState       *estate;
    CmdType        operation;
    DestReceiver *dest;
    bool        sendTuples;
    MemoryContext oldcontext;

    /* sanity checks */
    Assert(queryDesc != NULL);

    estate = queryDesc->estate;

    Assert(estate != NULL);
    Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));

    /*
     * Switch into per-query memory context
     */
    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    /* Allow instrumentation of Executor overall runtime */
    if (queryDesc->totaltime)
        InstrStartNode(queryDesc->totaltime);

    /*
     * extract information from the query descriptor and the query feature.
     */
    operation = queryDesc->operation;
    dest = queryDesc->dest;

    /*
     * startup tuple receiver, if we will be emitting tuples
     */
    estate->es_processed = 0;
    estate->es_lastoid = InvalidOid;

    sendTuples = (operation == CMD_SELECT ||
                  queryDesc->plannedstmt->hasReturning);

    if (sendTuples)
        (*dest->rStartup) (dest, operation, queryDesc->tupDesc);

    /*
     * run plan
     */
    if (!ScanDirectionIsNoMovement(direction))
        ExecutePlan(estate,
                    queryDesc->planstate,
                    operation,
                    sendTuples,
                    count,
                    direction,
                    dest);

    /*
     * shutdown tuple receiver, if we started it
     */
    if (sendTuples)
        (*dest->rShutdown) (dest);

    if (queryDesc->totaltime)
        InstrStopNode(queryDesc->totaltime, estate->es_processed);

    MemoryContextSwitchTo(oldcontext);
}
PostgreSQL在何处处理 sql查询之九