From c7f40df3f5d79c811bf807486eae5b363688efb1 Mon Sep 17 00:00:00 2001
From: David Geier <geidav.pg@gmail.com>
Date: Thu, 3 Sep 2026 13:00:51 +0200
Subject: [PATCH v1 5/8] Move out partition members

---
 src/backend/partitioning/partdesc.c |  37 +++++----
 src/backend/utils/cache/partcache.c |  49 ++++++-----
 src/backend/utils/cache/relcache.c  | 121 ++++++++++++++--------------
 src/include/utils/rel_internal.h    |  70 ++++++++++------
 4 files changed, 156 insertions(+), 121 deletions(-)

diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index f29e5a323a1..1de70992c01 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -80,10 +80,10 @@ RelationGetPartitionDesc(Relation rel, bool omit_detached)
 	 * If there is no active snapshot, detached partitions aren't omitted
 	 * either, so we can use the cached descriptor too in that case.
 	 */
-	if (likely(rel->rd_partdesc &&
-			   (!rel->rd_partdesc->detached_exist || !omit_detached ||
+	if (likely(rel->rd_partinfo && rel->rd_partinfo->partdesc &&
+			   (!rel->rd_partinfo->partdesc->detached_exist || !omit_detached ||
 				!ActiveSnapshotSet())))
-		return rel->rd_partdesc;
+		return rel->rd_partinfo->partdesc;
 
 	/*
 	 * If we're asked to omit detached partitions, we may be able to use a
@@ -94,16 +94,17 @@ RelationGetPartitionDesc(Relation rel, bool omit_detached)
 	 * scratch.
 	 */
 	if (omit_detached &&
-		rel->rd_partdesc_nodetached &&
+		rel->rd_partinfo &&
+		rel->rd_partinfo->partdesc_nodetached &&
 		ActiveSnapshotSet())
 	{
 		Snapshot	activesnap;
 
-		Assert(TransactionIdIsValid(rel->rd_partdesc_nodetached_xmin));
+		Assert(TransactionIdIsValid(rel->rd_partinfo->partdesc_nodetached_xmin));
 		activesnap = GetActiveSnapshot();
 
-		if (!XidInMVCCSnapshot(rel->rd_partdesc_nodetached_xmin, activesnap))
-			return rel->rd_partdesc_nodetached;
+		if (!XidInMVCCSnapshot(rel->rd_partinfo->partdesc_nodetached_xmin, activesnap))
+			return rel->rd_partinfo->partdesc_nodetached;
 	}
 
 	return RelationBuildPartitionDesc(rel, omit_detached);
@@ -385,12 +386,16 @@ retry:
 	 * the regular partdesc in rd_pdcxt, and the partdesc-excluding-
 	 * detached-partitions in rd_pddcxt.)
 	 */
+	if (rel->rd_partinfo == NULL)
+		rel->rd_partinfo = MemoryContextAllocZero(CacheMemoryContext,
+												  sizeof(RelationPartitionInfo));
+
 	if (is_omit)
 	{
-		if (rel->rd_pddcxt != NULL)
-			MemoryContextSetParent(rel->rd_pddcxt, new_pdcxt);
-		rel->rd_pddcxt = new_pdcxt;
-		rel->rd_partdesc_nodetached = partdesc;
+		if (rel->rd_partinfo->pddcxt != NULL)
+			MemoryContextSetParent(rel->rd_partinfo->pddcxt, new_pdcxt);
+		rel->rd_partinfo->pddcxt = new_pdcxt;
+		rel->rd_partinfo->partdesc_nodetached = partdesc;
 
 		/*
 		 * For partdescs built excluding detached partitions, which we save
@@ -401,14 +406,14 @@ retry:
 		 * with.
 		 */
 		Assert(TransactionIdIsValid(detached_xmin));
-		rel->rd_partdesc_nodetached_xmin = detached_xmin;
+		rel->rd_partinfo->partdesc_nodetached_xmin = detached_xmin;
 	}
 	else
 	{
-		if (rel->rd_pdcxt != NULL)
-			MemoryContextSetParent(rel->rd_pdcxt, new_pdcxt);
-		rel->rd_pdcxt = new_pdcxt;
-		rel->rd_partdesc = partdesc;
+		if (rel->rd_partinfo->pdcxt != NULL)
+			MemoryContextSetParent(rel->rd_partinfo->pdcxt, new_pdcxt);
+		rel->rd_partinfo->pdcxt = new_pdcxt;
+		rel->rd_partinfo->partdesc = partdesc;
 	}
 
 	return partdesc;
diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index c86efd65dd7..959ac904bf7 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -53,10 +53,10 @@ RelationGetPartitionKey(Relation rel)
 	if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
 		return NULL;
 
-	if (unlikely(rel->rd_partkey == NULL))
+	if (unlikely(rel->rd_partinfo == NULL || rel->rd_partinfo->partkey == NULL))
 		RelationBuildPartitionKey(rel);
 
-	return rel->rd_partkey;
+	return rel->rd_partinfo->partkey;
 }
 
 /*
@@ -256,16 +256,19 @@ RelationBuildPartitionKey(Relation relation)
 	ReleaseSysCache(tuple);
 
 	/* Assert that we're not leaking any old data during assignments below */
-	Assert(relation->rd_partkeycxt == NULL);
-	Assert(relation->rd_partkey == NULL);
+	Assert(relation->rd_partinfo == NULL || relation->rd_partinfo->partkeycxt == NULL);
+	Assert(relation->rd_partinfo == NULL || relation->rd_partinfo->partkey == NULL);
 
 	/*
 	 * Success --- reparent our context and make the relcache point to the
 	 * newly constructed key
 	 */
 	MemoryContextSetParent(partkeycxt, CacheMemoryContext);
-	relation->rd_partkeycxt = partkeycxt;
-	relation->rd_partkey = key;
+	if (relation->rd_partinfo == NULL)
+		relation->rd_partinfo = MemoryContextAllocZero(CacheMemoryContext,
+													   sizeof(RelationPartitionInfo));
+	relation->rd_partinfo->partkeycxt = partkeycxt;
+	relation->rd_partinfo->partkey = key;
 }
 
 /*
@@ -350,13 +353,13 @@ generate_partition_qual(Relation rel)
 	check_stack_depth();
 
 	/*
-	 * rd_partcheck/rd_partcheckvalid/rd_partcheckcxt only exist for
-	 * table-like relations; they are overlaid in a union with index-only
-	 * fields (see RelationData in rel_internal.h). generate_partition_qual()
-	 * is also invoked for partitioned indexes (an index partition never has
-	 * a partition bound of its own, so this always ends up computing an
-	 * empty qual list for them), so guard against misinterpreting unrelated
-	 * index data, and don't cache results for indexes.
+	 * rd_partinfo only exists for table-like relations; it is overlaid in a
+	 * union with index-only fields (see RelationData in rel_internal.h).
+	 * generate_partition_qual() is also invoked for partitioned indexes (an
+	 * index partition never has a partition bound of its own, so this always
+	 * ends up computing an empty qual list for them), so guard against
+	 * misinterpreting unrelated index data, and don't cache results for
+	 * indexes.
 	 */
 	if (rel->rd_rel->relkind == RELKIND_INDEX ||
 		rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
@@ -365,8 +368,8 @@ generate_partition_qual(Relation rel)
 		is_index = false;
 
 	/* If we already cached the result, just return a copy */
-	if (!is_index && rel->rd_partcheckvalid)
-		return copyObject(rel->rd_partcheck);
+	if (!is_index && rel->rd_partinfo && rel->rd_partinfo->partcheckvalid)
+		return copyObject(rel->rd_partinfo->partcheck);
 
 	/*
 	 * Grab at least an AccessShareLock on the parent table.  Must do this
@@ -421,8 +424,12 @@ generate_partition_qual(Relation rel)
 	}
 
 	/* Assert that we're not leaking any old data during assignments below */
-	Assert(rel->rd_partcheckcxt == NULL);
-	Assert(rel->rd_partcheck == NIL);
+	Assert(rel->rd_partinfo == NULL || rel->rd_partinfo->partcheckcxt == NULL);
+	Assert(rel->rd_partinfo == NULL || rel->rd_partinfo->partcheck == NIL);
+
+	if (rel->rd_partinfo == NULL)
+		rel->rd_partinfo = MemoryContextAllocZero(CacheMemoryContext,
+												  sizeof(RelationPartitionInfo));
 
 	/*
 	 * Save a copy in the relcache.  The order of these operations is fairly
@@ -457,12 +464,12 @@ generate_partition_qual(Relation rel)
 		/* finally, link the allocations and memctx into the right places */
 		MemoryContextSetParent(partctx, CacheMemoryContext);
 
-		rel->rd_partcheckcxt = partctx;
-		rel->rd_partcheck = partcheck;
+		rel->rd_partinfo->partcheckcxt = partctx;
+		rel->rd_partinfo->partcheck = partcheck;
 	}
 	else
-		rel->rd_partcheck = NIL;
-	rel->rd_partcheckvalid = true;
+		rel->rd_partinfo->partcheck = NIL;
+	rel->rd_partinfo->partcheckvalid = true;
 
 	/* Keep the parent locked until commit */
 	relation_close(parent, NoLock);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index b33c14f5dab..88d8fdf404b 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1206,16 +1206,7 @@ retry:
 	relation->rd_fkeyvalid = false;
 
 	/* partitioning data is not loaded till asked for */
-	relation->rd_partkey = NULL;
-	relation->rd_partkeycxt = NULL;
-	relation->rd_partdesc = NULL;
-	relation->rd_partdesc_nodetached = NULL;
-	relation->rd_partdesc_nodetached_xmin = InvalidTransactionId;
-	relation->rd_pdcxt = NULL;
-	relation->rd_pddcxt = NULL;
-	relation->rd_partcheck = NIL;
-	relation->rd_partcheckvalid = false;
-	relation->rd_partcheckcxt = NULL;
+	relation->rd_partinfo = NULL;
 
 	/*
 	 * initialize access method information
@@ -2246,15 +2237,16 @@ RelationCloseCleanup(Relation relation)
 	 */
 	if (RelationHasReferenceCountZero(relation) &&
 		relation->rd_rel->relkind != RELKIND_INDEX &&
-		relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+		relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX &&
+		relation->rd_partinfo != NULL)
 	{
-		if (relation->rd_pdcxt != NULL &&
-			relation->rd_pdcxt->firstchild != NULL)
-			MemoryContextDeleteChildren(relation->rd_pdcxt);
+		if (relation->rd_partinfo->pdcxt != NULL &&
+			relation->rd_partinfo->pdcxt->firstchild != NULL)
+			MemoryContextDeleteChildren(relation->rd_partinfo->pdcxt);
 
-		if (relation->rd_pddcxt != NULL &&
-			relation->rd_pddcxt->firstchild != NULL)
-			MemoryContextDeleteChildren(relation->rd_pddcxt);
+		if (relation->rd_partinfo->pddcxt != NULL &&
+			relation->rd_partinfo->pddcxt->firstchild != NULL)
+			MemoryContextDeleteChildren(relation->rd_partinfo->pddcxt);
 	}
 
 #ifdef RELCACHE_FORCE_RELEASE
@@ -2456,7 +2448,7 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
 	Assert(RelationHasReferenceCountZero(relation));
 
 	/*
-	 * rd_index/rd_indexcxt/etc and rd_rules/trigdesc/rd_partkey/etc are
+	 * rd_index/rd_indexcxt/etc and rd_rules/trigdesc/rd_partinfo/etc are
 	 * overlaid in a union (see RelationData in rel_internal.h), since a
 	 * relation is never both an index and a table-like relation at once.
 	 * Capture which set of fields is "live" for this relation before
@@ -2524,14 +2516,18 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
 			MemoryContextDelete(relation->rd_rulescxt);
 		if (relation->rd_rsdesc)
 			MemoryContextDelete(relation->rd_rsdesc->rscxt);
-		if (relation->rd_partkeycxt)
-			MemoryContextDelete(relation->rd_partkeycxt);
-		if (relation->rd_pdcxt)
-			MemoryContextDelete(relation->rd_pdcxt);
-		if (relation->rd_pddcxt)
-			MemoryContextDelete(relation->rd_pddcxt);
-		if (relation->rd_partcheckcxt)
-			MemoryContextDelete(relation->rd_partcheckcxt);
+		if (relation->rd_partinfo)
+		{
+			if (relation->rd_partinfo->partkeycxt)
+				MemoryContextDelete(relation->rd_partinfo->partkeycxt);
+			if (relation->rd_partinfo->pdcxt)
+				MemoryContextDelete(relation->rd_partinfo->pdcxt);
+			if (relation->rd_partinfo->pddcxt)
+				MemoryContextDelete(relation->rd_partinfo->pddcxt);
+			if (relation->rd_partinfo->partcheckcxt)
+				MemoryContextDelete(relation->rd_partinfo->partcheckcxt);
+			pfree(relation->rd_partinfo);
+		}
 	}
 	else
 	{
@@ -2733,7 +2729,7 @@ RelationRebuildRelation(Relation relation)
 		keep_tupdesc = equalTupleDescs(relation->rd_att, newrel->rd_att);
 
 		/*
-		 * rd_rules/rd_rsdesc/rd_partkey only exist for table-like
+		 * rd_rules/rd_rsdesc/rd_partinfo only exist for table-like
 		 * relations; they are overlaid in a union with index-only fields
 		 * (see RelationData in rel_internal.h).  We normally only reach
 		 * this generic rebuild path for indexes whose access info hasn't
@@ -2752,7 +2748,8 @@ RelationRebuildRelation(Relation relation)
 			keep_rules = equalRuleLocks(relation->rd_rules, newrel->rd_rules);
 			keep_policies = equalRSDesc(relation->rd_rsdesc, newrel->rd_rsdesc);
 			/* partkey is immutable once set up, so we can always keep it */
-			keep_partkey = (relation->rd_partkey != NULL);
+			keep_partkey = (relation->rd_partinfo != NULL &&
+							relation->rd_partinfo->partkey != NULL);
 		}
 
 		/*
@@ -2811,27 +2808,39 @@ RelationRebuildRelation(Relation relation)
 		/* pgstat_info / enabled must be preserved */
 		SWAPFIELD(struct PgStat_RelationStatus *, pgstat_info);
 		SWAPFIELD(bool, pgstat_enabled);
-		/* preserve old partition key if we have one */
+		/*
+		 * preserve old partition key if we have one; rd_partinfo as a whole
+		 * has already been swapped above along with the rest of the struct,
+		 * so at this point "relation" holds the freshly-built (usually NULL)
+		 * rd_partinfo and "newrel" holds the old one.
+		 */
 		if (keep_partkey)
 		{
-			SWAPFIELD(PartitionKey, rd_partkey);
-			SWAPFIELD(MemoryContext, rd_partkeycxt);
+			Assert(newrel->rd_partinfo != NULL);
+			if (relation->rd_partinfo == NULL)
+				relation->rd_partinfo = MemoryContextAllocZero(CacheMemoryContext,
+																sizeof(RelationPartitionInfo));
+			relation->rd_partinfo->partkey = newrel->rd_partinfo->partkey;
+			relation->rd_partinfo->partkeycxt = newrel->rd_partinfo->partkeycxt;
+			newrel->rd_partinfo->partkey = NULL;
+			newrel->rd_partinfo->partkeycxt = NULL;
 		}
-		if (newrel->rd_pdcxt != NULL || newrel->rd_pddcxt != NULL)
+		if (newrel->rd_partinfo != NULL &&
+			(newrel->rd_partinfo->pdcxt != NULL || newrel->rd_partinfo->pddcxt != NULL))
 		{
 			/*
 			 * We are rebuilding a partitioned relation with a non-zero
 			 * reference count, so we must keep the old partition descriptor
 			 * around, in case there's a PartitionDirectory with a pointer to
-			 * it.  This means we can't free the old rd_pdcxt yet.  (This is
+			 * it.  This means we can't free the old pdcxt yet.  (This is
 			 * necessary because RelationGetPartitionDesc hands out direct
 			 * pointers to the relcache's data structure, unlike our usual
 			 * practice which is to hand out copies.  We'd have the same
-			 * problem with rd_partkey, except that we always preserve that
+			 * problem with partkey, except that we always preserve that
 			 * once created.)
 			 *
 			 * To ensure that it's not leaked completely, re-attach it to the
-			 * new reldesc, or make it a child of the new reldesc's rd_pdcxt
+			 * new reldesc, or make it a child of the new reldesc's pdcxt
 			 * in the unlikely event that there is one already.  (Compare hack
 			 * in RelationBuildPartitionDesc.)  RelationClose will clean up
 			 * any such contexts once the reference count reaches zero.
@@ -2844,23 +2853,26 @@ RelationRebuildRelation(Relation relation)
 			 * "old" partition descriptor is actually the one hanging off of
 			 * newrel.
 			 */
-			relation->rd_partdesc = NULL;	/* ensure rd_partdesc is invalid */
-			relation->rd_partdesc_nodetached = NULL;
-			relation->rd_partdesc_nodetached_xmin = InvalidTransactionId;
-			if (relation->rd_pdcxt != NULL) /* probably never happens */
-				MemoryContextSetParent(newrel->rd_pdcxt, relation->rd_pdcxt);
+			if (relation->rd_partinfo == NULL)
+				relation->rd_partinfo = MemoryContextAllocZero(CacheMemoryContext,
+																sizeof(RelationPartitionInfo));
+			relation->rd_partinfo->partdesc = NULL; /* ensure partdesc is invalid */
+			relation->rd_partinfo->partdesc_nodetached = NULL;
+			relation->rd_partinfo->partdesc_nodetached_xmin = InvalidTransactionId;
+			if (relation->rd_partinfo->pdcxt != NULL) /* probably never happens */
+				MemoryContextSetParent(newrel->rd_partinfo->pdcxt, relation->rd_partinfo->pdcxt);
 			else
-				relation->rd_pdcxt = newrel->rd_pdcxt;
-			if (relation->rd_pddcxt != NULL)
-				MemoryContextSetParent(newrel->rd_pddcxt, relation->rd_pddcxt);
+				relation->rd_partinfo->pdcxt = newrel->rd_partinfo->pdcxt;
+			if (relation->rd_partinfo->pddcxt != NULL)
+				MemoryContextSetParent(newrel->rd_partinfo->pddcxt, relation->rd_partinfo->pddcxt);
 			else
-				relation->rd_pddcxt = newrel->rd_pddcxt;
+				relation->rd_partinfo->pddcxt = newrel->rd_partinfo->pddcxt;
 			/* drop newrel's pointers so we don't destroy it below */
-			newrel->rd_partdesc = NULL;
-			newrel->rd_partdesc_nodetached = NULL;
-			newrel->rd_partdesc_nodetached_xmin = InvalidTransactionId;
-			newrel->rd_pdcxt = NULL;
-			newrel->rd_pddcxt = NULL;
+			newrel->rd_partinfo->partdesc = NULL;
+			newrel->rd_partinfo->partdesc_nodetached = NULL;
+			newrel->rd_partinfo->partdesc_nodetached_xmin = InvalidTransactionId;
+			newrel->rd_partinfo->pdcxt = NULL;
+			newrel->rd_partinfo->pddcxt = NULL;
 		}
 
 #undef SWAPFIELD
@@ -6543,16 +6555,7 @@ load_relcache_init_file(bool shared)
 			rel->rd_rulescxt = NULL;
 			rel->trigdesc = NULL;
 			rel->rd_rsdesc = NULL;
-			rel->rd_partkey = NULL;
-			rel->rd_partkeycxt = NULL;
-			rel->rd_partdesc = NULL;
-			rel->rd_partdesc_nodetached = NULL;
-			rel->rd_partdesc_nodetached_xmin = InvalidTransactionId;
-			rel->rd_pdcxt = NULL;
-			rel->rd_pddcxt = NULL;
-			rel->rd_partcheck = NIL;
-			rel->rd_partcheckvalid = false;
-			rel->rd_partcheckcxt = NULL;
+			rel->rd_partinfo = NULL;
 			rel->rd_keyattr = NULL;
 			rel->rd_pkattr = NULL;
 			rel->rd_idattr = NULL;
diff --git a/src/include/utils/rel_internal.h b/src/include/utils/rel_internal.h
index c96b3df1f85..9849c7b4406 100644
--- a/src/include/utils/rel_internal.h
+++ b/src/include/utils/rel_internal.h
@@ -29,6 +29,45 @@ typedef struct LockRelId
 	Oid			dbId;			/* a database identifier */
 } LockRelId;
 
+/*
+ * RelationPartitionInfo
+ *		Partition-related data cached for a relation, allocated lazily on
+ *		first use.  Only ever populated for partitioned tables (partkey and
+ *		the partdesc fields) and/or partitions (partcheck fields); most
+ *		relations need none of this, hence it's a separate lazily-allocated
+ *		struct rather than a set of fields embedded directly in
+ *		RelationData.
+ */
+typedef struct RelationPartitionInfo
+{
+	/* data managed by RelationGetPartitionKey: */
+	PartitionKey partkey;		/* partition key, or NULL */
+	MemoryContext partkeycxt;	/* private context for partkey, if any */
+
+	/* data managed by RelationGetPartitionDesc: */
+	PartitionDesc partdesc;		/* partition descriptor, or NULL */
+	MemoryContext pdcxt;		/* private context for partdesc, if any */
+
+	/* Same as above, for partdescs that omit detached partitions */
+	PartitionDesc partdesc_nodetached; /* partdesc w/o detached parts */
+	MemoryContext pddcxt;		/* for partdesc_nodetached, if any */
+
+	/* data managed by RelationGetPartitionQual: */
+	List	   *partcheck;		/* partition CHECK quals */
+	MemoryContext partcheckcxt; /* private cxt for partcheck, if any */
+
+	/*
+	 * pg_inherits.xmin of the partition that was excluded in
+	 * partdesc_nodetached.  This informs a future user of that partdesc: if
+	 * this value is not in progress for the active snapshot, then the
+	 * partdesc can be used, otherwise they have to build a new one.  (This
+	 * matches what find_inheritance_children_extended would do).
+	 */
+	TransactionId partdesc_nodetached_xmin;
+
+	bool		partcheckvalid; /* true if partcheck has been computed */
+} RelationPartitionInfo;
+
 /*
  * Here are the contents of a relation cache entry.
  */
@@ -135,21 +174,12 @@ typedef struct RelationData
 			/* data managed by RelationGetFKeyList: */
 			List	   *rd_fkeylist;	/* list of ForeignKeyCacheInfo (see below) */
 
-			/* data managed by RelationGetPartitionKey: */
-			PartitionKey rd_partkey;	/* partition key, or NULL */
-			MemoryContext rd_partkeycxt;	/* private context for rd_partkey, if any */
-
-			/* data managed by RelationGetPartitionDesc: */
-			PartitionDesc rd_partdesc;	/* partition descriptor, or NULL */
-			MemoryContext rd_pdcxt;		/* private context for rd_partdesc, if any */
-
-			/* Same as above, for partdescs that omit detached partitions */
-			PartitionDesc rd_partdesc_nodetached;	/* partdesc w/o detached parts */
-			MemoryContext rd_pddcxt;	/* for rd_partdesc_nodetached, if any */
-
-			/* data managed by RelationGetPartitionQual: */
-			List	   *rd_partcheck;	/* partition CHECK quals */
-			MemoryContext rd_partcheckcxt;	/* private cxt for rd_partcheck, if any */
+			/*
+			 * data managed by RelationGetPartitionKey, RelationGetPartitionDesc,
+			 * and RelationGetPartitionQual; NULL if none of these has been
+			 * called for this relation.  See RelationPartitionInfo above.
+			 */
+			RelationPartitionInfo *rd_partinfo;
 
 			/* data managed by RelationGetIndexAttrBitmap: */
 			Bitmapset  *rd_keyattr;		/* cols that can be ref'd by foreign keys */
@@ -170,17 +200,7 @@ typedef struct RelationData
 			/* use "struct" here to avoid needing to include fdwapi.h: */
 			struct FdwRoutine *rd_fdwroutine;	/* cached function pointers, or NULL */
 
-			/*
-			 * pg_inherits.xmin of the partition that was excluded in
-			 * rd_partdesc_nodetached.  This informs a future user of that partdesc:
-			 * if this value is not in progress for the active snapshot, then the
-			 * partdesc can be used, otherwise they have to build a new one.  (This
-			 * matches what find_inheritance_children_extended would do).
-			 */
-			TransactionId rd_partdesc_nodetached_xmin;
-
 			bool		rd_fkeyvalid;	/* true if rd_fkeylist has been computed */
-			bool		rd_partcheckvalid;	/* true if rd_partcheck has been computed */
 		};
 
 		/* fields used only for an index relation */
-- 
2.51.0

