From 4066b913cc6c46ae6ff1eb941eae1cbc8fb7540b Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Mon, 26 Nov 2018 14:31:53 -0500
Subject: [PATCH 1/5] Move code for managing PartitionDescs into a new file,
 partdesc.c

---
 src/backend/catalog/heap.c            |   1 +
 src/backend/catalog/partition.c       |  16 --
 src/backend/catalog/pg_constraint.c   |   2 +-
 src/backend/commands/indexcmds.c      |   2 +-
 src/backend/commands/tablecmds.c      |   1 +
 src/backend/commands/trigger.c        |   1 +
 src/backend/executor/execPartition.c  |   1 +
 src/backend/optimizer/util/inherit.c  |   1 +
 src/backend/optimizer/util/plancat.c  |   2 +-
 src/backend/partitioning/Makefile     |   2 +-
 src/backend/partitioning/partbounds.c |   6 +-
 src/backend/partitioning/partdesc.c   | 221 ++++++++++++++++++++++++++
 src/backend/utils/cache/partcache.c   | 124 ---------------
 src/backend/utils/cache/relcache.c    |  57 +------
 src/include/catalog/partition.h       |  15 --
 src/include/partitioning/partdesc.h   |  39 +++++
 src/include/utils/partcache.h         |   1 -
 17 files changed, 274 insertions(+), 218 deletions(-)
 create mode 100644 src/backend/partitioning/partdesc.c
 create mode 100644 src/include/partitioning/partdesc.h

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 06d18a1cfb..6305cbbf06 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -69,6 +69,7 @@
 #include "parser/parse_collate.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
+#include "partitioning/partdesc.h"
 #include "storage/lmgr.h"
 #include "storage/predicate.h"
 #include "storage/smgr.h"
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 0d3bc3a2c7..3ccdaff8c4 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -253,22 +253,6 @@ has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr)
 	return false;
 }
 
-/*
- * get_default_oid_from_partdesc
- *
- * Given a partition descriptor, return the OID of the default partition, if
- * one exists; else, return InvalidOid.
- */
-Oid
-get_default_oid_from_partdesc(PartitionDesc partdesc)
-{
-	if (partdesc && partdesc->boundinfo &&
-		partition_bound_has_default(partdesc->boundinfo))
-		return partdesc->oids[partdesc->boundinfo->default_index];
-
-	return InvalidOid;
-}
-
 /*
  * get_default_partition_oid
  *
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 698b493fc4..ea8817e8c8 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -24,12 +24,12 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
-#include "catalog/partition.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "commands/tablecmds.h"
+#include "partitioning/partdesc.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index bd85099c28..fc176d39ab 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -24,7 +24,6 @@
 #include "catalog/catalog.h"
 #include "catalog/index.h"
 #include "catalog/indexing.h"
-#include "catalog/partition.h"
 #include "catalog/pg_am.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_inherits.h"
@@ -46,6 +45,7 @@
 #include "parser/parse_coerce.h"
 #include "parser/parse_func.h"
 #include "parser/parse_oper.h"
+#include "partitioning/partdesc.h"
 #include "rewrite/rewriteManip.h"
 #include "storage/lmgr.h"
 #include "storage/proc.h"
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 35a9ade059..5646e6e075 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -74,6 +74,7 @@
 #include "parser/parse_utilcmd.h"
 #include "parser/parser.h"
 #include "partitioning/partbounds.h"
+#include "partitioning/partdesc.h"
 #include "pgstat.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteHandler.h"
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 7b5896b98f..f5c911b5a7 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -42,6 +42,7 @@
 #include "parser/parse_func.h"
 #include "parser/parse_relation.h"
 #include "parser/parsetree.h"
+#include "partitioning/partdesc.h"
 #include "pgstat.h"
 #include "rewrite/rewriteManip.h"
 #include "storage/bufmgr.h"
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 2a7bc01563..58666fcf26 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -24,6 +24,7 @@
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "partitioning/partbounds.h"
+#include "partitioning/partdesc.h"
 #include "partitioning/partprune.h"
 #include "rewrite/rewriteManip.h"
 #include "utils/lsyscache.h"
diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c
index eaf788e578..faba493200 100644
--- a/src/backend/optimizer/util/inherit.c
+++ b/src/backend/optimizer/util/inherit.c
@@ -23,6 +23,7 @@
 #include "optimizer/inherit.h"
 #include "optimizer/planner.h"
 #include "optimizer/prep.h"
+#include "partitioning/partdesc.h"
 #include "utils/rel.h"
 
 
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 3efa1bdc1a..eec1e09e35 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -27,7 +27,6 @@
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/heap.h"
-#include "catalog/partition.h"
 #include "catalog/pg_am.h"
 #include "catalog/pg_statistic_ext.h"
 #include "foreign/fdwapi.h"
@@ -39,6 +38,7 @@
 #include "optimizer/plancat.h"
 #include "optimizer/prep.h"
 #include "partitioning/partbounds.h"
+#include "partitioning/partdesc.h"
 #include "parser/parse_relation.h"
 #include "parser/parsetree.h"
 #include "rewrite/rewriteManip.h"
diff --git a/src/backend/partitioning/Makefile b/src/backend/partitioning/Makefile
index 278fac3afa..82093c615f 100644
--- a/src/backend/partitioning/Makefile
+++ b/src/backend/partitioning/Makefile
@@ -12,6 +12,6 @@ subdir = src/backend/partitioning
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = partprune.o partbounds.o
+OBJS = partbounds.o partdesc.o partprune.o
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index d478ae7e19..e71eb3793b 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -10,7 +10,8 @@
  *		  src/backend/partitioning/partbounds.c
  *
  *-------------------------------------------------------------------------
-*/
+ */
+
 #include "postgres.h"
 
 #include "access/heapam.h"
@@ -23,8 +24,9 @@
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
 #include "parser/parse_coerce.h"
-#include "partitioning/partprune.h"
 #include "partitioning/partbounds.h"
+#include "partitioning/partdesc.h"
+#include "partitioning/partprune.h"
 #include "utils/builtins.h"
 #include "utils/datum.h"
 #include "utils/fmgroids.h"
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
new file mode 100644
index 0000000000..8a4b63aa26
--- /dev/null
+++ b/src/backend/partitioning/partdesc.c
@@ -0,0 +1,221 @@
+/*-------------------------------------------------------------------------
+ *
+ * partdesc.c
+ *		Support routines for manipulating partition descriptors
+ *
+ * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *		  src/backend/partitioning/partdesc.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "catalog/partition.h"
+#include "catalog/pg_inherits.h"
+#include "partitioning/partbounds.h"
+#include "partitioning/partdesc.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+#include "utils/partcache.h"
+#include "utils/syscache.h"
+
+/*
+ * RelationBuildPartitionDesc
+ *		Form rel's partition descriptor
+ *
+ * Not flushed from the cache by RelationClearRelation() unless changed because
+ * of addition or removal of partition.
+ */
+void
+RelationBuildPartitionDesc(Relation rel)
+{
+	PartitionDesc partdesc;
+	PartitionBoundInfo boundinfo = NULL;
+	List	   *inhoids;
+	PartitionBoundSpec **boundspecs = NULL;
+	Oid		   *oids = NULL;
+	ListCell   *cell;
+	int			i,
+				nparts;
+	PartitionKey key = RelationGetPartitionKey(rel);
+	MemoryContext oldcxt;
+	int		   *mapping;
+
+	/* Get partition oids from pg_inherits */
+	inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock);
+	nparts = list_length(inhoids);
+
+	if (nparts > 0)
+	{
+		oids = palloc(nparts * sizeof(Oid));
+		boundspecs = palloc(nparts * sizeof(PartitionBoundSpec *));
+	}
+
+	/* Collect bound spec nodes for each partition */
+	i = 0;
+	foreach(cell, inhoids)
+	{
+		Oid			inhrelid = lfirst_oid(cell);
+		HeapTuple	tuple;
+		Datum		datum;
+		bool		isnull;
+		PartitionBoundSpec *boundspec;
+
+		tuple = SearchSysCache1(RELOID, inhrelid);
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for relation %u", inhrelid);
+
+		datum = SysCacheGetAttr(RELOID, tuple,
+								Anum_pg_class_relpartbound,
+								&isnull);
+		if (isnull)
+			elog(ERROR, "null relpartbound for relation %u", inhrelid);
+		boundspec = stringToNode(TextDatumGetCString(datum));
+		if (!IsA(boundspec, PartitionBoundSpec))
+			elog(ERROR, "invalid relpartbound for relation %u", inhrelid);
+
+		/*
+		 * Sanity check: If the PartitionBoundSpec says this is the default
+		 * partition, its OID should correspond to whatever's stored in
+		 * pg_partitioned_table.partdefid; if not, the catalog is corrupt.
+		 */
+		if (boundspec->is_default)
+		{
+			Oid			partdefid;
+
+			partdefid = get_default_partition_oid(RelationGetRelid(rel));
+			if (partdefid != inhrelid)
+				elog(ERROR, "expected partdefid %u, but got %u",
+					 inhrelid, partdefid);
+		}
+
+		oids[i] = inhrelid;
+		boundspecs[i] = boundspec;
+		++i;
+		ReleaseSysCache(tuple);
+	}
+
+	/* Now build the actual relcache partition descriptor */
+	rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
+										  "partition descriptor",
+										  ALLOCSET_DEFAULT_SIZES);
+	MemoryContextCopyAndSetIdentifier(rel->rd_pdcxt,
+									  RelationGetRelationName(rel));
+
+	oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
+	partdesc = (PartitionDescData *) palloc0(sizeof(PartitionDescData));
+	partdesc->nparts = nparts;
+	/* oids and boundinfo are allocated below. */
+
+	MemoryContextSwitchTo(oldcxt);
+
+	if (nparts == 0)
+	{
+		rel->rd_partdesc = partdesc;
+		return;
+	}
+
+	/* First create PartitionBoundInfo */
+	boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
+
+	/* Now copy boundinfo and oids into partdesc. */
+	oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
+	partdesc->boundinfo = partition_bounds_copy(boundinfo, key);
+	partdesc->oids = (Oid *) palloc(partdesc->nparts * sizeof(Oid));
+	partdesc->is_leaf = (bool *) palloc(partdesc->nparts * sizeof(bool));
+
+	/*
+	 * Now assign OIDs from the original array into mapped indexes of the
+	 * result array.  The order of OIDs in the former is defined by the
+	 * catalog scan that retrieved them, whereas that in the latter is defined
+	 * by canonicalized representation of the partition bounds.
+	 */
+	for (i = 0; i < partdesc->nparts; i++)
+	{
+		int			index = mapping[i];
+
+		partdesc->oids[index] = oids[i];
+		/* Record if the partition is a leaf partition */
+		partdesc->is_leaf[index] =
+				(get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
+	}
+	MemoryContextSwitchTo(oldcxt);
+
+	rel->rd_partdesc = partdesc;
+}
+
+/*
+ * equalPartitionDescs
+ *		Compare two partition descriptors for logical equality
+ */
+bool
+equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1,
+					PartitionDesc partdesc2)
+{
+	int			i;
+
+	if (partdesc1 != NULL)
+	{
+		if (partdesc2 == NULL)
+			return false;
+		if (partdesc1->nparts != partdesc2->nparts)
+			return false;
+
+		Assert(key != NULL || partdesc1->nparts == 0);
+
+		/*
+		 * Same oids? If the partitioning structure did not change, that is,
+		 * no partitions were added or removed to the relation, the oids array
+		 * should still match element-by-element.
+		 */
+		for (i = 0; i < partdesc1->nparts; i++)
+		{
+			if (partdesc1->oids[i] != partdesc2->oids[i])
+				return false;
+		}
+
+		/*
+		 * Now compare partition bound collections.  The logic to iterate over
+		 * the collections is private to partition.c.
+		 */
+		if (partdesc1->boundinfo != NULL)
+		{
+			if (partdesc2->boundinfo == NULL)
+				return false;
+
+			if (!partition_bounds_equal(key->partnatts, key->parttyplen,
+										key->parttypbyval,
+										partdesc1->boundinfo,
+										partdesc2->boundinfo))
+				return false;
+		}
+		else if (partdesc2->boundinfo != NULL)
+			return false;
+	}
+	else if (partdesc2 != NULL)
+		return false;
+
+	return true;
+}
+
+/*
+ * get_default_oid_from_partdesc
+ *
+ * Given a partition descriptor, return the OID of the default partition, if
+ * one exists; else, return InvalidOid.
+ */
+Oid
+get_default_oid_from_partdesc(PartitionDesc partdesc)
+{
+	if (partdesc && partdesc->boundinfo &&
+		partition_bound_has_default(partdesc->boundinfo))
+		return partdesc->oids[partdesc->boundinfo->default_index];
+
+	return InvalidOid;
+}
diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index 1b50f283c5..2b55f25e75 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -243,130 +243,6 @@ RelationBuildPartitionKey(Relation relation)
 	relation->rd_partkey = key;
 }
 
-/*
- * RelationBuildPartitionDesc
- *		Form rel's partition descriptor
- *
- * Not flushed from the cache by RelationClearRelation() unless changed because
- * of addition or removal of partition.
- */
-void
-RelationBuildPartitionDesc(Relation rel)
-{
-	PartitionDesc partdesc;
-	PartitionBoundInfo boundinfo = NULL;
-	List	   *inhoids;
-	PartitionBoundSpec **boundspecs = NULL;
-	Oid		   *oids = NULL;
-	ListCell   *cell;
-	int			i,
-				nparts;
-	PartitionKey key = RelationGetPartitionKey(rel);
-	MemoryContext oldcxt;
-	int		   *mapping;
-
-	/* Get partition oids from pg_inherits */
-	inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock);
-	nparts = list_length(inhoids);
-
-	if (nparts > 0)
-	{
-		oids = palloc(nparts * sizeof(Oid));
-		boundspecs = palloc(nparts * sizeof(PartitionBoundSpec *));
-	}
-
-	/* Collect bound spec nodes for each partition */
-	i = 0;
-	foreach(cell, inhoids)
-	{
-		Oid			inhrelid = lfirst_oid(cell);
-		HeapTuple	tuple;
-		Datum		datum;
-		bool		isnull;
-		PartitionBoundSpec *boundspec;
-
-		tuple = SearchSysCache1(RELOID, inhrelid);
-		if (!HeapTupleIsValid(tuple))
-			elog(ERROR, "cache lookup failed for relation %u", inhrelid);
-
-		datum = SysCacheGetAttr(RELOID, tuple,
-								Anum_pg_class_relpartbound,
-								&isnull);
-		if (isnull)
-			elog(ERROR, "null relpartbound for relation %u", inhrelid);
-		boundspec = stringToNode(TextDatumGetCString(datum));
-		if (!IsA(boundspec, PartitionBoundSpec))
-			elog(ERROR, "invalid relpartbound for relation %u", inhrelid);
-
-		/*
-		 * Sanity check: If the PartitionBoundSpec says this is the default
-		 * partition, its OID should correspond to whatever's stored in
-		 * pg_partitioned_table.partdefid; if not, the catalog is corrupt.
-		 */
-		if (boundspec->is_default)
-		{
-			Oid			partdefid;
-
-			partdefid = get_default_partition_oid(RelationGetRelid(rel));
-			if (partdefid != inhrelid)
-				elog(ERROR, "expected partdefid %u, but got %u",
-					 inhrelid, partdefid);
-		}
-
-		oids[i] = inhrelid;
-		boundspecs[i] = boundspec;
-		++i;
-		ReleaseSysCache(tuple);
-	}
-
-	/* Now build the actual relcache partition descriptor */
-	rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
-										  "partition descriptor",
-										  ALLOCSET_DEFAULT_SIZES);
-	MemoryContextCopyAndSetIdentifier(rel->rd_pdcxt, RelationGetRelationName(rel));
-
-	oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
-	partdesc = (PartitionDescData *) palloc0(sizeof(PartitionDescData));
-	partdesc->nparts = nparts;
-	/* oids and boundinfo are allocated below. */
-
-	MemoryContextSwitchTo(oldcxt);
-
-	if (nparts == 0)
-	{
-		rel->rd_partdesc = partdesc;
-		return;
-	}
-
-	/* First create PartitionBoundInfo */
-	boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
-
-	/* Now copy boundinfo and oids into partdesc. */
-	oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
-	partdesc->boundinfo = partition_bounds_copy(boundinfo, key);
-	partdesc->oids = (Oid *) palloc(partdesc->nparts * sizeof(Oid));
-	partdesc->is_leaf = (bool *) palloc(partdesc->nparts * sizeof(bool));
-
-	/*
-	 * Now assign OIDs from the original array into mapped indexes of the
-	 * result array.  The order of OIDs in the former is defined by the
-	 * catalog scan that retrieved them, whereas that in the latter is defined
-	 * by canonicalized representation of the partition bounds.
-	 */
-	for (i = 0; i < partdesc->nparts; i++)
-	{
-		int			index = mapping[i];
-
-		partdesc->oids[index] = oids[i];
-		/* Record if the partition is a leaf partition */
-		partdesc->is_leaf[index] =
-				(get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
-	}
-	MemoryContextSwitchTo(oldcxt);
-
-	rel->rd_partdesc = partdesc;
-}
-
 /*
  * RelationGetPartitionQual
  *
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 721c9dab95..54a40ef00b 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -72,6 +72,7 @@
 #include "nodes/nodeFuncs.h"
 #include "optimizer/optimizer.h"
 #include "partitioning/partbounds.h"
+#include "partitioning/partdesc.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rowsecurity.h"
 #include "storage/lmgr.h"
@@ -283,8 +284,6 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
 				  StrategyNumber numSupport);
 static void RelationCacheInitFileRemoveInDir(const char *tblspcpath);
 static void unlink_initfile(const char *initfilename, int elevel);
-static bool equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1,
-					PartitionDesc partdesc2);
 
 
 /*
@@ -995,60 +994,6 @@ equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
 	return true;
 }
 
-/*
- * equalPartitionDescs
- *		Compare two partition descriptors for logical equality
- */
-static bool
-equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1,
-					PartitionDesc partdesc2)
-{
-	int			i;
-
-	if (partdesc1 != NULL)
-	{
-		if (partdesc2 == NULL)
-			return false;
-		if (partdesc1->nparts != partdesc2->nparts)
-			return false;
-
-		Assert(key != NULL || partdesc1->nparts == 0);
-
-		/*
-		 * Same oids? If the partitioning structure did not change, that is,
-		 * no partitions were added or removed to the relation, the oids array
-		 * should still match element-by-element.
-		 */
-		for (i = 0; i < partdesc1->nparts; i++)
-		{
-			if (partdesc1->oids[i] != partdesc2->oids[i])
-				return false;
-		}
-
-		/*
-		 * Now compare partition bound collections.  The logic to iterate over
-		 * the collections is private to partition.c.
-		 */
-		if (partdesc1->boundinfo != NULL)
-		{
-			if (partdesc2->boundinfo == NULL)
-				return false;
-
-			if (!partition_bounds_equal(key->partnatts, key->parttyplen,
-										key->parttypbyval,
-										partdesc1->boundinfo,
-										partdesc2->boundinfo))
-				return false;
-		}
-		else if (partdesc2->boundinfo != NULL)
-			return false;
-	}
-	else if (partdesc2 != NULL)
-		return false;
-
-	return true;
-}
-
 /*
  *		RelationBuildDesc
  *
diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h
index 5685d2fd57..d84e325983 100644
--- a/src/include/catalog/partition.h
+++ b/src/include/catalog/partition.h
@@ -19,20 +19,6 @@
 /* Seed for the extended hash function */
 #define HASH_PARTITION_SEED UINT64CONST(0x7A5B22367996DCFD)
 
-/*
- * Information about partitions of a partitioned table.
- */
-typedef struct PartitionDescData
-{
-	int			nparts;			/* Number of partitions */
-	Oid		   *oids;			/* Array of 'nparts' elements containing
-								 * partition OIDs in order of the their bounds */
-	bool	   *is_leaf;		/* Array of 'nparts' elements storing whether
-								 * the corresponding 'oids' element belongs to
-								 * a leaf partition or not */
-	PartitionBoundInfo boundinfo;	/* collection of partition bounds */
-} PartitionDescData;
-
 extern Oid	get_partition_parent(Oid relid);
 extern List *get_partition_ancestors(Oid relid);
 extern List *map_partition_varattnos(List *expr, int fromrel_varno,
@@ -41,7 +27,6 @@ extern List *map_partition_varattnos(List *expr, int fromrel_varno,
 extern bool has_partition_attrs(Relation rel, Bitmapset *attnums,
 					bool *used_in_expr);
 
-extern Oid	get_default_oid_from_partdesc(PartitionDesc partdesc);
 extern Oid	get_default_partition_oid(Oid parentId);
 extern void update_default_partition_oid(Oid parentId, Oid defaultPartId);
 extern List *get_proposed_default_constraint(List *new_part_constaints);
diff --git a/src/include/partitioning/partdesc.h b/src/include/partitioning/partdesc.h
new file mode 100644
index 0000000000..f72b70dded
--- /dev/null
+++ b/src/include/partitioning/partdesc.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * partdesc.h
+ *
+ * Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ *
+ * src/include/utils/partdesc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PARTDESC_H
+#define PARTDESC_H
+
+#include "partitioning/partdefs.h"
+#include "utils/relcache.h"
+
+/*
+ * Information about partitions of a partitioned table.
+ */
+typedef struct PartitionDescData
+{
+	int			nparts;			/* Number of partitions */
+	Oid		   *oids;			/* Array of 'nparts' elements containing
+								 * partition OIDs in order of the their bounds */
+	bool	   *is_leaf;		/* Array of 'nparts' elements storing whether
+								 * the corresponding 'oids' element belongs to
+								 * a leaf partition or not */
+	PartitionBoundInfo boundinfo;	/* collection of partition bounds */
+} PartitionDescData;
+
+extern void RelationBuildPartitionDesc(Relation rel);
+
+extern Oid	get_default_oid_from_partdesc(PartitionDesc partdesc);
+
+extern bool equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1,
+					PartitionDesc partdesc2);
+
+#endif							/* PARTCACHE_H */
diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h
index 7c2f973f68..823ad2eeb6 100644
--- a/src/include/utils/partcache.h
+++ b/src/include/utils/partcache.h
@@ -47,7 +47,6 @@ typedef struct PartitionKeyData
 }			PartitionKeyData;
 
 extern void RelationBuildPartitionKey(Relation relation);
-extern void RelationBuildPartitionDesc(Relation rel);
 extern List *RelationGetPartitionQual(Relation rel);
 extern Expr *get_partition_qual_relid(Oid relid);
 
-- 
2.17.2 (Apple Git-113)

