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