]> granicus.if.org Git - postgresql/commitdiff
Simplify and encapsulate tuple routing support code.
authorRobert Haas <rhaas@postgresql.org>
Thu, 4 Jan 2018 20:48:15 +0000 (15:48 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 4 Jan 2018 20:48:15 +0000 (15:48 -0500)
Instead of having ExecSetupPartitionTupleRouting return multiple out
parameters, have it return a pointer to a structure containing all of
those different things.  Also, provide and use a cleanup function,
ExecCleanupTupleRouting, instead of cleaning up all of the resources
allocated by ExecSetupPartitionTupleRouting individually.

Amit Khandekar, reviewed by Amit Langote, David Rowley, and me

Discussion: http://postgr.es/m/CAJ3gD9fWfxgKC+PfJZF3hkgAcNOy-LpfPxVYitDEXKHjeieWQQ@mail.gmail.com

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

index 118115aa42a05463871c18c5175df8c60204334f..66cbff7eadc28ccdd4f7da9b7686cc72893190b1 100644 (file)
@@ -166,12 +166,9 @@ typedef struct CopyStateData
        bool            volatile_defexprs;      /* is any of defexprs volatile? */
        List       *range_table;
 
-       PartitionDispatch *partition_dispatch_info;
-       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 pointers */
-       TupleConversionMap **partition_tupconv_maps;
-       TupleTableSlot *partition_tuple_slot;
+       /* Tuple-routing support info */
+       PartitionTupleRouting *partition_tuple_routing;
+
        TransitionCaptureState *transition_capture;
        TupleConversionMap **transition_tupconv_maps;
 
@@ -2472,28 +2469,10 @@ CopyFrom(CopyState cstate)
         */
        if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
        {
-               PartitionDispatch *partition_dispatch_info;
-               ResultRelInfo **partitions;
-               TupleConversionMap **partition_tupconv_maps;
-               TupleTableSlot *partition_tuple_slot;
-               int                     num_parted,
-                                       num_partitions;
-
-               ExecSetupPartitionTupleRouting(NULL,
-                                                                          cstate->rel,
-                                                                          1,
-                                                                          estate,
-                                                                          &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;
+               PartitionTupleRouting *proute;
+
+               proute = cstate->partition_tuple_routing =
+                       ExecSetupPartitionTupleRouting(NULL, cstate->rel, 1, estate);
 
                /*
                 * If we are capturing transition tuples, they may need to be
@@ -2506,11 +2485,11 @@ CopyFrom(CopyState cstate)
                        int                     i;
 
                        cstate->transition_tupconv_maps = (TupleConversionMap **)
-                               palloc0(sizeof(TupleConversionMap *) * cstate->num_partitions);
-                       for (i = 0; i < cstate->num_partitions; ++i)
+                               palloc0(sizeof(TupleConversionMap *) * proute->num_partitions);
+                       for (i = 0; i < proute->num_partitions; ++i)
                        {
                                cstate->transition_tupconv_maps[i] =
-                                       convert_tuples_by_name(RelationGetDescr(cstate->partitions[i]->ri_RelationDesc),
+                                       convert_tuples_by_name(RelationGetDescr(proute->partitions[i]->ri_RelationDesc),
                                                                                   RelationGetDescr(cstate->rel),
                                                                                   gettext_noop("could not convert row type"));
                        }
@@ -2530,7 +2509,7 @@ CopyFrom(CopyState cstate)
        if ((resultRelInfo->ri_TrigDesc != NULL &&
                 (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
                  resultRelInfo->ri_TrigDesc->trig_insert_instead_row)) ||
-               cstate->partition_dispatch_info != NULL ||
+               cstate->partition_tuple_routing != NULL ||
                cstate->volatile_defexprs)
        {
                useHeapMultiInsert = false;
@@ -2605,10 +2584,11 @@ CopyFrom(CopyState cstate)
                ExecStoreTuple(tuple, slot, InvalidBuffer, false);
 
                /* Determine the partition to heap_insert the tuple into */
-               if (cstate->partition_dispatch_info)
+               if (cstate->partition_tuple_routing)
                {
                        int                     leaf_part_index;
                        TupleConversionMap *map;
+                       PartitionTupleRouting *proute = cstate->partition_tuple_routing;
 
                        /*
                         * Away we go ... If we end up not finding a partition after all,
@@ -2619,11 +2599,11 @@ CopyFrom(CopyState cstate)
                         * partition, respectively.
                         */
                        leaf_part_index = ExecFindPartition(resultRelInfo,
-                                                                                               cstate->partition_dispatch_info,
+                                                                                               proute->partition_dispatch_info,
                                                                                                slot,
                                                                                                estate);
                        Assert(leaf_part_index >= 0 &&
-                                  leaf_part_index < cstate->num_partitions);
+                                  leaf_part_index < proute->num_partitions);
 
                        /*
                         * If this tuple is mapped to a partition that is not same as the
@@ -2641,7 +2621,7 @@ CopyFrom(CopyState cstate)
                         * to the selected partition.
                         */
                        saved_resultRelInfo = resultRelInfo;
-                       resultRelInfo = cstate->partitions[leaf_part_index];
+                       resultRelInfo = proute->partitions[leaf_part_index];
 
                        /* We do not yet have a way to insert into a foreign partition */
                        if (resultRelInfo->ri_FdwRoutine)
@@ -2688,7 +2668,7 @@ CopyFrom(CopyState cstate)
                         * We might need to convert from the parent rowtype to the
                         * partition rowtype.
                         */
-                       map = cstate->partition_tupconv_maps[leaf_part_index];
+                       map = proute->partition_tupconv_maps[leaf_part_index];
                        if (map)
                        {
                                Relation        partrel = resultRelInfo->ri_RelationDesc;
@@ -2700,7 +2680,7 @@ CopyFrom(CopyState cstate)
                                 * point on.  Use a dedicated slot from this point on until
                                 * we're finished dealing with the partition.
                                 */
-                               slot = cstate->partition_tuple_slot;
+                               slot = proute->partition_tuple_slot;
                                Assert(slot != NULL);
                                ExecSetSlotDescriptor(slot, RelationGetDescr(partrel));
                                ExecStoreTuple(tuple, slot, InvalidBuffer, true);
@@ -2852,34 +2832,8 @@ CopyFrom(CopyState cstate)
        ExecCloseIndices(resultRelInfo);
 
        /* Close all the partitioned tables, leaf partitions, and their indices */
-       if (cstate->partition_dispatch_info)
-       {
-               int                     i;
-
-               /*
-                * Remember cstate->partition_dispatch_info[0] corresponds to the root
-                * partitioned table, which we must not try to close, because it is
-                * the main target table of COPY that will be closed eventually by
-                * DoCopy().  Also, tupslot is NULL for the root partitioned table.
-                */
-               for (i = 1; i < cstate->num_dispatch; i++)
-               {
-                       PartitionDispatch pd = cstate->partition_dispatch_info[i];
-
-                       heap_close(pd->reldesc, NoLock);
-                       ExecDropSingleTupleTableSlot(pd->tupslot);
-               }
-               for (i = 0; i < cstate->num_partitions; i++)
-               {
-                       ResultRelInfo *resultRelInfo = cstate->partitions[i];
-
-                       ExecCloseIndices(resultRelInfo);
-                       heap_close(resultRelInfo->ri_RelationDesc, NoLock);
-               }
-
-               /* Release the standalone partition tuple descriptor */
-               ExecDropSingleTupleTableSlot(cstate->partition_tuple_slot);
-       }
+       if (cstate->partition_tuple_routing)
+               ExecCleanupTupleRouting(cstate->partition_tuple_routing);
 
        /* Close any trigger target relations */
        ExecCleanUpTriggerState(estate);
index 89c523ef448acd81d18b88335f12e89afcf2eaf7..115be026353762baf7d611a8792b2f870b9da37f 100644 (file)
@@ -38,58 +38,40 @@ static char *ExecBuildSlotPartitionKeyDescription(Relation rel,
                                                                         int maxfieldlen);
 
 /*
- * ExecSetupPartitionTupleRouting - set up information needed during
- * tuple routing for partitioned tables
- *
- * Output arguments:
- * 'pd' receives an array of PartitionDispatch objects with one entry for
- *             every partitioned table in the partition tree
- * 'partitions' receives an array of ResultRelInfo* objects with one entry for
- *             every leaf partition in the partition tree
- * 'tup_conv_maps' receives an array of TupleConversionMap objects with one
- *             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
- *             tree (= the number of entries in the 'partitions' and 'tup_conv_maps'
- *             output arrays
+ * ExecSetupPartitionTupleRouting - sets up information needed during
+ * tuple routing for partitioned tables, encapsulates it in
+ * PartitionTupleRouting, and returns it.
  *
  * Note that all the relations in the partition tree are locked using the
  * RowExclusiveLock mode upon return from this function.
  */
-void
+PartitionTupleRouting *
 ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
-                                                          Relation rel,
-                                                          Index resultRTindex,
-                                                          EState *estate,
-                                                          PartitionDispatch **pd,
-                                                          ResultRelInfo ***partitions,
-                                                          TupleConversionMap ***tup_conv_maps,
-                                                          TupleTableSlot **partition_tuple_slot,
-                                                          int *num_parted, int *num_partitions)
+                                                          Relation rel, Index resultRTindex,
+                                                          EState *estate)
 {
        TupleDesc       tupDesc = RelationGetDescr(rel);
        List       *leaf_parts;
        ListCell   *cell;
        int                     i;
        ResultRelInfo *leaf_part_rri;
+       PartitionTupleRouting *proute;
 
        /*
         * Get the information about the partition tree after locking all the
         * partitions.
         */
        (void) find_all_inheritors(RelationGetRelid(rel), RowExclusiveLock, NULL);
-       *pd = RelationGetPartitionDispatchInfo(rel, num_parted, &leaf_parts);
-       *num_partitions = list_length(leaf_parts);
-       *partitions = (ResultRelInfo **) palloc(*num_partitions *
-                                                                                       sizeof(ResultRelInfo *));
-       *tup_conv_maps = (TupleConversionMap **) palloc0(*num_partitions *
-                                                                                                        sizeof(TupleConversionMap *));
+       proute = (PartitionTupleRouting *) palloc0(sizeof(PartitionTupleRouting));
+       proute->partition_dispatch_info =
+               RelationGetPartitionDispatchInfo(rel, &proute->num_dispatch,
+                                                                                &leaf_parts);
+       proute->num_partitions = list_length(leaf_parts);
+       proute->partitions = (ResultRelInfo **) palloc(proute->num_partitions *
+                                                                                                  sizeof(ResultRelInfo *));
+       proute->partition_tupconv_maps =
+               (TupleConversionMap **) palloc0(proute->num_partitions *
+                                                                               sizeof(TupleConversionMap *));
 
        /*
         * Initialize an empty slot that will be used to manipulate tuples of any
@@ -97,9 +79,9 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
         * (such as ModifyTableState) and released when the node finishes
         * processing.
         */
-       *partition_tuple_slot = MakeTupleTableSlot();
+       proute->partition_tuple_slot = MakeTupleTableSlot();
 
-       leaf_part_rri = (ResultRelInfo *) palloc0(*num_partitions *
+       leaf_part_rri = (ResultRelInfo *) palloc0(proute->num_partitions *
                                                                                          sizeof(ResultRelInfo));
        i = 0;
        foreach(cell, leaf_parts)
@@ -109,8 +91,8 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
 
                /*
                 * We locked all the partitions above including the leaf partitions.
-                * Note that each of the relations in *partitions are eventually
-                * closed by the caller.
+                * Note that each of the relations in proute->partitions are
+                * eventually closed by the caller.
                 */
                partrel = heap_open(lfirst_oid(cell), NoLock);
                part_tupdesc = RelationGetDescr(partrel);
@@ -119,8 +101,9 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
                 * Save a tuple conversion map to convert a tuple routed to this
                 * partition from the parent's type to the partition's.
                 */
-               (*tup_conv_maps)[i] = convert_tuples_by_name(tupDesc, part_tupdesc,
-                                                                                                        gettext_noop("could not convert row type"));
+               proute->partition_tupconv_maps[i] =
+                       convert_tuples_by_name(tupDesc, part_tupdesc,
+                                                                  gettext_noop("could not convert row type"));
 
                InitResultRelInfo(leaf_part_rri,
                                                  partrel,
@@ -149,9 +132,11 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
                estate->es_leaf_result_relations =
                        lappend(estate->es_leaf_result_relations, leaf_part_rri);
 
-               (*partitions)[i] = leaf_part_rri++;
+               proute->partitions[i] = leaf_part_rri++;
                i++;
        }
+
+       return proute;
 }
 
 /*
@@ -272,6 +257,45 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
        return result;
 }
 
+/*
+ * ExecCleanupTupleRouting -- Clean up objects allocated for partition tuple
+ * routing.
+ *
+ * Close all the partitioned tables, leaf partitions, and their indices.
+ */
+void
+ExecCleanupTupleRouting(PartitionTupleRouting * proute)
+{
+       int                     i;
+
+       /*
+        * Remember, proute->partition_dispatch_info[0] corresponds to the root
+        * partitioned table, which we must not try to close, because it is the
+        * main target table of the query that will be closed by callers such as
+        * ExecEndPlan() or DoCopy(). Also, tupslot is NULL for the root
+        * partitioned table.
+        */
+       for (i = 1; i < proute->num_dispatch; i++)
+       {
+               PartitionDispatch pd = proute->partition_dispatch_info[i];
+
+               heap_close(pd->reldesc, NoLock);
+               ExecDropSingleTupleTableSlot(pd->tupslot);
+       }
+
+       for (i = 0; i < proute->num_partitions; i++)
+       {
+               ResultRelInfo *resultRelInfo = proute->partitions[i];
+
+               ExecCloseIndices(resultRelInfo);
+               heap_close(resultRelInfo->ri_RelationDesc, NoLock);
+       }
+
+       /* Release the standalone partition tuple descriptor, if any */
+       if (proute->partition_tuple_slot)
+               ExecDropSingleTupleTableSlot(proute->partition_tuple_slot);
+}
+
 /*
  * RelationGetPartitionDispatchInfo
  *             Returns information necessary to route tuples down a partition tree
index e52a3bb95ee4530f20596f7d04fa7715875da841..95e0748d8f40fdf8fc8b8535fbfe870d036c8356 100644 (file)
@@ -279,32 +279,33 @@ ExecInsert(ModifyTableState *mtstate,
        resultRelInfo = estate->es_result_relation_info;
 
        /* Determine the partition to heap_insert the tuple into */
-       if (mtstate->mt_partition_dispatch_info)
+       if (mtstate->mt_partition_tuple_routing)
        {
                int                     leaf_part_index;
+               PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
                TupleConversionMap *map;
 
                /*
                 * Away we go ... If we end up not finding a partition after all,
                 * ExecFindPartition() does not return and errors out instead.
                 * Otherwise, the returned value is to be used as an index into arrays
-                * mt_partitions[] and mt_partition_tupconv_maps[] that will get us
-                * the ResultRelInfo and TupleConversionMap for the partition,
+                * proute->partitions[] and proute->partition_tupconv_maps[] that will
+                * get us the ResultRelInfo and TupleConversionMap for the partition,
                 * respectively.
                 */
                leaf_part_index = ExecFindPartition(resultRelInfo,
-                                                                                       mtstate->mt_partition_dispatch_info,
+                                                                                       proute->partition_dispatch_info,
                                                                                        slot,
                                                                                        estate);
                Assert(leaf_part_index >= 0 &&
-                          leaf_part_index < mtstate->mt_num_partitions);
+                          leaf_part_index < proute->num_partitions);
 
                /*
                 * Save the old ResultRelInfo and switch to the one corresponding to
                 * the selected partition.
                 */
                saved_resultRelInfo = resultRelInfo;
-               resultRelInfo = mtstate->mt_partitions[leaf_part_index];
+               resultRelInfo = proute->partitions[leaf_part_index];
 
                /* We do not yet have a way to insert into a foreign partition */
                if (resultRelInfo->ri_FdwRoutine)
@@ -352,7 +353,7 @@ ExecInsert(ModifyTableState *mtstate,
                 * We might need to convert from the parent rowtype to the partition
                 * rowtype.
                 */
-               map = mtstate->mt_partition_tupconv_maps[leaf_part_index];
+               map = proute->partition_tupconv_maps[leaf_part_index];
                if (map)
                {
                        Relation        partrel = resultRelInfo->ri_RelationDesc;
@@ -364,7 +365,7 @@ ExecInsert(ModifyTableState *mtstate,
                         * on, until we're finished dealing with the partition. Use the
                         * dedicated slot for that.
                         */
-                       slot = mtstate->mt_partition_tuple_slot;
+                       slot = proute->partition_tuple_slot;
                        Assert(slot != NULL);
                        ExecSetSlotDescriptor(slot, RelationGetDescr(partrel));
                        ExecStoreTuple(tuple, slot, InvalidBuffer, true);
@@ -1500,9 +1501,10 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
                mtstate->mt_oc_transition_capture != NULL)
        {
                int                     numResultRelInfos;
+               PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
 
-               numResultRelInfos = (mtstate->mt_partition_tuple_slot != NULL ?
-                                                        mtstate->mt_num_partitions :
+               numResultRelInfos = (proute != NULL ?
+                                                        proute->num_partitions :
                                                         mtstate->mt_nplans);
 
                /*
@@ -1515,13 +1517,13 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
                        palloc0(sizeof(TupleConversionMap *) * numResultRelInfos);
 
                /* Choose the right set of partitions */
-               if (mtstate->mt_partition_dispatch_info != NULL)
+               if (proute != NULL)
                {
                        /*
                         * For tuple routing among partitions, we need TupleDescs based on
                         * the partition routing table.
                         */
-                       ResultRelInfo **resultRelInfos = mtstate->mt_partitions;
+                       ResultRelInfo **resultRelInfos = proute->partitions;
 
                        for (i = 0; i < numResultRelInfos; ++i)
                        {
@@ -1832,6 +1834,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
        ListCell   *l;
        int                     i;
        Relation        rel;
+       PartitionTupleRouting *proute = NULL;
+       int                     num_partitions = 0;
 
        /* check for unsupported flags */
        Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -1945,28 +1949,11 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
        if (operation == CMD_INSERT &&
                rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
        {
-               PartitionDispatch *partition_dispatch_info;
-               ResultRelInfo **partitions;
-               TupleConversionMap **partition_tupconv_maps;
-               TupleTableSlot *partition_tuple_slot;
-               int                     num_parted,
-                                       num_partitions;
-
-               ExecSetupPartitionTupleRouting(mtstate,
-                                                                          rel,
-                                                                          node->nominalRelation,
-                                                                          estate,
-                                                                          &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;
-               mtstate->mt_partition_tuple_slot = partition_tuple_slot;
+               proute = mtstate->mt_partition_tuple_routing =
+                       ExecSetupPartitionTupleRouting(mtstate,
+                                                                                  rel, node->nominalRelation,
+                                                                                  estate);
+               num_partitions = proute->num_partitions;
        }
 
        /*
@@ -2009,7 +1996,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
         * will suffice.  This only occurs for the INSERT case; UPDATE/DELETE
         * cases are handled above.
         */
-       if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
+       if (node->withCheckOptionLists != NIL && num_partitions > 0)
        {
                List       *wcoList;
                PlanState  *plan;
@@ -2026,14 +2013,14 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
                           mtstate->mt_nplans == 1);
                wcoList = linitial(node->withCheckOptionLists);
                plan = mtstate->mt_plans[0];
-               for (i = 0; i < mtstate->mt_num_partitions; i++)
+               for (i = 0; i < num_partitions; i++)
                {
                        Relation        partrel;
                        List       *mapped_wcoList;
                        List       *wcoExprs = NIL;
                        ListCell   *ll;
 
-                       resultRelInfo = mtstate->mt_partitions[i];
+                       resultRelInfo = proute->partitions[i];
                        partrel = resultRelInfo->ri_RelationDesc;
 
                        /* varno = node->nominalRelation */
@@ -2101,12 +2088,12 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
                 * are handled above.
                 */
                returningList = linitial(node->returningLists);
-               for (i = 0; i < mtstate->mt_num_partitions; i++)
+               for (i = 0; i < num_partitions; i++)
                {
                        Relation        partrel;
                        List       *rlist;
 
-                       resultRelInfo = mtstate->mt_partitions[i];
+                       resultRelInfo = proute->partitions[i];
                        partrel = resultRelInfo->ri_RelationDesc;
 
                        /* varno = node->nominalRelation */
@@ -2372,32 +2359,9 @@ ExecEndModifyTable(ModifyTableState *node)
                                                                                                                   resultRelInfo);
        }
 
-       /*
-        * Close all the partitioned tables, leaf partitions, and their indices
-        *
-        * Remember node->mt_partition_dispatch_info[0] corresponds to the root
-        * partitioned table, which we must not try to close, because it is the
-        * main target table of the query that will be closed by ExecEndPlan().
-        * Also, tupslot is NULL for the root partitioned table.
-        */
-       for (i = 1; i < node->mt_num_dispatch; i++)
-       {
-               PartitionDispatch pd = node->mt_partition_dispatch_info[i];
-
-               heap_close(pd->reldesc, NoLock);
-               ExecDropSingleTupleTableSlot(pd->tupslot);
-       }
-       for (i = 0; i < node->mt_num_partitions; i++)
-       {
-               ResultRelInfo *resultRelInfo = node->mt_partitions[i];
-
-               ExecCloseIndices(resultRelInfo);
-               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);
+       /* Close all the partitioned tables, leaf partitions, and their indices */
+       if (node->mt_partition_tuple_routing)
+               ExecCleanupTupleRouting(node->mt_partition_tuple_routing);
 
        /*
         * Free the exprcontext
index f0998cb82fb84216fcac89034739bb65c08cf00b..b5df357acdfc3d79c98ccc7bce0d6555ae764e2d 100644 (file)
@@ -49,18 +49,47 @@ typedef struct PartitionDispatchData
 
 typedef struct PartitionDispatchData *PartitionDispatch;
 
-extern void ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
-                                                          Relation rel,
-                                                          Index resultRTindex,
-                                                          EState *estate,
-                                                          PartitionDispatch **pd,
-                                                          ResultRelInfo ***partitions,
-                                                          TupleConversionMap ***tup_conv_maps,
-                                                          TupleTableSlot **partition_tuple_slot,
-                                                          int *num_parted, int *num_partitions);
+/*-----------------------
+ * PartitionTupleRouting - Encapsulates all information required to execute
+ * tuple-routing between partitions.
+ *
+ * partition_dispatch_info             Array of PartitionDispatch objects with one
+ *                                                             entry for every partitioned table in the
+ *                                                             partition tree.
+ * num_dispatch                                        number of partitioned tables in the partition
+ *                                                             tree (= length of partition_dispatch_info[])
+ * partitions                                  Array of ResultRelInfo* objects with one entry
+ *                                                             for every leaf partition in the partition tree.
+ * num_partitions                              Number of leaf partitions in the partition tree
+ *                                                             (= 'partitions' array length)
+ * partition_tupconv_maps              Array of TupleConversionMap objects with one
+ *                                                             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                        TupleTableSlot to be used to manipulate any
+ *                                                             given leaf partition's rowtype after that
+ *                                                             partition is chosen for insertion by
+ *                                                             tuple-routing.
+ *-----------------------
+ */
+typedef struct PartitionTupleRouting
+{
+       PartitionDispatch *partition_dispatch_info;
+       int                     num_dispatch;
+       ResultRelInfo **partitions;
+       int                     num_partitions;
+       TupleConversionMap **partition_tupconv_maps;
+       TupleTableSlot *partition_tuple_slot;
+} PartitionTupleRouting;
+
+extern PartitionTupleRouting *ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
+                                                          Relation rel, Index resultRTindex,
+                                                          EState *estate);
 extern int ExecFindPartition(ResultRelInfo *resultRelInfo,
                                  PartitionDispatch *pd,
                                  TupleTableSlot *slot,
                                  EState *estate);
+extern void ExecCleanupTupleRouting(PartitionTupleRouting *proute);
 
 #endif                                                 /* EXECPARTITION_H */
index 3ad58cdfe7c05786ada584b4902126e9dc6f16c4..2a4f7407a162972f198ee26f9e9c4bb0cb494fa7 100644 (file)
@@ -985,15 +985,8 @@ typedef struct ModifyTableState
        TupleTableSlot *mt_existing;    /* slot to store existing target tuple in */
        List       *mt_excludedtlist;   /* the excluded pseudo relation's tlist  */
        TupleTableSlot *mt_conflproj;   /* CONFLICT ... SET ... projection target */
-       struct PartitionDispatchData **mt_partition_dispatch_info;
+       struct PartitionTupleRouting *mt_partition_tuple_routing;
        /* Tuple-routing support info */
-       int                     mt_num_dispatch;        /* Number of entries in the above array */
-       int                     mt_num_partitions;      /* Number of members in the following
-                                                                        * arrays */
-       ResultRelInfo **mt_partitions;  /* Per partition result relation pointers */
-       TupleConversionMap **mt_partition_tupconv_maps;
-       /* Per partition tuple conversion map */
-       TupleTableSlot *mt_partition_tuple_slot;
        struct TransitionCaptureState *mt_transition_capture;
        /* controls transition table population for specified operation */
        struct TransitionCaptureState *mt_oc_transition_capture;