Use ResultRelInfo ** rather than ResultRelInfo * for tuple routing.
authorRobert Haas <rhaas@postgresql.org>
Thu, 12 Oct 2017 20:50:53 +0000 (16:50 -0400)
committerRobert Haas <rhaas@postgresql.org>
Thu, 12 Oct 2017 20:50:53 +0000 (16:50 -0400)
The previous convention doesn't lend itself to creating ResultRelInfos
lazily, as we already do in ExecGetTriggerResultRel.  This patch
doesn't make anything lazier than before, but the pending patch for
UPDATE tuple routing proposes to do so (and there might be other
opportunities as well).

Amit Khandekar with some adjustments by me.

Discussion: http://postgr.es/m/CA+TgmoYPVP9Lyf6vUFA5DwxS4c--x6LOj2y36BsJaYtp62eXPQ@mail.gmail.com

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 64550f9c680a17c926861ae7755420c8da85476e..8006df32a810c90cc8feab48979af3b1d8ea83c1 100644 (file)
@@ -167,7 +167,7 @@ typedef struct CopyStateData
    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 */
+   ResultRelInfo **partitions; /* Per partition result relation pointers */
    TupleConversionMap **partition_tupconv_maps;
    TupleTableSlot *partition_tuple_slot;
    TransitionCaptureState *transition_capture;
@@ -2459,7 +2459,7 @@ CopyFrom(CopyState cstate)
    if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
    {
        PartitionDispatch *partition_dispatch_info;
-       ResultRelInfo *partitions;
+       ResultRelInfo **partitions;
        TupleConversionMap **partition_tupconv_maps;
        TupleTableSlot *partition_tuple_slot;
        int         num_parted,
@@ -2495,7 +2495,7 @@ CopyFrom(CopyState cstate)
            for (i = 0; i < cstate->num_partitions; ++i)
            {
                cstate->transition_tupconv_maps[i] =
-                   convert_tuples_by_name(RelationGetDescr(cstate->partitions[i].ri_RelationDesc),
+                   convert_tuples_by_name(RelationGetDescr(cstate->partitions[i]->ri_RelationDesc),
                                           RelationGetDescr(cstate->rel),
                                           gettext_noop("could not convert row type"));
            }
@@ -2626,7 +2626,7 @@ CopyFrom(CopyState cstate)
             * to the selected partition.
             */
            saved_resultRelInfo = resultRelInfo;
-           resultRelInfo = cstate->partitions + leaf_part_index;
+           resultRelInfo = cstate->partitions[leaf_part_index];
 
            /* We do not yet have a way to insert into a foreign partition */
            if (resultRelInfo->ri_FdwRoutine)
@@ -2856,7 +2856,7 @@ CopyFrom(CopyState cstate)
        }
        for (i = 0; i < cstate->num_partitions; i++)
        {
-           ResultRelInfo *resultRelInfo = cstate->partitions + i;
+           ResultRelInfo *resultRelInfo = cstate->partitions[i];
 
            ExecCloseIndices(resultRelInfo);
            heap_close(resultRelInfo->ri_RelationDesc, NoLock);
index 8359beb463a3ddff18580b5c96ba4139b1712ac1..968942991228bc00883e570b5073f8066bdb37cc 100644 (file)
@@ -3242,7 +3242,7 @@ EvalPlanQualEnd(EPQState *epqstate)
  * 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
+ * '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
@@ -3265,7 +3265,7 @@ ExecSetupPartitionTupleRouting(Relation rel,
                               Index resultRTindex,
                               EState *estate,
                               PartitionDispatch **pd,
-                              ResultRelInfo **partitions,
+                              ResultRelInfo ***partitions,
                               TupleConversionMap ***tup_conv_maps,
                               TupleTableSlot **partition_tuple_slot,
                               int *num_parted, int *num_partitions)
@@ -3283,8 +3283,8 @@ ExecSetupPartitionTupleRouting(Relation rel,
    (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));
+   *partitions = (ResultRelInfo **) palloc(*num_partitions *
+                                           sizeof(ResultRelInfo *));
    *tup_conv_maps = (TupleConversionMap **) palloc0(*num_partitions *
                                                     sizeof(TupleConversionMap *));
 
@@ -3296,7 +3296,8 @@ ExecSetupPartitionTupleRouting(Relation rel,
     */
    *partition_tuple_slot = MakeTupleTableSlot();
 
-   leaf_part_rri = *partitions;
+   leaf_part_rri = (ResultRelInfo *) palloc0(*num_partitions *
+                                             sizeof(ResultRelInfo));
    i = 0;
    foreach(cell, leaf_parts)
    {
@@ -3341,7 +3342,7 @@ ExecSetupPartitionTupleRouting(Relation rel,
        estate->es_leaf_result_relations =
            lappend(estate->es_leaf_result_relations, leaf_part_rri);
 
-       leaf_part_rri++;
+       (*partitions)[i] = leaf_part_rri++;
        i++;
    }
 }
index 845c409540a735f1c15e6ed1fce8500740416f30..0027d21253f0521edad0c5ae99e03e288096b521 100644 (file)
@@ -303,7 +303,7 @@ ExecInsert(ModifyTableState *mtstate,
         * the selected partition.
         */
        saved_resultRelInfo = resultRelInfo;
-       resultRelInfo = mtstate->mt_partitions + leaf_part_index;
+       resultRelInfo = mtstate->mt_partitions[leaf_part_index];
 
        /* We do not yet have a way to insert into a foreign partition */
        if (resultRelInfo->ri_FdwRoutine)
@@ -1498,25 +1498,11 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
    if (mtstate->mt_transition_capture != NULL ||
        mtstate->mt_oc_transition_capture != NULL)
    {
-       ResultRelInfo *resultRelInfos;
        int         numResultRelInfos;
 
-       /* Find the set of partitions so that we can find their TupleDescs. */
-       if (mtstate->mt_partition_dispatch_info != NULL)
-       {
-           /*
-            * For INSERT via partitioned table, so we need TupleDescs based
-            * on the partition routing table.
-            */
-           resultRelInfos = mtstate->mt_partitions;
-           numResultRelInfos = mtstate->mt_num_partitions;
-       }
-       else
-       {
-           /* Otherwise we need the ResultRelInfo for each subplan. */
-           resultRelInfos = mtstate->resultRelInfo;
-           numResultRelInfos = mtstate->mt_nplans;
-       }
+       numResultRelInfos = (mtstate->mt_partition_tuple_slot != NULL ?
+                            mtstate->mt_num_partitions :
+                            mtstate->mt_nplans);
 
        /*
         * Build array of conversion maps from each child's TupleDesc to the
@@ -1526,12 +1512,36 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
         */
        mtstate->mt_transition_tupconv_maps = (TupleConversionMap **)
            palloc0(sizeof(TupleConversionMap *) * numResultRelInfos);
-       for (i = 0; i < numResultRelInfos; ++i)
+
+       /* Choose the right set of partitions */
+       if (mtstate->mt_partition_dispatch_info != NULL)
        {
-           mtstate->mt_transition_tupconv_maps[i] =
-               convert_tuples_by_name(RelationGetDescr(resultRelInfos[i].ri_RelationDesc),
-                                      RelationGetDescr(targetRelInfo->ri_RelationDesc),
-                                      gettext_noop("could not convert row type"));
+           /*
+            * For tuple routing among partitions, we need TupleDescs based
+            * on the partition routing table.
+            */
+           ResultRelInfo **resultRelInfos = mtstate->mt_partitions;
+
+           for (i = 0; i < numResultRelInfos; ++i)
+           {
+               mtstate->mt_transition_tupconv_maps[i] =
+                   convert_tuples_by_name(RelationGetDescr(resultRelInfos[i]->ri_RelationDesc),
+                                          RelationGetDescr(targetRelInfo->ri_RelationDesc),
+                                          gettext_noop("could not convert row type"));
+           }
+       }
+       else
+       {
+           /* Otherwise we need the ResultRelInfo for each subplan. */
+           ResultRelInfo *resultRelInfos = mtstate->resultRelInfo;
+
+           for (i = 0; i < numResultRelInfos; ++i)
+           {
+               mtstate->mt_transition_tupconv_maps[i] =
+                   convert_tuples_by_name(RelationGetDescr(resultRelInfos[i].ri_RelationDesc),
+                                          RelationGetDescr(targetRelInfo->ri_RelationDesc),
+                                          gettext_noop("could not convert row type"));
+           }
        }
 
        /*
@@ -1935,7 +1945,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
        rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
    {
        PartitionDispatch *partition_dispatch_info;
-       ResultRelInfo *partitions;
+       ResultRelInfo **partitions;
        TupleConversionMap **partition_tupconv_maps;
        TupleTableSlot *partition_tuple_slot;
        int         num_parted,
@@ -2014,14 +2024,16 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
               mtstate->mt_nplans == 1);
        wcoList = linitial(node->withCheckOptionLists);
        plan = mtstate->mt_plans[0];
-       resultRelInfo = mtstate->mt_partitions;
        for (i = 0; i < mtstate->mt_num_partitions; i++)
        {
-           Relation    partrel = resultRelInfo->ri_RelationDesc;
+           Relation    partrel;
            List       *mapped_wcoList;
            List       *wcoExprs = NIL;
            ListCell   *ll;
 
+           resultRelInfo = mtstate->mt_partitions[i];
+           partrel = resultRelInfo->ri_RelationDesc;
+
            /* varno = node->nominalRelation */
            mapped_wcoList = map_partition_varattnos(wcoList,
                                                     node->nominalRelation,
@@ -2037,7 +2049,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 
            resultRelInfo->ri_WithCheckOptions = mapped_wcoList;
            resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
-           resultRelInfo++;
        }
    }
 
@@ -2088,13 +2099,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
         * will suffice.  This only occurs for the INSERT case; UPDATE/DELETE
         * are handled above.
         */
-       resultRelInfo = mtstate->mt_partitions;
        returningList = linitial(node->returningLists);
        for (i = 0; i < mtstate->mt_num_partitions; i++)
        {
-           Relation    partrel = resultRelInfo->ri_RelationDesc;
+           Relation    partrel;
            List       *rlist;
 
+           resultRelInfo = mtstate->mt_partitions[i];
+           partrel = resultRelInfo->ri_RelationDesc;
+
            /* varno = node->nominalRelation */
            rlist = map_partition_varattnos(returningList,
                                            node->nominalRelation,
@@ -2102,7 +2115,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
            resultRelInfo->ri_projectReturning =
                ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
                                        resultRelInfo->ri_RelationDesc->rd_att);
-           resultRelInfo++;
        }
    }
    else
@@ -2376,7 +2388,7 @@ ExecEndModifyTable(ModifyTableState *node)
    }
    for (i = 0; i < node->mt_num_partitions; i++)
    {
-       ResultRelInfo *resultRelInfo = node->mt_partitions + i;
+       ResultRelInfo *resultRelInfo = node->mt_partitions[i];
 
        ExecCloseIndices(resultRelInfo);
        heap_close(resultRelInfo->ri_RelationDesc, NoLock);
index 37fd6b2700a9d5510ba4361af06867b73446bf07..c4ecf0d50f3e3c2d46afb1867a42cc281ec3bb42 100644 (file)
@@ -210,7 +210,7 @@ extern void ExecSetupPartitionTupleRouting(Relation rel,
                               Index resultRTindex,
                               EState *estate,
                               PartitionDispatch **pd,
-                              ResultRelInfo **partitions,
+                              ResultRelInfo ***partitions,
                               TupleConversionMap ***tup_conv_maps,
                               TupleTableSlot **partition_tuple_slot,
                               int *num_parted, int *num_partitions);
index d4ce8d8f494bcfcab17026481ae1aa9354ffa6b0..01ceeef39c7f4f669c0c574db51007b660b6bd02 100644 (file)
@@ -979,7 +979,7 @@ typedef struct ModifyTableState
    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 */
+   ResultRelInfo **mt_partitions;  /* Per partition result relation pointers */
    TupleConversionMap **mt_partition_tupconv_maps;
    /* Per partition tuple conversion map */
    TupleTableSlot *mt_partition_tuple_slot;