aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execScan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execScan.c')
-rw-r--r--src/backend/executor/execScan.c207
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);
}
/*