diff options
Diffstat (limited to 'src/backend/executor/execScan.c')
-rw-r--r-- | src/backend/executor/execScan.c | 207 |
1 files changed, 9 insertions, 198 deletions
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c index 556a5d98e78..90726949a87 100644 --- a/src/backend/executor/execScan.c +++ b/src/backend/executor/execScan.c @@ -19,118 +19,9 @@ #include "postgres.h" #include "executor/executor.h" +#include "executor/execScan.h" #include "miscadmin.h" - - -/* - * ExecScanFetch -- check interrupts & 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; - - CHECK_FOR_INTERRUPTS(); - - if (estate->es_epq_active != NULL) - { - EPQState *epqstate = estate->es_epq_active; - - /* - * 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; - - if (scanrelid == 0) - { - /* - * This is a ForeignScan or CustomScan which has pushed down a - * join to the remote side. The recheck method is responsible not - * only for rechecking the scan/join quals but also for storing - * the correct tuple in the slot. - */ - - TupleTableSlot *slot = node->ss_ScanTupleSlot; - - if (!(*recheckMtd) (node, slot)) - ExecClearTuple(slot); /* would not be returned by scan */ - return slot; - } - else if (epqstate->relsubs_done[scanrelid - 1]) - { - /* - * Return empty slot, as either there is no EPQ tuple for this rel - * or we already returned it. - */ - - TupleTableSlot *slot = node->ss_ScanTupleSlot; - - return ExecClearTuple(slot); - } - else if (epqstate->relsubs_slot[scanrelid - 1] != NULL) - { - /* - * Return replacement tuple provided by the EPQ caller. - */ - - TupleTableSlot *slot = epqstate->relsubs_slot[scanrelid - 1]; - - Assert(epqstate->relsubs_rowmark[scanrelid - 1] == NULL); - - /* Mark to remember that we shouldn't return it again */ - epqstate->relsubs_done[scanrelid - 1] = true; - - /* Return empty slot if we haven't got a test tuple */ - if (TupIsNull(slot)) - return NULL; - - /* Check if it meets the access-method conditions */ - if (!(*recheckMtd) (node, slot)) - return ExecClearTuple(slot); /* would not be returned by - * scan */ - return slot; - } - else if (epqstate->relsubs_rowmark[scanrelid - 1] != NULL) - { - /* - * Fetch and return replacement tuple using a non-locking rowmark. - */ - - TupleTableSlot *slot = node->ss_ScanTupleSlot; - - /* Mark to remember that we shouldn't return more */ - epqstate->relsubs_done[scanrelid - 1] = true; - - if (!EvalPlanQualFetchRowMark(epqstate, scanrelid, slot)) - return NULL; - - /* Return empty slot if we haven't got a test tuple */ - if (TupIsNull(slot)) - return NULL; - - /* Check if it meets the access-method conditions */ - if (!(*recheckMtd) (node, slot)) - return 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); -} - /* ---------------------------------------------------------------- * ExecScan * @@ -157,100 +48,20 @@ ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, /* function returning a tuple */ ExecScanRecheckMtd recheckMtd) { - ExprContext *econtext; + EPQState *epqstate; ExprState *qual; ProjectionInfo *projInfo; - /* - * Fetch data from node - */ + epqstate = node->ps.state->es_epq_active; qual = node->ps.qual; projInfo = node->ps.ps_ProjInfo; - econtext = node->ps.ps_ExprContext; - - /* interrupt checks are in ExecScanFetch */ - - /* - * If we have neither a qual to check nor a projection to do, just skip - * all the overhead and return the raw scan tuple. - */ - if (!qual && !projInfo) - { - ResetExprContext(econtext); - return ExecScanFetch(node, accessMtd, recheckMtd); - } - - /* - * Reset per-tuple memory context to free any expression evaluation - * storage allocated in the previous tuple cycle. - */ - ResetExprContext(econtext); - - /* - * get a tuple from the access method. Loop until we obtain a tuple that - * passes the qualification. - */ - for (;;) - { - TupleTableSlot *slot; - 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_state.resultslot); - else - return slot; - } - - /* - * place the current tuple into the expr context - */ - econtext->ecxt_scantuple = slot; - - /* - * check that the current tuple satisfies the qual-clause - * - * check for non-null qual here to avoid a function call to ExecQual() - * when the qual is null ... saves only a few cycles, but they add up - * ... - */ - if (qual == NULL || ExecQual(qual, econtext)) - { - /* - * Found a satisfactory scan tuple. - */ - if (projInfo) - { - /* - * Form a projection tuple, store it in the result tuple slot - * and return it. - */ - return ExecProject(projInfo); - } - else - { - /* - * Here, we aren't projecting, so just return scan tuple. - */ - return slot; - } - } - else - InstrCountFiltered1(node, 1); - - /* - * Tuple fails qual, so free per-tuple memory and try again. - */ - ResetExprContext(econtext); - } + return ExecScanExtended(node, + accessMtd, + recheckMtd, + epqstate, + qual, + projInfo); } /* |