From ee174e99c2a8a3382645b87f4e1d0098dd01f7f9 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Thu, 17 Jan 2019 10:04:15 -0500
Subject: [PATCH 5/8] Adapt the optimizer to use a PartitionDirectory.

Along the way, make expand_partitioned_rtentry responsible for
acquiring locks.

Hey, it's in the wrong order, but maybe I won't worry about that
for right now.
---
 src/backend/optimizer/util/inherit.c | 68 +++++++++++++++-------------
 src/backend/optimizer/util/plancat.c |  2 +-
 src/include/nodes/relation.h         |  3 ++
 3 files changed, 40 insertions(+), 33 deletions(-)

diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c
index faba493200..04a930d65b 100644
--- a/src/backend/optimizer/util/inherit.c
+++ b/src/backend/optimizer/util/inherit.c
@@ -124,28 +124,15 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
 
 	/*
 	 * The rewriter should already have obtained an appropriate lock on each
-	 * relation named in the query.  However, for each child relation we add
-	 * to the query, we must obtain an appropriate lock, because this will be
-	 * the first use of those relations in the parse/rewrite/plan pipeline.
-	 * Child rels should use the same lockmode as their parent.
+	 * relation named in the query, so we can open the parent relation without
+	 * locking it.  However, for each child relation we add to the query, we
+	 * must obtain an appropriate lock, because this will be the first use of
+	 * those relations in the parse/rewrite/plan pipeline.  Child rels should
+	 * use the same lockmode as their parent.
 	 */
+	oldrelation = table_open(parentOID, NoLock);
 	lockmode = rte->rellockmode;
 
-	/* Scan for all members of inheritance set, acquire needed locks */
-	inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
-
-	/*
-	 * Check that there's at least one descendant, else treat as no-child
-	 * case.  This could happen despite above has_subclass() check, if table
-	 * once had a child but no longer does.
-	 */
-	if (list_length(inhOIDs) < 2)
-	{
-		/* Clear flag before returning */
-		rte->inh = false;
-		return;
-	}
-
 	/*
 	 * If parent relation is selected FOR UPDATE/SHARE, we need to mark its
 	 * PlanRowMark as isParent = true, and generate a new PlanRowMark for each
@@ -155,21 +142,19 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
 	if (oldrc)
 		oldrc->isParent = true;
 
-	/*
-	 * Must open the parent relation to examine its tupdesc.  We need not lock
-	 * it; we assume the rewriter already did.
-	 */
-	oldrelation = table_open(parentOID, NoLock);
-
 	/* Scan the inheritance set and expand it */
-	if (RelationGetPartitionDesc(oldrelation) != NULL)
+	if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
 	{
 		Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
 
+		if (root->partition_directory == NULL)
+			root->partition_directory =
+				CreatePartitionDirectory(CurrentMemoryContext);
+
 		/*
-		 * If this table has partitions, recursively expand them in the order
-		 * in which they appear in the PartitionDesc.  While at it, also
-		 * extract the partition key columns of all the partitioned tables.
+		 * If this table has partitions, recursively expand and lock them.
+		 * While at it, also extract the partition key columns of all the
+		 * partitioned tables.
 		 */
 		expand_partitioned_rtentry(root, rte, rti, oldrelation, oldrc,
 								   lockmode, &root->append_rel_list);
@@ -180,6 +165,22 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
 		RangeTblEntry *childrte;
 		Index		childRTindex;
 
+		/* Scan for all members of inheritance set, acquire needed locks */
+		inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
+
+		/*
+		 * Check that there's at least one descendant, else treat as no-child
+		 * case.  This could happen despite above has_subclass() check, if the
+		 * table once had a child but no longer does.
+		 */
+		if (list_length(inhOIDs) < 2)
+		{
+			/* Clear flag before returning */
+			rte->inh = false;
+			heap_close(oldrelation, NoLock);
+			return;
+		}
+
 		/*
 		 * This table has no partitions.  Expand any plain inheritance
 		 * children in the order the OIDs were returned by
@@ -249,7 +250,10 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
 	int			i;
 	RangeTblEntry *childrte;
 	Index		childRTindex;
-	PartitionDesc partdesc = RelationGetPartitionDesc(parentrel);
+	PartitionDesc partdesc;
+
+	partdesc = PartitionDirectoryLookup(root->partition_directory,
+										parentrel);
 
 	check_stack_depth();
 
@@ -289,8 +293,8 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
 		Oid			childOID = partdesc->oids[i];
 		Relation	childrel;
 
-		/* Open rel; we already have required locks */
-		childrel = table_open(childOID, NoLock);
+		/* Open rel, acquiring required locks */
+		childrel = table_open(childOID, lockmode);
 
 		/*
 		 * Temporary partitions belonging to other sessions should have been
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 1bb1edd8a4..e9a8d99063 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -1904,7 +1904,7 @@ set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel,
 
 	Assert(relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
 
-	partdesc = RelationGetPartitionDesc(relation);
+	partdesc = PartitionDirectoryLookup(root->partition_directory, relation);
 	partkey = RelationGetPartitionKey(relation);
 	rel->part_scheme = find_partition_scheme(root, relation);
 	Assert(partdesc != NULL && rel->part_scheme != NULL);
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 420ca05c30..a78481906e 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -342,6 +342,9 @@ typedef struct PlannerInfo
 
 	/* Does this query modify any partition key columns? */
 	bool		partColsUpdated;
+
+	/* Directory of partition descriptors. */
+	PartitionDirectory partition_directory;
 } PlannerInfo;
 
 
-- 
2.17.2 (Apple Git-113)

