Move partition_tuple_slot out of EState.
authorRobert Haas <rhaas@postgresql.org>
Wed, 4 Jan 2017 18:05:29 +0000 (13:05 -0500)
committerRobert Haas <rhaas@postgresql.org>
Wed, 4 Jan 2017 18:16:59 +0000 (13:16 -0500)
Commit 2ac3ef7a01df859c62d0a02333b646d65eaec5ff added a TupleTapleSlot
for partition tuple slot to EState (es_partition_tuple_slot) but it's
more logical to have it as part of ModifyTableState
(mt_partition_tuple_slot) and CopyState (partition_tuple_slot).

Discussion: http://postgr.es/m/1bd459d9-4c0c-197a-346e-e5e59e217d97@lab.ntt.co.jp

Amit Langote, per a gripe from me

src/backend/commands/copy.c
src/backend/executor/execMain.c
src/backend/executor/nodeModifyTable.c
src/include/executor/executor.h
src/include/nodes/execnodes.h

index 77a8631de1270fa667423573ce4e433078beaa43..071b97dee132a0356ed98c710ea248ab2fb138a1 100644 (file)
@@ -161,11 +161,14 @@ typedef struct CopyStateData
    ExprState **defexprs;       /* array of default att expressions */
    bool        volatile_defexprs;      /* is any of defexprs volatile? */
    List       *range_table;
+
    PartitionDispatch *partition_dispatch_info;
-   int         num_dispatch;
-   int         num_partitions;
-   ResultRelInfo *partitions;
+   int         num_dispatch;       /* Number of entries in the above array */
+   int         num_partitions;     /* Number of members in the following
+                                    * arrays */
+   ResultRelInfo  *partitions;     /* Per partition result relation */
    TupleConversionMap **partition_tupconv_maps;
+   TupleTableSlot *partition_tuple_slot;
 
    /*
     * These variables are used to reduce overhead in textual COPY FROM.
@@ -1409,6 +1412,7 @@ BeginCopy(ParseState *pstate,
            PartitionDispatch  *partition_dispatch_info;
            ResultRelInfo      *partitions;
            TupleConversionMap **partition_tupconv_maps;
+           TupleTableSlot     *partition_tuple_slot;
            int                 num_parted,
                                num_partitions;
 
@@ -1416,12 +1420,14 @@ BeginCopy(ParseState *pstate,
                                           &partition_dispatch_info,
                                           &partitions,
                                           &partition_tupconv_maps,
+                                          &partition_tuple_slot,
                                           &num_parted, &num_partitions);
            cstate->partition_dispatch_info = partition_dispatch_info;
            cstate->num_dispatch = num_parted;
            cstate->partitions = partitions;
            cstate->num_partitions = num_partitions;
            cstate->partition_tupconv_maps = partition_tupconv_maps;
+           cstate->partition_tuple_slot = partition_tuple_slot;
        }
    }
    else
@@ -2435,15 +2441,6 @@ CopyFrom(CopyState cstate)
    /* Triggers might need a slot as well */
    estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate);
 
-   /*
-    * Initialize a dedicated slot to manipulate tuples of any given
-    * partition's rowtype.
-    */
-   if (cstate->partition_dispatch_info)
-       estate->es_partition_tuple_slot = ExecInitExtraTupleSlot(estate);
-   else
-       estate->es_partition_tuple_slot = NULL;
-
    /*
     * It's more efficient to prepare a bunch of tuples for insertion, and
     * insert them in one heap_multi_insert() call, than call heap_insert()
@@ -2591,7 +2588,7 @@ CopyFrom(CopyState cstate)
                 * we're finished dealing with the partition.
                 */
                oldslot = slot;
-               slot = estate->es_partition_tuple_slot;
+               slot = cstate->partition_tuple_slot;
                Assert(slot != NULL);
                ExecSetSlotDescriptor(slot, RelationGetDescr(partrel));
                ExecStoreTuple(tuple, slot, InvalidBuffer, true);
@@ -2756,6 +2753,9 @@ CopyFrom(CopyState cstate)
            ExecCloseIndices(resultRelInfo);
            heap_close(resultRelInfo->ri_RelationDesc, NoLock);
        }
+
+       /* Release the standalone partition tuple descriptor */
+       ExecDropSingleTupleTableSlot(cstate->partition_tuple_slot);
    }
 
    FreeExecutorState(estate);
index 7e3c207018f36a2e0fc7dd6a1bd0ba5af7642941..eb9b528c4e4800df885c185f1d2bd4371f1137cf 100644 (file)
@@ -3012,6 +3012,9 @@ EvalPlanQualEnd(EPQState *epqstate)
  *     entry for every leaf partition (required to convert input tuple based
  *     on the root table's rowtype to a leaf partition's rowtype after tuple
  *     routing is done
+ * 'partition_tuple_slot' receives a standalone TupleTableSlot to be used
+ *     to manipulate any given leaf partition's rowtype after that partition
+ *     is chosen by tuple-routing.
  * 'num_parted' receives the number of partitioned tables in the partition
  *     tree (= the number of entries in the 'pd' output array)
  * 'num_partitions' receives the number of leaf partitions in the partition
@@ -3026,6 +3029,7 @@ ExecSetupPartitionTupleRouting(Relation rel,
                               PartitionDispatch **pd,
                               ResultRelInfo **partitions,
                               TupleConversionMap ***tup_conv_maps,
+                              TupleTableSlot **partition_tuple_slot,
                               int *num_parted, int *num_partitions)
 {
    TupleDesc   tupDesc = RelationGetDescr(rel);
@@ -3043,6 +3047,14 @@ ExecSetupPartitionTupleRouting(Relation rel,
    *tup_conv_maps = (TupleConversionMap **) palloc0(*num_partitions *
                                           sizeof(TupleConversionMap *));
 
+   /*
+    * Initialize an empty slot that will be used to manipulate tuples of any
+    * given partition's rowtype.  It is attached to the caller-specified node
+    * (such as ModifyTableState) and released when the node finishes
+    * processing.
+    */
+   *partition_tuple_slot = MakeTupleTableSlot();
+
    leaf_part_rri = *partitions;
    i = 0;
    foreach(cell, leaf_parts)
index c7dd148944eabf3506e856a6a542c3ca98dfdeb0..aa364707f8d321550eff2d182b349161370095dc 100644 (file)
@@ -329,7 +329,7 @@ ExecInsert(ModifyTableState *mtstate,
             * Use the dedicated slot for that.
             */
            oldslot = slot;
-           slot = estate->es_partition_tuple_slot;
+           slot = mtstate->mt_partition_tuple_slot;
            Assert(slot != NULL);
            ExecSetSlotDescriptor(slot, RelationGetDescr(partrel));
            ExecStoreTuple(tuple, slot, InvalidBuffer, true);
@@ -1738,6 +1738,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
        PartitionDispatch  *partition_dispatch_info;
        ResultRelInfo      *partitions;
        TupleConversionMap **partition_tupconv_maps;
+       TupleTableSlot     *partition_tuple_slot;
        int                 num_parted,
                            num_partitions;
 
@@ -1745,21 +1746,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
                                       &partition_dispatch_info,
                                       &partitions,
                                       &partition_tupconv_maps,
+                                      &partition_tuple_slot,
                                       &num_parted, &num_partitions);
        mtstate->mt_partition_dispatch_info = partition_dispatch_info;
        mtstate->mt_num_dispatch = num_parted;
        mtstate->mt_partitions = partitions;
        mtstate->mt_num_partitions = num_partitions;
        mtstate->mt_partition_tupconv_maps = partition_tupconv_maps;
-
-       /*
-        * Initialize a dedicated slot to manipulate tuples of any given
-        * partition's rowtype.
-        */
-       estate->es_partition_tuple_slot = ExecInitExtraTupleSlot(estate);
+       mtstate->mt_partition_tuple_slot = partition_tuple_slot;
    }
-   else
-       estate->es_partition_tuple_slot = NULL;
 
    /*
     * Initialize any WITH CHECK OPTION constraints if needed.
@@ -2100,6 +2095,10 @@ ExecEndModifyTable(ModifyTableState *node)
        heap_close(resultRelInfo->ri_RelationDesc, NoLock);
    }
 
+   /* Release the standalone partition tuple descriptor, if any */
+   if (node->mt_partition_tuple_slot)
+       ExecDropSingleTupleTableSlot(node->mt_partition_tuple_slot);
+
    /*
     * Free the exprcontext
     */
index a3fa5f076714126fd23402a9ce2bd44f1c39483a..4a7074edd70e9ac00108ec73f4870180ea18a5ed 100644 (file)
@@ -217,6 +217,7 @@ extern void ExecSetupPartitionTupleRouting(Relation rel,
                               PartitionDispatch **pd,
                               ResultRelInfo **partitions,
                               TupleConversionMap ***tup_conv_maps,
+                              TupleTableSlot **partition_tuple_slot,
                               int *num_parted, int *num_partitions);
 extern int ExecFindPartition(ResultRelInfo *resultRelInfo,
                  PartitionDispatch *pd,
index 486555eac4c867bc8779d6ce54da2f0963d5b130..0e05d472c90728e285429a566f249803855677fc 100644 (file)
@@ -384,9 +384,6 @@ typedef struct EState
    TupleTableSlot *es_trig_oldtup_slot;        /* for TriggerEnabled */
    TupleTableSlot *es_trig_newtup_slot;        /* for TriggerEnabled */
 
-   /* Slot used to manipulate a tuple after it is routed to a partition */
-   TupleTableSlot *es_partition_tuple_slot;
-
    /* Parameter info: */
    ParamListInfo es_param_list_info;   /* values of external params */
    ParamExecData *es_param_exec_vals;  /* values of internal params */
@@ -1165,6 +1162,7 @@ typedef struct ModifyTableState
    ResultRelInfo  *mt_partitions;  /* Per partition result relation */
    TupleConversionMap **mt_partition_tupconv_maps;
                                    /* Per partition tuple conversion map */
+   TupleTableSlot *mt_partition_tuple_slot;
 } ModifyTableState;
 
 /* ----------------