From 018513a0053272c3e60c79a6383f603bb78d20f7 Mon Sep 17 00:00:00 2001
From: David Geier <geidav.pg@gmail.com>
Date: Thu, 3 Sep 2026 13:31:32 +0200
Subject: [PATCH v1 6/8] Remove rd_fkeyvalid

---
 src/backend/utils/cache/relcache.c | 15 +++++++--------
 src/include/utils/rel_internal.h   | 22 ++++++++++++++++++----
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 88d8fdf404b..0501755dbce 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1202,8 +1202,7 @@ retry:
 	RelationBuildTupleDesc(relation);
 
 	/* foreign key data is not loaded till asked for */
-	relation->rd_fkeylist = NIL;
-	relation->rd_fkeyvalid = false;
+	relation->rd_fkeylist = RELCACHE_FKEYLIST_NOT_LOADED;
 
 	/* partitioning data is not loaded till asked for */
 	relation->rd_partinfo = NULL;
@@ -2502,7 +2501,8 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
 	if (!isindex)
 	{
 		FreeTriggerDesc(relation->trigdesc);
-		list_free_deep(relation->rd_fkeylist);
+		if (relation->rd_fkeylist != RELCACHE_FKEYLIST_NOT_LOADED)
+			list_free_deep(relation->rd_fkeylist);
 		bms_free(relation->rd_keyattr);
 		bms_free(relation->rd_pkattr);
 		bms_free(relation->rd_idattr);
@@ -4809,7 +4809,7 @@ RelationGetFKeyList(Relation relation)
 	MemoryContext oldcxt;
 
 	/* Quick exit if we already computed the list. */
-	if (relation->rd_fkeyvalid)
+	if (relation->rd_fkeylist != RELCACHE_FKEYLIST_NOT_LOADED)
 		return relation->rd_fkeylist;
 
 	/*
@@ -4862,11 +4862,11 @@ RelationGetFKeyList(Relation relation)
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 	oldlist = relation->rd_fkeylist;
 	relation->rd_fkeylist = copyObject(result);
-	relation->rd_fkeyvalid = true;
 	MemoryContextSwitchTo(oldcxt);
 
 	/* Don't leak the old list, if there is one */
-	list_free_deep(oldlist);
+	if (oldlist != RELCACHE_FKEYLIST_NOT_LOADED)
+		list_free_deep(oldlist);
 
 	return result;
 }
@@ -6563,8 +6563,7 @@ load_relcache_init_file(bool shared)
 			rel->rd_summarizedattr = NULL;
 			rel->rd_pubdesc = NULL;
 			rel->rd_fdwroutine = NULL;
-			rel->rd_fkeyvalid = false;
-			rel->rd_fkeylist = NIL;
+			rel->rd_fkeylist = RELCACHE_FKEYLIST_NOT_LOADED;
 		}
 
 		/*
diff --git a/src/include/utils/rel_internal.h b/src/include/utils/rel_internal.h
index 9849c7b4406..e059b8bf18b 100644
--- a/src/include/utils/rel_internal.h
+++ b/src/include/utils/rel_internal.h
@@ -29,6 +29,15 @@ typedef struct LockRelId
 	Oid			dbId;			/* a database identifier */
 } LockRelId;
 
+/*
+ * Sentinel value for RelationData.rd_fkeylist indicating that the foreign
+ * key list has not yet been computed by RelationGetFKeyList().  This is
+ * distinct from NIL, which is a valid "computed, relation has no foreign
+ * keys" result; using a sentinel here avoids needing a separate validity
+ * flag.
+ */
+#define RELCACHE_FKEYLIST_NOT_LOADED ((List *) -1)
+
 /*
  * RelationPartitionInfo
  *		Partition-related data cached for a relation, allocated lazily on
@@ -171,8 +180,15 @@ typedef struct RelationData
 			/* use "struct" here to avoid needing to include rowsecurity.h: */
 			struct RowSecurityDesc *rd_rsdesc;	/* row security policies, or NULL */
 
-			/* data managed by RelationGetFKeyList: */
-			List	   *rd_fkeylist;	/* list of ForeignKeyCacheInfo (see below) */
+			/*
+			 * data managed by RelationGetFKeyList: list of
+			 * ForeignKeyCacheInfo (see below), or the sentinel
+			 * RELCACHE_FKEYLIST_NOT_LOADED if not yet computed.  NIL is a
+			 * valid "computed, no FKs" result, so a sentinel pointer value
+			 * is used instead of a separate validity flag to distinguish
+			 * "not yet computed" from that case.
+			 */
+			List	   *rd_fkeylist;
 
 			/*
 			 * data managed by RelationGetPartitionKey, RelationGetPartitionDesc,
@@ -199,8 +215,6 @@ typedef struct RelationData
 			 */
 			/* use "struct" here to avoid needing to include fdwapi.h: */
 			struct FdwRoutine *rd_fdwroutine;	/* cached function pointers, or NULL */
-
-			bool		rd_fkeyvalid;	/* true if rd_fkeylist has been computed */
 		};
 
 		/* fields used only for an index relation */
-- 
2.51.0

