aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/execTuples.c73
-rw-r--r--src/backend/executor/execUtils.c8
-rw-r--r--src/backend/executor/nodeAgg.c2
-rw-r--r--src/backend/executor/nodeAppend.c2
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c7
-rw-r--r--src/backend/executor/nodeCtescan.c10
-rw-r--r--src/backend/executor/nodeCustom.c2
-rw-r--r--src/backend/executor/nodeForeignscan.c5
-rw-r--r--src/backend/executor/nodeFunctionscan.c8
-rw-r--r--src/backend/executor/nodeGather.c7
-rw-r--r--src/backend/executor/nodeGatherMerge.c7
-rw-r--r--src/backend/executor/nodeGroup.c2
-rw-r--r--src/backend/executor/nodeHash.c2
-rw-r--r--src/backend/executor/nodeHashjoin.c2
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c10
-rw-r--r--src/backend/executor/nodeIndexscan.c7
-rw-r--r--src/backend/executor/nodeLimit.c5
-rw-r--r--src/backend/executor/nodeLockRows.c5
-rw-r--r--src/backend/executor/nodeMaterial.c2
-rw-r--r--src/backend/executor/nodeMergeAppend.c4
-rw-r--r--src/backend/executor/nodeMergejoin.c2
-rw-r--r--src/backend/executor/nodeModifyTable.c7
-rw-r--r--src/backend/executor/nodeNamedtuplestorescan.c21
-rw-r--r--src/backend/executor/nodeNestloop.c2
-rw-r--r--src/backend/executor/nodeProjectSet.c2
-rw-r--r--src/backend/executor/nodeRecursiveunion.c7
-rw-r--r--src/backend/executor/nodeResult.c2
-rw-r--r--src/backend/executor/nodeSamplescan.c8
-rw-r--r--src/backend/executor/nodeSeqscan.c7
-rw-r--r--src/backend/executor/nodeSetOp.c2
-rw-r--r--src/backend/executor/nodeSort.c2
-rw-r--r--src/backend/executor/nodeSubqueryscan.c9
-rw-r--r--src/backend/executor/nodeTableFuncscan.c10
-rw-r--r--src/backend/executor/nodeTidscan.c7
-rw-r--r--src/backend/executor/nodeUnique.c2
-rw-r--r--src/backend/executor/nodeValuesscan.c10
-rw-r--r--src/backend/executor/nodeWindowAgg.c2
-rw-r--r--src/backend/executor/nodeWorktablescan.c8
-rw-r--r--src/include/executor/executor.h4
-rw-r--r--src/include/nodes/execnodes.h1
40 files changed, 168 insertions, 117 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 015752a93f1..eba52dc928f 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -19,18 +19,22 @@
*
* At ExecutorStart()
* ----------------
- * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
- * ExecInitResultTupleSlotTL() to construct TupleTableSlots
- * for the tuples returned by the access methods and the
- * tuples resulting from performing target list projections.
+
+ * - ExecInitSeqScan() calls ExecInitScanTupleSlot() to construct a
+ * TupleTableSlots for the tuples returned by the access method, and
+ * ExecInitResultTypeTL() to define the node's return
+ * type. ExecAssignScanProjectionInfo() will, if necessary, create
+ * another TupleTableSlot for the tuples resulting from performing
+ * target list projections.
*
* During ExecutorRun()
* ----------------
* - SeqNext() calls ExecStoreBufferHeapTuple() to place the tuple
- * returned by the access methods into the scan tuple slot.
+ * returned by the access method into the scan tuple slot.
*
- * - ExecSeqScan() calls ExecStoreHeapTuple() to take the result
- * tuple from ExecProject() and place it into the result tuple slot.
+ * - ExecSeqScan() (via ExecScan), if necessary, calls ExecProject(),
+ * putting the result of the projection in the result tuple slot. If
+ * not necessary, it directly returns the slot returned by SeqNext().
*
* - ExecutePlan() calls the output function.
*
@@ -902,23 +906,14 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
* ----------------------------------------------------------------
*/
-/* --------------------------------
- * ExecInit{Result,Scan,Extra}TupleSlot[TL]
- *
- * These are convenience routines to initialize the specified slot
- * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
- * is used for initializing special-purpose slots.
- * --------------------------------
- */
-
/* ----------------
- * ExecInitResultTupleSlotTL
+ * ExecInitResultTypeTL
*
- * Initialize result tuple slot, using the plan node's targetlist.
+ * Initialize result type, using the plan node's targetlist.
* ----------------
*/
void
-ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
+ExecInitResultTypeTL(PlanState *planstate)
{
bool hasoid;
TupleDesc tupDesc;
@@ -934,8 +929,46 @@ ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
}
tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
+ planstate->ps_ResultTupleDesc = tupDesc;
+}
- planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable, tupDesc);
+/* --------------------------------
+ * ExecInit{Result,Scan,Extra}TupleSlot[TL]
+ *
+ * These are convenience routines to initialize the specified slot
+ * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
+ * is used for initializing special-purpose slots.
+ * --------------------------------
+ */
+
+/* ----------------
+ * ExecInitResultTupleSlotTL
+ *
+ * Initialize result tuple slot, using the tuple descriptor previously
+ * computed with ExecInitResultTypeTL().
+ * ----------------
+ */
+void
+ExecInitResultSlot(PlanState *planstate)
+{
+ TupleTableSlot *slot;
+
+ slot = ExecAllocTableSlot(&planstate->state->es_tupleTable,
+ planstate->ps_ResultTupleDesc);
+ planstate->ps_ResultTupleSlot = slot;
+}
+
+/* ----------------
+ * ExecInitResultTupleSlotTL
+ *
+ * Initialize result tuple slot, using the plan node's targetlist.
+ * ----------------
+ */
+void
+ExecInitResultTupleSlotTL(PlanState *planstate)
+{
+ ExecInitResultTypeTL(planstate);
+ ExecInitResultSlot(planstate);
}
/* ----------------
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 71c6b5dc0a8..f9e7bb479f1 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -451,9 +451,7 @@ ExecAssignExprContext(EState *estate, PlanState *planstate)
TupleDesc
ExecGetResultType(PlanState *planstate)
{
- TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
-
- return slot->tts_tupleDescriptor;
+ return planstate->ps_ResultTupleDesc;
}
@@ -496,7 +494,11 @@ ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
inputDesc))
planstate->ps_ProjInfo = NULL;
else
+ {
+ if (!planstate->ps_ResultTupleSlot)
+ ExecInitResultSlot(planstate);
ExecAssignProjectionInfo(planstate, inputDesc);
+ }
}
static bool
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 2413f1f87db..85f1ec7140f 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -2219,7 +2219,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
/*
* Initialize result type, slot and projection.
*/
- ExecInitResultTupleSlotTL(estate, &aggstate->ss.ps);
+ ExecInitResultTupleSlotTL(&aggstate->ss.ps);
ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
/*
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index a16b6da4740..94a17c7c67c 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -196,7 +196,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
/*
* Initialize result tuple type and slot.
*/
- ExecInitResultTupleSlotTL(estate, &appendstate->ps);
+ ExecInitResultTupleSlotTL(&appendstate->ps);
appendplanstates = (PlanState **) palloc(nplans *
sizeof(PlanState *));
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 304ef07f2cc..c153d74f411 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -800,7 +800,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
/*
* clear out tuple table slots
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
@@ -916,9 +917,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index 24700dd3965..017b8772775 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -263,9 +263,9 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
ExecGetResultType(scanstate->cteplanstate));
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
@@ -294,7 +294,8 @@ ExecEndCteScan(CteScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
@@ -318,7 +319,8 @@ ExecReScanCteScan(CteScanState *node)
{
Tuplestorestate *tuplestorestate = node->leader->cte_table;
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecScanReScan(&node->ss);
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index 7972d5a952a..ab3e34790e8 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -87,7 +87,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &css->ss.ps);
+ ExecInitResultTupleSlotTL(&css->ss.ps);
ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
/* initialize child expressions */
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 2ec7fcb9621..5d2cd0ed717 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -198,7 +198,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno);
/*
@@ -256,7 +256,8 @@ ExecEndForeignScan(ForeignScanState *node)
ExecFreeExprContext(&node->ss.ps);
/* clean out the tuple table */
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
}
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index fb7c9f67875..0596adbb2f1 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -487,7 +487,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
@@ -529,7 +529,8 @@ ExecEndFunctionScan(FunctionScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
@@ -563,7 +564,8 @@ ExecReScanFunctionScan(FunctionScanState *node)
int i;
Bitmapset *chgparam = node->ss.ps.chgParam;
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
for (i = 0; i < node->nfuncs; i++)
{
FunctionScanPerFuncState *fs = &node->funcstates[i];
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index ad16c783bd8..afddb0a0394 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -92,9 +92,9 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
tupDesc = ExecGetResultType(outerPlanState(gatherstate));
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &gatherstate->ps);
+ ExecInitResultTypeTL(&gatherstate->ps);
ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR);
/*
@@ -231,7 +231,8 @@ ExecEndGather(GatherState *node)
ExecEndNode(outerPlanState(node)); /* let children clean up first */
ExecShutdownGather(node);
ExecFreeExprContext(&node->ps);
- ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ if (node->ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
}
/*
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 6362e4497a0..7ae067f9ebf 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -117,9 +117,9 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
gm_state->tupDesc = tupDesc;
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &gm_state->ps);
+ ExecInitResultTypeTL(&gm_state->ps);
ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR);
/*
@@ -272,7 +272,8 @@ ExecEndGatherMerge(GatherMergeState *node)
ExecEndNode(outerPlanState(node)); /* let children clean up first */
ExecShutdownGatherMerge(node);
ExecFreeExprContext(&node->ps);
- ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ if (node->ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index 2ea80e817d4..9c1e51bc954 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -193,7 +193,7 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &grpstate->ss.ps);
+ ExecInitResultTupleSlotTL(&grpstate->ss.ps);
ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
/*
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 6ffaa751f23..a9f812d66b8 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -382,7 +382,7 @@ ExecInitHash(Hash *node, EState *estate, int eflags)
* initialize our result slot and type. No need to build projection
* because this node doesn't do projections.
*/
- ExecInitResultTupleSlotTL(estate, &hashstate->ps);
+ ExecInitResultTupleSlotTL(&hashstate->ps);
hashstate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index d017bbfbd33..08a8bb3426c 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -644,7 +644,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &hjstate->js.ps);
+ ExecInitResultTupleSlotTL(&hjstate->js.ps);
ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
/*
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index daedf342f72..865a056c027 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -399,7 +399,8 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node)
/*
* clear out tuple table slots
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
@@ -529,11 +530,10 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc);
/*
- * Initialize result slot, type and projection info. The node's
- * targetlist will contain Vars with varno = INDEX_VAR, referencing the
- * scan tuple.
+ * Initialize result type and projection info. The node's targetlist will
+ * contain Vars with varno = INDEX_VAR, referencing the scan tuple.
*/
- ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
+ ExecInitResultTypeTL(&indexstate->ss.ps);
ExecAssignScanProjectionInfoWithVarno(&indexstate->ss, INDEX_VAR);
/*
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index ba7821b0e2b..8593c0e3050 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -822,7 +822,8 @@ ExecEndIndexScan(IndexScanState *node)
/*
* clear out tuple table slots
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
@@ -947,9 +948,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
RelationGetDescr(currentRelation));
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
+ ExecInitResultTypeTL(&indexstate->ss.ps);
ExecAssignScanProjectionInfo(&indexstate->ss);
/*
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index bb28cf7d1db..f0b68191400 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -376,10 +376,9 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
(PlanState *) limitstate);
/*
- * Initialize result slot and type. (XXX not actually used, but upper
- * nodes access it to get this node's result tupledesc...)
+ * Initialize result type.
*/
- ExecInitResultTupleSlotTL(estate, &limitstate->ps);
+ ExecInitResultTypeTL(&limitstate->ps);
/*
* limit nodes do no projections, so initialize projection info for this
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index 6db345ae7ac..961798cecb3 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -381,10 +381,9 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
*/
/*
- * Tuple table initialization (XXX not actually used, but upper nodes
- * access it to get this node's result tupledesc...)
+ * Initialize result type.
*/
- ExecInitResultTupleSlotTL(estate, &lrstate->ps);
+ ExecInitResultTypeTL(&lrstate->ps);
/*
* then initialize outer plan
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 8c2e57dbd07..4ede428f908 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -223,7 +223,7 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
*
* material nodes only return tuples from their materialized relation.
*/
- ExecInitResultTupleSlotTL(estate, &matstate->ss.ps);
+ ExecInitResultTupleSlotTL(&matstate->ss.ps);
matstate->ss.ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index fde369d6220..dbed667d164 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -165,9 +165,9 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
* Miscellaneous initialization
*
* MergeAppend nodes do have Result slots, which hold pointers to tuples,
- * so we have to initialize them.
+ * so we have to initialize them. FIXME
*/
- ExecInitResultTupleSlotTL(estate, &mergestate->ps);
+ ExecInitResultTupleSlotTL(&mergestate->ps);
/*
* call ExecInitNode on each of the valid plans to be executed and save
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 5e52b90c007..9c978313318 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -1512,7 +1512,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &mergestate->js.ps);
+ ExecInitResultTupleSlotTL(&mergestate->js.ps);
ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
/*
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 528f58717e2..e2836b75ff3 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2407,7 +2407,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
/* Set up a slot for the output of the RETURNING projection(s) */
- ExecInitResultTupleSlotTL(estate, &mtstate->ps);
+ ExecInitResultTupleSlotTL(&mtstate->ps);
slot = mtstate->ps.ps_ResultTupleSlot;
/* Need an econtext too */
@@ -2437,7 +2437,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* expects one (maybe should change that?).
*/
mtstate->ps.plan->targetlist = NIL;
- ExecInitResultTupleSlotTL(estate, &mtstate->ps);
+ ExecInitResultTypeTL(&mtstate->ps);
mtstate->ps.ps_ExprContext = NULL;
}
@@ -2716,7 +2716,8 @@ ExecEndModifyTable(ModifyTableState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ if (node->ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
/*
* Terminate EPQ execution if active
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
index b260ad25948..cf1b7b4f872 100644
--- a/src/backend/executor/nodeNamedtuplestorescan.c
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -135,22 +135,21 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * Tuple table and result type initialization. The scan tuple type is
- * specified for the tuplestore.
+ * The scan tuple type is specified for the tuplestore.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc);
/*
- * initialize child expressions
+ * Initialize result type and projection.
*/
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
/*
- * Initialize projection.
+ * initialize child expressions
*/
- ExecAssignScanProjectionInfo(&scanstate->ss);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
return scanstate;
}
@@ -172,7 +171,8 @@ ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
}
@@ -187,7 +187,8 @@ ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
{
Tuplestorestate *tuplestorestate = node->relation;
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecScanReScan(&node->ss);
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 9ae9863226c..8dbec685eb1 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -304,7 +304,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &nlstate->js.ps);
+ ExecInitResultTupleSlotTL(&nlstate->js.ps);
ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
/*
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 6d6ed38ceeb..e4dd4142177 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -256,7 +256,7 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
/*
* tuple table and result type initialization
*/
- ExecInitResultTupleSlotTL(estate, &state->ps);
+ ExecInitResultTupleSlotTL(&state->ps);
/* Create workspace for per-tlist-entry expr state & SRF-is-done state */
state->nelems = list_length(node->plan.targetlist);
diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c
index 6b3ea5afb31..2d26cec8315 100644
--- a/src/backend/executor/nodeRecursiveunion.c
+++ b/src/backend/executor/nodeRecursiveunion.c
@@ -229,7 +229,7 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags)
* RecursiveUnion nodes still have Result slots, which hold pointers to
* tuples, so we have to initialize them.
*/
- ExecInitResultTupleSlotTL(estate, &rustate->ps);
+ ExecInitResultTypeTL(&rustate->ps);
/*
* Initialize result tuple type. (Note: we have to set up the result type
@@ -280,11 +280,6 @@ ExecEndRecursiveUnion(RecursiveUnionState *node)
MemoryContextDelete(node->tableContext);
/*
- * clean out the upper tuple table
- */
- ExecClearTuple(node->ps.ps_ResultTupleSlot);
-
- /*
* close down subplans
*/
ExecEndNode(outerPlanState(node));
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index e4418a29bba..2bbb2e78848 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -217,7 +217,7 @@ ExecInitResult(Result *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &resstate->ps);
+ ExecInitResultTupleSlotTL(&resstate->ps);
ExecAssignProjectionInfo(&resstate->ps, NULL);
/*
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index f01fc3b62a0..cfa26535d7b 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -149,10 +149,9 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
RelationGetDescr(scanstate->ss.ss_currentRelation));
/*
- * Initialize result slot, type and projection. tuple table and result
- * tuple initialization
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
@@ -211,7 +210,8 @@ ExecEndSampleScan(SampleScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 79729dbbecb..b4bea67610f 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -175,9 +175,9 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
RelationGetDescr(scanstate->ss.ss_currentRelation));
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
@@ -213,7 +213,8 @@ ExecEndSeqScan(SeqScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 3535b19c41d..46bf77775c4 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -532,7 +532,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
* Initialize result slot and type. Setop nodes do no projections, so
* initialize projection info for this node appropriately.
*/
- ExecInitResultTupleSlotTL(estate, &setopstate->ps);
+ ExecInitResultTupleSlotTL(&setopstate->ps);
setopstate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index 0d2acb665af..5492cd45579 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -217,7 +217,7 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
* Initialize return slot and type. No need to initialize projection info
* because this node doesn't do projections.
*/
- ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps);
+ ExecInitResultTupleSlotTL(&sortstate->ss.ps);
sortstate->ss.ps.ps_ProjInfo = NULL;
SO1_printf("ExecInitSort: %s\n",
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index fa618847851..b84c6892d50 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -126,15 +126,15 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
/*
- * Initialize scan slot and type (needed by ExecInitResultTupleSlotTL)
+ * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
*/
ExecInitScanTupleSlot(estate, &subquerystate->ss,
ExecGetResultType(subquerystate->subplan));
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &subquerystate->ss.ps);
+ ExecInitResultTypeTL(&subquerystate->ss.ps);
ExecAssignScanProjectionInfo(&subquerystate->ss);
/*
@@ -163,7 +163,8 @@ ExecEndSubqueryScan(SubqueryScanState *node)
/*
* clean out the upper tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index a9fd3fda6be..b0c94d7e063 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -150,9 +150,9 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
@@ -221,7 +221,8 @@ ExecEndTableFuncScan(TableFuncScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
@@ -243,7 +244,8 @@ ExecReScanTableFuncScan(TableFuncScanState *node)
{
Bitmapset *chgparam = node->ss.ps.chgParam;
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecScanReScan(&node->ss);
/*
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index d21d6553e42..bc859e3d516 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -487,7 +487,8 @@ ExecEndTidScan(TidScanState *node)
/*
* clear out tuple table slots
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
}
@@ -545,9 +546,9 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
RelationGetDescr(currentRelation));
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &tidstate->ss.ps);
+ ExecInitResultTypeTL(&tidstate->ss.ps);
ExecAssignScanProjectionInfo(&tidstate->ss);
/*
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index 05d65330a0e..c791f89b48c 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -141,7 +141,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
* Initialize result slot and type. Unique nodes do no projections, so
* initialize projection info for this node appropriately.
*/
- ExecInitResultTupleSlotTL(estate, &uniquestate->ps);
+ ExecInitResultTupleSlotTL(&uniquestate->ps);
uniquestate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index f76999d40ae..fa49d0470fc 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -264,9 +264,9 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
/*
- * Initialize result slot, type and projection.
+ * Initialize result type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
@@ -312,7 +312,8 @@ ExecEndValuesScan(ValuesScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
}
@@ -325,7 +326,8 @@ ExecEndValuesScan(ValuesScanState *node)
void
ExecReScanValuesScan(ValuesScanState *node)
{
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecScanReScan(&node->ss);
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 729c376d86b..6e597e82856 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2349,7 +2349,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
/*
* Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlotTL(estate, &winstate->ss.ps);
+ ExecInitResultTupleSlotTL(&winstate->ss.ps);
ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
/* Set up data for comparing tuples */
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
index 2ff9a215b12..1ce8ae9f026 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -159,7 +159,7 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
/*
* tuple table initialization
*/
- ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitResultTypeTL(&scanstate->ss.ps);
ExecInitScanTupleSlot(estate, &scanstate->ss, NULL);
/*
@@ -193,7 +193,8 @@ ExecEndWorkTableScan(WorkTableScanState *node)
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
}
@@ -206,7 +207,8 @@ ExecEndWorkTableScan(WorkTableScanState *node)
void
ExecReScanWorkTableScan(WorkTableScanState *node)
{
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecScanReScan(&node->ss);
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index edf538365be..84412657845 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -429,7 +429,9 @@ extern void ExecScanReScan(ScanState *node);
/*
* prototypes from functions in execTuples.c
*/
-extern void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate);
+extern void ExecInitResultTypeTL(PlanState *planstate);
+extern void ExecInitResultSlot(PlanState *planstate);
+extern void ExecInitResultTupleSlotTL(PlanState *planstate);
extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc);
extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
TupleDesc tupleDesc);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 880a03e4e4b..18544566f70 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -966,6 +966,7 @@ typedef struct PlanState
/*
* Other run-time state needed by most if not all node types.
*/
+ TupleDesc ps_ResultTupleDesc; /* node's return type */
TupleTableSlot *ps_ResultTupleSlot; /* slot for my result tuples */
ExprContext *ps_ExprContext; /* node's expression-evaluation context */
ProjectionInfo *ps_ProjInfo; /* info for doing tuple projection */