]> granicus.if.org Git - postgresql/commitdiff
Allow tupleslots to have a fixed tupledesc, use in executor nodes.
authorAndres Freund <andres@anarazel.de>
Sat, 17 Feb 2018 05:17:38 +0000 (21:17 -0800)
committerAndres Freund <andres@anarazel.de>
Sat, 17 Feb 2018 05:17:38 +0000 (21:17 -0800)
The reason for doing so is that it will allow expression evaluation to
optimize based on the underlying tupledesc. In particular it will
allow to JIT tuple deforming together with the expression itself.

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

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

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

Author: Andres Freund
Discussion: https://postgr.es/m/20171206093717.vqdxe5icqttpxs3p@alap3.anarazel.de

52 files changed:
src/backend/commands/copy.c
src/backend/commands/trigger.c
src/backend/executor/README
src/backend/executor/execExpr.c
src/backend/executor/execMain.c
src/backend/executor/execPartition.c
src/backend/executor/execScan.c
src/backend/executor/execTuples.c
src/backend/executor/execUtils.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeAppend.c
src/backend/executor/nodeBitmapAnd.c
src/backend/executor/nodeBitmapHeapscan.c
src/backend/executor/nodeBitmapIndexscan.c
src/backend/executor/nodeBitmapOr.c
src/backend/executor/nodeCtescan.c
src/backend/executor/nodeCustom.c
src/backend/executor/nodeForeignscan.c
src/backend/executor/nodeFunctionscan.c
src/backend/executor/nodeGather.c
src/backend/executor/nodeGatherMerge.c
src/backend/executor/nodeGroup.c
src/backend/executor/nodeHash.c
src/backend/executor/nodeHashjoin.c
src/backend/executor/nodeIndexonlyscan.c
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeLimit.c
src/backend/executor/nodeLockRows.c
src/backend/executor/nodeMaterial.c
src/backend/executor/nodeMergeAppend.c
src/backend/executor/nodeMergejoin.c
src/backend/executor/nodeModifyTable.c
src/backend/executor/nodeNamedtuplestorescan.c
src/backend/executor/nodeNestloop.c
src/backend/executor/nodeProjectSet.c
src/backend/executor/nodeRecursiveunion.c
src/backend/executor/nodeResult.c
src/backend/executor/nodeSamplescan.c
src/backend/executor/nodeSeqscan.c
src/backend/executor/nodeSetOp.c
src/backend/executor/nodeSort.c
src/backend/executor/nodeSubplan.c
src/backend/executor/nodeSubqueryscan.c
src/backend/executor/nodeTableFuncscan.c
src/backend/executor/nodeTidscan.c
src/backend/executor/nodeUnique.c
src/backend/executor/nodeValuesscan.c
src/backend/executor/nodeWindowAgg.c
src/backend/executor/nodeWorktablescan.c
src/backend/replication/logical/worker.c
src/include/executor/executor.h
src/include/executor/tuptable.h

index b3933df9aff0561f971724932d9102dc80911753..d5883c98d150caa8ce1f429d7134e268e044cfe6 100644 (file)
@@ -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();
index 160d941c005efb6abae71eebb1ca996a27112e6d..fffc0095a79509ed6463e68e6707738529fee352 100644 (file)
@@ -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;
index b3e74aa1a54a879f738713a01e252c3abe2783b6..0d7cd552eb6918042e3c8c8d9670e65bbbc9570b 100644 (file)
@@ -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
index 463e185a9a9991f6eb995cb52bb52ac89dc308d7..db5fcafbfe48f7810e8d061a59f3d9fa29e930ff 100644 (file)
@@ -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));
                        }
                }
        }
index 5d3e923cca3294fcee58ce84f43c30c21e12025f..91ba939bdcade9e58db4f246abdcc215b89da908 100644 (file)
@@ -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 */
index 4048c3ebc613184cf71ac43ec3936eb13d8286a1..00523ce250d32e9e05ff0cf96823b35f048922fd 100644 (file)
@@ -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)
index bf4f603fd362017254294b3df3fa03c098329986..caf91730ce1005fb8439b85820e2ed73dcfa84f1 100644 (file)
@@ -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)
index 5df89e419c88f9877d599a095ec45a2f4899ee3c..c46d65cf938857115e6991b977aa25872886bb17 100644 (file)
@@ -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);
 }
index 50b6edce63d7e5b587735ba92e066833580d2baa..a8ae37ebc80c2af75f3e255e67d77737ae3cd1ed 100644 (file)
@@ -22,7 +22,6 @@
  *             ReScanExprContext
  *
  *             ExecAssignExprContext   Common code for plan node init routines.
- *             ExecAssignResultType
  *             etc
  *
  *             ExecOpenScanRelation    Common code for scan node init routines.
@@ -428,47 +427,6 @@ ExecAssignExprContext(EState *estate, PlanState *planstate)
        planstate->ps_ExprContext = CreateExprContext(estate);
 }
 
-/* ----------------
- *             ExecAssignResultType
- * ----------------
- */
-void
-ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
-{
-       TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
-
-       ExecSetSlotDescriptor(slot, tupDesc);
-}
-
-/* ----------------
- *             ExecAssignResultTypeFromTL
- * ----------------
- */
-void
-ExecAssignResultTypeFromTL(PlanState *planstate)
-{
-       bool            hasoid;
-       TupleDesc       tupDesc;
-
-       if (ExecContextForcesOids(planstate, &hasoid))
-       {
-               /* context forces OID choice; hasoid is now set correctly */
-       }
-       else
-       {
-               /* given free choice, don't leave space for OIDs in result tuples */
-               hasoid = false;
-       }
-
-       /*
-        * ExecTypeFromTL needs the parse-time representation of the tlist, not a
-        * list of ExprStates.  This is good because some plan nodes don't bother
-        * to set up planstate->targetlist ...
-        */
-       tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
-       ExecAssignResultType(planstate, tupDesc);
-}
-
 /* ----------------
  *             ExecGetResultType
  * ----------------
@@ -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
  *
index e74b3a939118e95d242a3025c863210fb4e49ad6..1b1334006fa84718fb112542d612eebfea1198a7 100644 (file)
@@ -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);
@@ -2198,31 +2198,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.
         *
@@ -2237,17 +2212,33 @@ 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.
         */
@@ -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 */
index 264d8fea8d931de4d5c7b07e4111ead15a7c8de4..7a3dd2ee2d0495c1f2ec13c79512da20e61832c2 100644 (file)
@@ -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;
 
        /*
index 913046c987e1b5b87f22361ef2a88bc89181b7a6..23d0d943269e8cf3baf0c57ac0ca1054b16c4e0f 100644 (file)
@@ -80,13 +80,6 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
        bitmapandstate->bitmapplans = bitmapplanstates;
        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;
 }
 
index fa65d4efbe7939c666f3ea68da35df74a12757f4..3e1c9e07145e322fc6ee2192fe7dbc61b32aed10 100644 (file)
@@ -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
@@ -952,26 +968,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
                                                                                                                 0,
                                                                                                                 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.
         */
index bb5e4da187cc03c765595fcbd3bacfdd3aff2fe3..d04f4901b48c039d849f4f06b8ca87e93a777e6a 100644 (file)
@@ -226,6 +226,15 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
        /* normally we don't make the result bitmap till runtime */
        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
         *
@@ -242,15 +251,6 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
         * sub-parts corresponding to runtime keys (see below).
         */
 
-       /*
-        * We do not open or lock the base relation here.  We assume that an
-        * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
-        * the heap relation throughout the execution of the plan tree.
-        */
-
-       indexstate->ss.ss_currentRelation = NULL;
-       indexstate->ss.ss_currentScanDesc = NULL;
-
        /*
         * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
         * here.  This allows an index-advisor plugin to EXPLAIN a plan containing
index 8047549f7df6b21c6bdc9dc29d7f519226957f8e..3f0a0a054424a5c17f93f5ddd5014392185c9335 100644 (file)
@@ -81,13 +81,6 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
        bitmaporstate->bitmapplans = bitmapplanstates;
        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;
 }
 
index ec6d75cbd419ab4a3ead9f3ba2fbf2161ea470ea..218619c760d6680b47e770cb84770d70f645ff68 100644 (file)
@@ -242,31 +242,25 @@ 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;
 }
 
index 936a2221f51265dd12600d6d7bbbfc1395614031..b816e0b31db6930cfbd33b11a3df392866d89108 100644 (file)
@@ -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.
index 59865f5ccad6d0781467bf511e6ae40198a28a77..0084234b3503bea2e0dca7ce881e1d6e7f8b2ecd 100644 (file)
@@ -155,20 +155,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,23 +180,31 @@ 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.
         */
index 69f8d3e81451636d602b1e58ccf111019c9f9e26..fb7c9f678758752e000f8bc69e76e2cf143f825c 100644 (file)
@@ -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,14 +479,23 @@ 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
index 58eadd45b83a882257d2d1594b407dff2c0fb99b..eaf7d2d56321e5bd87f72ad06e406e78d44f5522 100644 (file)
@@ -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. */
@@ -85,37 +84,29 @@ 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;
 }
index 6858c91e8c268f6e690328ec3143fcff91c68428..83221cdbaee5db7d13d297831ad3b295b4584aa3 100644 (file)
@@ -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. */
@@ -104,11 +103,6 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
         */
        Assert(!node->plan.qual);
 
-       /*
-        * tuple table initialization
-        */
-       ExecInitResultTupleSlot(estate, &gm_state->ps);
-
        /*
         * now initialize outer plan
         */
@@ -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 */
index 8f7bf459efe103088d0c8ee688082ea60718baeb..c6efd64d00d1e13357e6070897d0bb9f3cd1adab 100644 (file)
@@ -181,34 +181,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
         */
index b10f84745275c212efa977a8b1daeed0a5a4f82e..06bb44b1631ce35d1af0f191d2376860a18eccd3 100644 (file)
@@ -373,29 +373,24 @@ 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;
 }
 
index 03d78042fa092b15d43cd7a70a197b0fc61e6562..ab91eb25273673d23abbb9372b9a5d32b5b69e32 100644 (file)
@@ -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
@@ -622,17 +624,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
         *
@@ -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
index 8ffcc52bea5841b653024f709ce538ac13b0478a..ddc0ae90615f9f10f2a563314572a92043786eba 100644 (file)
@@ -518,23 +518,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.
         */
@@ -551,16 +534,27 @@ 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
index b8b961add4c6762055eba33001a3b79f8b580a32..01c9de88f4d98287da5168b1e83eed11ed340daa 100644 (file)
@@ -940,6 +940,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
         *
@@ -957,31 +977,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
        indexstate->indexorderbyorig =
                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
index 29d2deac23b5d88b0019f6e6ed9ae96e63f5e881..56d98b4490bfdf003333afb8010197c7c1fdb178 100644 (file)
@@ -353,6 +353,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
         */
@@ -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;
index 7961b4be6ab2dd208232c490297c6ba5c66a3cb4..b39ccf7dc131097e43e7d5b772581a2ed9226f6b 100644 (file)
@@ -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;
 
        /*
index 85afe87c443718b7d4260cc8c440bd1741040689..8c2e57dbd074474af5584302258e469f9c988986 100644 (file)
@@ -206,14 +206,6 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
         * ExecQual or ExecProject.
         */
 
-       /*
-        * tuple table initialization
-        *
-        * material nodes only return tuples from their materialized relation.
-        */
-       ExecInitResultTupleSlot(estate, &matstate->ss.ps);
-       ExecInitScanTupleSlot(estate, &matstate->ss);
-
        /*
         * initialize child nodes
         *
@@ -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;
 }
 
index ab4009c967e1a41f228421f02f998a8be018ebd4..118f4ef07df216d4d035bddd291c671a82d39c3a 100644 (file)
@@ -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;
 
        /*
index ec5f82f6a9250b158dc766a3f71597f2f6d45873..f3cbe2f889b2c1cc37fc57db416b567ce55f8770 100644 (file)
@@ -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
@@ -1466,17 +1469,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
        mergestate->mj_OuterEContext = CreateExprContext(estate);
        mergestate->mj_InnerEContext = CreateExprContext(estate);
 
-       /*
-        * initialize child expressions
-        */
-       mergestate->js.ps.qual =
-               ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
-       mergestate->js.jointype = node->join.jointype;
-       mergestate->js.joinqual =
-               ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
-       mergestate->mj_ConstFalseJoin = false;
-       /* mergeclauses are handled below */
-
        /*
         * initialize child nodes
         *
@@ -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
@@ -1514,14 +1508,25 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
        else
                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
@@ -1587,12 +1588,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
                                 (int) node->join.jointype);
        }
 
-       /*
-        * initialize tuple type and projection info
-        */
-       ExecAssignResultTypeFromTL(&mergestate->js.ps);
-       ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
-
        /*
         * preprocess the merge clauses
         */
index 2a8ecbd830da4b8c633db762b664dac479252846..93c03cfb0716242bb8b0809469d9696e6f93541d 100644 (file)
@@ -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
index c3b28176e447f3ae3c2ec8ca33abba957ebac296..4d898b1f83e3deea16d7b13f6a5f1e995c997813 100644 (file)
@@ -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;
index 9b4f8cc4320325f50d91217e0c7a5d64482a0e73..9ae9863226c02fd2b649a54397bd61d6d996421d 100644 (file)
@@ -285,15 +285,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
         *
@@ -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
@@ -338,12 +339,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
                                 (int) node->join.jointype);
        }
 
-       /*
-        * initialize tuple type and projection info
-        */
-       ExecAssignResultTypeFromTL(&nlstate->js.ps);
-       ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
-
        /*
         * finally, wipe the current outer tuple clean.
         */
index 3b79993ade8a24f2fccf3427bcbe6dcd5374dafa..6d6ed38ceeb45a4e12fe9a1022e96d0fe5c4b3ce 100644 (file)
@@ -243,14 +243,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
         */
@@ -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
index ba48a69a3be55ea0e550b775e0cf3d0ae895bc82..6b3ea5afb31946d133200c70cfc80b3a2b37e978 100644 (file)
@@ -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;
 
        /*
index 5860d9c1ce6c3cbc47a7950f87c9fa1aff42b94a..e4418a29bba743cde9cd66976ffb08a800cc2c66 100644 (file)
@@ -204,19 +204,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
         */
@@ -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;
 }
 
index e88cd1873732c2b2a7ef86a6c2069252dbf6ee7f..872d6e5735e0f6073e01ef2dfaf22ec03c1b93e0 100644 (file)
@@ -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);
@@ -106,35 +105,6 @@ ExecSampleScan(PlanState *pstate)
                                        (ExecScanRecheckMtd) SampleRecheck);
 }
 
-/* ----------------------------------------------------------------
- *             InitScanRelation
- *
- *             Set up to access the scan relation.
- * ----------------------------------------------------------------
- */
-static void
-InitScanRelation(SampleScanState *node, EState *estate, int eflags)
-{
-       Relation        currentRelation;
-
-       /*
-        * get the relation object id from the relid'th entry in the range table,
-        * open that relation and acquire appropriate lock on it.
-        */
-       currentRelation = ExecOpenScanRelation(estate,
-                                                                                  ((SampleScan *) node->ss.ps.plan)->scan.scanrelid,
-                                                                                  eflags);
-
-       node->ss.ss_currentRelation = currentRelation;
-
-       /* we won't set up the HeapScanDesc till later */
-       node->ss.ss_currentScanDesc = NULL;
-
-       /* and report the scan tuple slot's rowtype */
-       ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
-}
-
-
 /* ----------------------------------------------------------------
  *             ExecInitSampleScan
  * ----------------------------------------------------------------
@@ -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
index 58631378d5c276883f9797322afab2d05a581c40..9db368922a303315d65df932cbcd146d9c76cf6d 100644 (file)
@@ -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;
 }
index eb5449fc3e2826251654e6319ebd49b7024f8a60..3fa4a5fcc6554ccb328d48b901bdc155f8fcd196 100644 (file)
@@ -518,11 +518,6 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
                                                                  "SetOp hash table",
                                                                  ALLOCSET_DEFAULT_SIZES);
 
-       /*
-        * Tuple table initialization
-        */
-       ExecInitResultTupleSlot(estate, &setopstate->ps);
-
        /*
         * initialize child nodes
         *
@@ -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;
 
        /*
index d61c859fce609156a0ced9bc0e296144e51a1641..73f16c9abaa9b84114785e5ad5402e1b0f39a3ae 100644 (file)
@@ -198,14 +198,6 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
         * ExecQual or ExecProject.
         */
 
-       /*
-        * tuple table initialization
-        *
-        * sort nodes only return scan tuples from their sorted relation.
-        */
-       ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
-       ExecInitScanTupleSlot(estate, &sortstate->ss);
-
        /*
         * initialize child nodes
         *
@@ -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",
index 4927e212176965d7b01e79c1e337e060b046b0df..d5411500a2b27191516f68024094f18431e5c8f5 100644 (file)
@@ -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,
index 715a5b6a84167dcc395ff555b6cfa57709d8ca50..fa6188478511a44d49762f680222597fb9d44368 100644 (file)
@@ -120,35 +120,29 @@ 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;
 }
 
index 3b609765d41c137d7f7a30df995c8f87055bde8d..fed6f2b3a53e4305d50d8e820bea29cdc7059532 100644 (file)
@@ -139,18 +139,6 @@ 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
         */
@@ -158,15 +146,21 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
                                                                 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;
 
index f2737bb7ef156c0dda402b43297f6280e75a58d8..e207b1ffb511d168d55c43296591dbc37108e3d0 100644 (file)
@@ -530,20 +530,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
         */
@@ -562,14 +548,23 @@ 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.
         */
index 9f823c58e1ad4bef4e1eecbc5b31e9259deea957..05d65330a0eb5f5559dcb3bae58c43af47927363 100644 (file)
@@ -132,21 +132,16 @@ 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;
 
        /*
index c3d78b6295e4519e52882964eac4a3401a0f811b..63b7e7ef5b82bbf30b0ed6b08fda47f396b006ee 100644 (file)
@@ -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;
 }
 
index 1c807a829227454328da2bcc7d3c68de760be31a..a56c3e89fd5f661d05d9856b45883f8d1d112151 100644 (file)
@@ -2287,30 +2287,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
                                                          "WindowAgg Aggregates",
                                                          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 */
index 66d2111bd9f13ca71e72da0035d9393bfce96c07..2ff9a215b12f8d17040e7613db48e5b5cb2c22b7 100644 (file)
@@ -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;
 }
index 83c69092ae8d3286a25c1414abee7bba80298fc0..04985c9f91df8b0b12258969cb8a691305e7f836 100644 (file)
@@ -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());
index 621e7c3dc463c55b731e0b7b7916b5ad65c5ad6a..45a077a949c0c9db25b0883fff396e8cfa81d916 100644 (file)
@@ -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);
 
index 5b54834d33e916a4a10673449bbd804218f689b3..8be0d5edc29ec1e61121e5dd15e91d1ac640c085 100644 (file)
@@ -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);