Refactor partition tuple routing code to reduce duplication.
authorRobert Haas <rhaas@postgresql.org>
Wed, 21 Dec 2016 16:36:10 +0000 (11:36 -0500)
committerRobert Haas <rhaas@postgresql.org>
Wed, 21 Dec 2016 16:36:10 +0000 (11:36 -0500)
Amit Langote

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

index 7a8da338f075079dc72ce3d3645151660104ae54..d5901651db18c259de9235f895b72ea5dee83ad0 100644 (file)
@@ -1406,64 +1406,22 @@ BeginCopy(ParseState *pstate,
        /* Initialize state for CopyFrom tuple routing. */
        if (is_from && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
        {
-           List       *leaf_parts;
-           ListCell   *cell;
-           int         i,
-                       num_parted;
-           ResultRelInfo *leaf_part_rri;
-
-           /* Get the tuple-routing information and lock partitions */
-           cstate->partition_dispatch_info =
-               RelationGetPartitionDispatchInfo(rel, RowExclusiveLock,
-                                                &num_parted,
-                                                &leaf_parts);
+           PartitionDispatch  *partition_dispatch_info;
+           ResultRelInfo      *partitions;
+           TupleConversionMap **partition_tupconv_maps;
+           int                 num_parted,
+                               num_partitions;
+
+           ExecSetupPartitionTupleRouting(rel,
+                                          &partition_dispatch_info,
+                                          &partitions,
+                                          &partition_tupconv_maps,
+                                          &num_parted, &num_partitions);
+           cstate->partition_dispatch_info = partition_dispatch_info;
            cstate->num_dispatch = num_parted;
-           cstate->num_partitions = list_length(leaf_parts);
-           cstate->partitions = (ResultRelInfo *)
-               palloc(cstate->num_partitions *
-                      sizeof(ResultRelInfo));
-           cstate->partition_tupconv_maps = (TupleConversionMap **)
-               palloc0(cstate->num_partitions *
-                       sizeof(TupleConversionMap *));
-
-           leaf_part_rri = cstate->partitions;
-           i = 0;
-           foreach(cell, leaf_parts)
-           {
-               Relation    partrel;
-
-               /*
-                * We locked all the partitions above including the leaf
-                * partitions.  Note that each of the relations in
-                * cstate->partitions will be closed by CopyFrom() after it's
-                * finished with its processing.
-                */
-               partrel = heap_open(lfirst_oid(cell), NoLock);
-
-               /*
-                * Verify result relation is a valid target for the current
-                * operation.
-                */
-               CheckValidResultRel(partrel, CMD_INSERT);
-
-               InitResultRelInfo(leaf_part_rri,
-                                 partrel,
-                                 1,    /* dummy */
-                                 false,        /* no partition constraint
-                                                * check */
-                                 0);
-
-               /* Open partition indices */
-               ExecOpenIndices(leaf_part_rri, false);
-
-               if (!equalTupleDescs(tupDesc, RelationGetDescr(partrel)))
-                   cstate->partition_tupconv_maps[i] =
-                       convert_tuples_by_name(tupDesc,
-                                              RelationGetDescr(partrel),
-                                gettext_noop("could not convert row type"));
-               leaf_part_rri++;
-               i++;
-           }
+           cstate->partitions = partitions;
+           cstate->num_partitions = num_partitions;
+           cstate->partition_tupconv_maps = partition_tupconv_maps;
        }
    }
    else
index d43a204808078e2efa035c6be7080692b26fec8f..bca34a509cdb542c49b1df079ec9ac0f16a01538 100644 (file)
@@ -51,6 +51,7 @@
 #include "miscadmin.h"
 #include "optimizer/clauses.h"
 #include "parser/parsetree.h"
+#include "rewrite/rewriteManip.h"
 #include "storage/bufmgr.h"
 #include "storage/lmgr.h"
 #include "tcop/utility.h"
@@ -2998,6 +2999,97 @@ EvalPlanQualEnd(EPQState *epqstate)
    epqstate->origslot = NULL;
 }
 
+/*
+ * 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
+ * '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
+ *
+ * Note that all the relations in the partition tree are locked using the
+ * RowExclusiveLock mode upon return from this function.
+ */
+void
+ExecSetupPartitionTupleRouting(Relation rel,
+                              PartitionDispatch **pd,
+                              ResultRelInfo **partitions,
+                              TupleConversionMap ***tup_conv_maps,
+                              int *num_parted, int *num_partitions)
+{
+   TupleDesc   tupDesc = RelationGetDescr(rel);
+   List       *leaf_parts;
+   ListCell   *cell;
+   int         i;
+   ResultRelInfo *leaf_part_rri;
+
+   /* Get the tuple-routing information and lock partitions */
+   *pd = RelationGetPartitionDispatchInfo(rel, RowExclusiveLock, 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 *));
+
+   leaf_part_rri = *partitions;
+   i = 0;
+   foreach(cell, leaf_parts)
+   {
+       Relation    partrel;
+       TupleDesc   part_tupdesc;
+
+       /*
+        * We locked all the partitions above including the leaf partitions.
+        * Note that each of the relations in *partitions are eventually
+        * closed by the caller.
+        */
+       partrel = heap_open(lfirst_oid(cell), NoLock);
+       part_tupdesc = RelationGetDescr(partrel);
+
+       /*
+        * Verify result relation is a valid target for the current operation.
+        */
+       CheckValidResultRel(partrel, CMD_INSERT);
+
+       /*
+        * 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"));
+
+       InitResultRelInfo(leaf_part_rri,
+                         partrel,
+                         1,     /* dummy */
+                         false,
+                         0);
+
+       /*
+        * Open partition indices (remember we do not support ON CONFLICT in
+        * case of partitioned tables, so we do not need support information
+        * for speculative insertion)
+        */
+       if (leaf_part_rri->ri_RelationDesc->rd_rel->relhasindex &&
+           leaf_part_rri->ri_IndexRelationDescs == NULL)
+           ExecOpenIndices(leaf_part_rri, false);
+
+       leaf_part_rri++;
+       i++;
+   }
+}
+
 /*
  * ExecFindPartition -- Find a leaf partition in the partition tree rooted
  * at parent, for the heap tuple contained in *slot
index ec440b353d0aeca6f8f2ae0a637cc042d67dcf5c..a9546106ceca8e438ea5597f527230c5bffe8d61 100644 (file)
@@ -1718,68 +1718,22 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
    if (operation == CMD_INSERT &&
        rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
    {
-       int                 i,
-                           j,
-                           num_parted;
-       List               *leaf_parts;
-       ListCell           *cell;
-       ResultRelInfo      *leaf_part_rri;
-
-       /* Get the tuple-routing information and lock partitions */
-       mtstate->mt_partition_dispatch_info =
-                   RelationGetPartitionDispatchInfo(rel, RowExclusiveLock,
-                                                    &num_parted,
-                                                    &leaf_parts);
+       PartitionDispatch  *partition_dispatch_info;
+       ResultRelInfo      *partitions;
+       TupleConversionMap **partition_tupconv_maps;
+       int                 num_parted,
+                           num_partitions;
+
+       ExecSetupPartitionTupleRouting(rel,
+                                      &partition_dispatch_info,
+                                      &partitions,
+                                      &partition_tupconv_maps,
+                                      &num_parted, &num_partitions);
+       mtstate->mt_partition_dispatch_info = partition_dispatch_info;
        mtstate->mt_num_dispatch = num_parted;
-       mtstate->mt_num_partitions = list_length(leaf_parts);
-       mtstate->mt_partitions = (ResultRelInfo *)
-                       palloc0(mtstate->mt_num_partitions *
-                                               sizeof(ResultRelInfo));
-       mtstate->mt_partition_tupconv_maps = (TupleConversionMap **)
-                       palloc0(mtstate->mt_num_partitions *
-                                               sizeof(TupleConversionMap *));
-
-       leaf_part_rri = mtstate->mt_partitions;
-       i = j = 0;
-       foreach(cell, leaf_parts)
-       {
-           Oid         partrelid = lfirst_oid(cell);
-           Relation    partrel;
-
-           /*
-            * We locked all the partitions above including the leaf
-            * partitions.  Note that each of the relations in
-            * mtstate->mt_partitions will be closed by ExecEndModifyTable().
-            */
-           partrel = heap_open(partrelid, NoLock);
-
-           /*
-            * Verify result relation is a valid target for the current
-            * operation
-            */
-           CheckValidResultRel(partrel, CMD_INSERT);
-
-           InitResultRelInfo(leaf_part_rri,
-                             partrel,
-                             1,        /* dummy */
-                             false,    /* no partition constraint checks */
-                             eflags);
-
-           /* Open partition indices (note: ON CONFLICT unsupported)*/
-           if (partrel->rd_rel->relhasindex && operation != CMD_DELETE &&
-               leaf_part_rri->ri_IndexRelationDescs == NULL)
-               ExecOpenIndices(leaf_part_rri, false);
-
-           if (!equalTupleDescs(RelationGetDescr(rel),
-                                RelationGetDescr(partrel)))
-               mtstate->mt_partition_tupconv_maps[i] =
-                           convert_tuples_by_name(RelationGetDescr(rel),
-                                                  RelationGetDescr(partrel),
-                                 gettext_noop("could not convert row type"));
-
-           leaf_part_rri++;
-           i++;
-       }
+       mtstate->mt_partitions = partitions;
+       mtstate->mt_num_partitions = num_partitions;
+       mtstate->mt_partition_tupconv_maps = partition_tupconv_maps;
    }
 
    /*
index 3f649faf2fe1b24083dc6380e85e705d06713cc0..b74fa5eb5da53e4031c78aac8ff12d92ddf0fcd5 100644 (file)
@@ -213,6 +213,11 @@ extern void EvalPlanQualSetPlan(EPQState *epqstate,
 extern void EvalPlanQualSetTuple(EPQState *epqstate, Index rti,
                     HeapTuple tuple);
 extern HeapTuple EvalPlanQualGetTuple(EPQState *epqstate, Index rti);
+extern void ExecSetupPartitionTupleRouting(Relation rel,
+                              PartitionDispatch **pd,
+                              ResultRelInfo **partitions,
+                              TupleConversionMap ***tup_conv_maps,
+                              int *num_parted, int *num_partitions);
 extern int ExecFindPartition(ResultRelInfo *resultRelInfo,
                  PartitionDispatch *pd,
                  TupleTableSlot *slot,