PostgreSQL在何处处理 sql查询之三十九

时间:2022-12-22 16:36:35

接前面,这次重点分析 ExecScan:

其for 循环内部:

    for (;;)
    {
        TupleTableSlot *slot;

        CHECK_FOR_INTERRUPTS();

        slot = ExecScanFetch(node, accessMtd, recheckMtd); /*
         * if the slot returned by the accessMtd contains NULL, then it means
         * there is nothing more to scan so we just return an empty slot,
         * being careful to use the projection result slot so it has correct
         * tupleDesc.
         */
        if (TupIsNull(slot))
        {
            if (projInfo)
                return ExecClearTuple(projInfo->pi_slot);
            else
                return slot;
        }

        ...
    }

接着来看 ExecScanFetch:

/*
 * ExecScanFetch -- fetch next potential tuple
 *
 * This routine is concerned with substituting a test tuple if we are
 * inside an EvalPlanQual recheck.    If we aren't, just execute
 * the access method's next-tuple routine.
 */
static inline TupleTableSlot *
ExecScanFetch(ScanState *node,
              ExecScanAccessMtd accessMtd,
              ExecScanRecheckMtd recheckMtd)
{
    EState       *estate = node->ps.state;

    if (estate->es_epqTuple != NULL)
    {
        /*
         * We are inside an EvalPlanQual recheck.  Return the test tuple if
         * one is available, after rechecking any access-method-specific
         * conditions.
         */
        Index        scanrelid = ((Scan *) node->ps.plan)->scanrelid;

        Assert(scanrelid > 0);
        if (estate->es_epqTupleSet[scanrelid - 1])
        {
            TupleTableSlot *slot = node->ss_ScanTupleSlot;

            /* Return empty slot if we already returned a tuple */
            if (estate->es_epqScanDone[scanrelid - 1])
                return ExecClearTuple(slot);
            /* Else mark to remember that we shouldn't return more */
            estate->es_epqScanDone[scanrelid - 1] = true;

            /* Return empty slot if we haven't got a test tuple */
            if (estate->es_epqTuple[scanrelid - 1] == NULL)
                return ExecClearTuple(slot);

            /* Store test tuple in the plan node's scan slot */
            ExecStoreTuple(estate->es_epqTuple[scanrelid - 1],
                           slot, InvalidBuffer, false);

            /* Check if it meets the access-method conditions */
            if (!(*recheckMtd) (node, slot))
                ExecClearTuple(slot);    /* would not be returned by scan */

            return slot;
        }
    }

    /*
     * Run the node-type-specific access method function to get the next tuple
     */
    return (*accessMtd) (node);
}

上述的 <(estate->es_epqTuple != NULL)> 条件未能得到满足,所以

直接奔这个去了: return (*accessMtd) (node);

前面已经知道,因为没有index,所以就执行了:static TupleTableSlot * SeqNext(SeqScanState *node)