summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/executor/execProcnode.c252
-rw-r--r--src/backend/executor/nodeAgg.c6
-rw-r--r--src/backend/executor/nodeAppend.c8
-rw-r--r--src/backend/executor/nodeBitmapAnd.c14
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c7
-rw-r--r--src/backend/executor/nodeBitmapIndexscan.c14
-rw-r--r--src/backend/executor/nodeBitmapOr.c14
-rw-r--r--src/backend/executor/nodeCtescan.c7
-rw-r--r--src/backend/executor/nodeCustom.c11
-rw-r--r--src/backend/executor/nodeForeignscan.c9
-rw-r--r--src/backend/executor/nodeFunctionscan.c7
-rw-r--r--src/backend/executor/nodeGather.c7
-rw-r--r--src/backend/executor/nodeGatherMerge.c7
-rw-r--r--src/backend/executor/nodeGroup.c6
-rw-r--r--src/backend/executor/nodeHash.c5
-rw-r--r--src/backend/executor/nodeHashjoin.c6
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c7
-rw-r--r--src/backend/executor/nodeIndexscan.c7
-rw-r--r--src/backend/executor/nodeLimit.c6
-rw-r--r--src/backend/executor/nodeLockRows.c6
-rw-r--r--src/backend/executor/nodeMaterial.c6
-rw-r--r--src/backend/executor/nodeMergeAppend.c7
-rw-r--r--src/backend/executor/nodeMergejoin.c6
-rw-r--r--src/backend/executor/nodeModifyTable.c6
-rw-r--r--src/backend/executor/nodeNamedtuplestorescan.c7
-rw-r--r--src/backend/executor/nodeNestloop.c6
-rw-r--r--src/backend/executor/nodeProjectSet.c6
-rw-r--r--src/backend/executor/nodeRecursiveunion.c6
-rw-r--r--src/backend/executor/nodeResult.c6
-rw-r--r--src/backend/executor/nodeSamplescan.c9
-rw-r--r--src/backend/executor/nodeSeqscan.c9
-rw-r--r--src/backend/executor/nodeSetOp.c6
-rw-r--r--src/backend/executor/nodeSort.c6
-rw-r--r--src/backend/executor/nodeSubqueryscan.c7
-rw-r--r--src/backend/executor/nodeTableFuncscan.c7
-rw-r--r--src/backend/executor/nodeTidscan.c7
-rw-r--r--src/backend/executor/nodeUnique.c6
-rw-r--r--src/backend/executor/nodeValuesscan.c7
-rw-r--r--src/backend/executor/nodeWindowAgg.c6
-rw-r--r--src/backend/executor/nodeWorktablescan.c7
-rw-r--r--src/include/executor/executor.h21
-rw-r--r--src/include/executor/nodeAgg.h1
-rw-r--r--src/include/executor/nodeAppend.h1
-rw-r--r--src/include/executor/nodeBitmapHeapscan.h1
-rw-r--r--src/include/executor/nodeCtescan.h1
-rw-r--r--src/include/executor/nodeCustom.h1
-rw-r--r--src/include/executor/nodeForeignscan.h1
-rw-r--r--src/include/executor/nodeFunctionscan.h1
-rw-r--r--src/include/executor/nodeGather.h1
-rw-r--r--src/include/executor/nodeGatherMerge.h1
-rw-r--r--src/include/executor/nodeGroup.h1
-rw-r--r--src/include/executor/nodeHash.h1
-rw-r--r--src/include/executor/nodeHashjoin.h1
-rw-r--r--src/include/executor/nodeIndexonlyscan.h1
-rw-r--r--src/include/executor/nodeIndexscan.h1
-rw-r--r--src/include/executor/nodeLimit.h1
-rw-r--r--src/include/executor/nodeLockRows.h1
-rw-r--r--src/include/executor/nodeMaterial.h1
-rw-r--r--src/include/executor/nodeMergeAppend.h1
-rw-r--r--src/include/executor/nodeMergejoin.h1
-rw-r--r--src/include/executor/nodeModifyTable.h1
-rw-r--r--src/include/executor/nodeNamedtuplestorescan.h1
-rw-r--r--src/include/executor/nodeNestloop.h1
-rw-r--r--src/include/executor/nodeProjectSet.h1
-rw-r--r--src/include/executor/nodeRecursiveunion.h1
-rw-r--r--src/include/executor/nodeResult.h1
-rw-r--r--src/include/executor/nodeSamplescan.h1
-rw-r--r--src/include/executor/nodeSeqscan.h1
-rw-r--r--src/include/executor/nodeSetOp.h1
-rw-r--r--src/include/executor/nodeSort.h1
-rw-r--r--src/include/executor/nodeSubqueryscan.h1
-rw-r--r--src/include/executor/nodeTableFuncscan.h1
-rw-r--r--src/include/executor/nodeTidscan.h1
-rw-r--r--src/include/executor/nodeUnique.h1
-rw-r--r--src/include/executor/nodeValuesscan.h1
-rw-r--r--src/include/executor/nodeWindowAgg.h1
-rw-r--r--src/include/executor/nodeWorktablescan.h1
-rw-r--r--src/include/nodes/execnodes.h16
78 files changed, 313 insertions, 299 deletions
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index 20fd9f822ed..396920c0a23 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -17,15 +17,10 @@
*-------------------------------------------------------------------------
*/
/*
- * INTERFACE ROUTINES
- * ExecInitNode - initialize a plan node and its subplans
- * ExecProcNode - get a tuple by executing the plan node
- * ExecEndNode - shut down a plan node and its subplans
- *
* NOTES
* This used to be three files. It is now all combined into
- * one file so that it is easier to keep ExecInitNode, ExecProcNode,
- * and ExecEndNode in sync when new nodes are added.
+ * one file so that it is easier to keep the dispatch routines
+ * in sync when new nodes are added.
*
* EXAMPLE
* Suppose we want the age of the manager of the shoe department and
@@ -122,6 +117,10 @@
#include "miscadmin.h"
+static TupleTableSlot *ExecProcNodeFirst(PlanState *node);
+static TupleTableSlot *ExecProcNodeInstr(PlanState *node);
+
+
/* ------------------------------------------------------------------------
* ExecInitNode
*
@@ -149,6 +148,13 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
if (node == NULL)
return NULL;
+ /*
+ * Make sure there's enough stack available. Need to check here, in
+ * addition to ExecProcNode() (via ExecProcNodeFirst()), to ensure the
+ * stack isn't overrun while initializing the node tree.
+ */
+ check_stack_depth();
+
switch (nodeTag(node))
{
/*
@@ -365,6 +371,13 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
}
/*
+ * Add a wrapper around the ExecProcNode callback that checks stack depth
+ * during the first execution.
+ */
+ result->ExecProcNodeReal = result->ExecProcNode;
+ result->ExecProcNode = ExecProcNodeFirst;
+
+ /*
* Initialize any initPlans present in this node. The planner put them in
* a separate list for us.
*/
@@ -388,195 +401,51 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
}
-/* ----------------------------------------------------------------
- * ExecProcNode
- *
- * Execute the given node to return a(nother) tuple.
- * ----------------------------------------------------------------
+/*
+ * ExecProcNode wrapper that performs some one-time checks, before calling
+ * the relevant node method (possibly via an instrumentation wrapper).
*/
-TupleTableSlot *
-ExecProcNode(PlanState *node)
+static TupleTableSlot *
+ExecProcNodeFirst(PlanState *node)
{
- TupleTableSlot *result;
-
- if (node->chgParam != NULL) /* something changed */
- ExecReScan(node); /* let ReScan handle this */
+ /*
+ * Perform stack depth check during the first execution of the node. We
+ * only do so the first time round because it turns out to not be cheap on
+ * some common architectures (eg. x86). This relies on the assumption that
+ * ExecProcNode calls for a given plan node will always be made at roughly
+ * the same stack depth.
+ */
+ check_stack_depth();
+ /*
+ * If instrumentation is required, change the wrapper to one that just
+ * does instrumentation. Otherwise we can dispense with all wrappers and
+ * have ExecProcNode() directly call the relevant function from now on.
+ */
if (node->instrument)
- InstrStartNode(node->instrument);
-
- switch (nodeTag(node))
- {
- /*
- * control nodes
- */
- case T_ResultState:
- result = ExecResult((ResultState *) node);
- break;
-
- case T_ProjectSetState:
- result = ExecProjectSet((ProjectSetState *) node);
- break;
-
- case T_ModifyTableState:
- result = ExecModifyTable((ModifyTableState *) node);
- break;
-
- case T_AppendState:
- result = ExecAppend((AppendState *) node);
- break;
-
- case T_MergeAppendState:
- result = ExecMergeAppend((MergeAppendState *) node);
- break;
-
- case T_RecursiveUnionState:
- result = ExecRecursiveUnion((RecursiveUnionState *) node);
- break;
-
- /* BitmapAndState does not yield tuples */
-
- /* BitmapOrState does not yield tuples */
-
- /*
- * scan nodes
- */
- case T_SeqScanState:
- result = ExecSeqScan((SeqScanState *) node);
- break;
-
- case T_SampleScanState:
- result = ExecSampleScan((SampleScanState *) node);
- break;
-
- case T_IndexScanState:
- result = ExecIndexScan((IndexScanState *) node);
- break;
-
- case T_IndexOnlyScanState:
- result = ExecIndexOnlyScan((IndexOnlyScanState *) node);
- break;
-
- /* BitmapIndexScanState does not yield tuples */
-
- case T_BitmapHeapScanState:
- result = ExecBitmapHeapScan((BitmapHeapScanState *) node);
- break;
-
- case T_TidScanState:
- result = ExecTidScan((TidScanState *) node);
- break;
-
- case T_SubqueryScanState:
- result = ExecSubqueryScan((SubqueryScanState *) node);
- break;
-
- case T_FunctionScanState:
- result = ExecFunctionScan((FunctionScanState *) node);
- break;
-
- case T_TableFuncScanState:
- result = ExecTableFuncScan((TableFuncScanState *) node);
- break;
-
- case T_ValuesScanState:
- result = ExecValuesScan((ValuesScanState *) node);
- break;
-
- case T_CteScanState:
- result = ExecCteScan((CteScanState *) node);
- break;
-
- case T_NamedTuplestoreScanState:
- result = ExecNamedTuplestoreScan((NamedTuplestoreScanState *) node);
- break;
-
- case T_WorkTableScanState:
- result = ExecWorkTableScan((WorkTableScanState *) node);
- break;
-
- case T_ForeignScanState:
- result = ExecForeignScan((ForeignScanState *) node);
- break;
-
- case T_CustomScanState:
- result = ExecCustomScan((CustomScanState *) node);
- break;
-
- /*
- * join nodes
- */
- case T_NestLoopState:
- result = ExecNestLoop((NestLoopState *) node);
- break;
-
- case T_MergeJoinState:
- result = ExecMergeJoin((MergeJoinState *) node);
- break;
-
- case T_HashJoinState:
- result = ExecHashJoin((HashJoinState *) node);
- break;
-
- /*
- * materialization nodes
- */
- case T_MaterialState:
- result = ExecMaterial((MaterialState *) node);
- break;
-
- case T_SortState:
- result = ExecSort((SortState *) node);
- break;
-
- case T_GroupState:
- result = ExecGroup((GroupState *) node);
- break;
+ node->ExecProcNode = ExecProcNodeInstr;
+ else
+ node->ExecProcNode = node->ExecProcNodeReal;
- case T_AggState:
- result = ExecAgg((AggState *) node);
- break;
-
- case T_WindowAggState:
- result = ExecWindowAgg((WindowAggState *) node);
- break;
-
- case T_UniqueState:
- result = ExecUnique((UniqueState *) node);
- break;
-
- case T_GatherState:
- result = ExecGather((GatherState *) node);
- break;
-
- case T_GatherMergeState:
- result = ExecGatherMerge((GatherMergeState *) node);
- break;
-
- case T_HashState:
- result = ExecHash((HashState *) node);
- break;
+ return node->ExecProcNode(node);
+}
- case T_SetOpState:
- result = ExecSetOp((SetOpState *) node);
- break;
- case T_LockRowsState:
- result = ExecLockRows((LockRowsState *) node);
- break;
+/*
+ * ExecProcNode wrapper that performs instrumentation calls. By keeping
+ * this a separate function, we avoid overhead in the normal case where
+ * no instrumentation is wanted.
+ */
+static TupleTableSlot *
+ExecProcNodeInstr(PlanState *node)
+{
+ TupleTableSlot *result;
- case T_LimitState:
- result = ExecLimit((LimitState *) node);
- break;
+ InstrStartNode(node->instrument);
- default:
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
- result = NULL;
- break;
- }
+ result = node->ExecProcNodeReal(node);
- if (node->instrument)
- InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
+ InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
return result;
}
@@ -600,6 +469,8 @@ MultiExecProcNode(PlanState *node)
{
Node *result;
+ check_stack_depth();
+
CHECK_FOR_INTERRUPTS();
if (node->chgParam != NULL) /* something changed */
@@ -657,6 +528,13 @@ ExecEndNode(PlanState *node)
if (node == NULL)
return;
+ /*
+ * Make sure there's enough stack available. Need to check here, in
+ * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
+ * guaranteed that ExecProcNode() is reached for all nodes.
+ */
+ check_stack_depth();
+
if (node->chgParam != NULL)
{
bms_free(node->chgParam);
@@ -855,6 +733,8 @@ ExecShutdownNode(PlanState *node)
if (node == NULL)
return false;
+ check_stack_depth();
+
planstate_tree_walker(node, ExecShutdownNode, NULL);
switch (nodeTag(node))
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 377916dae75..6a26773a49f 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -2099,9 +2099,10 @@ lookup_hash_entries(AggState *aggstate)
* stored in the expression context to be used when ExecProject evaluates
* the result tuple.
*/
-TupleTableSlot *
-ExecAgg(AggState *node)
+static TupleTableSlot *
+ExecAgg(PlanState *pstate)
{
+ AggState *node = castNode(AggState, pstate);
TupleTableSlot *result = NULL;
CHECK_FOR_INTERRUPTS();
@@ -2695,6 +2696,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate = makeNode(AggState);
aggstate->ss.ps.plan = (Plan *) node;
aggstate->ss.ps.state = estate;
+ aggstate->ss.ps.ExecProcNode = ExecAgg;
aggstate->aggs = NIL;
aggstate->numaggs = 0;
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 58045e05e5d..bed9bb87138 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -61,6 +61,7 @@
#include "executor/nodeAppend.h"
#include "miscadmin.h"
+static TupleTableSlot *ExecAppend(PlanState *pstate);
static bool exec_append_initialize_next(AppendState *appendstate);
@@ -147,6 +148,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
*/
appendstate->ps.plan = (Plan *) node;
appendstate->ps.state = estate;
+ appendstate->ps.ExecProcNode = ExecAppend;
appendstate->appendplans = appendplanstates;
appendstate->as_nplans = nplans;
@@ -197,9 +199,11 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
* Handles iteration over multiple subplans.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecAppend(AppendState *node)
+static TupleTableSlot *
+ExecAppend(PlanState *pstate)
{
+ AppendState *node = castNode(AppendState, pstate);
+
for (;;)
{
PlanState *subnode;
diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c
index e4eb028ff9c..1c5c312c954 100644
--- a/src/backend/executor/nodeBitmapAnd.c
+++ b/src/backend/executor/nodeBitmapAnd.c
@@ -33,6 +33,19 @@
/* ----------------------------------------------------------------
+ * ExecBitmapAnd
+ *
+ * stub for pro forma compliance
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+ExecBitmapAnd(PlanState *pstate)
+{
+ elog(ERROR, "BitmapAnd node does not support ExecProcNode call convention");
+ return NULL;
+}
+
+/* ----------------------------------------------------------------
* ExecInitBitmapAnd
*
* Begin all of the subscans of the BitmapAnd node.
@@ -63,6 +76,7 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
*/
bitmapandstate->ps.plan = (Plan *) node;
bitmapandstate->ps.state = estate;
+ bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
bitmapandstate->bitmapplans = bitmapplanstates;
bitmapandstate->nplans = nplans;
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index cf109d5049f..79f534e4e92 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -665,9 +665,11 @@ BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
* ExecBitmapHeapScan(node)
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecBitmapHeapScan(BitmapHeapScanState *node)
+static TupleTableSlot *
+ExecBitmapHeapScan(PlanState *pstate)
{
+ BitmapHeapScanState *node = castNode(BitmapHeapScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) BitmapHeapNext,
(ExecScanRecheckMtd) BitmapHeapRecheck);
@@ -815,6 +817,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
scanstate = makeNode(BitmapHeapScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
scanstate->tbm = NULL;
scanstate->tbmiterator = NULL;
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index 2411a2e5c1a..6feb70f4ae3 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -29,6 +29,19 @@
/* ----------------------------------------------------------------
+ * ExecBitmapIndexScan
+ *
+ * stub for pro forma compliance
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+ExecBitmapIndexScan(PlanState *pstate)
+{
+ elog(ERROR, "BitmapIndexScan node does not support ExecProcNode call convention");
+ return NULL;
+}
+
+/* ----------------------------------------------------------------
* MultiExecBitmapIndexScan(node)
* ----------------------------------------------------------------
*/
@@ -208,6 +221,7 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
indexstate = makeNode(BitmapIndexScanState);
indexstate->ss.ps.plan = (Plan *) node;
indexstate->ss.ps.state = estate;
+ indexstate->ss.ps.ExecProcNode = ExecBitmapIndexScan;
/* normally we don't make the result bitmap till runtime */
indexstate->biss_result = NULL;
diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c
index 4f0ddc6dffd..66a7a89a8b7 100644
--- a/src/backend/executor/nodeBitmapOr.c
+++ b/src/backend/executor/nodeBitmapOr.c
@@ -34,6 +34,19 @@
/* ----------------------------------------------------------------
+ * ExecBitmapOr
+ *
+ * stub for pro forma compliance
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+ExecBitmapOr(PlanState *pstate)
+{
+ elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
+ return NULL;
+}
+
+/* ----------------------------------------------------------------
* ExecInitBitmapOr
*
* Begin all of the subscans of the BitmapOr node.
@@ -64,6 +77,7 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
*/
bitmaporstate->ps.plan = (Plan *) node;
bitmaporstate->ps.state = estate;
+ bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
bitmaporstate->bitmapplans = bitmapplanstates;
bitmaporstate->nplans = nplans;
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index bed7949c5a0..79676ca9787 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -149,9 +149,11 @@ CteScanRecheck(CteScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecCteScan(CteScanState *node)
+static TupleTableSlot *
+ExecCteScan(PlanState *pstate)
{
+ CteScanState *node = castNode(CteScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) CteScanNext,
(ExecScanRecheckMtd) CteScanRecheck);
@@ -191,6 +193,7 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
scanstate = makeNode(CteScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecCteScan;
scanstate->eflags = eflags;
scanstate->cte_table = NULL;
scanstate->eof_cte = false;
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index fc15974a2d0..fb7645b1f46 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -21,6 +21,10 @@
#include "utils/memutils.h"
#include "utils/rel.h"
+
+static TupleTableSlot *ExecCustomScan(PlanState *pstate);
+
+
CustomScanState *
ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
{
@@ -45,6 +49,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
/* fill up fields of ScanState */
css->ss.ps.plan = &cscan->scan.plan;
css->ss.ps.state = estate;
+ css->ss.ps.ExecProcNode = ExecCustomScan;
/* create expression context for node */
ExecAssignExprContext(estate, &css->ss.ps);
@@ -102,9 +107,11 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
return css;
}
-TupleTableSlot *
-ExecCustomScan(CustomScanState *node)
+static TupleTableSlot *
+ExecCustomScan(PlanState *pstate)
{
+ CustomScanState *node = castNode(CustomScanState, pstate);
+
CHECK_FOR_INTERRUPTS();
Assert(node->methods->ExecCustomScan != NULL);
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 9cde112554b..140e82ef5e4 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -113,10 +113,12 @@ ForeignRecheck(ForeignScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecForeignScan(ForeignScanState *node)
+static TupleTableSlot *
+ExecForeignScan(PlanState *pstate)
{
- return ExecScan((ScanState *) node,
+ ForeignScanState *node = castNode(ForeignScanState, pstate);
+
+ return ExecScan(&node->ss,
(ExecScanAccessMtd) ForeignNext,
(ExecScanRecheckMtd) ForeignRecheck);
}
@@ -144,6 +146,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
scanstate = makeNode(ForeignScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecForeignScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 3217d641d76..9f87a7e5cdd 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -262,9 +262,11 @@ FunctionRecheck(FunctionScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecFunctionScan(FunctionScanState *node)
+static TupleTableSlot *
+ExecFunctionScan(PlanState *pstate)
{
+ FunctionScanState *node = castNode(FunctionScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) FunctionNext,
(ExecScanRecheckMtd) FunctionRecheck);
@@ -299,6 +301,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
scanstate = makeNode(FunctionScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecFunctionScan;
scanstate->eflags = eflags;
/*
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 5dbe19c056d..e8d94ee6f38 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -43,6 +43,7 @@
#include "utils/rel.h"
+static TupleTableSlot *ExecGather(PlanState *pstate);
static TupleTableSlot *gather_getnext(GatherState *gatherstate);
static HeapTuple gather_readnext(GatherState *gatherstate);
static void ExecShutdownGatherWorkers(GatherState *node);
@@ -69,6 +70,7 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
gatherstate = makeNode(GatherState);
gatherstate->ps.plan = (Plan *) node;
gatherstate->ps.state = estate;
+ gatherstate->ps.ExecProcNode = ExecGather;
gatherstate->need_to_scan_locally = !node->single_copy;
/*
@@ -120,9 +122,10 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
* the next qualifying tuple.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecGather(GatherState *node)
+static TupleTableSlot *
+ExecGather(PlanState *pstate)
{
+ GatherState *node = castNode(GatherState, pstate);
TupleTableSlot *fslot = node->funnel_slot;
int i;
TupleTableSlot *slot;
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 0aff3798f75..9a81e225100 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -44,6 +44,7 @@ typedef struct GMReaderTupleBuffer
*/
#define MAX_TUPLE_STORE 10
+static TupleTableSlot *ExecGatherMerge(PlanState *pstate);
static int32 heap_compare_slots(Datum a, Datum b, void *arg);
static TupleTableSlot *gather_merge_getnext(GatherMergeState *gm_state);
static HeapTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader,
@@ -75,6 +76,7 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
gm_state = makeNode(GatherMergeState);
gm_state->ps.plan = (Plan *) node;
gm_state->ps.state = estate;
+ gm_state->ps.ExecProcNode = ExecGatherMerge;
/*
* Miscellaneous initialization
@@ -157,9 +159,10 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
* the next qualifying tuple.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecGatherMerge(GatherMergeState *node)
+static TupleTableSlot *
+ExecGatherMerge(PlanState *pstate)
{
+ GatherMergeState *node = castNode(GatherMergeState, pstate);
TupleTableSlot *slot;
ExprContext *econtext;
int i;
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index fc5e0e59bcc..ab4ae24a6bc 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -32,9 +32,10 @@
*
* Return one tuple for each group of matching input tuples.
*/
-TupleTableSlot *
-ExecGroup(GroupState *node)
+static TupleTableSlot *
+ExecGroup(PlanState *pstate)
{
+ GroupState *node = castNode(GroupState, pstate);
ExprContext *econtext;
int numCols;
AttrNumber *grpColIdx;
@@ -175,6 +176,7 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
grpstate = makeNode(GroupState);
grpstate->ss.ps.plan = (Plan *) node;
grpstate->ss.ps.state = estate;
+ grpstate->ss.ps.ExecProcNode = ExecGroup;
grpstate->grp_done = FALSE;
/*
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index fbeb562489c..d10d94ccc26 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -56,8 +56,8 @@ static void *dense_alloc(HashJoinTable hashtable, Size size);
* stub for pro forma compliance
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecHash(HashState *node)
+static TupleTableSlot *
+ExecHash(PlanState *pstate)
{
elog(ERROR, "Hash node does not support ExecProcNode call convention");
return NULL;
@@ -172,6 +172,7 @@ ExecInitHash(Hash *node, EState *estate, int eflags)
hashstate = makeNode(HashState);
hashstate->ps.plan = (Plan *) node;
hashstate->ps.state = estate;
+ hashstate->ps.ExecProcNode = ExecHash;
hashstate->hashtable = NULL;
hashstate->hashkeys = NIL; /* will be set by parent HashJoin */
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 252960c81c5..ab1632cc13d 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -58,9 +58,10 @@ static bool ExecHashJoinNewBatch(HashJoinState *hjstate);
* the other one is "outer".
* ----------------------------------------------------------------
*/
-TupleTableSlot * /* return: a tuple or NULL */
-ExecHashJoin(HashJoinState *node)
+static TupleTableSlot * /* return: a tuple or NULL */
+ExecHashJoin(PlanState *pstate)
{
+ HashJoinState *node = castNode(HashJoinState, pstate);
PlanState *outerNode;
HashState *hashNode;
ExprState *joinqual;
@@ -399,6 +400,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
hjstate = makeNode(HashJoinState);
hjstate->js.ps.plan = (Plan *) node;
hjstate->js.ps.state = estate;
+ hjstate->js.ps.ExecProcNode = ExecHashJoin;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index e2000764a46..fe7ba3f1a4f 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -306,9 +306,11 @@ IndexOnlyRecheck(IndexOnlyScanState *node, TupleTableSlot *slot)
* ExecIndexOnlyScan(node)
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecIndexOnlyScan(IndexOnlyScanState *node)
+static TupleTableSlot *
+ExecIndexOnlyScan(PlanState *pstate)
{
+ IndexOnlyScanState *node = castNode(IndexOnlyScanState, pstate);
+
/*
* If we have runtime keys and they've not already been set up, do it now.
*/
@@ -476,6 +478,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
indexstate = makeNode(IndexOnlyScanState);
indexstate->ss.ps.plan = (Plan *) node;
indexstate->ss.ps.state = estate;
+ indexstate->ss.ps.ExecProcNode = ExecIndexOnlyScan;
indexstate->ioss_HeapFetches = 0;
/*
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 6704ede9955..404076d5930 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -542,9 +542,11 @@ reorderqueue_pop(IndexScanState *node)
* ExecIndexScan(node)
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecIndexScan(IndexScanState *node)
+static TupleTableSlot *
+ExecIndexScan(PlanState *pstate)
{
+ IndexScanState *node = castNode(IndexScanState, pstate);
+
/*
* If we have runtime keys and they've not already been set up, do it now.
*/
@@ -910,6 +912,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
indexstate = makeNode(IndexScanState);
indexstate->ss.ps.plan = (Plan *) node;
indexstate->ss.ps.state = estate;
+ indexstate->ss.ps.ExecProcNode = ExecIndexScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index 2ed3523257f..ac5a2ff0e60 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -37,9 +37,10 @@ static void pass_down_bound(LimitState *node, PlanState *child_node);
* filtering on the stream of tuples returned by a subplan.
* ----------------------------------------------------------------
*/
-TupleTableSlot * /* return: a tuple or NULL */
-ExecLimit(LimitState *node)
+static TupleTableSlot * /* return: a tuple or NULL */
+ExecLimit(PlanState *pstate)
{
+ LimitState *node = castNode(LimitState, pstate);
ScanDirection direction;
TupleTableSlot *slot;
PlanState *outerPlan;
@@ -378,6 +379,7 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
limitstate = makeNode(LimitState);
limitstate->ps.plan = (Plan *) node;
limitstate->ps.state = estate;
+ limitstate->ps.ExecProcNode = ExecLimit;
limitstate->lstate = LIMIT_INITIAL;
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index dd4e2c5f2f1..93895600a5d 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -36,9 +36,10 @@
* ExecLockRows
* ----------------------------------------------------------------
*/
-TupleTableSlot * /* return: a tuple or NULL */
-ExecLockRows(LockRowsState *node)
+static TupleTableSlot * /* return: a tuple or NULL */
+ExecLockRows(PlanState *pstate)
{
+ LockRowsState *node = castNode(LockRowsState, pstate);
TupleTableSlot *slot;
EState *estate;
PlanState *outerPlan;
@@ -364,6 +365,7 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
lrstate = makeNode(LockRowsState);
lrstate->ps.plan = (Plan *) node;
lrstate->ps.state = estate;
+ lrstate->ps.ExecProcNode = ExecLockRows;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 33429495909..91178f10198 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -35,9 +35,10 @@
*
* ----------------------------------------------------------------
*/
-TupleTableSlot * /* result tuple from subplan */
-ExecMaterial(MaterialState *node)
+static TupleTableSlot * /* result tuple from subplan */
+ExecMaterial(PlanState *pstate)
{
+ MaterialState *node = castNode(MaterialState, pstate);
EState *estate;
ScanDirection dir;
bool forward;
@@ -173,6 +174,7 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
matstate = makeNode(MaterialState);
matstate->ss.ps.plan = (Plan *) node;
matstate->ss.ps.state = estate;
+ matstate->ss.ps.ExecProcNode = ExecMaterial;
/*
* We must have a tuplestore buffering the subplan output to do backward
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index d41def13506..6bf490bd700 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -50,6 +50,7 @@
*/
typedef int32 SlotNumber;
+static TupleTableSlot *ExecMergeAppend(PlanState *pstate);
static int heap_compare_slots(Datum a, Datum b, void *arg);
@@ -89,6 +90,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
*/
mergestate->ps.plan = (Plan *) node;
mergestate->ps.state = estate;
+ mergestate->ps.ExecProcNode = ExecMergeAppend;
mergestate->mergeplans = mergeplanstates;
mergestate->ms_nplans = nplans;
@@ -169,9 +171,10 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
* Handles iteration over multiple subplans.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecMergeAppend(MergeAppendState *node)
+static TupleTableSlot *
+ExecMergeAppend(PlanState *pstate)
{
+ MergeAppendState *node = castNode(MergeAppendState, pstate);
TupleTableSlot *result;
SlotNumber i;
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 324b61b8c0c..925b4cf5535 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -596,9 +596,10 @@ ExecMergeTupleDump(MergeJoinState *mergestate)
* ExecMergeJoin
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecMergeJoin(MergeJoinState *node)
+static TupleTableSlot *
+ExecMergeJoin(PlanState *pstate)
{
+ MergeJoinState *node = castNode(MergeJoinState, pstate);
ExprState *joinqual;
ExprState *otherqual;
bool qualResult;
@@ -1448,6 +1449,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate = makeNode(MergeJoinState);
mergestate->js.ps.plan = (Plan *) node;
mergestate->js.ps.state = estate;
+ mergestate->js.ps.ExecProcNode = ExecMergeJoin;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 637a582e1cc..0dde0ed6eb2 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1535,9 +1535,10 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
* if needed.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecModifyTable(ModifyTableState *node)
+static TupleTableSlot *
+ExecModifyTable(PlanState *pstate)
{
+ ModifyTableState *node = castNode(ModifyTableState, pstate);
EState *estate = node->ps.state;
CmdType operation = node->operation;
ResultRelInfo *saved_resultRelInfo;
@@ -1806,6 +1807,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate = makeNode(ModifyTableState);
mtstate->ps.plan = (Plan *) node;
mtstate->ps.state = estate;
+ mtstate->ps.ExecProcNode = ExecModifyTable;
mtstate->operation = operation;
mtstate->canSetTag = node->canSetTag;
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
index 62234869abb..3a65b9f5dc9 100644
--- a/src/backend/executor/nodeNamedtuplestorescan.c
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -63,9 +63,11 @@ NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecNamedTuplestoreScan(NamedTuplestoreScanState *node)
+static TupleTableSlot *
+ExecNamedTuplestoreScan(PlanState *pstate)
{
+ NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) NamedTuplestoreScanNext,
(ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
@@ -97,6 +99,7 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
scanstate = makeNode(NamedTuplestoreScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan;
enr = get_ENR(estate->es_queryEnv, node->enrname);
if (!enr)
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index bedc374ef05..4447b7c051a 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -57,9 +57,10 @@
* are prepared to return the first tuple.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecNestLoop(NestLoopState *node)
+static TupleTableSlot *
+ExecNestLoop(PlanState *pstate)
{
+ NestLoopState *node = castNode(NestLoopState, pstate);
NestLoop *nl;
PlanState *innerPlan;
PlanState *outerPlan;
@@ -275,6 +276,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
nlstate = makeNode(NestLoopState);
nlstate->js.ps.plan = (Plan *) node;
nlstate->js.ps.state = estate;
+ nlstate->js.ps.ExecProcNode = ExecNestLoop;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 3b69c7adeea..d93462c5421 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -39,9 +39,10 @@ static TupleTableSlot *ExecProjectSRF(ProjectSetState *node, bool continuing);
* returning functions).
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecProjectSet(ProjectSetState *node)
+static TupleTableSlot *
+ExecProjectSet(PlanState *pstate)
{
+ ProjectSetState *node = castNode(ProjectSetState, pstate);
TupleTableSlot *outerTupleSlot;
TupleTableSlot *resultSlot;
PlanState *outerPlan;
@@ -215,6 +216,7 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
state = makeNode(ProjectSetState);
state->ps.plan = (Plan *) node;
state->ps.state = estate;
+ state->ps.ExecProcNode = ExecProjectSet;
state->pending_srf_tuples = false;
diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c
index 2802fffa2b6..a64dd1397a4 100644
--- a/src/backend/executor/nodeRecursiveunion.c
+++ b/src/backend/executor/nodeRecursiveunion.c
@@ -66,9 +66,10 @@ build_hash_table(RecursiveUnionState *rustate)
* 2.6 go back to 2.2
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecRecursiveUnion(RecursiveUnionState *node)
+static TupleTableSlot *
+ExecRecursiveUnion(PlanState *pstate)
{
+ RecursiveUnionState *node = castNode(RecursiveUnionState, pstate);
PlanState *outerPlan = outerPlanState(node);
PlanState *innerPlan = innerPlanState(node);
RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan;
@@ -172,6 +173,7 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags)
rustate = makeNode(RecursiveUnionState);
rustate->ps.plan = (Plan *) node;
rustate->ps.state = estate;
+ rustate->ps.ExecProcNode = ExecRecursiveUnion;
rustate->eqfunctions = NULL;
rustate->hashfunctions = NULL;
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index f007f46784f..4c879d87655 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -64,9 +64,10 @@
* 'nil' if the constant qualification is not satisfied.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecResult(ResultState *node)
+static TupleTableSlot *
+ExecResult(PlanState *pstate)
{
+ ResultState *node = castNode(ResultState, pstate);
TupleTableSlot *outerTupleSlot;
PlanState *outerPlan;
ExprContext *econtext;
@@ -191,6 +192,7 @@ ExecInitResult(Result *node, EState *estate, int eflags)
resstate = makeNode(ResultState);
resstate->ps.plan = (Plan *) node;
resstate->ps.state = estate;
+ resstate->ps.ExecProcNode = ExecResult;
resstate->rs_done = false;
resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index b710ef7edf2..9c74a836e40 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -96,10 +96,12 @@ SampleRecheck(SampleScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecSampleScan(SampleScanState *node)
+static TupleTableSlot *
+ExecSampleScan(PlanState *pstate)
{
- return ExecScan((ScanState *) node,
+ SampleScanState *node = castNode(SampleScanState, pstate);
+
+ return ExecScan(&node->ss,
(ExecScanAccessMtd) SampleNext,
(ExecScanRecheckMtd) SampleRecheck);
}
@@ -153,6 +155,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
scanstate = makeNode(SampleScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecSampleScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 307df87c82f..5c49d4ca8a9 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -121,10 +121,12 @@ SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecSeqScan(SeqScanState *node)
+static TupleTableSlot *
+ExecSeqScan(PlanState *pstate)
{
- return ExecScan((ScanState *) node,
+ SeqScanState *node = castNode(SeqScanState, pstate);
+
+ return ExecScan(&node->ss,
(ExecScanAccessMtd) SeqNext,
(ExecScanRecheckMtd) SeqRecheck);
}
@@ -177,6 +179,7 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
scanstate = makeNode(SeqScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecSeqScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 56c5643f175..571cbf86b1d 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -180,9 +180,10 @@ set_output_count(SetOpState *setopstate, SetOpStatePerGroup pergroup)
* ExecSetOp
* ----------------------------------------------------------------
*/
-TupleTableSlot * /* return: a tuple or NULL */
-ExecSetOp(SetOpState *node)
+static TupleTableSlot * /* return: a tuple or NULL */
+ExecSetOp(PlanState *pstate)
{
+ SetOpState *node = castNode(SetOpState, pstate);
SetOp *plannode = (SetOp *) node->ps.plan;
TupleTableSlot *resultTupleSlot = node->ps.ps_ResultTupleSlot;
@@ -485,6 +486,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
setopstate = makeNode(SetOpState);
setopstate->ps.plan = (Plan *) node;
setopstate->ps.state = estate;
+ setopstate->ps.ExecProcNode = ExecSetOp;
setopstate->eqfunctions = NULL;
setopstate->hashfunctions = NULL;
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index 799a4e92042..aae4150e2c8 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -35,9 +35,10 @@
* -- the outer child is prepared to return the first tuple.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecSort(SortState *node)
+static TupleTableSlot *
+ExecSort(PlanState *pstate)
{
+ SortState *node = castNode(SortState, pstate);
EState *estate;
ScanDirection dir;
Tuplesortstate *tuplesortstate;
@@ -165,6 +166,7 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
sortstate = makeNode(SortState);
sortstate->ss.ps.plan = (Plan *) node;
sortstate->ss.ps.state = estate;
+ sortstate->ss.ps.ExecProcNode = ExecSort;
/*
* We must have random access to the sort output to do backward scan or
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index ae184700a67..088c92992ec 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -79,9 +79,11 @@ SubqueryRecheck(SubqueryScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecSubqueryScan(SubqueryScanState *node)
+static TupleTableSlot *
+ExecSubqueryScan(PlanState *pstate)
{
+ SubqueryScanState *node = castNode(SubqueryScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) SubqueryNext,
(ExecScanRecheckMtd) SubqueryRecheck);
@@ -109,6 +111,7 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
subquerystate = makeNode(SubqueryScanState);
subquerystate->ss.ps.plan = (Plan *) node;
subquerystate->ss.ps.state = estate;
+ subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index 2859363fe2c..b03d2ef7622 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -93,9 +93,11 @@ TableFuncRecheck(TableFuncScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecTableFuncScan(TableFuncScanState *node)
+static TupleTableSlot *
+ExecTableFuncScan(PlanState *pstate)
{
+ TableFuncScanState *node = castNode(TableFuncScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) TableFuncNext,
(ExecScanRecheckMtd) TableFuncRecheck);
@@ -128,6 +130,7 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
scanstate = makeNode(TableFuncScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecTableFuncScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index c122473bdf8..0ee76e7d252 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -445,9 +445,11 @@ TidRecheck(TidScanState *node, TupleTableSlot *slot)
* -- tidPtr is -1.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecTidScan(TidScanState *node)
+static TupleTableSlot *
+ExecTidScan(PlanState *pstate)
{
+ TidScanState *node = castNode(TidScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) TidNext,
(ExecScanRecheckMtd) TidRecheck);
@@ -519,6 +521,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
tidstate = makeNode(TidScanState);
tidstate->ss.ps.plan = (Plan *) node;
tidstate->ss.ps.state = estate;
+ tidstate->ss.ps.ExecProcNode = ExecTidScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index db78c88368b..621fdd9b9c1 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -43,9 +43,10 @@
* ExecUnique
* ----------------------------------------------------------------
*/
-TupleTableSlot * /* return: a tuple or NULL */
-ExecUnique(UniqueState *node)
+static TupleTableSlot * /* return: a tuple or NULL */
+ExecUnique(PlanState *pstate)
{
+ UniqueState *node = castNode(UniqueState, pstate);
Unique *plannode = (Unique *) node->ps.plan;
TupleTableSlot *resultTupleSlot;
TupleTableSlot *slot;
@@ -125,6 +126,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
uniquestate = makeNode(UniqueState);
uniquestate->ps.plan = (Plan *) node;
uniquestate->ps.state = estate;
+ uniquestate->ps.ExecProcNode = ExecUnique;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index 9ee776c4c32..6eacaed8bb8 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -185,9 +185,11 @@ ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecValuesScan(ValuesScanState *node)
+static TupleTableSlot *
+ExecValuesScan(PlanState *pstate)
{
+ ValuesScanState *node = castNode(ValuesScanState, pstate);
+
return ExecScan(&node->ss,
(ExecScanAccessMtd) ValuesNext,
(ExecScanRecheckMtd) ValuesRecheck);
@@ -218,6 +220,7 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
scanstate = makeNode(ValuesScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecValuesScan;
/*
* Miscellaneous initialization
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 9da35ac506b..80be46029f4 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1587,9 +1587,10 @@ update_frametailpos(WindowObject winobj, TupleTableSlot *slot)
* returned rows is exactly the same as its outer subplan's result.
* -----------------
*/
-TupleTableSlot *
-ExecWindowAgg(WindowAggState *winstate)
+static TupleTableSlot *
+ExecWindowAgg(PlanState *pstate)
{
+ WindowAggState *winstate = castNode(WindowAggState, pstate);
ExprContext *econtext;
int i;
int numfuncs;
@@ -1790,6 +1791,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
winstate = makeNode(WindowAggState);
winstate->ss.ps.plan = (Plan *) node;
winstate->ss.ps.state = estate;
+ winstate->ss.ps.ExecProcNode = ExecWindowAgg;
/*
* Create expression contexts. We need two, one for per-input-tuple
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
index d7616be0652..d5ffadda3e8 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -77,9 +77,11 @@ WorkTableScanRecheck(WorkTableScanState *node, TupleTableSlot *slot)
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecWorkTableScan(WorkTableScanState *node)
+static TupleTableSlot *
+ExecWorkTableScan(PlanState *pstate)
{
+ WorkTableScanState *node = castNode(WorkTableScanState, pstate);
+
/*
* On the first call, find the ancestor RecursiveUnion's state via the
* Param slot reserved for it. (We can't do this during node init because
@@ -144,6 +146,7 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
scanstate = makeNode(WorkTableScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecWorkTableScan;
scanstate->rustate = NULL; /* we'll set this later */
/*
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 59c28b709e6..60326f9d037 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -225,14 +225,31 @@ extern void EvalPlanQualBegin(EPQState *epqstate, EState *parentestate);
extern void EvalPlanQualEnd(EPQState *epqstate);
/*
- * prototypes from functions in execProcnode.c
+ * functions in execProcnode.c
*/
extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecProcNode(PlanState *node);
extern Node *MultiExecProcNode(PlanState *node);
extern void ExecEndNode(PlanState *node);
extern bool ExecShutdownNode(PlanState *node);
+
+/* ----------------------------------------------------------------
+ * ExecProcNode
+ *
+ * Execute the given node to return a(nother) tuple.
+ * ----------------------------------------------------------------
+ */
+#ifndef FRONTEND
+static inline TupleTableSlot *
+ExecProcNode(PlanState *node)
+{
+ if (node->chgParam != NULL) /* something changed? */
+ ExecReScan(node); /* let ReScan handle this */
+
+ return node->ExecProcNode(node);
+}
+#endif
+
/*
* prototypes from functions in execExpr.c
*/
diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h
index fa11ba93a6b..eff5af9c2a4 100644
--- a/src/include/executor/nodeAgg.h
+++ b/src/include/executor/nodeAgg.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern AggState *ExecInitAgg(Agg *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecAgg(AggState *node);
extern void ExecEndAgg(AggState *node);
extern void ExecReScanAgg(AggState *node);
diff --git a/src/include/executor/nodeAppend.h b/src/include/executor/nodeAppend.h
index ee0b6ad23dd..4e38a1380e2 100644
--- a/src/include/executor/nodeAppend.h
+++ b/src/include/executor/nodeAppend.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern AppendState *ExecInitAppend(Append *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecAppend(AppendState *node);
extern void ExecEndAppend(AppendState *node);
extern void ExecReScanAppend(AppendState *node);
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
index f477d1c7720..c77694cf22f 100644
--- a/src/include/executor/nodeBitmapHeapscan.h
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -18,7 +18,6 @@
#include "access/parallel.h"
extern BitmapHeapScanState *ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecBitmapHeapScan(BitmapHeapScanState *node);
extern void ExecEndBitmapHeapScan(BitmapHeapScanState *node);
extern void ExecReScanBitmapHeapScan(BitmapHeapScanState *node);
extern void ExecBitmapHeapEstimate(BitmapHeapScanState *node,
diff --git a/src/include/executor/nodeCtescan.h b/src/include/executor/nodeCtescan.h
index 397bdfdd1ce..d2fbcbd5868 100644
--- a/src/include/executor/nodeCtescan.h
+++ b/src/include/executor/nodeCtescan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern CteScanState *ExecInitCteScan(CteScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecCteScan(CteScanState *node);
extern void ExecEndCteScan(CteScanState *node);
extern void ExecReScanCteScan(CteScanState *node);
diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h
index e81bcf7f21c..a1cc63ae1f3 100644
--- a/src/include/executor/nodeCustom.h
+++ b/src/include/executor/nodeCustom.h
@@ -21,7 +21,6 @@
*/
extern CustomScanState *ExecInitCustomScan(CustomScan *custom_scan,
EState *estate, int eflags);
-extern TupleTableSlot *ExecCustomScan(CustomScanState *node);
extern void ExecEndCustomScan(CustomScanState *node);
extern void ExecReScanCustomScan(CustomScanState *node);
diff --git a/src/include/executor/nodeForeignscan.h b/src/include/executor/nodeForeignscan.h
index 3ff4ecd8c93..0b662597d8f 100644
--- a/src/include/executor/nodeForeignscan.h
+++ b/src/include/executor/nodeForeignscan.h
@@ -18,7 +18,6 @@
#include "nodes/execnodes.h"
extern ForeignScanState *ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecForeignScan(ForeignScanState *node);
extern void ExecEndForeignScan(ForeignScanState *node);
extern void ExecReScanForeignScan(ForeignScanState *node);
diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h
index 5e830ebdeae..aaa9d8c3166 100644
--- a/src/include/executor/nodeFunctionscan.h
+++ b/src/include/executor/nodeFunctionscan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecFunctionScan(FunctionScanState *node);
extern void ExecEndFunctionScan(FunctionScanState *node);
extern void ExecReScanFunctionScan(FunctionScanState *node);
diff --git a/src/include/executor/nodeGather.h b/src/include/executor/nodeGather.h
index b0006934d4d..189bd70041f 100644
--- a/src/include/executor/nodeGather.h
+++ b/src/include/executor/nodeGather.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern GatherState *ExecInitGather(Gather *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecGather(GatherState *node);
extern void ExecEndGather(GatherState *node);
extern void ExecShutdownGather(GatherState *node);
extern void ExecReScanGather(GatherState *node);
diff --git a/src/include/executor/nodeGatherMerge.h b/src/include/executor/nodeGatherMerge.h
index 14b31a086c3..0154d733129 100644
--- a/src/include/executor/nodeGatherMerge.h
+++ b/src/include/executor/nodeGatherMerge.h
@@ -19,7 +19,6 @@
extern GatherMergeState *ExecInitGatherMerge(GatherMerge *node,
EState *estate,
int eflags);
-extern TupleTableSlot *ExecGatherMerge(GatherMergeState *node);
extern void ExecEndGatherMerge(GatherMergeState *node);
extern void ExecReScanGatherMerge(GatherMergeState *node);
extern void ExecShutdownGatherMerge(GatherMergeState *node);
diff --git a/src/include/executor/nodeGroup.h b/src/include/executor/nodeGroup.h
index 7358b61707c..b0d7e312c98 100644
--- a/src/include/executor/nodeGroup.h
+++ b/src/include/executor/nodeGroup.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern GroupState *ExecInitGroup(Group *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecGroup(GroupState *node);
extern void ExecEndGroup(GroupState *node);
extern void ExecReScanGroup(GroupState *node);
diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h
index 8052f27d0b1..3ae556fb6c5 100644
--- a/src/include/executor/nodeHash.h
+++ b/src/include/executor/nodeHash.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern HashState *ExecInitHash(Hash *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecHash(HashState *node);
extern Node *MultiExecHash(HashState *node);
extern void ExecEndHash(HashState *node);
extern void ExecReScanHash(HashState *node);
diff --git a/src/include/executor/nodeHashjoin.h b/src/include/executor/nodeHashjoin.h
index 541c81edc71..7469bfbf60c 100644
--- a/src/include/executor/nodeHashjoin.h
+++ b/src/include/executor/nodeHashjoin.h
@@ -18,7 +18,6 @@
#include "storage/buffile.h"
extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecHashJoin(HashJoinState *node);
extern void ExecEndHashJoin(HashJoinState *node);
extern void ExecReScanHashJoin(HashJoinState *node);
diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h
index cf227daae04..c8a709c26ed 100644
--- a/src/include/executor/nodeIndexonlyscan.h
+++ b/src/include/executor/nodeIndexonlyscan.h
@@ -18,7 +18,6 @@
#include "access/parallel.h"
extern IndexOnlyScanState *ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecIndexOnlyScan(IndexOnlyScanState *node);
extern void ExecEndIndexOnlyScan(IndexOnlyScanState *node);
extern void ExecIndexOnlyMarkPos(IndexOnlyScanState *node);
extern void ExecIndexOnlyRestrPos(IndexOnlyScanState *node);
diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h
index 0118234eca7..1668e347eef 100644
--- a/src/include/executor/nodeIndexscan.h
+++ b/src/include/executor/nodeIndexscan.h
@@ -18,7 +18,6 @@
#include "nodes/execnodes.h"
extern IndexScanState *ExecInitIndexScan(IndexScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecIndexScan(IndexScanState *node);
extern void ExecEndIndexScan(IndexScanState *node);
extern void ExecIndexMarkPos(IndexScanState *node);
extern void ExecIndexRestrPos(IndexScanState *node);
diff --git a/src/include/executor/nodeLimit.h b/src/include/executor/nodeLimit.h
index 7bb20d99786..db65b5524cd 100644
--- a/src/include/executor/nodeLimit.h
+++ b/src/include/executor/nodeLimit.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern LimitState *ExecInitLimit(Limit *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecLimit(LimitState *node);
extern void ExecEndLimit(LimitState *node);
extern void ExecReScanLimit(LimitState *node);
diff --git a/src/include/executor/nodeLockRows.h b/src/include/executor/nodeLockRows.h
index 6b90756e4c0..c9d05b87f1a 100644
--- a/src/include/executor/nodeLockRows.h
+++ b/src/include/executor/nodeLockRows.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern LockRowsState *ExecInitLockRows(LockRows *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecLockRows(LockRowsState *node);
extern void ExecEndLockRows(LockRowsState *node);
extern void ExecReScanLockRows(LockRowsState *node);
diff --git a/src/include/executor/nodeMaterial.h b/src/include/executor/nodeMaterial.h
index f69abbca82b..4b3c2578c9c 100644
--- a/src/include/executor/nodeMaterial.h
+++ b/src/include/executor/nodeMaterial.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern MaterialState *ExecInitMaterial(Material *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecMaterial(MaterialState *node);
extern void ExecEndMaterial(MaterialState *node);
extern void ExecMaterialMarkPos(MaterialState *node);
extern void ExecMaterialRestrPos(MaterialState *node);
diff --git a/src/include/executor/nodeMergeAppend.h b/src/include/executor/nodeMergeAppend.h
index 3cc6ef549b3..a0ccbae9651 100644
--- a/src/include/executor/nodeMergeAppend.h
+++ b/src/include/executor/nodeMergeAppend.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern MergeAppendState *ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecMergeAppend(MergeAppendState *node);
extern void ExecEndMergeAppend(MergeAppendState *node);
extern void ExecReScanMergeAppend(MergeAppendState *node);
diff --git a/src/include/executor/nodeMergejoin.h b/src/include/executor/nodeMergejoin.h
index 32df25ae8b3..d20e41505db 100644
--- a/src/include/executor/nodeMergejoin.h
+++ b/src/include/executor/nodeMergejoin.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecMergeJoin(MergeJoinState *node);
extern void ExecEndMergeJoin(MergeJoinState *node);
extern void ExecReScanMergeJoin(MergeJoinState *node);
diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h
index 5a406f236d4..a2e7af98de8 100644
--- a/src/include/executor/nodeModifyTable.h
+++ b/src/include/executor/nodeModifyTable.h
@@ -16,7 +16,6 @@
#include "nodes/execnodes.h"
extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecModifyTable(ModifyTableState *node);
extern void ExecEndModifyTable(ModifyTableState *node);
extern void ExecReScanModifyTable(ModifyTableState *node);
diff --git a/src/include/executor/nodeNamedtuplestorescan.h b/src/include/executor/nodeNamedtuplestorescan.h
index 7f72fbe98af..395d978f624 100644
--- a/src/include/executor/nodeNamedtuplestorescan.h
+++ b/src/include/executor/nodeNamedtuplestorescan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern NamedTuplestoreScanState *ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecNamedTuplestoreScan(NamedTuplestoreScanState *node);
extern void ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node);
extern void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node);
diff --git a/src/include/executor/nodeNestloop.h b/src/include/executor/nodeNestloop.h
index 8e0fcc1922c..0d6486cc57a 100644
--- a/src/include/executor/nodeNestloop.h
+++ b/src/include/executor/nodeNestloop.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecNestLoop(NestLoopState *node);
extern void ExecEndNestLoop(NestLoopState *node);
extern void ExecReScanNestLoop(NestLoopState *node);
diff --git a/src/include/executor/nodeProjectSet.h b/src/include/executor/nodeProjectSet.h
index 2f6999e8db3..a0b0521f8d2 100644
--- a/src/include/executor/nodeProjectSet.h
+++ b/src/include/executor/nodeProjectSet.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern ProjectSetState *ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecProjectSet(ProjectSetState *node);
extern void ExecEndProjectSet(ProjectSetState *node);
extern void ExecReScanProjectSet(ProjectSetState *node);
diff --git a/src/include/executor/nodeRecursiveunion.h b/src/include/executor/nodeRecursiveunion.h
index f0eba05bee9..e6ce1b47831 100644
--- a/src/include/executor/nodeRecursiveunion.h
+++ b/src/include/executor/nodeRecursiveunion.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern RecursiveUnionState *ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecRecursiveUnion(RecursiveUnionState *node);
extern void ExecEndRecursiveUnion(RecursiveUnionState *node);
extern void ExecReScanRecursiveUnion(RecursiveUnionState *node);
diff --git a/src/include/executor/nodeResult.h b/src/include/executor/nodeResult.h
index 61d3cb2cc2e..20e0063410e 100644
--- a/src/include/executor/nodeResult.h
+++ b/src/include/executor/nodeResult.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern ResultState *ExecInitResult(Result *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecResult(ResultState *node);
extern void ExecEndResult(ResultState *node);
extern void ExecResultMarkPos(ResultState *node);
extern void ExecResultRestrPos(ResultState *node);
diff --git a/src/include/executor/nodeSamplescan.h b/src/include/executor/nodeSamplescan.h
index ed06e77e4ee..607bbd94125 100644
--- a/src/include/executor/nodeSamplescan.h
+++ b/src/include/executor/nodeSamplescan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern SampleScanState *ExecInitSampleScan(SampleScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecSampleScan(SampleScanState *node);
extern void ExecEndSampleScan(SampleScanState *node);
extern void ExecReScanSampleScan(SampleScanState *node);
diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h
index 06e0686b0b7..0fba79f8de6 100644
--- a/src/include/executor/nodeSeqscan.h
+++ b/src/include/executor/nodeSeqscan.h
@@ -18,7 +18,6 @@
#include "nodes/execnodes.h"
extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecSeqScan(SeqScanState *node);
extern void ExecEndSeqScan(SeqScanState *node);
extern void ExecReScanSeqScan(SeqScanState *node);
diff --git a/src/include/executor/nodeSetOp.h b/src/include/executor/nodeSetOp.h
index af859771838..c15f9450468 100644
--- a/src/include/executor/nodeSetOp.h
+++ b/src/include/executor/nodeSetOp.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecSetOp(SetOpState *node);
extern void ExecEndSetOp(SetOpState *node);
extern void ExecReScanSetOp(SetOpState *node);
diff --git a/src/include/executor/nodeSort.h b/src/include/executor/nodeSort.h
index 1d2b7130b32..ed0e9dbb53e 100644
--- a/src/include/executor/nodeSort.h
+++ b/src/include/executor/nodeSort.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern SortState *ExecInitSort(Sort *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecSort(SortState *node);
extern void ExecEndSort(SortState *node);
extern void ExecSortMarkPos(SortState *node);
extern void ExecSortRestrPos(SortState *node);
diff --git a/src/include/executor/nodeSubqueryscan.h b/src/include/executor/nodeSubqueryscan.h
index c852e2947f9..710e050285c 100644
--- a/src/include/executor/nodeSubqueryscan.h
+++ b/src/include/executor/nodeSubqueryscan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecSubqueryScan(SubqueryScanState *node);
extern void ExecEndSubqueryScan(SubqueryScanState *node);
extern void ExecReScanSubqueryScan(SubqueryScanState *node);
diff --git a/src/include/executor/nodeTableFuncscan.h b/src/include/executor/nodeTableFuncscan.h
index c58156e99c2..c4672c0ac04 100644
--- a/src/include/executor/nodeTableFuncscan.h
+++ b/src/include/executor/nodeTableFuncscan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern TableFuncScanState *ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecTableFuncScan(TableFuncScanState *node);
extern void ExecEndTableFuncScan(TableFuncScanState *node);
extern void ExecReScanTableFuncScan(TableFuncScanState *node);
diff --git a/src/include/executor/nodeTidscan.h b/src/include/executor/nodeTidscan.h
index d07ed7c8641..e68aaf38290 100644
--- a/src/include/executor/nodeTidscan.h
+++ b/src/include/executor/nodeTidscan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern TidScanState *ExecInitTidScan(TidScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecTidScan(TidScanState *node);
extern void ExecEndTidScan(TidScanState *node);
extern void ExecReScanTidScan(TidScanState *node);
diff --git a/src/include/executor/nodeUnique.h b/src/include/executor/nodeUnique.h
index 3d0ac9dde16..008774ae0f0 100644
--- a/src/include/executor/nodeUnique.h
+++ b/src/include/executor/nodeUnique.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern UniqueState *ExecInitUnique(Unique *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecUnique(UniqueState *node);
extern void ExecEndUnique(UniqueState *node);
extern void ExecReScanUnique(UniqueState *node);
diff --git a/src/include/executor/nodeValuesscan.h b/src/include/executor/nodeValuesscan.h
index c28bb1acce6..772a5e9705d 100644
--- a/src/include/executor/nodeValuesscan.h
+++ b/src/include/executor/nodeValuesscan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern ValuesScanState *ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecValuesScan(ValuesScanState *node);
extern void ExecEndValuesScan(ValuesScanState *node);
extern void ExecReScanValuesScan(ValuesScanState *node);
diff --git a/src/include/executor/nodeWindowAgg.h b/src/include/executor/nodeWindowAgg.h
index db1ad60677a..1c177309ae6 100644
--- a/src/include/executor/nodeWindowAgg.h
+++ b/src/include/executor/nodeWindowAgg.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern WindowAggState *ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecWindowAgg(WindowAggState *node);
extern void ExecEndWindowAgg(WindowAggState *node);
extern void ExecReScanWindowAgg(WindowAggState *node);
diff --git a/src/include/executor/nodeWorktablescan.h b/src/include/executor/nodeWorktablescan.h
index c222d9f6b4d..df05e75111b 100644
--- a/src/include/executor/nodeWorktablescan.h
+++ b/src/include/executor/nodeWorktablescan.h
@@ -17,7 +17,6 @@
#include "nodes/execnodes.h"
extern WorkTableScanState *ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags);
-extern TupleTableSlot *ExecWorkTableScan(WorkTableScanState *node);
extern void ExecEndWorkTableScan(WorkTableScanState *node);
extern void ExecReScanWorkTableScan(WorkTableScanState *node);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 85fac8ab91b..35c28a61431 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -818,6 +818,18 @@ typedef struct DomainConstraintState
* ----------------------------------------------------------------
*/
+struct PlanState;
+
+/* ----------------
+ * ExecProcNodeMtd
+ *
+ * This is the method called by ExecProcNode to return the next tuple
+ * from an executor node. It returns NULL, or an empty TupleTableSlot,
+ * if no more tuples are available.
+ * ----------------
+ */
+typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);
+
/* ----------------
* PlanState node
*
@@ -835,6 +847,10 @@ typedef struct PlanState
* nodes point to one EState for the whole
* top-level plan */
+ ExecProcNodeMtd ExecProcNode; /* function to return next tuple */
+ ExecProcNodeMtd ExecProcNodeReal; /* actual function, if above is a
+ * wrapper */
+
Instrumentation *instrument; /* Optional runtime stats for this node */
WorkerInstrumentation *worker_instrument; /* per-worker instrumentation */