Commit ad7dbee3 authored by Andres Freund's avatar Andres Freund

Allow tupleslots to have a fixed tupledesc, use in executor nodes.

The reason for doing so is that it will allow expression evaluation to
optimize based on the underlying tupledesc. In particular it will
allow to JIT tuple deforming together with the expression itself.

For that expression initialization needs to be moved after the
relevant slots are initialized - mostly unproblematic, except in the
case of nodeWorktablescan.c.

After doing so there's no need for ExecAssignResultType() and
ExecAssignResultTypeFromTL() anymore, as all former callers have been
converted to create a slot with a fixed descriptor.

When creating a slot with a fixed descriptor, tts_values/isnull can be
allocated together with the main slot, reducing allocation overhead
and increasing cache density a bit.

Author: Andres Freund
Discussion: https://postgr.es/m/20171206093717.vqdxe5icqttpxs3p@alap3.anarazel.de
parent bf6c614a
...@@ -2444,10 +2444,9 @@ CopyFrom(CopyState cstate) ...@@ -2444,10 +2444,9 @@ CopyFrom(CopyState cstate)
estate->es_range_table = cstate->range_table; estate->es_range_table = cstate->range_table;
/* Set up a tuple slot too */ /* Set up a tuple slot too */
myslot = ExecInitExtraTupleSlot(estate); myslot = ExecInitExtraTupleSlot(estate, tupDesc);
ExecSetSlotDescriptor(myslot, tupDesc);
/* Triggers might need a slot as well */ /* 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. */ /* Prepare to catch AFTER triggers. */
AfterTriggerBeginQuery(); AfterTriggerBeginQuery();
......
...@@ -3251,7 +3251,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo, ...@@ -3251,7 +3251,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
if (estate->es_trig_oldtup_slot == NULL) if (estate->es_trig_oldtup_slot == NULL)
{ {
oldContext = MemoryContextSwitchTo(estate->es_query_cxt); oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
estate->es_trig_oldtup_slot = ExecInitExtraTupleSlot(estate); estate->es_trig_oldtup_slot =
ExecInitExtraTupleSlot(estate, NULL);
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
} }
oldslot = estate->es_trig_oldtup_slot; oldslot = estate->es_trig_oldtup_slot;
...@@ -3264,7 +3265,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo, ...@@ -3264,7 +3265,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
if (estate->es_trig_newtup_slot == NULL) if (estate->es_trig_newtup_slot == NULL)
{ {
oldContext = MemoryContextSwitchTo(estate->es_query_cxt); oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
estate->es_trig_newtup_slot = ExecInitExtraTupleSlot(estate); estate->es_trig_newtup_slot =
ExecInitExtraTupleSlot(estate, NULL);
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
} }
newslot = estate->es_trig_newtup_slot; newslot = estate->es_trig_newtup_slot;
......
...@@ -243,6 +243,8 @@ This is a sketch of control flow for full query processing: ...@@ -243,6 +243,8 @@ This is a sketch of control flow for full query processing:
switch to per-query context to run ExecInitNode switch to per-query context to run ExecInitNode
AfterTriggerBeginQuery AfterTriggerBeginQuery
ExecInitNode --- recursively scans plan tree ExecInitNode --- recursively scans plan tree
ExecInitNode
recurse into subsidiary nodes
CreateExprContext CreateExprContext
creates per-tuple context creates per-tuple context
ExecInitExpr ExecInitExpr
......
...@@ -2415,7 +2415,7 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state) ...@@ -2415,7 +2415,7 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
scratch->d.wholerow.junkFilter = scratch->d.wholerow.junkFilter =
ExecInitJunkFilter(subplan->plan->targetlist, ExecInitJunkFilter(subplan->plan->targetlist,
ExecGetResultType(subplan)->tdhasoid, ExecGetResultType(subplan)->tdhasoid,
ExecInitExtraTupleSlot(parent->state)); ExecInitExtraTupleSlot(parent->state, NULL));
} }
} }
} }
......
...@@ -1073,7 +1073,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) ...@@ -1073,7 +1073,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
j = ExecInitJunkFilter(planstate->plan->targetlist, j = ExecInitJunkFilter(planstate->plan->targetlist,
tupType->tdhasoid, tupType->tdhasoid,
ExecInitExtraTupleSlot(estate)); ExecInitExtraTupleSlot(estate, NULL));
estate->es_junkFilter = j; estate->es_junkFilter = j;
/* Want to return the cleaned tuple type */ /* Want to return the cleaned tuple type */
......
...@@ -93,7 +93,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, ...@@ -93,7 +93,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
* We need an additional tuple slot for storing transient tuples that * We need an additional tuple slot for storing transient tuples that
* are converted to the root table descriptor. * are converted to the root table descriptor.
*/ */
proute->root_tuple_slot = MakeTupleTableSlot(); proute->root_tuple_slot = MakeTupleTableSlot(NULL);
} }
else else
{ {
...@@ -112,7 +112,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, ...@@ -112,7 +112,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
* (such as ModifyTableState) and released when the node finishes * (such as ModifyTableState) and released when the node finishes
* processing. * processing.
*/ */
proute->partition_tuple_slot = MakeTupleTableSlot(); proute->partition_tuple_slot = MakeTupleTableSlot(NULL);
i = 0; i = 0;
foreach(cell, leaf_parts) foreach(cell, leaf_parts)
......
...@@ -229,7 +229,7 @@ ExecScan(ScanState *node, ...@@ -229,7 +229,7 @@ ExecScan(ScanState *node,
* the scan node, because the planner will preferentially generate a matching * the scan node, because the planner will preferentially generate a matching
* tlist. * tlist.
* *
* ExecAssignScanType must have been called already. * The scan slot's descriptor must have been set already.
*/ */
void void
ExecAssignScanProjectionInfo(ScanState *node) ExecAssignScanProjectionInfo(ScanState *node)
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
* At ExecutorStart() * At ExecutorStart()
* ---------------- * ----------------
* - ExecInitSeqScan() calls ExecInitScanTupleSlot() and * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
* ExecInitResultTupleSlot() to construct TupleTableSlots * ExecInitResultTupleSlotTL() to construct TupleTableSlots
* for the tuples returned by the access methods and the * for the tuples returned by the access methods and the
* tuples resulting from performing target list projections. * tuples resulting from performing target list projections.
* *
...@@ -104,19 +104,36 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList, ...@@ -104,19 +104,36 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList,
/* -------------------------------- /* --------------------------------
* MakeTupleTableSlot * 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 * 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_isempty = true;
slot->tts_shouldFree = false; slot->tts_shouldFree = false;
slot->tts_shouldFreeMin = false; slot->tts_shouldFreeMin = false;
slot->tts_tuple = NULL; slot->tts_tuple = NULL;
slot->tts_tupleDescriptor = NULL; slot->tts_fixedTupleDescriptor = tupleDesc != NULL;
slot->tts_tupleDescriptor = tupleDesc;
slot->tts_mcxt = CurrentMemoryContext; slot->tts_mcxt = CurrentMemoryContext;
slot->tts_buffer = InvalidBuffer; slot->tts_buffer = InvalidBuffer;
slot->tts_nvalid = 0; slot->tts_nvalid = 0;
...@@ -124,6 +141,19 @@ MakeTupleTableSlot(void) ...@@ -124,6 +141,19 @@ MakeTupleTableSlot(void)
slot->tts_isnull = NULL; slot->tts_isnull = NULL;
slot->tts_mintuple = 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; return slot;
} }
...@@ -134,9 +164,9 @@ MakeTupleTableSlot(void) ...@@ -134,9 +164,9 @@ MakeTupleTableSlot(void)
* -------------------------------- * --------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecAllocTableSlot(List **tupleTable) ExecAllocTableSlot(List **tupleTable, TupleDesc desc)
{ {
TupleTableSlot *slot = MakeTupleTableSlot(); TupleTableSlot *slot = MakeTupleTableSlot(desc);
*tupleTable = lappend(*tupleTable, slot); *tupleTable = lappend(*tupleTable, slot);
...@@ -173,10 +203,13 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */ ...@@ -173,10 +203,13 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
/* If shouldFree, release memory occupied by the slot itself */ /* If shouldFree, release memory occupied by the slot itself */
if (shouldFree) if (shouldFree)
{ {
if (slot->tts_values) if (!slot->tts_fixedTupleDescriptor)
pfree(slot->tts_values); {
if (slot->tts_isnull) if (slot->tts_values)
pfree(slot->tts_isnull); pfree(slot->tts_values);
if (slot->tts_isnull)
pfree(slot->tts_isnull);
}
pfree(slot); pfree(slot);
} }
} }
...@@ -198,9 +231,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */ ...@@ -198,9 +231,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
TupleTableSlot * TupleTableSlot *
MakeSingleTupleTableSlot(TupleDesc tupdesc) MakeSingleTupleTableSlot(TupleDesc tupdesc)
{ {
TupleTableSlot *slot = MakeTupleTableSlot(); TupleTableSlot *slot = MakeTupleTableSlot(tupdesc);
ExecSetSlotDescriptor(slot, tupdesc);
return slot; return slot;
} }
...@@ -220,10 +251,13 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot) ...@@ -220,10 +251,13 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
ExecClearTuple(slot); ExecClearTuple(slot);
if (slot->tts_tupleDescriptor) if (slot->tts_tupleDescriptor)
ReleaseTupleDesc(slot->tts_tupleDescriptor); ReleaseTupleDesc(slot->tts_tupleDescriptor);
if (slot->tts_values) if (!slot->tts_fixedTupleDescriptor)
pfree(slot->tts_values); {
if (slot->tts_isnull) if (slot->tts_values)
pfree(slot->tts_isnull); pfree(slot->tts_values);
if (slot->tts_isnull)
pfree(slot->tts_isnull);
}
pfree(slot); pfree(slot);
} }
...@@ -247,6 +281,8 @@ void ...@@ -247,6 +281,8 @@ void
ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */ ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
TupleDesc tupdesc) /* new tuple descriptor */ TupleDesc tupdesc) /* new tuple descriptor */
{ {
Assert(!slot->tts_fixedTupleDescriptor);
/* For safety, make sure slot is empty before changing it */ /* For safety, make sure slot is empty before changing it */
ExecClearTuple(slot); ExecClearTuple(slot);
...@@ -816,7 +852,7 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot) ...@@ -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 * These are convenience routines to initialize the specified slot
* in nodes inheriting the appropriate state. ExecInitExtraTupleSlot * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
...@@ -825,13 +861,30 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot) ...@@ -825,13 +861,30 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
*/ */
/* ---------------- /* ----------------
* ExecInitResultTupleSlot * ExecInitResultTupleSlotTL
*
* Initialize result tuple slot, using the plan node's targetlist.
* ---------------- * ----------------
*/ */
void 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) ...@@ -839,19 +892,24 @@ ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
* ---------------- * ----------------
*/ */
void 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 * 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 * 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) ...@@ -865,9 +923,7 @@ ExecInitExtraTupleSlot(EState *estate)
TupleTableSlot * TupleTableSlot *
ExecInitNullTupleSlot(EState *estate, TupleDesc tupType) ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
{ {
TupleTableSlot *slot = ExecInitExtraTupleSlot(estate); TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType);
ExecSetSlotDescriptor(slot, tupType);
return ExecStoreAllNullTuple(slot); return ExecStoreAllNullTuple(slot);
} }
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* ReScanExprContext * ReScanExprContext
* *
* ExecAssignExprContext Common code for plan node init routines. * ExecAssignExprContext Common code for plan node init routines.
* ExecAssignResultType
* etc * etc
* *
* ExecOpenScanRelation Common code for scan node init routines. * ExecOpenScanRelation Common code for scan node init routines.
...@@ -428,47 +427,6 @@ ExecAssignExprContext(EState *estate, PlanState *planstate) ...@@ -428,47 +427,6 @@ ExecAssignExprContext(EState *estate, PlanState *planstate)
planstate->ps_ExprContext = CreateExprContext(estate); planstate->ps_ExprContext = CreateExprContext(estate);
} }
/* ----------------
* 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 * ExecGetResultType
* ---------------- * ----------------
...@@ -609,13 +567,9 @@ ExecFreeExprContext(PlanState *planstate) ...@@ -609,13 +567,9 @@ ExecFreeExprContext(PlanState *planstate)
planstate->ps_ExprContext = NULL; planstate->ps_ExprContext = NULL;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* the following scan type support functions are for * Scan node support
* 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
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
...@@ -632,11 +586,11 @@ ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc) ...@@ -632,11 +586,11 @@ ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
} }
/* ---------------- /* ----------------
* ExecAssignScanTypeFromOuterPlan * ExecCreateSlotFromOuterPlan
* ---------------- * ----------------
*/ */
void void
ExecAssignScanTypeFromOuterPlan(ScanState *scanstate) ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
{ {
PlanState *outerPlan; PlanState *outerPlan;
TupleDesc tupDesc; TupleDesc tupDesc;
...@@ -644,15 +598,9 @@ ExecAssignScanTypeFromOuterPlan(ScanState *scanstate) ...@@ -644,15 +598,9 @@ ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
outerPlan = outerPlanState(scanstate); outerPlan = outerPlanState(scanstate);
tupDesc = ExecGetResultType(outerPlan); tupDesc = ExecGetResultType(outerPlan);
ExecAssignScanType(scanstate, tupDesc); ExecInitScanTupleSlot(estate, scanstate, tupDesc);
} }
/* ----------------------------------------------------------------
* Scan node support
* ----------------------------------------------------------------
*/
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecRelationIsTargetRelation * ExecRelationIsTargetRelation
* *
......
...@@ -1402,8 +1402,8 @@ find_hash_columns(AggState *aggstate) ...@@ -1402,8 +1402,8 @@ find_hash_columns(AggState *aggstate)
perhash->aggnode->grpOperators, perhash->aggnode->grpOperators,
&perhash->eqfuncoids, &perhash->eqfuncoids,
&perhash->hashfunctions); &perhash->hashfunctions);
perhash->hashslot = ExecAllocTableSlot(&estate->es_tupleTable); perhash->hashslot =
ExecSetSlotDescriptor(perhash->hashslot, hashDesc); ExecAllocTableSlot(&estate->es_tupleTable, hashDesc);
list_free(hashTlist); list_free(hashTlist);
bms_free(colnos); bms_free(colnos);
...@@ -2198,31 +2198,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2198,31 +2198,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &aggstate->ss.ps); 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. * Initialize child nodes.
* *
...@@ -2237,17 +2212,33 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ...@@ -2237,17 +2212,33 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
/* /*
* initialize source tuple type. * initialize source tuple type.
*/ */
ExecAssignScanTypeFromOuterPlan(&aggstate->ss); ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss);
scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor; scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
if (node->chain) 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); 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. * We should now have found all Aggrefs in the targetlist and quals.
*/ */
...@@ -3071,8 +3062,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, ...@@ -3071,8 +3062,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
if (numSortCols > 0 || aggref->aggfilter) if (numSortCols > 0 || aggref->aggfilter)
{ {
pertrans->sortdesc = ExecTypeFromTL(aggref->args, false); pertrans->sortdesc = ExecTypeFromTL(aggref->args, false);
pertrans->sortslot = ExecInitExtraTupleSlot(estate); pertrans->sortslot =
ExecSetSlotDescriptor(pertrans->sortslot, pertrans->sortdesc); ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
} }
if (numSortCols > 0) if (numSortCols > 0)
...@@ -3093,9 +3084,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, ...@@ -3093,9 +3084,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
else if (numDistinctCols > 0) else if (numDistinctCols > 0)
{ {
/* we will need an extra slot to store prior values */ /* we will need an extra slot to store prior values */
pertrans->uniqslot = ExecInitExtraTupleSlot(estate); pertrans->uniqslot =
ExecSetSlotDescriptor(pertrans->uniqslot, ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
pertrans->sortdesc);
} }
/* Extract the sort information for use later */ /* Extract the sort information for use later */
......
...@@ -129,17 +129,9 @@ ExecInitAppend(Append *node, EState *estate, int eflags) ...@@ -129,17 +129,9 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
appendstate->as_nplans = nplans; appendstate->as_nplans = nplans;
/* /*
* Miscellaneous initialization * Initialize result tuple type and slot.
*
* Append plans don't have expression contexts because they never call
* ExecQual or ExecProject.
*/ */
ExecInitResultTupleSlotTL(estate, &appendstate->ps);
/*
* append nodes still have Result slots, which hold pointers to tuples, so
* we have to initialize them.
*/
ExecInitResultTupleSlot(estate, &appendstate->ps);
/* /*
* call ExecInitNode on each of the plans to be executed and save the * call ExecInitNode on each of the plans to be executed and save the
...@@ -155,9 +147,11 @@ ExecInitAppend(Append *node, EState *estate, int eflags) ...@@ -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; appendstate->ps.ps_ProjInfo = NULL;
/* /*
......
...@@ -80,13 +80,6 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags) ...@@ -80,13 +80,6 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
bitmapandstate->bitmapplans = bitmapplanstates; bitmapandstate->bitmapplans = bitmapplanstates;
bitmapandstate->nplans = nplans; 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 * call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates". * results into the array "bitmapplanstates".
...@@ -99,6 +92,13 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags) ...@@ -99,6 +92,13 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
i++; 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; return bitmapandstate;
} }
......
...@@ -907,23 +907,39 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) ...@@ -907,23 +907,39 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); ExecAssignExprContext(estate, &scanstate->ss.ps);
/* /*
* initialize child expressions * open the base relation and acquire appropriate lock on it.
*/ */
scanstate->ss.ps.qual = currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
scanstate->bitmapqualorig = /*
ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate); * 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 * Determine the maximum for prefetch_target. If the tablespace has a
...@@ -952,26 +968,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) ...@@ -952,26 +968,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
0, 0,
NULL); 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. * all done.
*/ */
......
...@@ -226,6 +226,15 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags) ...@@ -226,6 +226,15 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
/* normally we don't make the result bitmap till runtime */ /* normally we don't make the result bitmap till runtime */
indexstate->biss_result = NULL; 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 * Miscellaneous initialization
* *
...@@ -242,15 +251,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags) ...@@ -242,15 +251,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
* sub-parts corresponding to runtime keys (see below). * sub-parts corresponding to runtime keys (see below).
*/ */
/*
* 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 * 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 * here. This allows an index-advisor plugin to EXPLAIN a plan containing
......
...@@ -81,13 +81,6 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags) ...@@ -81,13 +81,6 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
bitmaporstate->bitmapplans = bitmapplanstates; bitmaporstate->bitmapplans = bitmapplanstates;
bitmaporstate->nplans = nplans; 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 * call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates". * results into the array "bitmapplanstates".
...@@ -100,6 +93,13 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags) ...@@ -100,6 +93,13 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
i++; 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; return bitmaporstate;
} }
......
...@@ -242,31 +242,25 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags) ...@@ -242,31 +242,25 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &scanstate->ss.ps); 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 * 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. * table) is the same as the result rowtype of the CTE query.
*/ */
ExecAssignScanType(&scanstate->ss, ExecInitScanTupleSlot(estate, &scanstate->ss,
ExecGetResultType(scanstate->cteplanstate)); 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); ExecAssignScanProjectionInfo(&scanstate->ss);
/*
* initialize child expressions
*/
scanstate->ss.ps.qual =
ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
return scanstate; return scanstate;
} }
......
...@@ -54,14 +54,6 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) ...@@ -54,14 +54,6 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
/* create expression context for node */ /* create expression context for node */
ExecAssignExprContext(estate, &css->ss.ps); 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 * open the base relation, if any, and acquire an appropriate lock on it
*/ */
...@@ -81,23 +73,27 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) ...@@ -81,23 +73,27 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
TupleDesc scan_tupdesc; TupleDesc scan_tupdesc;
scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false); 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 */ /* Node's targetlist will contain Vars with varno = INDEX_VAR */
tlistvarno = INDEX_VAR; tlistvarno = INDEX_VAR;
} }
else else
{ {
ExecAssignScanType(&css->ss, RelationGetDescr(scan_rel)); ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel));
/* Node's targetlist will contain Vars with varno = scanrelid */ /* Node's targetlist will contain Vars with varno = scanrelid */
tlistvarno = 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); 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 * The callback of custom-scan provider applies the final initialization
* of the custom-scan-state node according to its logic. * of the custom-scan-state node according to its logic.
......
...@@ -155,20 +155,6 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) ...@@ -155,20 +155,6 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &scanstate->ss.ps); 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; * open the base relation, if any, and acquire an appropriate lock on it;
* also acquire function pointers from the FDW's handler * also acquire function pointers from the FDW's handler
...@@ -194,23 +180,31 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) ...@@ -194,23 +180,31 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
TupleDesc scan_tupdesc; TupleDesc scan_tupdesc;
scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist, false); 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 */ /* Node's targetlist will contain Vars with varno = INDEX_VAR */
tlistvarno = INDEX_VAR; tlistvarno = INDEX_VAR;
} }
else else
{ {
ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); ExecInitScanTupleSlot(estate, &scanstate->ss, RelationGetDescr(currentRelation));
/* Node's targetlist will contain Vars with varno = scanrelid */ /* Node's targetlist will contain Vars with varno = scanrelid */
tlistvarno = 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); 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. * Initialize FDW-related state.
*/ */
......
...@@ -334,18 +334,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -334,18 +334,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &scanstate->ss.ps); 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)); scanstate->funcstates = palloc(nfuncs * sizeof(FunctionScanPerFuncState));
natts = 0; natts = 0;
...@@ -436,8 +424,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -436,8 +424,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
*/ */
if (!scanstate->simple) if (!scanstate->simple)
{ {
fs->func_slot = ExecInitExtraTupleSlot(estate); fs->func_slot = ExecInitExtraTupleSlot(estate, fs->tupdesc);
ExecSetSlotDescriptor(fs->func_slot, fs->tupdesc);
} }
else else
fs->func_slot = NULL; fs->func_slot = NULL;
...@@ -492,14 +479,23 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -492,14 +479,23 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
Assert(attno == natts); 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); 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 * Create a memory context that ExecMakeTableFunctionResult can use to
* evaluate function arguments in. We can't use the per-tuple context for * evaluate function arguments in. We can't use the per-tuple context for
......
...@@ -59,7 +59,6 @@ ExecInitGather(Gather *node, EState *estate, int eflags) ...@@ -59,7 +59,6 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
{ {
GatherState *gatherstate; GatherState *gatherstate;
Plan *outerNode; Plan *outerNode;
bool hasoid;
TupleDesc tupDesc; TupleDesc tupDesc;
/* Gather node doesn't have innerPlan node. */ /* Gather node doesn't have innerPlan node. */
...@@ -85,37 +84,29 @@ ExecInitGather(Gather *node, EState *estate, int eflags) ...@@ -85,37 +84,29 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &gatherstate->ps); 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 * now initialize outer plan
*/ */
outerNode = outerPlan(node); outerNode = outerPlan(node);
outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags); 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. * Initialize funnel slot to same tuple descriptor as outer plan.
*/ */
if (!ExecContextForcesOids(outerPlanState(gatherstate), &hasoid)) gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc);
hasoid = false;
tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid);
ExecSetSlotDescriptor(gatherstate->funnel_slot, 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); Assert(!node->plan.qual);
ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR);
return gatherstate; return gatherstate;
} }
......
...@@ -73,7 +73,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) ...@@ -73,7 +73,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
{ {
GatherMergeState *gm_state; GatherMergeState *gm_state;
Plan *outerNode; Plan *outerNode;
bool hasoid;
TupleDesc tupDesc; TupleDesc tupDesc;
/* Gather merge node doesn't have innerPlan node. */ /* Gather merge node doesn't have innerPlan node. */
...@@ -104,11 +103,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) ...@@ -104,11 +103,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
*/ */
Assert(!node->plan.qual); Assert(!node->plan.qual);
/*
* tuple table initialization
*/
ExecInitResultTupleSlot(estate, &gm_state->ps);
/* /*
* now initialize outer plan * now initialize outer plan
*/ */
...@@ -119,15 +113,13 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) ...@@ -119,15 +113,13 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
* Store the tuple descriptor into gather merge state, so we can use it * Store the tuple descriptor into gather merge state, so we can use it
* while initializing the gather merge slots. * while initializing the gather merge slots.
*/ */
if (!ExecContextForcesOids(outerPlanState(gm_state), &hasoid)) tupDesc = ExecGetResultType(outerPlanState(gm_state));
hasoid = false;
tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid);
gm_state->tupDesc = tupDesc; 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); ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR);
/* /*
...@@ -410,9 +402,8 @@ gather_merge_setup(GatherMergeState *gm_state) ...@@ -410,9 +402,8 @@ gather_merge_setup(GatherMergeState *gm_state)
(HeapTuple *) palloc0(sizeof(HeapTuple) * MAX_TUPLE_STORE); (HeapTuple *) palloc0(sizeof(HeapTuple) * MAX_TUPLE_STORE);
/* Initialize tuple slot for worker */ /* Initialize tuple slot for worker */
gm_state->gm_slots[i + 1] = ExecInitExtraTupleSlot(gm_state->ps.state); gm_state->gm_slots[i + 1] =
ExecSetSlotDescriptor(gm_state->gm_slots[i + 1], ExecInitExtraTupleSlot(gm_state->ps.state, gm_state->tupDesc);
gm_state->tupDesc);
} }
/* Allocate the resources for the merge */ /* Allocate the resources for the merge */
......
...@@ -181,34 +181,28 @@ ExecInitGroup(Group *node, EState *estate, int eflags) ...@@ -181,34 +181,28 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &grpstate->ss.ps); 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 * initialize child nodes
*/ */
outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate, eflags); 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); 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 * Precompute fmgr lookup data for inner loop
*/ */
......
...@@ -373,29 +373,24 @@ ExecInitHash(Hash *node, EState *estate, int eflags) ...@@ -373,29 +373,24 @@ ExecInitHash(Hash *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &hashstate->ps); 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 * initialize child nodes
*/ */
outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate, eflags); outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate, eflags);
/* /*
* initialize tuple type. no need to initialize projection info because * initialize our result slot and type. No need to build projection
* this node doesn't do projections * because this node doesn't do projections.
*/ */
ExecAssignResultTypeFromTL(&hashstate->ps); ExecInitResultTupleSlotTL(estate, &hashstate->ps);
hashstate->ps.ps_ProjInfo = NULL; hashstate->ps.ps_ProjInfo = NULL;
/*
* initialize child expressions
*/
hashstate->ps.qual =
ExecInitQual(node->plan.qual, (PlanState *) hashstate);
return hashstate; return hashstate;
} }
......
...@@ -596,6 +596,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) ...@@ -596,6 +596,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
List *lclauses; List *lclauses;
List *rclauses; List *rclauses;
List *hoperators; List *hoperators;
TupleDesc outerDesc, innerDesc;
ListCell *l; ListCell *l;
/* check for unsupported flags */ /* check for unsupported flags */
...@@ -614,6 +615,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) ...@@ -614,6 +615,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
* managed to launch a parallel query. * managed to launch a parallel query.
*/ */
hjstate->js.ps.ExecProcNode = ExecHashJoin; hjstate->js.ps.ExecProcNode = ExecHashJoin;
hjstate->js.jointype = node->join.jointype;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
...@@ -622,17 +624,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) ...@@ -622,17 +624,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &hjstate->js.ps); 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 * initialize child nodes
* *
...@@ -644,13 +635,20 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) ...@@ -644,13 +635,20 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
hashNode = (Hash *) innerPlan(node); hashNode = (Hash *) innerPlan(node);
outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags); outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags);
outerDesc = ExecGetResultType(outerPlanState(hjstate));
innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate, eflags); 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 * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &hjstate->js.ps); hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc);
hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
/* /*
* detect whether we need only consider the first matching inner tuple * detect whether we need only consider the first matching inner tuple
...@@ -667,21 +665,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) ...@@ -667,21 +665,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
case JOIN_LEFT: case JOIN_LEFT:
case JOIN_ANTI: case JOIN_ANTI:
hjstate->hj_NullInnerTupleSlot = hjstate->hj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, innerDesc);
ExecGetResultType(innerPlanState(hjstate)));
break; break;
case JOIN_RIGHT: case JOIN_RIGHT:
hjstate->hj_NullOuterTupleSlot = hjstate->hj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, outerDesc);
ExecGetResultType(outerPlanState(hjstate)));
break; break;
case JOIN_FULL: case JOIN_FULL:
hjstate->hj_NullOuterTupleSlot = hjstate->hj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, outerDesc);
ExecGetResultType(outerPlanState(hjstate)));
hjstate->hj_NullInnerTupleSlot = hjstate->hj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, innerDesc);
ExecGetResultType(innerPlanState(hjstate)));
break; break;
default: default:
elog(ERROR, "unrecognized join type: %d", elog(ERROR, "unrecognized join type: %d",
...@@ -703,13 +697,14 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) ...@@ -703,13 +697,14 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
} }
/* /*
* initialize tuple type and projection info * initialize child expressions
*/ */
ExecAssignResultTypeFromTL(&hjstate->js.ps); hjstate->js.ps.qual =
ExecAssignProjectionInfo(&hjstate->js.ps, NULL); ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
hjstate->js.joinqual =
ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot, ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
ExecGetResultType(outerPlanState(hjstate))); hjstate->hashclauses =
ExecInitQual(node->hashclauses, (PlanState *) hjstate);
/* /*
* initialize hash-specific info * initialize hash-specific info
......
...@@ -518,23 +518,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) ...@@ -518,23 +518,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &indexstate->ss.ps); 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. * open the base relation and acquire appropriate lock on it.
*/ */
...@@ -551,16 +534,27 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) ...@@ -551,16 +534,27 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
* suitable data anyway.) * suitable data anyway.)
*/ */
tupDesc = ExecTypeFromTL(node->indextlist, false); 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 * targetlist will contain Vars with varno = INDEX_VAR, referencing the
* scan tuple. * scan tuple.
*/ */
ExecAssignResultTypeFromTL(&indexstate->ss.ps); ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
ExecAssignScanProjectionInfoWithVarno(&indexstate->ss, INDEX_VAR); 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 * 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 * here. This allows an index-advisor plugin to EXPLAIN a plan containing
......
...@@ -940,6 +940,26 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) ...@@ -940,6 +940,26 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &indexstate->ss.ps); 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 * initialize child expressions
* *
...@@ -957,31 +977,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) ...@@ -957,31 +977,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
indexstate->indexorderbyorig = indexstate->indexorderbyorig =
ExecInitExprList(node->indexorderbyorig, (PlanState *) indexstate); 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 * 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 * here. This allows an index-advisor plugin to EXPLAIN a plan containing
......
...@@ -353,6 +353,12 @@ ExecInitLimit(Limit *node, EState *estate, int eflags) ...@@ -353,6 +353,12 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &limitstate->ps); ExecAssignExprContext(estate, &limitstate->ps);
/*
* initialize outer plan
*/
outerPlan = outerPlan(node);
outerPlanState(limitstate) = ExecInitNode(outerPlan, estate, eflags);
/* /*
* initialize child expressions * initialize child expressions
*/ */
...@@ -362,21 +368,15 @@ ExecInitLimit(Limit *node, EState *estate, int eflags) ...@@ -362,21 +368,15 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
(PlanState *) limitstate); (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); ExecInitResultTupleSlotTL(estate, &limitstate->ps);
/*
* then initialize outer plan
*/
outerPlan = outerPlan(node);
outerPlanState(limitstate) = ExecInitNode(outerPlan, estate, eflags);
/* /*
* limit nodes do no projections, so initialize projection info for this * limit nodes do no projections, so initialize projection info for this
* node appropriately * node appropriately
*/ */
ExecAssignResultTypeFromTL(&limitstate->ps);
limitstate->ps.ps_ProjInfo = NULL; limitstate->ps.ps_ProjInfo = NULL;
return limitstate; return limitstate;
......
...@@ -370,13 +370,15 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags) ...@@ -370,13 +370,15 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
/* /*
* Miscellaneous initialization * 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 * then initialize outer plan
...@@ -387,7 +389,6 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags) ...@@ -387,7 +389,6 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
* LockRows nodes do no projections, so initialize projection info for * LockRows nodes do no projections, so initialize projection info for
* this node appropriately * this node appropriately
*/ */
ExecAssignResultTypeFromTL(&lrstate->ps);
lrstate->ps.ps_ProjInfo = NULL; lrstate->ps.ps_ProjInfo = NULL;
/* /*
......
...@@ -206,14 +206,6 @@ ExecInitMaterial(Material *node, EState *estate, int eflags) ...@@ -206,14 +206,6 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
* ExecQual or ExecProject. * ExecQual or ExecProject.
*/ */
/*
* tuple table initialization
*
* material nodes only return tuples from their materialized relation.
*/
ExecInitResultTupleSlot(estate, &matstate->ss.ps);
ExecInitScanTupleSlot(estate, &matstate->ss);
/* /*
* initialize child nodes * initialize child nodes
* *
...@@ -226,13 +218,19 @@ ExecInitMaterial(Material *node, EState *estate, int eflags) ...@@ -226,13 +218,19 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags); outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags);
/* /*
* initialize tuple type. no need to initialize projection info because * Initialize result type and slot. No need to initialize projection info
* this node doesn't do projections. * because this node doesn't do projections.
*
* material nodes only return tuples from their materialized relation.
*/ */
ExecAssignResultTypeFromTL(&matstate->ss.ps); ExecInitResultTupleSlotTL(estate, &matstate->ss.ps);
ExecAssignScanTypeFromOuterPlan(&matstate->ss);
matstate->ss.ps.ps_ProjInfo = NULL; matstate->ss.ps.ps_ProjInfo = NULL;
/*
* initialize tuple type.
*/
ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss);
return matstate; return matstate;
} }
......
...@@ -109,7 +109,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) ...@@ -109,7 +109,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
* MergeAppend nodes do have Result slots, which hold pointers to tuples, * MergeAppend nodes do have Result slots, which hold pointers to tuples,
* so we have to initialize them. * 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 * call ExecInitNode on each of the plans to be executed and save the
...@@ -124,10 +124,6 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) ...@@ -124,10 +124,6 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
i++; i++;
} }
/*
* initialize output tuple type
*/
ExecAssignResultTypeFromTL(&mergestate->ps);
mergestate->ps.ps_ProjInfo = NULL; mergestate->ps.ps_ProjInfo = NULL;
/* /*
......
...@@ -1436,6 +1436,7 @@ MergeJoinState * ...@@ -1436,6 +1436,7 @@ MergeJoinState *
ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
{ {
MergeJoinState *mergestate; MergeJoinState *mergestate;
TupleDesc outerDesc, innerDesc;
/* check for unsupported flags */ /* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
...@@ -1450,6 +1451,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ...@@ -1450,6 +1451,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->js.ps.plan = (Plan *) node; mergestate->js.ps.plan = (Plan *) node;
mergestate->js.ps.state = estate; mergestate->js.ps.state = estate;
mergestate->js.ps.ExecProcNode = ExecMergeJoin; mergestate->js.ps.ExecProcNode = ExecMergeJoin;
mergestate->js.jointype = node->join.jointype;
mergestate->mj_ConstFalseJoin = false;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
...@@ -1466,17 +1469,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ...@@ -1466,17 +1469,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_OuterEContext = CreateExprContext(estate); mergestate->mj_OuterEContext = CreateExprContext(estate);
mergestate->mj_InnerEContext = CreateExprContext(estate); 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 * initialize child nodes
* *
...@@ -1488,10 +1480,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ...@@ -1488,10 +1480,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_SkipMarkRestore = node->skip_mark_restore; mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags); outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
outerDesc = ExecGetResultType(outerPlanState(mergestate));
innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate, innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
mergestate->mj_SkipMarkRestore ? mergestate->mj_SkipMarkRestore ?
eflags : eflags :
(eflags | EXEC_FLAG_MARK)); (eflags | EXEC_FLAG_MARK));
innerDesc = ExecGetResultType(innerPlanState(mergestate));
/* /*
* For certain types of inner child nodes, it is advantageous to issue * For certain types of inner child nodes, it is advantageous to issue
...@@ -1514,14 +1508,25 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ...@@ -1514,14 +1508,25 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
else else
mergestate->mj_ExtraMarks = false; mergestate->mj_ExtraMarks = false;
/*
* Initialize result slot, type and projection.
*/
ExecInitResultTupleSlotTL(estate, &mergestate->js.ps);
ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &mergestate->js.ps); mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc);
mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate); /*
ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot, * initialize child expressions
ExecGetResultType(innerPlanState(mergestate))); */
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 * detect whether we need only consider the first matching inner tuple
...@@ -1542,15 +1547,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ...@@ -1542,15 +1547,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_FillOuter = true; mergestate->mj_FillOuter = true;
mergestate->mj_FillInner = false; mergestate->mj_FillInner = false;
mergestate->mj_NullInnerTupleSlot = mergestate->mj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, innerDesc);
ExecGetResultType(innerPlanState(mergestate)));
break; break;
case JOIN_RIGHT: case JOIN_RIGHT:
mergestate->mj_FillOuter = false; mergestate->mj_FillOuter = false;
mergestate->mj_FillInner = true; mergestate->mj_FillInner = true;
mergestate->mj_NullOuterTupleSlot = mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, outerDesc);
ExecGetResultType(outerPlanState(mergestate)));
/* /*
* Can't handle right or full join with non-constant extra * Can't handle right or full join with non-constant extra
...@@ -1566,11 +1569,9 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ...@@ -1566,11 +1569,9 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_FillOuter = true; mergestate->mj_FillOuter = true;
mergestate->mj_FillInner = true; mergestate->mj_FillInner = true;
mergestate->mj_NullOuterTupleSlot = mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, outerDesc);
ExecGetResultType(outerPlanState(mergestate)));
mergestate->mj_NullInnerTupleSlot = mergestate->mj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate, innerDesc);
ExecGetResultType(innerPlanState(mergestate)));
/* /*
* Can't handle right or full join with non-constant extra * Can't handle right or full join with non-constant extra
...@@ -1587,12 +1588,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ...@@ -1587,12 +1588,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
(int) node->join.jointype); (int) node->join.jointype);
} }
/*
* initialize tuple type and projection info
*/
ExecAssignResultTypeFromTL(&mergestate->js.ps);
ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
/* /*
* preprocess the merge clauses * preprocess the merge clauses
*/ */
......
...@@ -2367,8 +2367,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ...@@ -2367,8 +2367,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists); mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
/* Set up a slot for the output of the RETURNING projection(s) */ /* Set up a slot for the output of the RETURNING projection(s) */
ExecInitResultTupleSlot(estate, &mtstate->ps); ExecInitResultTupleSlotTL(estate, &mtstate->ps);
ExecAssignResultTypeFromTL(&mtstate->ps);
slot = mtstate->ps.ps_ResultTupleSlot; slot = mtstate->ps.ps_ResultTupleSlot;
/* Need an econtext too */ /* Need an econtext too */
...@@ -2435,8 +2434,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ...@@ -2435,8 +2434,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* expects one (maybe should change that?). * expects one (maybe should change that?).
*/ */
mtstate->ps.plan->targetlist = NIL; mtstate->ps.plan->targetlist = NIL;
ExecInitResultTupleSlot(estate, &mtstate->ps); ExecInitResultTupleSlotTL(estate, &mtstate->ps);
ExecAssignResultTypeFromTL(&mtstate->ps);
mtstate->ps.ps_ExprContext = NULL; mtstate->ps.ps_ExprContext = NULL;
} }
...@@ -2449,6 +2447,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ...@@ -2449,6 +2447,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (node->onConflictAction == ONCONFLICT_UPDATE) if (node->onConflictAction == ONCONFLICT_UPDATE)
{ {
ExprContext *econtext; ExprContext *econtext;
TupleDesc relationDesc;
TupleDesc tupDesc; TupleDesc tupDesc;
/* insert may only have one plan, inheritance is not expanded */ /* insert may only have one plan, inheritance is not expanded */
...@@ -2459,26 +2458,26 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ...@@ -2459,26 +2458,26 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &mtstate->ps); ExecAssignExprContext(estate, &mtstate->ps);
econtext = mtstate->ps.ps_ExprContext; econtext = mtstate->ps.ps_ExprContext;
relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
/* initialize slot for the existing tuple */ /* initialize slot for the existing tuple */
mtstate->mt_existing = ExecInitExtraTupleSlot(mtstate->ps.state); mtstate->mt_existing =
ExecSetSlotDescriptor(mtstate->mt_existing, ExecInitExtraTupleSlot(mtstate->ps.state, relationDesc);
resultRelInfo->ri_RelationDesc->rd_att);
/* carried forward solely for the benefit of explain */ /* carried forward solely for the benefit of explain */
mtstate->mt_excludedtlist = node->exclRelTlist; mtstate->mt_excludedtlist = node->exclRelTlist;
/* create target slot for UPDATE SET projection */ /* create target slot for UPDATE SET projection */
tupDesc = ExecTypeFromTL((List *) node->onConflictSet, tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
resultRelInfo->ri_RelationDesc->rd_rel->relhasoids); relationDesc->tdhasoid);
mtstate->mt_conflproj = ExecInitExtraTupleSlot(mtstate->ps.state); mtstate->mt_conflproj =
ExecSetSlotDescriptor(mtstate->mt_conflproj, tupDesc); ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc);
/* build UPDATE SET projection state */ /* build UPDATE SET projection state */
resultRelInfo->ri_onConflictSetProj = resultRelInfo->ri_onConflictSetProj =
ExecBuildProjectionInfo(node->onConflictSet, econtext, ExecBuildProjectionInfo(node->onConflictSet, econtext,
mtstate->mt_conflproj, &mtstate->ps, mtstate->mt_conflproj, &mtstate->ps,
resultRelInfo->ri_RelationDesc->rd_att); relationDesc);
/* build DO UPDATE WHERE clause expression */ /* build DO UPDATE WHERE clause expression */
if (node->onConflictWhere) if (node->onConflictWhere)
...@@ -2583,7 +2582,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ...@@ -2583,7 +2582,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
j = ExecInitJunkFilter(subplan->targetlist, j = ExecInitJunkFilter(subplan->targetlist,
resultRelInfo->ri_RelationDesc->rd_att->tdhasoid, resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
ExecInitExtraTupleSlot(estate)); ExecInitExtraTupleSlot(estate, NULL));
if (operation == CMD_UPDATE || operation == CMD_DELETE) if (operation == CMD_UPDATE || operation == CMD_DELETE)
{ {
...@@ -2633,7 +2632,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ...@@ -2633,7 +2632,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* we keep it in the estate. * we keep it in the estate.
*/ */
if (estate->es_trig_tuple_slot == NULL) 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 * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
......
...@@ -133,26 +133,21 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag ...@@ -133,26 +133,21 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
ExecAssignExprContext(estate, &scanstate->ss.ps); 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 = ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc);
/* /*
* tuple table initialization * initialize child expressions
*/
ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
ExecInitScanTupleSlot(estate, &scanstate->ss);
/*
* The scan tuple type is specified for the tuplestore.
*/ */
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); ExecAssignScanProjectionInfo(&scanstate->ss);
return scanstate; return scanstate;
......
...@@ -285,15 +285,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags) ...@@ -285,15 +285,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &nlstate->js.ps); 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 * initialize child nodes
* *
...@@ -311,9 +302,19 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags) ...@@ -311,9 +302,19 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate, 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 * detect whether we need only consider the first matching inner tuple
...@@ -338,12 +339,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags) ...@@ -338,12 +339,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
(int) node->join.jointype); (int) node->join.jointype);
} }
/*
* initialize tuple type and projection info
*/
ExecAssignResultTypeFromTL(&nlstate->js.ps);
ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
/* /*
* finally, wipe the current outer tuple clean. * finally, wipe the current outer tuple clean.
*/ */
......
...@@ -243,14 +243,6 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags) ...@@ -243,14 +243,6 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &state->ps); 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 * initialize child nodes
*/ */
...@@ -262,9 +254,9 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags) ...@@ -262,9 +254,9 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
Assert(innerPlan(node) == NULL); 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 */ /* Create workspace for per-tlist-entry expr state & SRF-is-done state */
state->nelems = list_length(node->plan.targetlist); state->nelems = list_length(node->plan.targetlist);
...@@ -301,6 +293,8 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags) ...@@ -301,6 +293,8 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
off++; 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 * Create a memory context that ExecMakeFunctionResult can use to evaluate
......
...@@ -229,14 +229,13 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags) ...@@ -229,14 +229,13 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags)
* RecursiveUnion nodes still have Result slots, which hold pointers to * RecursiveUnion nodes still have Result slots, which hold pointers to
* tuples, so we have to initialize them. * 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 * Initialize result tuple type. (Note: we have to set up the result type
* set up the result type before initializing child nodes, because * before initializing child nodes, because nodeWorktablescan.c expects it
* nodeWorktablescan.c expects it to be valid.) * to be valid.)
*/ */
ExecAssignResultTypeFromTL(&rustate->ps);
rustate->ps.ps_ProjInfo = NULL; rustate->ps.ps_ProjInfo = NULL;
/* /*
......
...@@ -204,19 +204,6 @@ ExecInitResult(Result *node, EState *estate, int eflags) ...@@ -204,19 +204,6 @@ ExecInitResult(Result *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &resstate->ps); 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 * initialize child nodes
*/ */
...@@ -228,11 +215,19 @@ ExecInitResult(Result *node, EState *estate, int eflags) ...@@ -228,11 +215,19 @@ ExecInitResult(Result *node, EState *estate, int eflags)
Assert(innerPlan(node) == NULL); 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); 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; return resstate;
} }
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "utils/rel.h" #include "utils/rel.h"
#include "utils/tqual.h" #include "utils/tqual.h"
static void InitScanRelation(SampleScanState *node, EState *estate, int eflags);
static TupleTableSlot *SampleNext(SampleScanState *node); static TupleTableSlot *SampleNext(SampleScanState *node);
static void tablesample_init(SampleScanState *scanstate); static void tablesample_init(SampleScanState *scanstate);
static HeapTuple tablesample_getnext(SampleScanState *scanstate); static HeapTuple tablesample_getnext(SampleScanState *scanstate);
...@@ -106,35 +105,6 @@ ExecSampleScan(PlanState *pstate) ...@@ -106,35 +105,6 @@ ExecSampleScan(PlanState *pstate)
(ExecScanRecheckMtd) SampleRecheck); (ExecScanRecheckMtd) SampleRecheck);
} }
/* ----------------------------------------------------------------
* 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 * ExecInitSampleScan
* ---------------------------------------------------------------- * ----------------------------------------------------------------
...@@ -165,31 +135,39 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags) ...@@ -165,31 +135,39 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); 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 = scanstate->ss.ss_currentRelation =
ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); ExecOpenScanRelation(estate,
node->scan.scanrelid,
eflags);
scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate); /* we won't set up the HeapScanDesc till later */
scanstate->repeatable = scanstate->ss.ss_currentScanDesc = NULL;
ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
/* /* and create slot with appropriate rowtype */
* tuple table initialization ExecInitScanTupleSlot(estate, &scanstate->ss,
*/ RelationGetDescr(scanstate->ss.ss_currentRelation));
ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
ExecInitScanTupleSlot(estate, &scanstate->ss);
/* /*
* 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); scanstate->ss.ps.qual =
ExecAssignScanProjectionInfo(&scanstate->ss); 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 * If we don't have a REPEATABLE clause, select a random seed. We want to
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include "executor/nodeSeqscan.h" #include "executor/nodeSeqscan.h"
#include "utils/rel.h" #include "utils/rel.h"
static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
static TupleTableSlot *SeqNext(SeqScanState *node); static TupleTableSlot *SeqNext(SeqScanState *node);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -132,31 +131,6 @@ ExecSeqScan(PlanState *pstate) ...@@ -132,31 +131,6 @@ ExecSeqScan(PlanState *pstate)
(ExecScanRecheckMtd) SeqRecheck); (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 * ExecInitSeqScan
...@@ -190,27 +164,31 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) ...@@ -190,27 +164,31 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); 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 = scanstate->ss.ss_currentRelation =
ExecInitQual(node->plan.qual, (PlanState *) scanstate); ExecOpenScanRelation(estate,
node->scanrelid,
eflags);
/* /* and create slot with the appropriate rowtype */
* tuple table initialization ExecInitScanTupleSlot(estate, &scanstate->ss,
*/ RelationGetDescr(scanstate->ss.ss_currentRelation));
ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
ExecInitScanTupleSlot(estate, &scanstate->ss);
/* /*
* 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); scanstate->ss.ps.qual =
ExecAssignScanProjectionInfo(&scanstate->ss); ExecInitQual(node->plan.qual, (PlanState *) scanstate);
return scanstate; return scanstate;
} }
......
...@@ -518,11 +518,6 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags) ...@@ -518,11 +518,6 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
"SetOp hash table", "SetOp hash table",
ALLOCSET_DEFAULT_SIZES); ALLOCSET_DEFAULT_SIZES);
/*
* Tuple table initialization
*/
ExecInitResultTupleSlot(estate, &setopstate->ps);
/* /*
* initialize child nodes * initialize child nodes
* *
...@@ -535,10 +530,10 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags) ...@@ -535,10 +530,10 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
outerDesc = ExecGetResultType(outerPlanState(setopstate)); outerDesc = ExecGetResultType(outerPlanState(setopstate));
/* /*
* setop nodes do no projections, so initialize projection info for this * Initialize result slot and type. Setop nodes do no projections, so
* node appropriately * initialize projection info for this node appropriately.
*/ */
ExecAssignResultTypeFromTL(&setopstate->ps); ExecInitResultTupleSlotTL(estate, &setopstate->ps);
setopstate->ps.ps_ProjInfo = NULL; setopstate->ps.ps_ProjInfo = NULL;
/* /*
......
...@@ -198,14 +198,6 @@ ExecInitSort(Sort *node, EState *estate, int eflags) ...@@ -198,14 +198,6 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
* ExecQual or ExecProject. * ExecQual or ExecProject.
*/ */
/*
* 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 * initialize child nodes
* *
...@@ -217,11 +209,15 @@ ExecInitSort(Sort *node, EState *estate, int eflags) ...@@ -217,11 +209,15 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate, 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. * this node doesn't do projections.
*/ */
ExecAssignResultTypeFromTL(&sortstate->ss.ps); ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps);
ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
sortstate->ss.ps.ps_ProjInfo = NULL; sortstate->ss.ps.ps_ProjInfo = NULL;
SO1_printf("ExecInitSort: %s\n", SO1_printf("ExecInitSort: %s\n",
......
...@@ -957,8 +957,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) ...@@ -957,8 +957,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
* own innerecontext. * own innerecontext.
*/ */
tupDescLeft = ExecTypeFromTL(lefttlist, false); tupDescLeft = ExecTypeFromTL(lefttlist, false);
slot = ExecInitExtraTupleSlot(estate); slot = ExecInitExtraTupleSlot(estate, tupDescLeft);
ExecSetSlotDescriptor(slot, tupDescLeft);
sstate->projLeft = ExecBuildProjectionInfo(lefttlist, sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
NULL, NULL,
slot, slot,
...@@ -966,8 +965,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) ...@@ -966,8 +965,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
NULL); NULL);
sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false); sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false);
slot = ExecInitExtraTupleSlot(estate); slot = ExecInitExtraTupleSlot(estate, tupDescRight);
ExecSetSlotDescriptor(slot, tupDescRight);
sstate->projRight = ExecBuildProjectionInfo(righttlist, sstate->projRight = ExecBuildProjectionInfo(righttlist,
sstate->innerecontext, sstate->innerecontext,
slot, slot,
......
...@@ -120,35 +120,29 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags) ...@@ -120,35 +120,29 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &subquerystate->ss.ps); 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 * initialize subquery
*/ */
subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags); 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, ExecInitScanTupleSlot(estate, &subquerystate->ss,
ExecGetResultType(subquerystate->subplan)); 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); ExecAssignScanProjectionInfo(&subquerystate->ss);
/*
* initialize child expressions
*/
subquerystate->ss.ps.qual =
ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
return subquerystate; return subquerystate;
} }
......
...@@ -139,18 +139,6 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags) ...@@ -139,18 +139,6 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &scanstate->ss.ps); 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 * initialize source tuple type
*/ */
...@@ -158,15 +146,21 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags) ...@@ -158,15 +146,21 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
tf->coltypes, tf->coltypes,
tf->coltypmods, tf->coltypmods,
tf->colcollations); tf->colcollations);
/* and the corresponding scan slot */
ExecAssignScanType(&scanstate->ss, tupdesc); 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); ExecAssignScanProjectionInfo(&scanstate->ss);
/*
* initialize child expressions
*/
scanstate->ss.ps.qual =
ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
/* Only XMLTABLE is supported currently */ /* Only XMLTABLE is supported currently */
scanstate->routine = &XmlTableRoutine; scanstate->routine = &XmlTableRoutine;
......
...@@ -530,20 +530,6 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags) ...@@ -530,20 +530,6 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &tidstate->ss.ps); 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 * mark tid list as not computed yet
*/ */
...@@ -562,14 +548,23 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags) ...@@ -562,14 +548,23 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
/* /*
* get the scan type from the relation descriptor. * 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); ExecAssignScanProjectionInfo(&tidstate->ss);
/*
* initialize child expressions
*/
tidstate->ss.ps.qual =
ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
TidExprListCreate(tidstate);
/* /*
* all done. * all done.
*/ */
......
...@@ -132,21 +132,16 @@ ExecInitUnique(Unique *node, EState *estate, int eflags) ...@@ -132,21 +132,16 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
*/ */
ExecAssignExprContext(estate, &uniquestate->ps); ExecAssignExprContext(estate, &uniquestate->ps);
/*
* Tuple table initialization
*/
ExecInitResultTupleSlot(estate, &uniquestate->ps);
/* /*
* then initialize outer plan * then initialize outer plan
*/ */
outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags); outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
/* /*
* unique nodes do no projections, so initialize projection info for this * Initialize result slot and type. Unique nodes do no projections, so
* node appropriately * initialize projection info for this node appropriately.
*/ */
ExecAssignResultTypeFromTL(&uniquestate->ps); ExecInitResultTupleSlotTL(estate, &uniquestate->ps);
uniquestate->ps.ps_ProjInfo = NULL; uniquestate->ps.ps_ProjInfo = NULL;
/* /*
......
...@@ -248,23 +248,22 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) ...@@ -248,23 +248,22 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, planstate); ExecAssignExprContext(estate, planstate);
/* /*
* tuple table initialization * Get info about values list, initialize scan slot with it.
*/ */
ExecInitResultTupleSlot(estate, &scanstate->ss.ps); tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
ExecInitScanTupleSlot(estate, &scanstate->ss); ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
/* /*
* initialize child expressions * Initialize result slot, type and projection.
*/ */
scanstate->ss.ps.qual = ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); ExecAssignScanProjectionInfo(&scanstate->ss);
/* /*
* get info about values list * initialize child expressions
*/ */
tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists)); scanstate->ss.ps.qual =
ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
ExecAssignScanType(&scanstate->ss, tupdesc);
/* /*
* Other node-specific setup * Other node-specific setup
...@@ -281,12 +280,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) ...@@ -281,12 +280,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
scanstate->exprlists[i++] = (List *) lfirst(vtl); scanstate->exprlists[i++] = (List *) lfirst(vtl);
} }
/*
* Initialize result tuple type and projection info.
*/
ExecAssignResultTypeFromTL(&scanstate->ss.ps);
ExecAssignScanProjectionInfo(&scanstate->ss);
return scanstate; return scanstate;
} }
......
...@@ -2287,30 +2287,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) ...@@ -2287,30 +2287,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
"WindowAgg Aggregates", "WindowAgg Aggregates",
ALLOCSET_DEFAULT_SIZES); 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 * 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) * logical top level of a query (ie, after any WHERE or HAVING filters)
...@@ -2328,28 +2304,35 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) ...@@ -2328,28 +2304,35 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
* initialize source tuple type (which is also the tuple type that we'll * initialize source tuple type (which is also the tuple type that we'll
* store in the tuplestore and use in all our working slots). * 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; scanDesc = winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
ExecSetSlotDescriptor(winstate->first_part_slot, /*
winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor); * tuple table initialization
ExecSetSlotDescriptor(winstate->agg_row_slot, */
winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor); winstate->first_part_slot = ExecInitExtraTupleSlot(estate, scanDesc);
ExecSetSlotDescriptor(winstate->temp_slot_1, winstate->agg_row_slot = ExecInitExtraTupleSlot(estate, scanDesc);
winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor); winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate, scanDesc);
ExecSetSlotDescriptor(winstate->temp_slot_2, winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc);
winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
if (winstate->framehead_slot) /*
ExecSetSlotDescriptor(winstate->framehead_slot, * create frame head and tail slots only if needed (must match logic in
winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor); * update_frameheadpos and update_frametailpos)
if (winstate->frametail_slot) */
ExecSetSlotDescriptor(winstate->frametail_slot, winstate->framehead_slot = winstate->frametail_slot = NULL;
winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor);
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); ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
/* Set up data for comparing tuples */ /* Set up data for comparing tuples */
......
...@@ -157,21 +157,21 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags) ...@@ -157,21 +157,21 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
ExecAssignExprContext(estate, &scanstate->ss.ps); ExecAssignExprContext(estate, &scanstate->ss.ps);
/* /*
* initialize child expressions * tuple table initialization
*/ */
scanstate->ss.ps.qual = ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); ExecInitScanTupleSlot(estate, &scanstate->ss, NULL);
/* /*
* tuple table initialization * initialize child expressions
*/ */
ExecInitResultTupleSlot(estate, &scanstate->ss.ps); scanstate->ss.ps.qual =
ExecInitScanTupleSlot(estate, &scanstate->ss); 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; return scanstate;
} }
......
...@@ -208,7 +208,7 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel) ...@@ -208,7 +208,7 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel)
/* Triggers might need a slot */ /* Triggers might need a slot */
if (resultRelInfo->ri_TrigDesc) if (resultRelInfo->ri_TrigDesc)
estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate); estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
/* Prepare to catch AFTER triggers. */ /* Prepare to catch AFTER triggers. */
AfterTriggerBeginQuery(); AfterTriggerBeginQuery();
...@@ -585,8 +585,8 @@ apply_handle_insert(StringInfo s) ...@@ -585,8 +585,8 @@ apply_handle_insert(StringInfo s)
/* Initialize the executor state. */ /* Initialize the executor state. */
estate = create_estate_for_relation(rel); estate = create_estate_for_relation(rel);
remoteslot = ExecInitExtraTupleSlot(estate); remoteslot = ExecInitExtraTupleSlot(estate,
ExecSetSlotDescriptor(remoteslot, RelationGetDescr(rel->localrel)); RelationGetDescr(rel->localrel));
/* Process and store remote tuple in the slot */ /* Process and store remote tuple in the slot */
oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
...@@ -689,10 +689,10 @@ apply_handle_update(StringInfo s) ...@@ -689,10 +689,10 @@ apply_handle_update(StringInfo s)
/* Initialize the executor state. */ /* Initialize the executor state. */
estate = create_estate_for_relation(rel); estate = create_estate_for_relation(rel);
remoteslot = ExecInitExtraTupleSlot(estate); remoteslot = ExecInitExtraTupleSlot(estate,
ExecSetSlotDescriptor(remoteslot, RelationGetDescr(rel->localrel)); RelationGetDescr(rel->localrel));
localslot = ExecInitExtraTupleSlot(estate); localslot = ExecInitExtraTupleSlot(estate,
ExecSetSlotDescriptor(localslot, RelationGetDescr(rel->localrel)); RelationGetDescr(rel->localrel));
EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1); EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
PushActiveSnapshot(GetTransactionSnapshot()); PushActiveSnapshot(GetTransactionSnapshot());
...@@ -807,10 +807,10 @@ apply_handle_delete(StringInfo s) ...@@ -807,10 +807,10 @@ apply_handle_delete(StringInfo s)
/* Initialize the executor state. */ /* Initialize the executor state. */
estate = create_estate_for_relation(rel); estate = create_estate_for_relation(rel);
remoteslot = ExecInitExtraTupleSlot(estate); remoteslot = ExecInitExtraTupleSlot(estate,
ExecSetSlotDescriptor(remoteslot, RelationGetDescr(rel->localrel)); RelationGetDescr(rel->localrel));
localslot = ExecInitExtraTupleSlot(estate); localslot = ExecInitExtraTupleSlot(estate,
ExecSetSlotDescriptor(localslot, RelationGetDescr(rel->localrel)); RelationGetDescr(rel->localrel));
EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1); EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
PushActiveSnapshot(GetTransactionSnapshot()); PushActiveSnapshot(GetTransactionSnapshot());
......
...@@ -431,9 +431,10 @@ extern void ExecScanReScan(ScanState *node); ...@@ -431,9 +431,10 @@ extern void ExecScanReScan(ScanState *node);
/* /*
* prototypes from functions in execTuples.c * prototypes from functions in execTuples.c
*/ */
extern void ExecInitResultTupleSlot(EState *estate, PlanState *planstate); extern void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate);
extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate); extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc);
extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
TupleDesc tupleDesc);
extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
TupleDesc tupType); TupleDesc tupType);
extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid); extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
...@@ -502,8 +503,6 @@ extern ExprContext *MakePerTupleExprContext(EState *estate); ...@@ -502,8 +503,6 @@ extern ExprContext *MakePerTupleExprContext(EState *estate);
} while (0) } while (0)
extern void ExecAssignExprContext(EState *estate, PlanState *planstate); 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 TupleDesc ExecGetResultType(PlanState *planstate);
extern void ExecAssignProjectionInfo(PlanState *planstate, extern void ExecAssignProjectionInfo(PlanState *planstate,
TupleDesc inputDesc); TupleDesc inputDesc);
...@@ -511,7 +510,7 @@ extern void ExecConditionalAssignProjectionInfo(PlanState *planstate, ...@@ -511,7 +510,7 @@ extern void ExecConditionalAssignProjectionInfo(PlanState *planstate,
TupleDesc inputDesc, Index varno); TupleDesc inputDesc, Index varno);
extern void ExecFreeExprContext(PlanState *planstate); extern void ExecFreeExprContext(PlanState *planstate);
extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc); 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); extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
......
...@@ -127,6 +127,7 @@ typedef struct TupleTableSlot ...@@ -127,6 +127,7 @@ typedef struct TupleTableSlot
MinimalTuple tts_mintuple; /* minimal tuple, or NULL if none */ MinimalTuple tts_mintuple; /* minimal tuple, or NULL if none */
HeapTupleData tts_minhdr; /* workspace for minimal-tuple-only case */ HeapTupleData tts_minhdr; /* workspace for minimal-tuple-only case */
long tts_off; /* saved state for slot_deform_tuple */ long tts_off; /* saved state for slot_deform_tuple */
bool tts_fixedTupleDescriptor; /* descriptor can't be changed */
} TupleTableSlot; } TupleTableSlot;
#define TTS_HAS_PHYSICAL_TUPLE(slot) \ #define TTS_HAS_PHYSICAL_TUPLE(slot) \
...@@ -139,8 +140,8 @@ typedef struct TupleTableSlot ...@@ -139,8 +140,8 @@ typedef struct TupleTableSlot
((slot) == NULL || (slot)->tts_isempty) ((slot) == NULL || (slot)->tts_isempty)
/* in executor/execTuples.c */ /* in executor/execTuples.c */
extern TupleTableSlot *MakeTupleTableSlot(void); extern TupleTableSlot *MakeTupleTableSlot(TupleDesc desc);
extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable); extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc);
extern void ExecResetTupleTable(List *tupleTable, bool shouldFree); extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc); extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot); extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment