aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/copy.c5
-rw-r--r--src/backend/commands/trigger.c6
-rw-r--r--src/backend/executor/README2
-rw-r--r--src/backend/executor/execExpr.c2
-rw-r--r--src/backend/executor/execMain.c2
-rw-r--r--src/backend/executor/execPartition.c4
-rw-r--r--src/backend/executor/execScan.c2
-rw-r--r--src/backend/executor/execTuples.c114
-rw-r--r--src/backend/executor/execUtils.c62
-rw-r--r--src/backend/executor/nodeAgg.c62
-rw-r--r--src/backend/executor/nodeAppend.c18
-rw-r--r--src/backend/executor/nodeBitmapAnd.c14
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c56
-rw-r--r--src/backend/executor/nodeBitmapIndexscan.c18
-rw-r--r--src/backend/executor/nodeBitmapOr.c14
-rw-r--r--src/backend/executor/nodeCtescan.c26
-rw-r--r--src/backend/executor/nodeCustom.c20
-rw-r--r--src/backend/executor/nodeForeignscan.c30
-rw-r--r--src/backend/executor/nodeFunctionscan.c30
-rw-r--r--src/backend/executor/nodeGather.c31
-rw-r--r--src/backend/executor/nodeGatherMerge.c19
-rw-r--r--src/backend/executor/nodeGroup.c26
-rw-r--r--src/backend/executor/nodeHash.c23
-rw-r--r--src/backend/executor/nodeHashjoin.c49
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c34
-rw-r--r--src/backend/executor/nodeIndexscan.c45
-rw-r--r--src/backend/executor/nodeLimit.c18
-rw-r--r--src/backend/executor/nodeLockRows.c9
-rw-r--r--src/backend/executor/nodeMaterial.c22
-rw-r--r--src/backend/executor/nodeMergeAppend.c6
-rw-r--r--src/backend/executor/nodeMergejoin.c53
-rw-r--r--src/backend/executor/nodeModifyTable.c25
-rw-r--r--src/backend/executor/nodeNamedtuplestorescan.c21
-rw-r--r--src/backend/executor/nodeNestloop.c29
-rw-r--r--src/backend/executor/nodeProjectSet.c14
-rw-r--r--src/backend/executor/nodeRecursiveunion.c9
-rw-r--r--src/backend/executor/nodeResult.c25
-rw-r--r--src/backend/executor/nodeSamplescan.c70
-rw-r--r--src/backend/executor/nodeSeqscan.c56
-rw-r--r--src/backend/executor/nodeSetOp.c11
-rw-r--r--src/backend/executor/nodeSort.c18
-rw-r--r--src/backend/executor/nodeSubplan.c6
-rw-r--r--src/backend/executor/nodeSubqueryscan.c28
-rw-r--r--src/backend/executor/nodeTableFuncscan.c26
-rw-r--r--src/backend/executor/nodeTidscan.c29
-rw-r--r--src/backend/executor/nodeUnique.c11
-rw-r--r--src/backend/executor/nodeValuesscan.c25
-rw-r--r--src/backend/executor/nodeWindowAgg.c65
-rw-r--r--src/backend/executor/nodeWorktablescan.c16
-rw-r--r--src/backend/replication/logical/worker.c22
-rw-r--r--src/include/executor/executor.h11
-rw-r--r--src/include/executor/tuptable.h5
52 files changed, 566 insertions, 778 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index b3933df9aff..d5883c98d15 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2444,10 +2444,9 @@ CopyFrom(CopyState cstate)
estate->es_range_table = cstate->range_table;
/* Set up a tuple slot too */
- myslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(myslot, tupDesc);
+ myslot = ExecInitExtraTupleSlot(estate, tupDesc);
/* Triggers might need a slot as well */
- estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate);
+ estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
/* Prepare to catch AFTER triggers. */
AfterTriggerBeginQuery();
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 160d941c005..fffc0095a79 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -3251,7 +3251,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
if (estate->es_trig_oldtup_slot == NULL)
{
oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
- estate->es_trig_oldtup_slot = ExecInitExtraTupleSlot(estate);
+ estate->es_trig_oldtup_slot =
+ ExecInitExtraTupleSlot(estate, NULL);
MemoryContextSwitchTo(oldContext);
}
oldslot = estate->es_trig_oldtup_slot;
@@ -3264,7 +3265,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
if (estate->es_trig_newtup_slot == NULL)
{
oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
- estate->es_trig_newtup_slot = ExecInitExtraTupleSlot(estate);
+ estate->es_trig_newtup_slot =
+ ExecInitExtraTupleSlot(estate, NULL);
MemoryContextSwitchTo(oldContext);
}
newslot = estate->es_trig_newtup_slot;
diff --git a/src/backend/executor/README b/src/backend/executor/README
index b3e74aa1a54..0d7cd552eb6 100644
--- a/src/backend/executor/README
+++ b/src/backend/executor/README
@@ -243,6 +243,8 @@ This is a sketch of control flow for full query processing:
switch to per-query context to run ExecInitNode
AfterTriggerBeginQuery
ExecInitNode --- recursively scans plan tree
+ ExecInitNode
+ recurse into subsidiary nodes
CreateExprContext
creates per-tuple context
ExecInitExpr
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 463e185a9a9..db5fcafbfe4 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2415,7 +2415,7 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
scratch->d.wholerow.junkFilter =
ExecInitJunkFilter(subplan->plan->targetlist,
ExecGetResultType(subplan)->tdhasoid,
- ExecInitExtraTupleSlot(parent->state));
+ ExecInitExtraTupleSlot(parent->state, NULL));
}
}
}
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 5d3e923cca3..91ba939bdca 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1073,7 +1073,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
j = ExecInitJunkFilter(planstate->plan->targetlist,
tupType->tdhasoid,
- ExecInitExtraTupleSlot(estate));
+ ExecInitExtraTupleSlot(estate, NULL));
estate->es_junkFilter = j;
/* Want to return the cleaned tuple type */
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 4048c3ebc61..00523ce250d 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -93,7 +93,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
* We need an additional tuple slot for storing transient tuples that
* are converted to the root table descriptor.
*/
- proute->root_tuple_slot = MakeTupleTableSlot();
+ proute->root_tuple_slot = MakeTupleTableSlot(NULL);
}
else
{
@@ -112,7 +112,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
* (such as ModifyTableState) and released when the node finishes
* processing.
*/
- proute->partition_tuple_slot = MakeTupleTableSlot();
+ proute->partition_tuple_slot = MakeTupleTableSlot(NULL);
i = 0;
foreach(cell, leaf_parts)
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index bf4f603fd36..caf91730ce1 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -229,7 +229,7 @@ ExecScan(ScanState *node,
* the scan node, because the planner will preferentially generate a matching
* tlist.
*
- * ExecAssignScanType must have been called already.
+ * The scan slot's descriptor must have been set already.
*/
void
ExecAssignScanProjectionInfo(ScanState *node)
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 5df89e419c8..c46d65cf938 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -58,7 +58,7 @@
* At ExecutorStart()
* ----------------
* - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
- * ExecInitResultTupleSlot() to construct TupleTableSlots
+ * ExecInitResultTupleSlotTL() to construct TupleTableSlots
* for the tuples returned by the access methods and the
* tuples resulting from performing target list projections.
*
@@ -104,19 +104,36 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList,
/* --------------------------------
* MakeTupleTableSlot
*
- * Basic routine to make an empty TupleTableSlot.
+ * Basic routine to make an empty TupleTableSlot. If tupleDesc is
+ * specified the slot's descriptor is fixed for it's lifetime, gaining
+ * some efficiency. If that's undesirable, pass NULL.
* --------------------------------
*/
TupleTableSlot *
-MakeTupleTableSlot(void)
+MakeTupleTableSlot(TupleDesc tupleDesc)
{
- TupleTableSlot *slot = makeNode(TupleTableSlot);
+ Size sz;
+ TupleTableSlot *slot;
+ /*
+ * When a fixed descriptor is specified, we can reduce overhead by
+ * allocating the entire slot in one go.
+ */
+ if (tupleDesc)
+ sz = MAXALIGN(sizeof(TupleTableSlot)) +
+ MAXALIGN(tupleDesc->natts * sizeof(Datum)) +
+ MAXALIGN(tupleDesc->natts * sizeof(bool));
+ else
+ sz = sizeof(TupleTableSlot);
+
+ slot = palloc0(sz);
+ slot->type = T_TupleTableSlot;
slot->tts_isempty = true;
slot->tts_shouldFree = false;
slot->tts_shouldFreeMin = false;
slot->tts_tuple = NULL;
- slot->tts_tupleDescriptor = NULL;
+ slot->tts_fixedTupleDescriptor = tupleDesc != NULL;
+ slot->tts_tupleDescriptor = tupleDesc;
slot->tts_mcxt = CurrentMemoryContext;
slot->tts_buffer = InvalidBuffer;
slot->tts_nvalid = 0;
@@ -124,6 +141,19 @@ MakeTupleTableSlot(void)
slot->tts_isnull = NULL;
slot->tts_mintuple = NULL;
+ if (tupleDesc != NULL)
+ {
+ slot->tts_values = (Datum *)
+ (((char *) slot)
+ + MAXALIGN(sizeof(TupleTableSlot)));
+ slot->tts_isnull = (bool *)
+ (((char *) slot)
+ + MAXALIGN(sizeof(TupleTableSlot))
+ + MAXALIGN(tupleDesc->natts * sizeof(Datum)));
+
+ PinTupleDesc(tupleDesc);
+ }
+
return slot;
}
@@ -134,9 +164,9 @@ MakeTupleTableSlot(void)
* --------------------------------
*/
TupleTableSlot *
-ExecAllocTableSlot(List **tupleTable)
+ExecAllocTableSlot(List **tupleTable, TupleDesc desc)
{
- TupleTableSlot *slot = MakeTupleTableSlot();
+ TupleTableSlot *slot = MakeTupleTableSlot(desc);
*tupleTable = lappend(*tupleTable, slot);
@@ -173,10 +203,13 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
/* If shouldFree, release memory occupied by the slot itself */
if (shouldFree)
{
- if (slot->tts_values)
- pfree(slot->tts_values);
- if (slot->tts_isnull)
- pfree(slot->tts_isnull);
+ if (!slot->tts_fixedTupleDescriptor)
+ {
+ if (slot->tts_values)
+ pfree(slot->tts_values);
+ if (slot->tts_isnull)
+ pfree(slot->tts_isnull);
+ }
pfree(slot);
}
}
@@ -198,9 +231,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
TupleTableSlot *
MakeSingleTupleTableSlot(TupleDesc tupdesc)
{
- TupleTableSlot *slot = MakeTupleTableSlot();
-
- ExecSetSlotDescriptor(slot, tupdesc);
+ TupleTableSlot *slot = MakeTupleTableSlot(tupdesc);
return slot;
}
@@ -220,10 +251,13 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)
ReleaseTupleDesc(slot->tts_tupleDescriptor);
- if (slot->tts_values)
- pfree(slot->tts_values);
- if (slot->tts_isnull)
- pfree(slot->tts_isnull);
+ if (!slot->tts_fixedTupleDescriptor)
+ {
+ if (slot->tts_values)
+ pfree(slot->tts_values);
+ if (slot->tts_isnull)
+ pfree(slot->tts_isnull);
+ }
pfree(slot);
}
@@ -247,6 +281,8 @@ void
ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
TupleDesc tupdesc) /* new tuple descriptor */
{
+ Assert(!slot->tts_fixedTupleDescriptor);
+
/* For safety, make sure slot is empty before changing it */
ExecClearTuple(slot);
@@ -816,7 +852,7 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
*/
/* --------------------------------
- * ExecInit{Result,Scan,Extra}TupleSlot
+ * ExecInit{Result,Scan,Extra}TupleSlot[TL]
*
* These are convenience routines to initialize the specified slot
* in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
@@ -825,13 +861,30 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
*/
/* ----------------
- * ExecInitResultTupleSlot
+ * ExecInitResultTupleSlotTL
+ *
+ * Initialize result tuple slot, using the plan node's targetlist.
* ----------------
*/
void
-ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
+ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
{
- planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable);
+ bool hasoid;
+ TupleDesc tupDesc;
+
+ if (ExecContextForcesOids(planstate, &hasoid))
+ {
+ /* context forces OID choice; hasoid is now set correctly */
+ }
+ else
+ {
+ /* given free choice, don't leave space for OIDs in result tuples */
+ hasoid = false;
+ }
+
+ tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
+
+ planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable, tupDesc);
}
/* ----------------
@@ -839,19 +892,24 @@ ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
* ----------------
*/
void
-ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
+ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
{
- scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable);
+ scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable,
+ tupledesc);
}
/* ----------------
* ExecInitExtraTupleSlot
+ *
+ * Return a newly created slot. If tupledesc is non-NULL the slot will have
+ * that as its fixed tupledesc. Otherwise the caller needs to use
+ * ExecSetSlotDescriptor() to set the descriptor before use.
* ----------------
*/
TupleTableSlot *
-ExecInitExtraTupleSlot(EState *estate)
+ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
{
- return ExecAllocTableSlot(&estate->es_tupleTable);
+ return ExecAllocTableSlot(&estate->es_tupleTable, tupledesc);
}
/* ----------------
@@ -865,9 +923,7 @@ ExecInitExtraTupleSlot(EState *estate)
TupleTableSlot *
ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
{
- TupleTableSlot *slot = ExecInitExtraTupleSlot(estate);
-
- ExecSetSlotDescriptor(slot, tupType);
+ TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType);
return ExecStoreAllNullTuple(slot);
}
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 50b6edce63d..a8ae37ebc80 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -22,7 +22,6 @@
* ReScanExprContext
*
* ExecAssignExprContext Common code for plan node init routines.
- * ExecAssignResultType
* etc
*
* ExecOpenScanRelation Common code for scan node init routines.
@@ -429,47 +428,6 @@ ExecAssignExprContext(EState *estate, PlanState *planstate)
}
/* ----------------
- * ExecAssignResultType
- * ----------------
- */
-void
-ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
-{
- TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
-
- ExecSetSlotDescriptor(slot, tupDesc);
-}
-
-/* ----------------
- * ExecAssignResultTypeFromTL
- * ----------------
- */
-void
-ExecAssignResultTypeFromTL(PlanState *planstate)
-{
- bool hasoid;
- TupleDesc tupDesc;
-
- if (ExecContextForcesOids(planstate, &hasoid))
- {
- /* context forces OID choice; hasoid is now set correctly */
- }
- else
- {
- /* given free choice, don't leave space for OIDs in result tuples */
- hasoid = false;
- }
-
- /*
- * ExecTypeFromTL needs the parse-time representation of the tlist, not a
- * list of ExprStates. This is good because some plan nodes don't bother
- * to set up planstate->targetlist ...
- */
- tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
- ExecAssignResultType(planstate, tupDesc);
-}
-
-/* ----------------
* ExecGetResultType
* ----------------
*/
@@ -609,13 +567,9 @@ ExecFreeExprContext(PlanState *planstate)
planstate->ps_ExprContext = NULL;
}
+
/* ----------------------------------------------------------------
- * the following scan type support functions are for
- * those nodes which are stubborn and return tuples in
- * their Scan tuple slot instead of their Result tuple
- * slot.. luck fur us, these nodes do not do projections
- * so we don't have to worry about getting the ProjectionInfo
- * right for them... -cim 6/3/91
+ * Scan node support
* ----------------------------------------------------------------
*/
@@ -632,11 +586,11 @@ ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
}
/* ----------------
- * ExecAssignScanTypeFromOuterPlan
+ * ExecCreateSlotFromOuterPlan
* ----------------
*/
void
-ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
+ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
{
PlanState *outerPlan;
TupleDesc tupDesc;
@@ -644,15 +598,9 @@ ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
outerPlan = outerPlanState(scanstate);
tupDesc = ExecGetResultType(outerPlan);
- ExecAssignScanType(scanstate, tupDesc);
+ ExecInitScanTupleSlot(estate, scanstate, tupDesc);
}
-
-/* ----------------------------------------------------------------
- * Scan node support
- * ----------------------------------------------------------------
- */
-
/* ----------------------------------------------------------------
* ExecRelationIsTargetRelation
*
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index e74b3a93911..1b1334006fa 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1402,8 +1402,8 @@ find_hash_columns(AggState *aggstate)
perhash->aggnode->grpOperators,
&perhash->eqfuncoids,
&perhash->hashfunctions);
- perhash->hashslot = ExecAllocTableSlot(&estate->es_tupleTable);
- ExecSetSlotDescriptor(perhash->hashslot, hashDesc);
+ perhash->hashslot =
+ ExecAllocTableSlot(&estate->es_tupleTable, hashDesc);
list_free(hashTlist);
bms_free(colnos);
@@ -2199,31 +2199,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &aggstate->ss.ps);
/*
- * tuple table initialization.
- *
- * For hashtables, we create some additional slots below.
- */
- ExecInitScanTupleSlot(estate, &aggstate->ss);
- ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
- aggstate->sort_slot = ExecInitExtraTupleSlot(estate);
-
- /*
- * initialize child expressions
- *
- * We expect the parser to have checked that no aggs contain other agg
- * calls in their arguments (and just to be sure, we verify it again while
- * initializing the plan node). This would make no sense under SQL
- * semantics, and it's forbidden by the spec. Because it is true, we
- * don't need to worry about evaluating the aggs in any particular order.
- *
- * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
- * nodes to aggstate->aggs. Aggrefs in the qual are found here; Aggrefs
- * in the targetlist are found during ExecAssignProjectionInfo, below.
- */
- aggstate->ss.ps.qual =
- ExecInitQual(node->plan.qual, (PlanState *) aggstate);
-
- /*
* Initialize child nodes.
*
* If we are doing a hashed aggregation then the child plan does not need
@@ -2237,18 +2212,34 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
/*
* initialize source tuple type.
*/
- ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
+ ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss);
scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
if (node->chain)
- ExecSetSlotDescriptor(aggstate->sort_slot, scanDesc);
+ aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc);
/*
- * Initialize result tuple type and projection info.
+ * Initialize result type, slot and projection.
*/
- ExecAssignResultTypeFromTL(&aggstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &aggstate->ss.ps);
ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
/*
+ * initialize child expressions
+ *
+ * We expect the parser to have checked that no aggs contain other agg
+ * calls in their arguments (and just to be sure, we verify it again while
+ * initializing the plan node). This would make no sense under SQL
+ * semantics, and it's forbidden by the spec. Because it is true, we
+ * don't need to worry about evaluating the aggs in any particular order.
+ *
+ * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
+ * nodes to aggstate->aggs. Aggrefs in the qual are found here; Aggrefs
+ * in the targetlist are found during ExecAssignProjectionInfo, below.
+ */
+ aggstate->ss.ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) aggstate);
+
+ /*
* We should now have found all Aggrefs in the targetlist and quals.
*/
numaggs = aggstate->numaggs;
@@ -3071,8 +3062,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
if (numSortCols > 0 || aggref->aggfilter)
{
pertrans->sortdesc = ExecTypeFromTL(aggref->args, false);
- pertrans->sortslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(pertrans->sortslot, pertrans->sortdesc);
+ pertrans->sortslot =
+ ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
}
if (numSortCols > 0)
@@ -3093,9 +3084,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
else if (numDistinctCols > 0)
{
/* we will need an extra slot to store prior values */
- pertrans->uniqslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(pertrans->uniqslot,
- pertrans->sortdesc);
+ pertrans->uniqslot =
+ ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
}
/* Extract the sort information for use later */
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 264d8fea8d9..7a3dd2ee2d0 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -129,17 +129,9 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
appendstate->as_nplans = nplans;
/*
- * Miscellaneous initialization
- *
- * Append plans don't have expression contexts because they never call
- * ExecQual or ExecProject.
+ * Initialize result tuple type and slot.
*/
-
- /*
- * append nodes still have Result slots, which hold pointers to tuples, so
- * we have to initialize them.
- */
- ExecInitResultTupleSlot(estate, &appendstate->ps);
+ ExecInitResultTupleSlotTL(estate, &appendstate->ps);
/*
* call ExecInitNode on each of the plans to be executed and save the
@@ -155,9 +147,11 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
}
/*
- * initialize output tuple type
+ * Miscellaneous initialization
+ *
+ * Append plans don't have expression contexts because they never call
+ * ExecQual or ExecProject.
*/
- ExecAssignResultTypeFromTL(&appendstate->ps);
appendstate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c
index 913046c987e..23d0d943269 100644
--- a/src/backend/executor/nodeBitmapAnd.c
+++ b/src/backend/executor/nodeBitmapAnd.c
@@ -81,13 +81,6 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
bitmapandstate->nplans = nplans;
/*
- * Miscellaneous initialization
- *
- * BitmapAnd plans don't have expression contexts because they never call
- * ExecQual or ExecProject. They don't need any tuple slots either.
- */
-
- /*
* call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates".
*/
@@ -99,6 +92,13 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
i++;
}
+ /*
+ * Miscellaneous initialization
+ *
+ * BitmapAnd plans don't have expression contexts because they never call
+ * ExecQual or ExecProject. They don't need any tuple slots either.
+ */
+
return bitmapandstate;
}
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index fa65d4efbe7..3e1c9e07145 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -907,23 +907,39 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
+ * open the base relation and acquire appropriate lock on it.
*/
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
- scanstate->bitmapqualorig =
- ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
+ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
+
+ /*
+ * initialize child nodes
+ *
+ * We do this after ExecOpenScanRelation because the child nodes will open
+ * indexscans on our relation's indexes, and we want to be sure we have
+ * acquired a lock on the relation first.
+ */
+ outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
- * tuple table initialization
+ * get the scan type from the relation descriptor.
*/
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
+ ExecInitScanTupleSlot(estate, &scanstate->ss,
+ RelationGetDescr(currentRelation));
+
/*
- * open the base relation and acquire appropriate lock on it.
+ * Initialize result slot, type and projection.
*/
- currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
+
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ scanstate->bitmapqualorig =
+ ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
/*
* Determine the maximum for prefetch_target. If the tablespace has a
@@ -953,26 +969,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
NULL);
/*
- * get the scan type from the relation descriptor.
- */
- ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation));
-
- /*
- * Initialize result tuple type and projection info.
- */
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
- ExecAssignScanProjectionInfo(&scanstate->ss);
-
- /*
- * initialize child nodes
- *
- * We do this last because the child nodes will open indexscans on our
- * relation's indexes, and we want to be sure we have acquired a lock on
- * the relation first.
- */
- outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
-
- /*
* all done.
*/
return scanstate;
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index bb5e4da187c..d04f4901b48 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -227,6 +227,15 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
indexstate->biss_result = NULL;
/*
+ * We do not open or lock the base relation here. We assume that an
+ * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
+ * the heap relation throughout the execution of the plan tree.
+ */
+
+ indexstate->ss.ss_currentRelation = NULL;
+ indexstate->ss.ss_currentScanDesc = NULL;
+
+ /*
* Miscellaneous initialization
*
* We do not need a standard exprcontext for this node, though we may
@@ -243,15 +252,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
*/
/*
- * We do not open or lock the base relation here. We assume that an
- * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
- * the heap relation throughout the execution of the plan tree.
- */
-
- indexstate->ss.ss_currentRelation = NULL;
- indexstate->ss.ss_currentScanDesc = NULL;
-
- /*
* If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
* here. This allows an index-advisor plugin to EXPLAIN a plan containing
* references to nonexistent indexes.
diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c
index 8047549f7df..3f0a0a05442 100644
--- a/src/backend/executor/nodeBitmapOr.c
+++ b/src/backend/executor/nodeBitmapOr.c
@@ -82,13 +82,6 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
bitmaporstate->nplans = nplans;
/*
- * Miscellaneous initialization
- *
- * BitmapOr plans don't have expression contexts because they never call
- * ExecQual or ExecProject. They don't need any tuple slots either.
- */
-
- /*
* call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates".
*/
@@ -100,6 +93,13 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
i++;
}
+ /*
+ * Miscellaneous initialization
+ *
+ * BitmapOr plans don't have expression contexts because they never call
+ * ExecQual or ExecProject. They don't need any tuple slots either.
+ */
+
return bitmaporstate;
}
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index ec6d75cbd41..218619c760d 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -243,30 +243,24 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
- */
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
-
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
-
- /*
* The scan tuple type (ie, the rowtype we expect to find in the work
* table) is the same as the result rowtype of the CTE query.
*/
- ExecAssignScanType(&scanstate->ss,
- ExecGetResultType(scanstate->cteplanstate));
+ ExecInitScanTupleSlot(estate, &scanstate->ss,
+ ExecGetResultType(scanstate->cteplanstate));
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+
return scanstate;
}
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index 936a2221f51..b816e0b31db 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -54,14 +54,6 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
/* create expression context for node */
ExecAssignExprContext(estate, &css->ss.ps);
- /* initialize child expressions */
- css->ss.ps.qual =
- ExecInitQual(cscan->scan.plan.qual, (PlanState *) css);
-
- /* tuple table initialization */
- ExecInitScanTupleSlot(estate, &css->ss);
- ExecInitResultTupleSlot(estate, &css->ss.ps);
-
/*
* open the base relation, if any, and acquire an appropriate lock on it
*/
@@ -81,23 +73,27 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
TupleDesc scan_tupdesc;
scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false);
- ExecAssignScanType(&css->ss, scan_tupdesc);
+ ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc);
/* Node's targetlist will contain Vars with varno = INDEX_VAR */
tlistvarno = INDEX_VAR;
}
else
{
- ExecAssignScanType(&css->ss, RelationGetDescr(scan_rel));
+ ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel));
/* Node's targetlist will contain Vars with varno = scanrelid */
tlistvarno = scanrelid;
}
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&css->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &css->ss.ps);
ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
+ /* initialize child expressions */
+ css->ss.ps.qual =
+ ExecInitQual(cscan->scan.plan.qual, (PlanState *) css);
+
/*
* The callback of custom-scan provider applies the final initialization
* of the custom-scan-state node according to its logic.
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 59865f5ccad..0084234b350 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -156,20 +156,6 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
- */
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
- scanstate->fdw_recheck_quals =
- ExecInitQual(node->fdw_recheck_quals, (PlanState *) scanstate);
-
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
-
- /*
* open the base relation, if any, and acquire an appropriate lock on it;
* also acquire function pointers from the FDW's handler
*/
@@ -194,24 +180,32 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
TupleDesc scan_tupdesc;
scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist, false);
- ExecAssignScanType(&scanstate->ss, scan_tupdesc);
+ ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
/* Node's targetlist will contain Vars with varno = INDEX_VAR */
tlistvarno = INDEX_VAR;
}
else
{
- ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation));
+ ExecInitScanTupleSlot(estate, &scanstate->ss, RelationGetDescr(currentRelation));
/* Node's targetlist will contain Vars with varno = scanrelid */
tlistvarno = scanrelid;
}
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno);
/*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ scanstate->fdw_recheck_quals =
+ ExecInitQual(node->fdw_recheck_quals, (PlanState *) scanstate);
+
+ /*
* Initialize FDW-related state.
*/
scanstate->fdwroutine = fdwroutine;
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 69f8d3e8145..fb7c9f67875 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -334,18 +334,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &scanstate->ss.ps);
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
-
- /*
- * initialize child expressions
- */
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
-
scanstate->funcstates = palloc(nfuncs * sizeof(FunctionScanPerFuncState));
natts = 0;
@@ -436,8 +424,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
*/
if (!scanstate->simple)
{
- fs->func_slot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(fs->func_slot, fs->tupdesc);
+ fs->func_slot = ExecInitExtraTupleSlot(estate, fs->tupdesc);
}
else
fs->func_slot = NULL;
@@ -492,15 +479,24 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
Assert(attno == natts);
}
- ExecAssignScanType(&scanstate->ss, scan_tupdesc);
+ /*
+ * Initialize scan slot and type.
+ */
+ ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
/*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+
+ /*
* Create a memory context that ExecMakeTableFunctionResult can use to
* evaluate function arguments in. We can't use the per-tuple context for
* this because it gets reset too often; but we don't want to leak
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 58eadd45b83..eaf7d2d5632 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -59,7 +59,6 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
{
GatherState *gatherstate;
Plan *outerNode;
- bool hasoid;
TupleDesc tupDesc;
/* Gather node doesn't have innerPlan node. */
@@ -86,36 +85,28 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &gatherstate->ps);
/*
- * Gather doesn't support checking a qual (it's always more efficient to
- * do it in the child node).
- */
- Assert(!node->plan.qual);
-
- /*
- * tuple table initialization
- */
- gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate);
- ExecInitResultTupleSlot(estate, &gatherstate->ps);
-
- /*
* now initialize outer plan
*/
outerNode = outerPlan(node);
outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags);
+ tupDesc = ExecGetResultType(outerPlanState(gatherstate));
+
+ /*
+ * Initialize result slot, type and projection.
+ */
+ ExecInitResultTupleSlotTL(estate, &gatherstate->ps);
+ ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR);
/*
* Initialize funnel slot to same tuple descriptor as outer plan.
*/
- if (!ExecContextForcesOids(outerPlanState(gatherstate), &hasoid))
- hasoid = false;
- tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid);
- ExecSetSlotDescriptor(gatherstate->funnel_slot, tupDesc);
+ gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc);
/*
- * Initialize result tuple type and projection info.
+ * Gather doesn't support checking a qual (it's always more efficient to
+ * do it in the child node).
*/
- ExecAssignResultTypeFromTL(&gatherstate->ps);
- ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR);
+ Assert(!node->plan.qual);
return gatherstate;
}
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 6858c91e8c2..83221cdbaee 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -73,7 +73,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
{
GatherMergeState *gm_state;
Plan *outerNode;
- bool hasoid;
TupleDesc tupDesc;
/* Gather merge node doesn't have innerPlan node. */
@@ -105,11 +104,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
Assert(!node->plan.qual);
/*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &gm_state->ps);
-
- /*
* now initialize outer plan
*/
outerNode = outerPlan(node);
@@ -119,15 +113,13 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
* Store the tuple descriptor into gather merge state, so we can use it
* while initializing the gather merge slots.
*/
- if (!ExecContextForcesOids(outerPlanState(gm_state), &hasoid))
- hasoid = false;
- tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid);
+ tupDesc = ExecGetResultType(outerPlanState(gm_state));
gm_state->tupDesc = tupDesc;
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&gm_state->ps);
+ ExecInitResultTupleSlotTL(estate, &gm_state->ps);
ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR);
/*
@@ -410,9 +402,8 @@ gather_merge_setup(GatherMergeState *gm_state)
(HeapTuple *) palloc0(sizeof(HeapTuple) * MAX_TUPLE_STORE);
/* Initialize tuple slot for worker */
- gm_state->gm_slots[i + 1] = ExecInitExtraTupleSlot(gm_state->ps.state);
- ExecSetSlotDescriptor(gm_state->gm_slots[i + 1],
- gm_state->tupDesc);
+ gm_state->gm_slots[i + 1] =
+ ExecInitExtraTupleSlot(gm_state->ps.state, gm_state->tupDesc);
}
/* Allocate the resources for the merge */
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index 8f7bf459efe..c6efd64d00d 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -182,34 +182,28 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &grpstate->ss.ps);
/*
- * tuple table initialization
- */
- ExecInitScanTupleSlot(estate, &grpstate->ss);
- ExecInitResultTupleSlot(estate, &grpstate->ss.ps);
-
- /*
- * initialize child expressions
- */
- grpstate->ss.ps.qual =
- ExecInitQual(node->plan.qual, (PlanState *) grpstate);
-
- /*
* initialize child nodes
*/
outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
- * initialize tuple type.
+ * Initialize scan slot and type.
*/
- ExecAssignScanTypeFromOuterPlan(&grpstate->ss);
+ ExecCreateScanSlotFromOuterPlan(estate, &grpstate->ss);
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&grpstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &grpstate->ss.ps);
ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
/*
+ * initialize child expressions
+ */
+ grpstate->ss.ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) grpstate);
+
+ /*
* Precompute fmgr lookup data for inner loop
*/
grpstate->eqfunction =
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index b10f8474527..06bb44b1631 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -374,28 +374,23 @@ ExecInitHash(Hash *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &hashstate->ps);
/*
- * initialize our result slot
- */
- ExecInitResultTupleSlot(estate, &hashstate->ps);
-
- /*
- * initialize child expressions
- */
- hashstate->ps.qual =
- ExecInitQual(node->plan.qual, (PlanState *) hashstate);
-
- /*
* initialize child nodes
*/
outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
- * initialize tuple type. no need to initialize projection info because
- * this node doesn't do projections
+ * initialize our result slot and type. No need to build projection
+ * because this node doesn't do projections.
*/
- ExecAssignResultTypeFromTL(&hashstate->ps);
+ ExecInitResultTupleSlotTL(estate, &hashstate->ps);
hashstate->ps.ps_ProjInfo = NULL;
+ /*
+ * initialize child expressions
+ */
+ hashstate->ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) hashstate);
+
return hashstate;
}
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 03d78042fa0..ab91eb25273 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -596,6 +596,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
List *lclauses;
List *rclauses;
List *hoperators;
+ TupleDesc outerDesc, innerDesc;
ListCell *l;
/* check for unsupported flags */
@@ -614,6 +615,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
* managed to launch a parallel query.
*/
hjstate->js.ps.ExecProcNode = ExecHashJoin;
+ hjstate->js.jointype = node->join.jointype;
/*
* Miscellaneous initialization
@@ -623,17 +625,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &hjstate->js.ps);
/*
- * initialize child expressions
- */
- hjstate->js.ps.qual =
- ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
- hjstate->js.jointype = node->join.jointype;
- hjstate->js.joinqual =
- ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
- hjstate->hashclauses =
- ExecInitQual(node->hashclauses, (PlanState *) hjstate);
-
- /*
* initialize child nodes
*
* Note: we could suppress the REWIND flag for the inner input, which
@@ -644,13 +635,20 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
hashNode = (Hash *) innerPlan(node);
outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags);
+ outerDesc = ExecGetResultType(outerPlanState(hjstate));
innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate, eflags);
+ innerDesc = ExecGetResultType(innerPlanState(hjstate));
+
+ /*
+ * Initialize result slot, type and projection.
+ */
+ ExecInitResultTupleSlotTL(estate, &hjstate->js.ps);
+ ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &hjstate->js.ps);
- hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
+ hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc);
/*
* detect whether we need only consider the first matching inner tuple
@@ -667,21 +665,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
case JOIN_LEFT:
case JOIN_ANTI:
hjstate->hj_NullInnerTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(innerPlanState(hjstate)));
+ ExecInitNullTupleSlot(estate, innerDesc);
break;
case JOIN_RIGHT:
hjstate->hj_NullOuterTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(outerPlanState(hjstate)));
+ ExecInitNullTupleSlot(estate, outerDesc);
break;
case JOIN_FULL:
hjstate->hj_NullOuterTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(outerPlanState(hjstate)));
+ ExecInitNullTupleSlot(estate, outerDesc);
hjstate->hj_NullInnerTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(innerPlanState(hjstate)));
+ ExecInitNullTupleSlot(estate, innerDesc);
break;
default:
elog(ERROR, "unrecognized join type: %d",
@@ -703,13 +697,14 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
}
/*
- * initialize tuple type and projection info
+ * initialize child expressions
*/
- ExecAssignResultTypeFromTL(&hjstate->js.ps);
- ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
-
- ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot,
- ExecGetResultType(outerPlanState(hjstate)));
+ hjstate->js.ps.qual =
+ ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
+ hjstate->js.joinqual =
+ ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
+ hjstate->hashclauses =
+ ExecInitQual(node->hashclauses, (PlanState *) hjstate);
/*
* initialize hash-specific info
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 8ffcc52bea5..ddc0ae90615 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -519,23 +519,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &indexstate->ss.ps);
/*
- * initialize child expressions
- *
- * Note: we don't initialize all of the indexorderby expression, only the
- * sub-parts corresponding to runtime keys (see below).
- */
- indexstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) indexstate);
- indexstate->indexqual =
- ExecInitQual(node->indexqual, (PlanState *) indexstate);
-
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
- ExecInitScanTupleSlot(estate, &indexstate->ss);
-
- /*
* open the base relation and acquire appropriate lock on it.
*/
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
@@ -551,17 +534,28 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
* suitable data anyway.)
*/
tupDesc = ExecTypeFromTL(node->indextlist, false);
- ExecAssignScanType(&indexstate->ss, tupDesc);
+ ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc);
/*
- * Initialize result tuple type and projection info. The node's
+ * Initialize result slot, type and projection info. The node's
* targetlist will contain Vars with varno = INDEX_VAR, referencing the
* scan tuple.
*/
- ExecAssignResultTypeFromTL(&indexstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
ExecAssignScanProjectionInfoWithVarno(&indexstate->ss, INDEX_VAR);
/*
+ * initialize child expressions
+ *
+ * Note: we don't initialize all of the indexorderby expression, only the
+ * sub-parts corresponding to runtime keys (see below).
+ */
+ indexstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) indexstate);
+ indexstate->indexqual =
+ ExecInitQual(node->indexqual, (PlanState *) indexstate);
+
+ /*
* If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
* here. This allows an index-advisor plugin to EXPLAIN a plan containing
* references to nonexistent indexes.
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index b8b961add4c..01c9de88f4d 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -941,6 +941,26 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &indexstate->ss.ps);
/*
+ * open the base relation and acquire appropriate lock on it.
+ */
+ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
+
+ indexstate->ss.ss_currentRelation = currentRelation;
+ indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
+
+ /*
+ * get the scan type from the relation descriptor.
+ */
+ ExecInitScanTupleSlot(estate, &indexstate->ss,
+ RelationGetDescr(currentRelation));
+
+ /*
+ * Initialize result slot, type and projection.
+ */
+ ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
+ ExecAssignScanProjectionInfo(&indexstate->ss);
+
+ /*
* initialize child expressions
*
* Note: we don't initialize all of the indexqual expression, only the
@@ -958,31 +978,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
ExecInitExprList(node->indexorderbyorig, (PlanState *) indexstate);
/*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
- ExecInitScanTupleSlot(estate, &indexstate->ss);
-
- /*
- * open the base relation and acquire appropriate lock on it.
- */
- currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
-
- indexstate->ss.ss_currentRelation = currentRelation;
- indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
-
- /*
- * get the scan type from the relation descriptor.
- */
- ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation));
-
- /*
- * Initialize result tuple type and projection info.
- */
- ExecAssignResultTypeFromTL(&indexstate->ss.ps);
- ExecAssignScanProjectionInfo(&indexstate->ss);
-
- /*
* If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
* here. This allows an index-advisor plugin to EXPLAIN a plan containing
* references to nonexistent indexes.
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index 29d2deac23b..56d98b4490b 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -354,6 +354,12 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &limitstate->ps);
/*
+ * initialize outer plan
+ */
+ outerPlan = outerPlan(node);
+ outerPlanState(limitstate) = ExecInitNode(outerPlan, estate, eflags);
+
+ /*
* initialize child expressions
*/
limitstate->limitOffset = ExecInitExpr((Expr *) node->limitOffset,
@@ -362,21 +368,15 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
(PlanState *) limitstate);
/*
- * Tuple table initialization (XXX not actually used...)
+ * Initialize result slot and type. (XXX not actually used, but upper
+ * nodes access it to get this node's result tupledesc...)
*/
- ExecInitResultTupleSlot(estate, &limitstate->ps);
-
- /*
- * then initialize outer plan
- */
- outerPlan = outerPlan(node);
- outerPlanState(limitstate) = ExecInitNode(outerPlan, estate, eflags);
+ ExecInitResultTupleSlotTL(estate, &limitstate->ps);
/*
* limit nodes do no projections, so initialize projection info for this
* node appropriately
*/
- ExecAssignResultTypeFromTL(&limitstate->ps);
limitstate->ps.ps_ProjInfo = NULL;
return limitstate;
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index 7961b4be6ab..b39ccf7dc13 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -370,13 +370,15 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
/*
* Miscellaneous initialization
*
- * LockRows nodes never call ExecQual or ExecProject.
+ * LockRows nodes never call ExecQual or ExecProject, therefore no
+ * ExprContext is needed.
*/
/*
- * Tuple table initialization (XXX not actually used...)
+ * Tuple table initialization (XXX not actually used, but upper nodes
+ * access it to get this node's result tupledesc...)
*/
- ExecInitResultTupleSlot(estate, &lrstate->ps);
+ ExecInitResultTupleSlotTL(estate, &lrstate->ps);
/*
* then initialize outer plan
@@ -387,7 +389,6 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
* LockRows nodes do no projections, so initialize projection info for
* this node appropriately
*/
- ExecAssignResultTypeFromTL(&lrstate->ps);
lrstate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 85afe87c443..8c2e57dbd07 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -207,14 +207,6 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
*/
/*
- * tuple table initialization
- *
- * material nodes only return tuples from their materialized relation.
- */
- ExecInitResultTupleSlot(estate, &matstate->ss.ps);
- ExecInitScanTupleSlot(estate, &matstate->ss);
-
- /*
* initialize child nodes
*
* We shield the child node from the need to support REWIND, BACKWARD, or
@@ -226,13 +218,19 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags);
/*
- * initialize tuple type. no need to initialize projection info because
- * this node doesn't do projections.
+ * Initialize result type and slot. No need to initialize projection info
+ * because this node doesn't do projections.
+ *
+ * material nodes only return tuples from their materialized relation.
*/
- ExecAssignResultTypeFromTL(&matstate->ss.ps);
- ExecAssignScanTypeFromOuterPlan(&matstate->ss);
+ ExecInitResultTupleSlotTL(estate, &matstate->ss.ps);
matstate->ss.ps.ps_ProjInfo = NULL;
+ /*
+ * initialize tuple type.
+ */
+ ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss);
+
return matstate;
}
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index ab4009c967e..118f4ef07df 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -109,7 +109,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
* MergeAppend nodes do have Result slots, which hold pointers to tuples,
* so we have to initialize them.
*/
- ExecInitResultTupleSlot(estate, &mergestate->ps);
+ ExecInitResultTupleSlotTL(estate, &mergestate->ps);
/*
* call ExecInitNode on each of the plans to be executed and save the
@@ -124,10 +124,6 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
i++;
}
- /*
- * initialize output tuple type
- */
- ExecAssignResultTypeFromTL(&mergestate->ps);
mergestate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index ec5f82f6a92..f3cbe2f889b 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -1436,6 +1436,7 @@ MergeJoinState *
ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
{
MergeJoinState *mergestate;
+ TupleDesc outerDesc, innerDesc;
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -1450,6 +1451,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->js.ps.plan = (Plan *) node;
mergestate->js.ps.state = estate;
mergestate->js.ps.ExecProcNode = ExecMergeJoin;
+ mergestate->js.jointype = node->join.jointype;
+ mergestate->mj_ConstFalseJoin = false;
/*
* Miscellaneous initialization
@@ -1467,17 +1470,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_InnerEContext = CreateExprContext(estate);
/*
- * initialize child expressions
- */
- mergestate->js.ps.qual =
- ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
- mergestate->js.jointype = node->join.jointype;
- mergestate->js.joinqual =
- ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
- mergestate->mj_ConstFalseJoin = false;
- /* mergeclauses are handled below */
-
- /*
* initialize child nodes
*
* inner child must support MARK/RESTORE, unless we have detected that we
@@ -1488,10 +1480,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
+ outerDesc = ExecGetResultType(outerPlanState(mergestate));
innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
mergestate->mj_SkipMarkRestore ?
eflags :
(eflags | EXEC_FLAG_MARK));
+ innerDesc = ExecGetResultType(innerPlanState(mergestate));
/*
* For certain types of inner child nodes, it is advantageous to issue
@@ -1515,13 +1509,24 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_ExtraMarks = false;
/*
+ * Initialize result slot, type and projection.
+ */
+ ExecInitResultTupleSlotTL(estate, &mergestate->js.ps);
+ ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
+
+ /*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &mergestate->js.ps);
+ mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc);
- mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
- ExecGetResultType(innerPlanState(mergestate)));
+ /*
+ * initialize child expressions
+ */
+ mergestate->js.ps.qual =
+ ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
+ mergestate->js.joinqual =
+ ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
+ /* mergeclauses are handled below */
/*
* detect whether we need only consider the first matching inner tuple
@@ -1542,15 +1547,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_FillOuter = true;
mergestate->mj_FillInner = false;
mergestate->mj_NullInnerTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(innerPlanState(mergestate)));
+ ExecInitNullTupleSlot(estate, innerDesc);
break;
case JOIN_RIGHT:
mergestate->mj_FillOuter = false;
mergestate->mj_FillInner = true;
mergestate->mj_NullOuterTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(outerPlanState(mergestate)));
+ ExecInitNullTupleSlot(estate, outerDesc);
/*
* Can't handle right or full join with non-constant extra
@@ -1566,11 +1569,9 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_FillOuter = true;
mergestate->mj_FillInner = true;
mergestate->mj_NullOuterTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(outerPlanState(mergestate)));
+ ExecInitNullTupleSlot(estate, outerDesc);
mergestate->mj_NullInnerTupleSlot =
- ExecInitNullTupleSlot(estate,
- ExecGetResultType(innerPlanState(mergestate)));
+ ExecInitNullTupleSlot(estate, innerDesc);
/*
* Can't handle right or full join with non-constant extra
@@ -1588,12 +1589,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
}
/*
- * initialize tuple type and projection info
- */
- ExecAssignResultTypeFromTL(&mergestate->js.ps);
- ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
-
- /*
* preprocess the merge clauses
*/
mergestate->mj_NumClauses = list_length(node->mergeclauses);
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 2a8ecbd830d..93c03cfb071 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2367,8 +2367,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) */
- ExecInitResultTupleSlot(estate, &mtstate->ps);
- ExecAssignResultTypeFromTL(&mtstate->ps);
+ ExecInitResultTupleSlotTL(estate, &mtstate->ps);
slot = mtstate->ps.ps_ResultTupleSlot;
/* Need an econtext too */
@@ -2435,8 +2434,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* expects one (maybe should change that?).
*/
mtstate->ps.plan->targetlist = NIL;
- ExecInitResultTupleSlot(estate, &mtstate->ps);
- ExecAssignResultTypeFromTL(&mtstate->ps);
+ ExecInitResultTupleSlotTL(estate, &mtstate->ps);
mtstate->ps.ps_ExprContext = NULL;
}
@@ -2449,6 +2447,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (node->onConflictAction == ONCONFLICT_UPDATE)
{
ExprContext *econtext;
+ TupleDesc relationDesc;
TupleDesc tupDesc;
/* insert may only have one plan, inheritance is not expanded */
@@ -2459,26 +2458,26 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &mtstate->ps);
econtext = mtstate->ps.ps_ExprContext;
+ relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
/* initialize slot for the existing tuple */
- mtstate->mt_existing = ExecInitExtraTupleSlot(mtstate->ps.state);
- ExecSetSlotDescriptor(mtstate->mt_existing,
- resultRelInfo->ri_RelationDesc->rd_att);
+ mtstate->mt_existing =
+ ExecInitExtraTupleSlot(mtstate->ps.state, relationDesc);
/* carried forward solely for the benefit of explain */
mtstate->mt_excludedtlist = node->exclRelTlist;
/* create target slot for UPDATE SET projection */
tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
- resultRelInfo->ri_RelationDesc->rd_rel->relhasoids);
- mtstate->mt_conflproj = ExecInitExtraTupleSlot(mtstate->ps.state);
- ExecSetSlotDescriptor(mtstate->mt_conflproj, tupDesc);
+ relationDesc->tdhasoid);
+ mtstate->mt_conflproj =
+ ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc);
/* build UPDATE SET projection state */
resultRelInfo->ri_onConflictSetProj =
ExecBuildProjectionInfo(node->onConflictSet, econtext,
mtstate->mt_conflproj, &mtstate->ps,
- resultRelInfo->ri_RelationDesc->rd_att);
+ relationDesc);
/* build DO UPDATE WHERE clause expression */
if (node->onConflictWhere)
@@ -2583,7 +2582,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
j = ExecInitJunkFilter(subplan->targetlist,
resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
- ExecInitExtraTupleSlot(estate));
+ ExecInitExtraTupleSlot(estate, NULL));
if (operation == CMD_UPDATE || operation == CMD_DELETE)
{
@@ -2633,7 +2632,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* we keep it in the estate.
*/
if (estate->es_trig_tuple_slot == NULL)
- estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate);
+ estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
/*
* Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
index c3b28176e44..4d898b1f83e 100644
--- a/src/backend/executor/nodeNamedtuplestorescan.c
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -133,26 +133,21 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
+ * Tuple table and result type initialization. The scan tuple type is
+ * specified for the tuplestore.
*/
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc);
/*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
-
- /*
- * The scan tuple type is specified for the tuplestore.
+ * initialize child expressions
*/
- ExecAssignScanType(&scanstate->ss, scanstate->tupdesc);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
/*
- * Initialize result tuple type and projection info.
+ * Initialize projection.
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
return scanstate;
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 9b4f8cc4320..9ae9863226c 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -286,15 +286,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &nlstate->js.ps);
/*
- * initialize child expressions
- */
- nlstate->js.ps.qual =
- ExecInitQual(node->join.plan.qual, (PlanState *) nlstate);
- nlstate->js.jointype = node->join.jointype;
- nlstate->js.joinqual =
- ExecInitQual(node->join.joinqual, (PlanState *) nlstate);
-
- /*
* initialize child nodes
*
* If we have no parameters to pass into the inner rel from the outer,
@@ -311,9 +302,19 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate, eflags);
/*
- * tuple table initialization
+ * Initialize result slot, type and projection.
*/
- ExecInitResultTupleSlot(estate, &nlstate->js.ps);
+ ExecInitResultTupleSlotTL(estate, &nlstate->js.ps);
+ ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
+
+ /*
+ * initialize child expressions
+ */
+ nlstate->js.ps.qual =
+ ExecInitQual(node->join.plan.qual, (PlanState *) nlstate);
+ nlstate->js.jointype = node->join.jointype;
+ nlstate->js.joinqual =
+ ExecInitQual(node->join.joinqual, (PlanState *) nlstate);
/*
* detect whether we need only consider the first matching inner tuple
@@ -339,12 +340,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
}
/*
- * initialize tuple type and projection info
- */
- ExecAssignResultTypeFromTL(&nlstate->js.ps);
- ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
-
- /*
* finally, wipe the current outer tuple clean.
*/
nlstate->nl_NeedNewOuter = true;
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 3b79993ade8..6d6ed38ceeb 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -244,14 +244,6 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &state->ps);
/*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &state->ps);
-
- /* We don't support any qual on ProjectSet nodes */
- Assert(node->plan.qual == NIL);
-
- /*
* initialize child nodes
*/
outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags);
@@ -262,9 +254,9 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
Assert(innerPlan(node) == NULL);
/*
- * initialize tuple type and projection info
+ * tuple table and result type initialization
*/
- ExecAssignResultTypeFromTL(&state->ps);
+ ExecInitResultTupleSlotTL(estate, &state->ps);
/* Create workspace for per-tlist-entry expr state & SRF-is-done state */
state->nelems = list_length(node->plan.targetlist);
@@ -301,6 +293,8 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
off++;
}
+ /* We don't support any qual on ProjectSet nodes */
+ Assert(node->plan.qual == NIL);
/*
* Create a memory context that ExecMakeFunctionResult can use to evaluate
diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c
index ba48a69a3be..6b3ea5afb31 100644
--- a/src/backend/executor/nodeRecursiveunion.c
+++ b/src/backend/executor/nodeRecursiveunion.c
@@ -229,14 +229,13 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags)
* RecursiveUnion nodes still have Result slots, which hold pointers to
* tuples, so we have to initialize them.
*/
- ExecInitResultTupleSlot(estate, &rustate->ps);
+ ExecInitResultTupleSlotTL(estate, &rustate->ps);
/*
- * Initialize result tuple type and projection info. (Note: we have to
- * set up the result type before initializing child nodes, because
- * nodeWorktablescan.c expects it to be valid.)
+ * Initialize result tuple type. (Note: we have to set up the result type
+ * before initializing child nodes, because nodeWorktablescan.c expects it
+ * to be valid.)
*/
- ExecAssignResultTypeFromTL(&rustate->ps);
rustate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index 5860d9c1ce6..e4418a29bba 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -205,19 +205,6 @@ ExecInitResult(Result *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &resstate->ps);
/*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &resstate->ps);
-
- /*
- * initialize child expressions
- */
- resstate->ps.qual =
- ExecInitQual(node->plan.qual, (PlanState *) resstate);
- resstate->resconstantqual =
- ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
-
- /*
* initialize child nodes
*/
outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
@@ -228,11 +215,19 @@ ExecInitResult(Result *node, EState *estate, int eflags)
Assert(innerPlan(node) == NULL);
/*
- * initialize tuple type and projection info
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&resstate->ps);
+ ExecInitResultTupleSlotTL(estate, &resstate->ps);
ExecAssignProjectionInfo(&resstate->ps, NULL);
+ /*
+ * initialize child expressions
+ */
+ resstate->ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) resstate);
+ resstate->resconstantqual =
+ ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
+
return resstate;
}
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index e88cd187373..872d6e5735e 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -26,7 +26,6 @@
#include "utils/rel.h"
#include "utils/tqual.h"
-static void InitScanRelation(SampleScanState *node, EState *estate, int eflags);
static TupleTableSlot *SampleNext(SampleScanState *node);
static void tablesample_init(SampleScanState *scanstate);
static HeapTuple tablesample_getnext(SampleScanState *scanstate);
@@ -107,35 +106,6 @@ ExecSampleScan(PlanState *pstate)
}
/* ----------------------------------------------------------------
- * InitScanRelation
- *
- * Set up to access the scan relation.
- * ----------------------------------------------------------------
- */
-static void
-InitScanRelation(SampleScanState *node, EState *estate, int eflags)
-{
- Relation currentRelation;
-
- /*
- * get the relation object id from the relid'th entry in the range table,
- * open that relation and acquire appropriate lock on it.
- */
- currentRelation = ExecOpenScanRelation(estate,
- ((SampleScan *) node->ss.ps.plan)->scan.scanrelid,
- eflags);
-
- node->ss.ss_currentRelation = currentRelation;
-
- /* we won't set up the HeapScanDesc till later */
- node->ss.ss_currentScanDesc = NULL;
-
- /* and report the scan tuple slot's rowtype */
- ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
-}
-
-
-/* ----------------------------------------------------------------
* ExecInitSampleScan
* ----------------------------------------------------------------
*/
@@ -165,31 +135,39 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
+ * Initialize scan relation.
+ *
+ * Get the relation object id from the relid'th entry in the range table,
+ * open that relation and acquire appropriate lock on it.
*/
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ scanstate->ss.ss_currentRelation =
+ ExecOpenScanRelation(estate,
+ node->scan.scanrelid,
+ eflags);
- scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate);
- scanstate->repeatable =
- ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
+ /* we won't set up the HeapScanDesc till later */
+ scanstate->ss.ss_currentScanDesc = NULL;
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
+ /* and create slot with appropriate rowtype */
+ ExecInitScanTupleSlot(estate, &scanstate->ss,
+ RelationGetDescr(scanstate->ss.ss_currentRelation));
/*
- * initialize scan relation
+ * Initialize result slot, type and projection.
+ * tuple table and result tuple initialization
*/
- InitScanRelation(scanstate, estate, eflags);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
/*
- * Initialize result tuple type and projection info.
+ * initialize child expressions
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
- ExecAssignScanProjectionInfo(&scanstate->ss);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+
+ scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate);
+ scanstate->repeatable =
+ ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
/*
* If we don't have a REPEATABLE clause, select a random seed. We want to
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 58631378d5c..9db368922a3 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -32,7 +32,6 @@
#include "executor/nodeSeqscan.h"
#include "utils/rel.h"
-static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
static TupleTableSlot *SeqNext(SeqScanState *node);
/* ----------------------------------------------------------------
@@ -132,31 +131,6 @@ ExecSeqScan(PlanState *pstate)
(ExecScanRecheckMtd) SeqRecheck);
}
-/* ----------------------------------------------------------------
- * InitScanRelation
- *
- * Set up to access the scan relation.
- * ----------------------------------------------------------------
- */
-static void
-InitScanRelation(SeqScanState *node, EState *estate, int eflags)
-{
- Relation currentRelation;
-
- /*
- * get the relation object id from the relid'th entry in the range table,
- * open that relation and acquire appropriate lock on it.
- */
- currentRelation = ExecOpenScanRelation(estate,
- ((SeqScan *) node->ss.ps.plan)->scanrelid,
- eflags);
-
- node->ss.ss_currentRelation = currentRelation;
-
- /* and report the scan tuple slot's rowtype */
- ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
-}
-
/* ----------------------------------------------------------------
* ExecInitSeqScan
@@ -190,27 +164,31 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
+ * Initialize scan relation.
+ *
+ * Get the relation object id from the relid'th entry in the range table,
+ * open that relation and acquire appropriate lock on it.
*/
- scanstate->ss.ps.qual =
- ExecInitQual(node->plan.qual, (PlanState *) scanstate);
+ scanstate->ss.ss_currentRelation =
+ ExecOpenScanRelation(estate,
+ node->scanrelid,
+ eflags);
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
+ /* and create slot with the appropriate rowtype */
+ ExecInitScanTupleSlot(estate, &scanstate->ss,
+ RelationGetDescr(scanstate->ss.ss_currentRelation));
/*
- * initialize scan relation
+ * Initialize result slot, type and projection.
*/
- InitScanRelation(scanstate, estate, eflags);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
/*
- * Initialize result tuple type and projection info.
+ * initialize child expressions
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
- ExecAssignScanProjectionInfo(&scanstate->ss);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) scanstate);
return scanstate;
}
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index eb5449fc3e2..3fa4a5fcc65 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -519,11 +519,6 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
ALLOCSET_DEFAULT_SIZES);
/*
- * Tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &setopstate->ps);
-
- /*
* initialize child nodes
*
* If we are hashing then the child plan does not need to handle REWIND
@@ -535,10 +530,10 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
outerDesc = ExecGetResultType(outerPlanState(setopstate));
/*
- * setop nodes do no projections, so initialize projection info for this
- * node appropriately
+ * Initialize result slot and type. Setop nodes do no projections, so
+ * initialize projection info for this node appropriately.
*/
- ExecAssignResultTypeFromTL(&setopstate->ps);
+ ExecInitResultTupleSlotTL(estate, &setopstate->ps);
setopstate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index d61c859fce6..73f16c9abaa 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -199,14 +199,6 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
*/
/*
- * tuple table initialization
- *
- * sort nodes only return scan tuples from their sorted relation.
- */
- ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
- ExecInitScanTupleSlot(estate, &sortstate->ss);
-
- /*
* initialize child nodes
*
* We shield the child node from the need to support REWIND, BACKWARD, or
@@ -217,11 +209,15 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
- * initialize tuple type. no need to initialize projection info because
+ * Initialize scan slot and type.
+ */
+ ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss);
+
+ /*
+ * Initialize return slot and type. No need to initialize projection info because
* this node doesn't do projections.
*/
- ExecAssignResultTypeFromTL(&sortstate->ss.ps);
- ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
+ ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps);
sortstate->ss.ps.ps_ProjInfo = NULL;
SO1_printf("ExecInitSort: %s\n",
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 4927e212176..d5411500a2b 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -957,8 +957,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
* own innerecontext.
*/
tupDescLeft = ExecTypeFromTL(lefttlist, false);
- slot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(slot, tupDescLeft);
+ slot = ExecInitExtraTupleSlot(estate, tupDescLeft);
sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
NULL,
slot,
@@ -966,8 +965,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
NULL);
sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false);
- slot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(slot, tupDescRight);
+ slot = ExecInitExtraTupleSlot(estate, tupDescRight);
sstate->projRight = ExecBuildProjectionInfo(righttlist,
sstate->innerecontext,
slot,
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 715a5b6a841..fa618847851 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -121,34 +121,28 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &subquerystate->ss.ps);
/*
- * initialize child expressions
- */
- subquerystate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
-
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
- ExecInitScanTupleSlot(estate, &subquerystate->ss);
-
- /*
* initialize subquery
*/
subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
/*
- * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
+ * Initialize scan slot and type (needed by ExecInitResultTupleSlotTL)
*/
- ExecAssignScanType(&subquerystate->ss,
- ExecGetResultType(subquerystate->subplan));
+ ExecInitScanTupleSlot(estate, &subquerystate->ss,
+ ExecGetResultType(subquerystate->subplan));
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &subquerystate->ss.ps);
ExecAssignScanProjectionInfo(&subquerystate->ss);
+ /*
+ * initialize child expressions
+ */
+ subquerystate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
+
return subquerystate;
}
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index 3b609765d41..fed6f2b3a53 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -140,33 +140,27 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
- */
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
-
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
-
- /*
* initialize source tuple type
*/
tupdesc = BuildDescFromLists(tf->colnames,
tf->coltypes,
tf->coltypmods,
tf->colcollations);
-
- ExecAssignScanType(&scanstate->ss, tupdesc);
+ /* and the corresponding scan slot */
+ ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
+
/* Only XMLTABLE is supported currently */
scanstate->routine = &XmlTableRoutine;
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index f2737bb7ef1..e207b1ffb51 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -531,20 +531,6 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &tidstate->ss.ps);
/*
- * initialize child expressions
- */
- tidstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
-
- TidExprListCreate(tidstate);
-
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &tidstate->ss.ps);
- ExecInitScanTupleSlot(estate, &tidstate->ss);
-
- /*
* mark tid list as not computed yet
*/
tidstate->tss_TidList = NULL;
@@ -562,15 +548,24 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
/*
* get the scan type from the relation descriptor.
*/
- ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation));
+ ExecInitScanTupleSlot(estate, &tidstate->ss,
+ RelationGetDescr(currentRelation));
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&tidstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &tidstate->ss.ps);
ExecAssignScanProjectionInfo(&tidstate->ss);
/*
+ * initialize child expressions
+ */
+ tidstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
+
+ TidExprListCreate(tidstate);
+
+ /*
* all done.
*/
return tidstate;
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index 9f823c58e1a..05d65330a0e 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -133,20 +133,15 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &uniquestate->ps);
/*
- * Tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &uniquestate->ps);
-
- /*
* then initialize outer plan
*/
outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
- * unique nodes do no projections, so initialize projection info for this
- * node appropriately
+ * Initialize result slot and type. Unique nodes do no projections, so
+ * initialize projection info for this node appropriately.
*/
- ExecAssignResultTypeFromTL(&uniquestate->ps);
+ ExecInitResultTupleSlotTL(estate, &uniquestate->ps);
uniquestate->ps.ps_ProjInfo = NULL;
/*
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index c3d78b6295e..63b7e7ef5b8 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -248,23 +248,22 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, planstate);
/*
- * tuple table initialization
+ * Get info about values list, initialize scan slot with it.
*/
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
+ tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
+ ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
/*
- * initialize child expressions
+ * Initialize result slot, type and projection.
*/
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
/*
- * get info about values list
+ * initialize child expressions
*/
- tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
-
- ExecAssignScanType(&scanstate->ss, tupdesc);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
/*
* Other node-specific setup
@@ -281,12 +280,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
scanstate->exprlists[i++] = (List *) lfirst(vtl);
}
- /*
- * Initialize result tuple type and projection info.
- */
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
- ExecAssignScanProjectionInfo(&scanstate->ss);
-
return scanstate;
}
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 1c807a82922..a56c3e89fd5 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2288,30 +2288,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
ALLOCSET_DEFAULT_SIZES);
/*
- * tuple table initialization
- */
- ExecInitScanTupleSlot(estate, &winstate->ss);
- ExecInitResultTupleSlot(estate, &winstate->ss.ps);
- winstate->first_part_slot = ExecInitExtraTupleSlot(estate);
- winstate->agg_row_slot = ExecInitExtraTupleSlot(estate);
- winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate);
- winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate);
-
- /*
- * create frame head and tail slots only if needed (must match logic in
- * update_frameheadpos and update_frametailpos)
- */
- winstate->framehead_slot = winstate->frametail_slot = NULL;
-
- if (frameOptions & (FRAMEOPTION_RANGE | FRAMEOPTION_GROUPS))
- {
- if (!(frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING))
- winstate->framehead_slot = ExecInitExtraTupleSlot(estate);
- if (!(frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING))
- winstate->frametail_slot = ExecInitExtraTupleSlot(estate);
- }
-
- /*
* WindowAgg nodes never have quals, since they can only occur at the
* logical top level of a query (ie, after any WHERE or HAVING filters)
*/
@@ -2328,28 +2304,35 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
* initialize source tuple type (which is also the tuple type that we'll
* store in the tuplestore and use in all our working slots).
*/
- ExecAssignScanTypeFromOuterPlan(&winstate->ss);
+ ExecCreateScanSlotFromOuterPlan(estate, &winstate->ss);
scanDesc = winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
- ExecSetSlotDescriptor(winstate->first_part_slot,
- winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
- ExecSetSlotDescriptor(winstate->agg_row_slot,
- winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
- ExecSetSlotDescriptor(winstate->temp_slot_1,
- winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
- ExecSetSlotDescriptor(winstate->temp_slot_2,
- winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
- if (winstate->framehead_slot)
- ExecSetSlotDescriptor(winstate->framehead_slot,
- winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
- if (winstate->frametail_slot)
- ExecSetSlotDescriptor(winstate->frametail_slot,
- winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
+ /*
+ * tuple table initialization
+ */
+ winstate->first_part_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+ winstate->agg_row_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+ winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate, scanDesc);
+ winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc);
+
+ /*
+ * create frame head and tail slots only if needed (must match logic in
+ * update_frameheadpos and update_frametailpos)
+ */
+ winstate->framehead_slot = winstate->frametail_slot = NULL;
+
+ if (frameOptions & (FRAMEOPTION_RANGE | FRAMEOPTION_GROUPS))
+ {
+ if (!(frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING))
+ winstate->framehead_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+ if (!(frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING))
+ winstate->frametail_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+ }
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&winstate->ss.ps);
+ ExecInitResultTupleSlotTL(estate, &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 66d2111bd9f..2ff9a215b12 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -157,21 +157,21 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
+ * tuple table initialization
*/
- scanstate->ss.ps.qual =
- ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+ ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &scanstate->ss, NULL);
/*
- * tuple table initialization
+ * initialize child expressions
*/
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
/*
- * Initialize result tuple type, but not yet projection info.
+ * Do not yet initialize projection info, see ExecWorkTableScan() for
+ * details.
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
return scanstate;
}
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 83c69092ae8..04985c9f91d 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -208,7 +208,7 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel)
/* Triggers might need a slot */
if (resultRelInfo->ri_TrigDesc)
- estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate);
+ estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
/* Prepare to catch AFTER triggers. */
AfterTriggerBeginQuery();
@@ -585,8 +585,8 @@ apply_handle_insert(StringInfo s)
/* Initialize the executor state. */
estate = create_estate_for_relation(rel);
- remoteslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(remoteslot, RelationGetDescr(rel->localrel));
+ remoteslot = ExecInitExtraTupleSlot(estate,
+ RelationGetDescr(rel->localrel));
/* Process and store remote tuple in the slot */
oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
@@ -689,10 +689,10 @@ apply_handle_update(StringInfo s)
/* Initialize the executor state. */
estate = create_estate_for_relation(rel);
- remoteslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(remoteslot, RelationGetDescr(rel->localrel));
- localslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(localslot, RelationGetDescr(rel->localrel));
+ remoteslot = ExecInitExtraTupleSlot(estate,
+ RelationGetDescr(rel->localrel));
+ localslot = ExecInitExtraTupleSlot(estate,
+ RelationGetDescr(rel->localrel));
EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
PushActiveSnapshot(GetTransactionSnapshot());
@@ -807,10 +807,10 @@ apply_handle_delete(StringInfo s)
/* Initialize the executor state. */
estate = create_estate_for_relation(rel);
- remoteslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(remoteslot, RelationGetDescr(rel->localrel));
- localslot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(localslot, RelationGetDescr(rel->localrel));
+ remoteslot = ExecInitExtraTupleSlot(estate,
+ RelationGetDescr(rel->localrel));
+ localslot = ExecInitExtraTupleSlot(estate,
+ RelationGetDescr(rel->localrel));
EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
PushActiveSnapshot(GetTransactionSnapshot());
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 621e7c3dc46..45a077a949c 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -431,9 +431,10 @@ extern void ExecScanReScan(ScanState *node);
/*
* prototypes from functions in execTuples.c
*/
-extern void ExecInitResultTupleSlot(EState *estate, PlanState *planstate);
-extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate);
-extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
+extern void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate);
+extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc);
+extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
+ TupleDesc tupleDesc);
extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
TupleDesc tupType);
extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
@@ -502,8 +503,6 @@ extern ExprContext *MakePerTupleExprContext(EState *estate);
} while (0)
extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
-extern void ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc);
-extern void ExecAssignResultTypeFromTL(PlanState *planstate);
extern TupleDesc ExecGetResultType(PlanState *planstate);
extern void ExecAssignProjectionInfo(PlanState *planstate,
TupleDesc inputDesc);
@@ -511,7 +510,7 @@ extern void ExecConditionalAssignProjectionInfo(PlanState *planstate,
TupleDesc inputDesc, Index varno);
extern void ExecFreeExprContext(PlanState *planstate);
extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc);
-extern void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate);
+extern void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate);
extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 5b54834d33e..8be0d5edc29 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -127,6 +127,7 @@ typedef struct TupleTableSlot
MinimalTuple tts_mintuple; /* minimal tuple, or NULL if none */
HeapTupleData tts_minhdr; /* workspace for minimal-tuple-only case */
long tts_off; /* saved state for slot_deform_tuple */
+ bool tts_fixedTupleDescriptor; /* descriptor can't be changed */
} TupleTableSlot;
#define TTS_HAS_PHYSICAL_TUPLE(slot) \
@@ -139,8 +140,8 @@ typedef struct TupleTableSlot
((slot) == NULL || (slot)->tts_isempty)
/* in executor/execTuples.c */
-extern TupleTableSlot *MakeTupleTableSlot(void);
-extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable);
+extern TupleTableSlot *MakeTupleTableSlot(TupleDesc desc);
+extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc);
extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);