diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 015752a93f..eba52dc928 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -19,18 +19,22 @@ * * At ExecutorStart() * ---------------- - * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and - * ExecInitResultTupleSlotTL() to construct TupleTableSlots - * for the tuples returned by the access methods and the - * tuples resulting from performing target list projections. + + * - ExecInitSeqScan() calls ExecInitScanTupleSlot() to construct a + * TupleTableSlots for the tuples returned by the access method, and + * ExecInitResultTypeTL() to define the node's return + * type. ExecAssignScanProjectionInfo() will, if necessary, create + * another TupleTableSlot for the tuples resulting from performing + * target list projections. * * During ExecutorRun() * ---------------- * - SeqNext() calls ExecStoreBufferHeapTuple() to place the tuple - * returned by the access methods into the scan tuple slot. + * returned by the access method into the scan tuple slot. * - * - ExecSeqScan() calls ExecStoreHeapTuple() to take the result - * tuple from ExecProject() and place it into the result tuple slot. + * - ExecSeqScan() (via ExecScan), if necessary, calls ExecProject(), + * putting the result of the projection in the result tuple slot. If + * not necessary, it directly returns the slot returned by SeqNext(). * * - ExecutePlan() calls the output function. * @@ -902,23 +906,14 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot) * ---------------------------------------------------------------- */ -/* -------------------------------- - * ExecInit{Result,Scan,Extra}TupleSlot[TL] - * - * These are convenience routines to initialize the specified slot - * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot - * is used for initializing special-purpose slots. - * -------------------------------- - */ - /* ---------------- - * ExecInitResultTupleSlotTL + * ExecInitResultTypeTL * - * Initialize result tuple slot, using the plan node's targetlist. + * Initialize result type, using the plan node's targetlist. * ---------------- */ void -ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate) +ExecInitResultTypeTL(PlanState *planstate) { bool hasoid; TupleDesc tupDesc; @@ -934,8 +929,46 @@ ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate) } tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid); + planstate->ps_ResultTupleDesc = tupDesc; +} - planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable, tupDesc); +/* -------------------------------- + * ExecInit{Result,Scan,Extra}TupleSlot[TL] + * + * These are convenience routines to initialize the specified slot + * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot + * is used for initializing special-purpose slots. + * -------------------------------- + */ + +/* ---------------- + * ExecInitResultTupleSlotTL + * + * Initialize result tuple slot, using the tuple descriptor previously + * computed with ExecInitResultTypeTL(). + * ---------------- + */ +void +ExecInitResultSlot(PlanState *planstate) +{ + TupleTableSlot *slot; + + slot = ExecAllocTableSlot(&planstate->state->es_tupleTable, + planstate->ps_ResultTupleDesc); + planstate->ps_ResultTupleSlot = slot; +} + +/* ---------------- + * ExecInitResultTupleSlotTL + * + * Initialize result tuple slot, using the plan node's targetlist. + * ---------------- + */ +void +ExecInitResultTupleSlotTL(PlanState *planstate) +{ + ExecInitResultTypeTL(planstate); + ExecInitResultSlot(planstate); } /* ---------------- diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 71c6b5dc0a..f9e7bb479f 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -451,9 +451,7 @@ ExecAssignExprContext(EState *estate, PlanState *planstate) TupleDesc ExecGetResultType(PlanState *planstate) { - TupleTableSlot *slot = planstate->ps_ResultTupleSlot; - - return slot->tts_tupleDescriptor; + return planstate->ps_ResultTupleDesc; } @@ -496,7 +494,11 @@ ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc, inputDesc)) planstate->ps_ProjInfo = NULL; else + { + if (!planstate->ps_ResultTupleSlot) + ExecInitResultSlot(planstate); ExecAssignProjectionInfo(planstate, inputDesc); + } } static bool diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 2413f1f87d..85f1ec7140 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -2219,7 +2219,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) /* * Initialize result type, slot and projection. */ - ExecInitResultTupleSlotTL(estate, &aggstate->ss.ps); + ExecInitResultTupleSlotTL(&aggstate->ss.ps); ExecAssignProjectionInfo(&aggstate->ss.ps, NULL); /* diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index a16b6da474..94a17c7c67 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -196,7 +196,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags) /* * Initialize result tuple type and slot. */ - ExecInitResultTupleSlotTL(estate, &appendstate->ps); + ExecInitResultTupleSlotTL(&appendstate->ps); appendplanstates = (PlanState **) palloc(nplans * sizeof(PlanState *)); diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 304ef07f2c..c153d74f41 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -800,7 +800,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node) /* * clear out tuple table slots */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* @@ -916,9 +917,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c index 24700dd396..017b877277 100644 --- a/src/backend/executor/nodeCtescan.c +++ b/src/backend/executor/nodeCtescan.c @@ -263,9 +263,9 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags) ExecGetResultType(scanstate->cteplanstate)); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* @@ -294,7 +294,8 @@ ExecEndCteScan(CteScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* @@ -318,7 +319,8 @@ ExecReScanCteScan(CteScanState *node) { Tuplestorestate *tuplestorestate = node->leader->cte_table; - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c index 7972d5a952..ab3e34790e 100644 --- a/src/backend/executor/nodeCustom.c +++ b/src/backend/executor/nodeCustom.c @@ -87,7 +87,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &css->ss.ps); + ExecInitResultTupleSlotTL(&css->ss.ps); ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno); /* initialize child expressions */ diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index 2ec7fcb962..5d2cd0ed71 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -198,7 +198,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno); /* @@ -256,7 +256,8 @@ ExecEndForeignScan(ForeignScanState *node) ExecFreeExprContext(&node->ss.ps); /* clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); } diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index fb7c9f6787..0596adbb2f 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -487,7 +487,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* @@ -529,7 +529,8 @@ ExecEndFunctionScan(FunctionScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* @@ -563,7 +564,8 @@ ExecReScanFunctionScan(FunctionScanState *node) int i; Bitmapset *chgparam = node->ss.ps.chgParam; - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); for (i = 0; i < node->nfuncs; i++) { FunctionScanPerFuncState *fs = &node->funcstates[i]; diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index ad16c783bd..afddb0a039 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -92,9 +92,9 @@ ExecInitGather(Gather *node, EState *estate, int eflags) tupDesc = ExecGetResultType(outerPlanState(gatherstate)); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &gatherstate->ps); + ExecInitResultTypeTL(&gatherstate->ps); ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR); /* @@ -231,7 +231,8 @@ ExecEndGather(GatherState *node) ExecEndNode(outerPlanState(node)); /* let children clean up first */ ExecShutdownGather(node); ExecFreeExprContext(&node->ps); - ExecClearTuple(node->ps.ps_ResultTupleSlot); + if (node->ps.ps_ResultTupleSlot) + ExecClearTuple(node->ps.ps_ResultTupleSlot); } /* diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index 6362e4497a..7ae067f9eb 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -117,9 +117,9 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) gm_state->tupDesc = tupDesc; /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &gm_state->ps); + ExecInitResultTypeTL(&gm_state->ps); ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR); /* @@ -272,7 +272,8 @@ ExecEndGatherMerge(GatherMergeState *node) ExecEndNode(outerPlanState(node)); /* let children clean up first */ ExecShutdownGatherMerge(node); ExecFreeExprContext(&node->ps); - ExecClearTuple(node->ps.ps_ResultTupleSlot); + if (node->ps.ps_ResultTupleSlot) + ExecClearTuple(node->ps.ps_ResultTupleSlot); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index 2ea80e817d..9c1e51bc95 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -193,7 +193,7 @@ ExecInitGroup(Group *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &grpstate->ss.ps); + ExecInitResultTupleSlotTL(&grpstate->ss.ps); ExecAssignProjectionInfo(&grpstate->ss.ps, NULL); /* diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 6ffaa751f2..a9f812d66b 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -382,7 +382,7 @@ ExecInitHash(Hash *node, EState *estate, int eflags) * initialize our result slot and type. No need to build projection * because this node doesn't do projections. */ - ExecInitResultTupleSlotTL(estate, &hashstate->ps); + ExecInitResultTupleSlotTL(&hashstate->ps); hashstate->ps.ps_ProjInfo = NULL; /* diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index d017bbfbd3..08a8bb3426 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -644,7 +644,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &hjstate->js.ps); + ExecInitResultTupleSlotTL(&hjstate->js.ps); ExecAssignProjectionInfo(&hjstate->js.ps, NULL); /* diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index daedf342f7..865a056c02 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -399,7 +399,8 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node) /* * clear out tuple table slots */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* @@ -529,11 +530,10 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc); /* - * Initialize result slot, type and projection info. The node's - * targetlist will contain Vars with varno = INDEX_VAR, referencing the - * scan tuple. + * Initialize result type and projection info. The node's targetlist will + * contain Vars with varno = INDEX_VAR, referencing the scan tuple. */ - ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps); + ExecInitResultTypeTL(&indexstate->ss.ps); ExecAssignScanProjectionInfoWithVarno(&indexstate->ss, INDEX_VAR); /* diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index ba7821b0e2..8593c0e305 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -822,7 +822,8 @@ ExecEndIndexScan(IndexScanState *node) /* * clear out tuple table slots */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* @@ -947,9 +948,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) RelationGetDescr(currentRelation)); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps); + ExecInitResultTypeTL(&indexstate->ss.ps); ExecAssignScanProjectionInfo(&indexstate->ss); /* diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index bb28cf7d1d..f0b6819140 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -376,10 +376,9 @@ ExecInitLimit(Limit *node, EState *estate, int eflags) (PlanState *) limitstate); /* - * Initialize result slot and type. (XXX not actually used, but upper - * nodes access it to get this node's result tupledesc...) + * Initialize result type. */ - ExecInitResultTupleSlotTL(estate, &limitstate->ps); + ExecInitResultTypeTL(&limitstate->ps); /* * limit nodes do no projections, so initialize projection info for this diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index 6db345ae7a..961798cecb 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -381,10 +381,9 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags) */ /* - * Tuple table initialization (XXX not actually used, but upper nodes - * access it to get this node's result tupledesc...) + * Initialize result type. */ - ExecInitResultTupleSlotTL(estate, &lrstate->ps); + ExecInitResultTypeTL(&lrstate->ps); /* * then initialize outer plan diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 8c2e57dbd0..4ede428f90 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -223,7 +223,7 @@ ExecInitMaterial(Material *node, EState *estate, int eflags) * * material nodes only return tuples from their materialized relation. */ - ExecInitResultTupleSlotTL(estate, &matstate->ss.ps); + ExecInitResultTupleSlotTL(&matstate->ss.ps); matstate->ss.ps.ps_ProjInfo = NULL; /* diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index fde369d622..dbed667d16 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -165,9 +165,9 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) * Miscellaneous initialization * * MergeAppend nodes do have Result slots, which hold pointers to tuples, - * so we have to initialize them. + * so we have to initialize them. FIXME */ - ExecInitResultTupleSlotTL(estate, &mergestate->ps); + ExecInitResultTupleSlotTL(&mergestate->ps); /* * call ExecInitNode on each of the valid plans to be executed and save diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 5e52b90c00..9c97831331 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -1512,7 +1512,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &mergestate->js.ps); + ExecInitResultTupleSlotTL(&mergestate->js.ps); ExecAssignProjectionInfo(&mergestate->js.ps, NULL); /* diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 528f58717e..e2836b75ff 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -2407,7 +2407,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists); /* Set up a slot for the output of the RETURNING projection(s) */ - ExecInitResultTupleSlotTL(estate, &mtstate->ps); + ExecInitResultTupleSlotTL(&mtstate->ps); slot = mtstate->ps.ps_ResultTupleSlot; /* Need an econtext too */ @@ -2437,7 +2437,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) * expects one (maybe should change that?). */ mtstate->ps.plan->targetlist = NIL; - ExecInitResultTupleSlotTL(estate, &mtstate->ps); + ExecInitResultTypeTL(&mtstate->ps); mtstate->ps.ps_ExprContext = NULL; } @@ -2716,7 +2716,8 @@ ExecEndModifyTable(ModifyTableState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ps.ps_ResultTupleSlot); + if (node->ps.ps_ResultTupleSlot) + ExecClearTuple(node->ps.ps_ResultTupleSlot); /* * Terminate EPQ execution if active diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c index b260ad2594..cf1b7b4f87 100644 --- a/src/backend/executor/nodeNamedtuplestorescan.c +++ b/src/backend/executor/nodeNamedtuplestorescan.c @@ -135,23 +135,22 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag ExecAssignExprContext(estate, &scanstate->ss.ps); /* - * Tuple table and result type initialization. The scan tuple type is - * specified for the tuplestore. + * The scan tuple type is specified for the tuplestore. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc); + /* + * Initialize result type and projection. + */ + ExecInitResultTypeTL(&scanstate->ss.ps); + ExecAssignScanProjectionInfo(&scanstate->ss); + /* * initialize child expressions */ scanstate->ss.ps.qual = ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); - /* - * Initialize projection. - */ - ExecAssignScanProjectionInfo(&scanstate->ss); - return scanstate; } @@ -172,7 +171,8 @@ ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); } @@ -187,7 +187,8 @@ ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node) { Tuplestorestate *tuplestorestate = node->relation; - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index 9ae9863226..8dbec685eb 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -304,7 +304,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &nlstate->js.ps); + ExecInitResultTupleSlotTL(&nlstate->js.ps); ExecAssignProjectionInfo(&nlstate->js.ps, NULL); /* diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c index 6d6ed38cee..e4dd414217 100644 --- a/src/backend/executor/nodeProjectSet.c +++ b/src/backend/executor/nodeProjectSet.c @@ -256,7 +256,7 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags) /* * tuple table and result type initialization */ - ExecInitResultTupleSlotTL(estate, &state->ps); + ExecInitResultTupleSlotTL(&state->ps); /* Create workspace for per-tlist-entry expr state & SRF-is-done state */ state->nelems = list_length(node->plan.targetlist); diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c index 6b3ea5afb3..2d26cec831 100644 --- a/src/backend/executor/nodeRecursiveunion.c +++ b/src/backend/executor/nodeRecursiveunion.c @@ -229,7 +229,7 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags) * RecursiveUnion nodes still have Result slots, which hold pointers to * tuples, so we have to initialize them. */ - ExecInitResultTupleSlotTL(estate, &rustate->ps); + ExecInitResultTypeTL(&rustate->ps); /* * Initialize result tuple type. (Note: we have to set up the result type @@ -279,11 +279,6 @@ ExecEndRecursiveUnion(RecursiveUnionState *node) if (node->tableContext) MemoryContextDelete(node->tableContext); - /* - * clean out the upper tuple table - */ - ExecClearTuple(node->ps.ps_ResultTupleSlot); - /* * close down subplans */ diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index e4418a29bb..2bbb2e7884 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -217,7 +217,7 @@ ExecInitResult(Result *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &resstate->ps); + ExecInitResultTupleSlotTL(&resstate->ps); ExecAssignProjectionInfo(&resstate->ps, NULL); /* diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c index f01fc3b62a..cfa26535d7 100644 --- a/src/backend/executor/nodeSamplescan.c +++ b/src/backend/executor/nodeSamplescan.c @@ -149,10 +149,9 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags) RelationGetDescr(scanstate->ss.ss_currentRelation)); /* - * Initialize result slot, type and projection. tuple table and result - * tuple initialization + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* @@ -211,7 +210,8 @@ ExecEndSampleScan(SampleScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index 79729dbbec..b4bea67610 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -175,9 +175,9 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) RelationGetDescr(scanstate->ss.ss_currentRelation)); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* @@ -213,7 +213,8 @@ ExecEndSeqScan(SeqScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index 3535b19c41..46bf77775c 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -532,7 +532,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags) * Initialize result slot and type. Setop nodes do no projections, so * initialize projection info for this node appropriately. */ - ExecInitResultTupleSlotTL(estate, &setopstate->ps); + ExecInitResultTupleSlotTL(&setopstate->ps); setopstate->ps.ps_ProjInfo = NULL; /* diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 0d2acb665a..5492cd4557 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -217,7 +217,7 @@ ExecInitSort(Sort *node, EState *estate, int eflags) * Initialize return slot and type. No need to initialize projection info * because this node doesn't do projections. */ - ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps); + ExecInitResultTupleSlotTL(&sortstate->ss.ps); sortstate->ss.ps.ps_ProjInfo = NULL; SO1_printf("ExecInitSort: %s\n", diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index fa61884785..b84c6892d5 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -126,15 +126,15 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags) subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags); /* - * Initialize scan slot and type (needed by ExecInitResultTupleSlotTL) + * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo) */ ExecInitScanTupleSlot(estate, &subquerystate->ss, ExecGetResultType(subquerystate->subplan)); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &subquerystate->ss.ps); + ExecInitResultTypeTL(&subquerystate->ss.ps); ExecAssignScanProjectionInfo(&subquerystate->ss); /* @@ -163,7 +163,8 @@ ExecEndSubqueryScan(SubqueryScanState *node) /* * clean out the upper tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c index a9fd3fda6b..b0c94d7e06 100644 --- a/src/backend/executor/nodeTableFuncscan.c +++ b/src/backend/executor/nodeTableFuncscan.c @@ -150,9 +150,9 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags) ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* @@ -221,7 +221,8 @@ ExecEndTableFuncScan(TableFuncScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); /* @@ -243,7 +244,8 @@ ExecReScanTableFuncScan(TableFuncScanState *node) { Bitmapset *chgparam = node->ss.ps.chgParam; - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); /* diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index d21d6553e4..bc859e3d51 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -487,7 +487,8 @@ ExecEndTidScan(TidScanState *node) /* * clear out tuple table slots */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); } @@ -545,9 +546,9 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags) RelationGetDescr(currentRelation)); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &tidstate->ss.ps); + ExecInitResultTypeTL(&tidstate->ss.ps); ExecAssignScanProjectionInfo(&tidstate->ss); /* diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c index 05d65330a0..c791f89b48 100644 --- a/src/backend/executor/nodeUnique.c +++ b/src/backend/executor/nodeUnique.c @@ -141,7 +141,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags) * Initialize result slot and type. Unique nodes do no projections, so * initialize projection info for this node appropriately. */ - ExecInitResultTupleSlotTL(estate, &uniquestate->ps); + ExecInitResultTupleSlotTL(&uniquestate->ps); uniquestate->ps.ps_ProjInfo = NULL; /* diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c index f76999d40a..fa49d0470f 100644 --- a/src/backend/executor/nodeValuesscan.c +++ b/src/backend/executor/nodeValuesscan.c @@ -264,9 +264,9 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc); /* - * Initialize result slot, type and projection. + * Initialize result type and projection. */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* @@ -312,7 +312,8 @@ ExecEndValuesScan(ValuesScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); } @@ -325,7 +326,8 @@ ExecEndValuesScan(ValuesScanState *node) void ExecReScanValuesScan(ValuesScanState *node) { - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 729c376d86..6e597e8285 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -2349,7 +2349,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) /* * Initialize result slot, type and projection. */ - ExecInitResultTupleSlotTL(estate, &winstate->ss.ps); + ExecInitResultTupleSlotTL(&winstate->ss.ps); ExecAssignProjectionInfo(&winstate->ss.ps, NULL); /* Set up data for comparing tuples */ diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c index 2ff9a215b1..1ce8ae9f02 100644 --- a/src/backend/executor/nodeWorktablescan.c +++ b/src/backend/executor/nodeWorktablescan.c @@ -159,7 +159,7 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags) /* * tuple table initialization */ - ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps); + ExecInitResultTypeTL(&scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss, NULL); /* @@ -193,7 +193,8 @@ ExecEndWorkTableScan(WorkTableScanState *node) /* * clean out the tuple table */ - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); } @@ -206,7 +207,8 @@ ExecEndWorkTableScan(WorkTableScanState *node) void ExecReScanWorkTableScan(WorkTableScanState *node) { - ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index edf538365b..8441265784 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -429,7 +429,9 @@ extern void ExecScanReScan(ScanState *node); /* * prototypes from functions in execTuples.c */ -extern void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate); +extern void ExecInitResultTypeTL(PlanState *planstate); +extern void ExecInitResultSlot(PlanState *planstate); +extern void ExecInitResultTupleSlotTL(PlanState *planstate); extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc); extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate, TupleDesc tupleDesc); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 880a03e4e4..18544566f7 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -966,6 +966,7 @@ typedef struct PlanState /* * Other run-time state needed by most if not all node types. */ + TupleDesc ps_ResultTupleDesc; /* node's return type */ TupleTableSlot *ps_ResultTupleSlot; /* slot for my result tuples */ ExprContext *ps_ExprContext; /* node's expression-evaluation context */ ProjectionInfo *ps_ProjInfo; /* info for doing tuple projection */