From 2161c5870a498fc87b5cb052c81365d5e06f8949 Mon Sep 17 00:00:00 2001 From: David Geier 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 7bc6e124f6d..ac1636106fc 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; } @@ -6551,8 +6551,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.55.0