commit db7139f21cca1d1d6020ee1edbd026b2aae635f6
Author: Amit Khandekar <amit.khandekar@enterprisedb.com>
Date:   Fri Dec 22 16:23:06 2017 +0530

    Organize cleanup done for partition-tuple-routing.
    
    The same code that closes all the partitioned tables, leaf partitions,
    and their indices exists in two places, namely CopyFrom() and
    ExecEndModifyTable. Move this code into a common function
    ExecCleanupTupleRouting().

diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index d7638a1..ca73a22 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2838,34 +2838,7 @@ CopyFrom(CopyState cstate)
 
 	/* Close all the partitioned tables, leaf partitions, and their indices */
 	if (cstate->partition_tuple_routing)
-	{
-		PartitionTupleRouting *proute = cstate->partition_tuple_routing;
-		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 < 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 */
-		ExecDropSingleTupleTableSlot(proute->partition_tuple_slot);
-	}
+		ExecCleanupTupleRouting(cstate->partition_tuple_routing);
 
 	/* Close any trigger target relations */
 	ExecCleanUpTriggerState(estate);
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 8eaf7db..7d926f5 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -264,6 +264,45 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
 }
 
 /*
+ * 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
  *
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index ef0f680..ed12952 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2364,36 +2364,9 @@ ExecEndModifyTable(ModifyTableState *node)
 														   resultRelInfo);
 	}
 
-	/*
-	 * Close all the partitioned tables, leaf partitions, and their indices
-	 *
-	 * 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 ExecEndPlan().
-	 * Also, tupslot is NULL for the root partitioned table.
-	 */
+	/* Close all the partitioned tables, leaf partitions, and their indices */
 	if (node->mt_partition_tuple_routing)
-	{
-		PartitionTupleRouting *proute = node->mt_partition_tuple_routing;
-
-		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);
-	}
+		ExecCleanupTupleRouting(node->mt_partition_tuple_routing);
 
 	/*
 	 * Free the exprcontext
diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h
index 364d89f..1591b53 100644
--- a/src/include/executor/execPartition.h
+++ b/src/include/executor/execPartition.h
@@ -92,5 +92,6 @@ extern int ExecFindPartition(ResultRelInfo *resultRelInfo,
 				  PartitionDispatch *pd,
 				  TupleTableSlot *slot,
 				  EState *estate);
+extern void ExecCleanupTupleRouting(PartitionTupleRouting *proute);
 
 #endif							/* EXECPARTITION_H */
