Subject: Our ABI diff infrastructure ignores enum SysCacheIdentifier

From: Tom Lane <[email-masked]>
Date: Thu, 12 Feb 2026 11:17:37 -0500

I discovered $SUBJECT while working on commits dbb09fd8e et al.
The point of those commits was to back-patch addition of a syscache
that previously existed only in v18+, so naturally I was concerned
about not breaking ABI by changing any existing syscache's ID.
I tested whether abidiff would bleat about it if I intentionally
changed an ID, and found that *it didn't*.

I don't think this is (quite) a bug in libabigail.  They are pretty
clear that what they regard as ABI is:

       ... the descriptions of the types reachable by the interfaces
       (functions and variables) that are visible outside of their
       translation unit.

We do not use enum SysCacheIdentifier as the declared type of any
global variable or any globally-visible function argument or result.
Therefore it's not ABI per their definition.

This is frankly pretty scary.  Now that we know the rules, we can
fix it for enum SysCacheIdentifier, but we have other things that are
similarly vulnerable.  The thing I am most concerned about right now
is enum GUCs.  The guc.c APIs mandate that those be declared as type
int, so I think (haven't actually checked) that most if not all of
the associated enum values will not be perceived as ABI-relevant by
abidiff.  What can we do about that?

As for SysCacheIdentifier, the root of the problem is that
SearchSysCache and friends are declared to take "int cacheId"
not "enum SysCacheIdentifier cacheId".  Likely we should change
that in HEAD, but that'd be an actual not theoretical ABI break
(the enum's not necessarily int-width).  In the back branches
I'm thinking about adding a dummy function just for this purpose,
more or less as in the under-commented patch attached.

Thoughts?

			regards, tom lane

commit 12d2a8cd596d63dd908149b9140f527b723585cc
Author: Tom Lane <[email-masked]>
Date:   Sat Jan 10 18:28:39 2026 -0500

    Make SysCacheIdentifier be ABI.

diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index f7f4f56a4d2..1af3ab3afdf 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -671,6 +671,14 @@ GetSysCacheHashValue(int cacheId,
 	return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
 }
 
+/*
+ * Dummy function with an "enum SysCacheIdentifier" parameter.
+ */
+void
+SysCacheDummy(enum SysCacheIdentifier cacheId)
+{
+}
+
 /*
  * List-search interface
  */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index b541911c8fc..052c4550d22 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -72,6 +72,8 @@ extern Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
 extern uint32 GetSysCacheHashValue(int cacheId,
 								   Datum key1, Datum key2, Datum key3, Datum key4);
 
+extern void SysCacheDummy(enum SysCacheIdentifier cacheId);
+
 /* list-search interface.  Users of this must import catcache.h too */
 struct catclist;
 extern struct catclist *SearchSysCacheList(int cacheId, int nkeys,

---

From: Michael Paquier <[email-masked]>
Date: Fri, 13 Feb 2026 13:07:00 +0900

> changed an ID, and found that *it didn't*.

Well.  That's annoying.  This one is important to be careful about.

> (the enum's not necessarily int-width).

Enforcing a type for this sounds like a good idea in the long term on
HEAD, yes, even putting the ABI argument aside for a moment.  I'd
suggest the addition of an extra typedef in the code generated for 
syscache_ids.h to save from a couple of enum markers in these
declarations, once refactored to use the new enum type.

> In the back branches

Adding a comment explaining why this function needs to exist would be
good.
--
Michael

---

From: Andreas Karlsson <[email-masked]>
Date: Fri, 13 Feb 2026 06:46:55 +0100

> more or less as in the under-commented patch attached.

Attached a patch which changes that in HEAD and I think for HEAD the 
best solution is the just fix all cases where we use ints like this to 
actually use the enum.

As for back branches I agree with Michael, just add a comment explaining 
why this dummy function is necessary.

Andreas
From 889147d70a8edb1a2f92cf73b849eaf61e18d8dc Mon Sep 17 00:00:00 2001
From: Andreas Karlsson <[email-masked]>
Date: Fri, 13 Feb 2026 06:41:09 +0100
Subject: [PATCH v1] Use SysCacheIdentifier enum instead of int

This makes the ABI checker happy plus makes the itnent of the code clearer.
---
 src/backend/catalog/genbki.pl      |  4 ++--
 src/backend/utils/cache/syscache.c | 34 +++++++++++++++---------------
 src/include/utils/syscache.h       | 30 +++++++++++++-------------
 3 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index b2c1b1c5733..0ddded783b5 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -795,7 +795,7 @@ print $fk_info "};\n\n#endif\t\t\t\t\t\t\t/* SYSTEM_FK_INFO_H */\n";
 # Now generate syscache info
 
 print_boilerplate($syscache_ids_fh, "syscache_ids.h", "SysCache identifiers");
-print $syscache_ids_fh "enum SysCacheIdentifier
+print $syscache_ids_fh "typedef enum SysCacheIdentifier
 {
 ";
 
@@ -825,7 +825,7 @@ foreach my $syscache (sort keys %syscaches)
 	print $syscache_info_fh "\t},\n";
 }
 
-print $syscache_ids_fh "};\n";
+print $syscache_ids_fh "} SysCacheIdentifier;\n";
 print $syscache_ids_fh "#define SysCacheSize ($last_syscache + 1)\n";
 
 print $syscache_info_fh "};\n";
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index ae3d18e0e74..007a9a15d71 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -109,7 +109,7 @@ static int	oid_compare(const void *a, const void *b);
 void
 InitCatalogCache(void)
 {
-	int			cacheId;
+	SysCacheIdentifier cacheId;
 
 	Assert(!CacheInitialized);
 
@@ -179,7 +179,7 @@ InitCatalogCache(void)
 void
 InitCatalogCachePhase2(void)
 {
-	int			cacheId;
+	SysCacheIdentifier cacheId;
 
 	Assert(CacheInitialized);
 
@@ -205,7 +205,7 @@ InitCatalogCachePhase2(void)
  *	CAUTION: The tuple that is returned must NOT be freed by the caller!
  */
 HeapTuple
-SearchSysCache(int cacheId,
+SearchSysCache(SysCacheIdentifier cacheId,
 			   Datum key1,
 			   Datum key2,
 			   Datum key3,
@@ -217,7 +217,7 @@ SearchSysCache(int cacheId,
 }
 
 HeapTuple
-SearchSysCache1(int cacheId,
+SearchSysCache1(SysCacheIdentifier cacheId,
 				Datum key1)
 {
 	Assert(cacheId >= 0 && cacheId < SysCacheSize && SysCache[cacheId]);
@@ -227,7 +227,7 @@ SearchSysCache1(int cacheId,
 }
 
 HeapTuple
-SearchSysCache2(int cacheId,
+SearchSysCache2(SysCacheIdentifier cacheId,
 				Datum key1, Datum key2)
 {
 	Assert(cacheId >= 0 && cacheId < SysCacheSize && SysCache[cacheId]);
@@ -237,7 +237,7 @@ SearchSysCache2(int cacheId,
 }
 
 HeapTuple
-SearchSysCache3(int cacheId,
+SearchSysCache3(SysCacheIdentifier cacheId,
 				Datum key1, Datum key2, Datum key3)
 {
 	Assert(cacheId >= 0 && cacheId < SysCacheSize && SysCache[cacheId]);
@@ -247,7 +247,7 @@ SearchSysCache3(int cacheId,
 }
 
 HeapTuple
-SearchSysCache4(int cacheId,
+SearchSysCache4(SysCacheIdentifier cacheId,
 				Datum key1, Datum key2, Datum key3, Datum key4)
 {
 	Assert(cacheId >= 0 && cacheId < SysCacheSize && SysCache[cacheId]);
@@ -279,7 +279,7 @@ ReleaseSysCache(HeapTuple tuple)
  * doesn't prevent the "tuple concurrently updated" error.
  */
 HeapTuple
-SearchSysCacheLocked1(int cacheId,
+SearchSysCacheLocked1(SysCacheIdentifier cacheId,
 					  Datum key1)
 {
 	CatCache   *cache = SysCache[cacheId];
@@ -371,7 +371,7 @@ SearchSysCacheLocked1(int cacheId,
  * heap_freetuple() the result when done with it.
  */
 HeapTuple
-SearchSysCacheCopy(int cacheId,
+SearchSysCacheCopy(SysCacheIdentifier cacheId,
 				   Datum key1,
 				   Datum key2,
 				   Datum key3,
@@ -396,7 +396,7 @@ SearchSysCacheCopy(int cacheId,
  * heap_freetuple().
  */
 HeapTuple
-SearchSysCacheLockedCopy1(int cacheId,
+SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId,
 						  Datum key1)
 {
 	HeapTuple	tuple,
@@ -417,7 +417,7 @@ SearchSysCacheLockedCopy1(int cacheId,
  * No lock is retained on the syscache entry.
  */
 bool
-SearchSysCacheExists(int cacheId,
+SearchSysCacheExists(SysCacheIdentifier cacheId,
 					 Datum key1,
 					 Datum key2,
 					 Datum key3,
@@ -440,7 +440,7 @@ SearchSysCacheExists(int cacheId,
  * No lock is retained on the syscache entry.
  */
 Oid
-GetSysCacheOid(int cacheId,
+GetSysCacheOid(SysCacheIdentifier cacheId,
 			   AttrNumber oidcol,
 			   Datum key1,
 			   Datum key2,
@@ -592,7 +592,7 @@ SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
  * a different cache for the same catalog the tuple was fetched from.
  */
 Datum
-SysCacheGetAttr(int cacheId, HeapTuple tup,
+SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup,
 				AttrNumber attributeNumber,
 				bool *isNull)
 {
@@ -622,7 +622,7 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
  * be NULL.
  */
 Datum
-SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
+SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup,
 					   AttrNumber attributeNumber)
 {
 	bool		isnull;
@@ -652,7 +652,7 @@ SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
  * catcache code that need to be able to compute the hash values.
  */
 uint32
-GetSysCacheHashValue(int cacheId,
+GetSysCacheHashValue(SysCacheIdentifier cacheId,
 					 Datum key1,
 					 Datum key2,
 					 Datum key3,
@@ -668,7 +668,7 @@ GetSysCacheHashValue(int cacheId,
  * List-search interface
  */
 struct catclist *
-SearchSysCacheList(int cacheId, int nkeys,
+SearchSysCacheList(SysCacheIdentifier cacheId, int nkeys,
 				   Datum key1, Datum key2, Datum key3)
 {
 	if (cacheId < 0 || cacheId >= SysCacheSize || !SysCache[cacheId])
@@ -687,7 +687,7 @@ SearchSysCacheList(int cacheId, int nkeys,
  *	This routine is only quasi-public: it should only be used by inval.c.
  */
 void
-SysCacheInvalidate(int cacheId, uint32 hashValue)
+SysCacheInvalidate(SysCacheIdentifier cacheId, uint32 hashValue)
 {
 	if (cacheId < 0 || cacheId >= SysCacheSize)
 		elog(ERROR, "invalid cache ID: %d", cacheId);
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 13f49af9ed4..81e5933708e 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -25,35 +25,35 @@
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
 
-extern HeapTuple SearchSysCache(int cacheId,
+extern HeapTuple SearchSysCache(SysCacheIdentifier cacheId,
 								Datum key1, Datum key2, Datum key3, Datum key4);
 
 /*
  * The use of argument specific numbers is encouraged. They're faster, and
  * insulates the caller from changes in the maximum number of keys.
  */
-extern HeapTuple SearchSysCache1(int cacheId,
+extern HeapTuple SearchSysCache1(SysCacheIdentifier cacheId,
 								 Datum key1);
-extern HeapTuple SearchSysCache2(int cacheId,
+extern HeapTuple SearchSysCache2(SysCacheIdentifier cacheId,
 								 Datum key1, Datum key2);
-extern HeapTuple SearchSysCache3(int cacheId,
+extern HeapTuple SearchSysCache3(SysCacheIdentifier cacheId,
 								 Datum key1, Datum key2, Datum key3);
-extern HeapTuple SearchSysCache4(int cacheId,
+extern HeapTuple SearchSysCache4(SysCacheIdentifier cacheId,
 								 Datum key1, Datum key2, Datum key3, Datum key4);
 
 extern void ReleaseSysCache(HeapTuple tuple);
 
-extern HeapTuple SearchSysCacheLocked1(int cacheId,
+extern HeapTuple SearchSysCacheLocked1(SysCacheIdentifier cacheId,
 									   Datum key1);
 
 /* convenience routines */
-extern HeapTuple SearchSysCacheCopy(int cacheId,
+extern HeapTuple SearchSysCacheCopy(SysCacheIdentifier cacheId,
 									Datum key1, Datum key2, Datum key3, Datum key4);
-extern HeapTuple SearchSysCacheLockedCopy1(int cacheId,
+extern HeapTuple SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId,
 										   Datum key1);
-extern bool SearchSysCacheExists(int cacheId,
+extern bool SearchSysCacheExists(SysCacheIdentifier cacheId,
 								 Datum key1, Datum key2, Datum key3, Datum key4);
-extern Oid	GetSysCacheOid(int cacheId, AttrNumber oidcol,
+extern Oid	GetSysCacheOid(SysCacheIdentifier cacheId, AttrNumber oidcol,
 						   Datum key1, Datum key2, Datum key3, Datum key4);
 
 extern HeapTuple SearchSysCacheAttName(Oid relid, const char *attname);
@@ -63,21 +63,21 @@ extern bool SearchSysCacheExistsAttName(Oid relid, const char *attname);
 extern HeapTuple SearchSysCacheAttNum(Oid relid, int16 attnum);
 extern HeapTuple SearchSysCacheCopyAttNum(Oid relid, int16 attnum);
 
-extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup,
+extern Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup,
 							 AttrNumber attributeNumber, bool *isNull);
 
-extern Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
+extern Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup,
 									AttrNumber attributeNumber);
 
-extern uint32 GetSysCacheHashValue(int cacheId,
+extern uint32 GetSysCacheHashValue(SysCacheIdentifier cacheId,
 								   Datum key1, Datum key2, Datum key3, Datum key4);
 
 /* list-search interface.  Users of this must import catcache.h too */
 struct catclist;
-extern struct catclist *SearchSysCacheList(int cacheId, int nkeys,
+extern struct catclist *SearchSysCacheList(SysCacheIdentifier cacheId, int nkeys,
 										   Datum key1, Datum key2, Datum key3);
 
-extern void SysCacheInvalidate(int cacheId, uint32 hashValue);
+extern void SysCacheInvalidate(SysCacheIdentifier cacheId, uint32 hashValue);
 
 extern bool RelationInvalidatesSnapshotsOnly(Oid relid);
 extern bool RelationHasSysCache(Oid relid);
-- 
2.47.3

---

From: Michael Paquier <[email-masked]>
Date: Fri, 13 Feb 2026 17:24:30 +0900

On Fri, Feb 13, 2026 at 06:46:55AM +0100, Andreas Karlsson wrote:
> Attached a patch which changes that in HEAD and I think for HEAD the best
> solution is the just fix all cases where we use ints like this to actually
> use the enum.

I was expecting something a bit more complicated.  Nice at quick
glance, Andreas.
--
Michael

---

From: Andreas Karlsson <[email-masked]>
Date: Fri, 13 Feb 2026 10:36:41 +0100

> I was expecting something a bit more complicated.  Nice at quick

It is a bit more code churn if I also include inval.c, but I still do 
not think it would be too bad.

Andreas
From f80783c028ae3e4d1c8a72409e93b7e3c3fa6542 Mon Sep 17 00:00:00 2001
From: Andreas Karlsson <[email-masked]>
Date: Fri, 13 Feb 2026 06:41:09 +0100
Subject: [PATCH v2] Use SysCacheIdentifier enum instead of int

This makes the ABI checker happy plus makes the itnent of the code clearer.
---
 contrib/postgres_fdw/connection.c           |  4 +--
 contrib/postgres_fdw/shippable.c            |  2 +-
 src/backend/catalog/aclchk.c                | 10 +++---
 src/backend/catalog/dependency.c            |  2 +-
 src/backend/catalog/genbki.pl               |  4 +--
 src/backend/catalog/namespace.c             |  4 +--
 src/backend/catalog/objectaddress.c         | 12 ++++----
 src/backend/commands/alter.c                |  8 ++---
 src/backend/commands/extension.c            |  4 +--
 src/backend/optimizer/util/predtest.c       |  4 +--
 src/backend/parser/parse_oper.c             |  4 +--
 src/backend/replication/logical/syncutils.c |  2 +-
 src/backend/replication/logical/worker.c    |  2 +-
 src/backend/replication/pgoutput/pgoutput.c |  8 ++---
 src/backend/utils/adt/acl.c                 |  4 +--
 src/backend/utils/adt/ri_triggers.c         |  4 +--
 src/backend/utils/cache/attoptcache.c       |  2 +-
 src/backend/utils/cache/evtcache.c          |  4 +--
 src/backend/utils/cache/inval.c             |  4 +--
 src/backend/utils/cache/plancache.c         |  8 ++---
 src/backend/utils/cache/spccache.c          |  2 +-
 src/backend/utils/cache/syscache.c          | 34 ++++++++++-----------
 src/backend/utils/cache/ts_cache.c          |  2 +-
 src/backend/utils/cache/typcache.c          | 12 ++++----
 src/backend/utils/misc/superuser.c          |  4 +--
 src/include/catalog/objectaddress.h         |  5 +--
 src/include/replication/worker_internal.h   |  2 +-
 src/include/utils/inval.h                   |  7 +++--
 src/include/utils/syscache.h                | 30 +++++++++---------
 29 files changed, 98 insertions(+), 96 deletions(-)

diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 487a1a23170..16e44071577 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -150,7 +150,7 @@ static void pgfdw_subxact_callback(SubXactEvent event,
 								   SubTransactionId mySubid,
 								   SubTransactionId parentSubid,
 								   void *arg);
-static void pgfdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue);
+static void pgfdw_inval_callback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry);
 static void pgfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel);
 static bool pgfdw_cancel_query(PGconn *conn);
@@ -1309,7 +1309,7 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid,
  * individual option values, but it seems too much effort for the gain.
  */
 static void
-pgfdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue)
+pgfdw_inval_callback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS scan;
 	ConnCacheEntry *entry;
diff --git a/contrib/postgres_fdw/shippable.c b/contrib/postgres_fdw/shippable.c
index d32d3d0e461..e07eadd3630 100644
--- a/contrib/postgres_fdw/shippable.c
+++ b/contrib/postgres_fdw/shippable.c
@@ -62,7 +62,7 @@ typedef struct
  * made for them, however.
  */
 static void
-InvalidateShippableCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateShippableCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	ShippableCacheEntry *entry;
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index a431fc0926f..1dd6df71d14 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -2115,7 +2115,7 @@ static void
 ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs,
 				 void (*object_check) (InternalGrant *istmt, HeapTuple tuple))
 {
-	int			cacheid;
+	SysCacheIdentifier cacheid;
 	Relation	relation;
 	ListCell   *cell;
 
@@ -3058,7 +3058,7 @@ object_aclmask_ext(Oid classid, Oid objectid, Oid roleid,
 				   AclMode mask, AclMaskHow how,
 				   bool *is_missing)
 {
-	int			cacheid;
+	SysCacheIdentifier cacheid;
 	AclMode		result;
 	HeapTuple	tuple;
 	Datum		aclDatum;
@@ -4089,7 +4089,7 @@ pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode,
 bool
 object_ownercheck(Oid classid, Oid objectid, Oid roleid)
 {
-	int			cacheid;
+	SysCacheIdentifier cacheid;
 	Oid			ownerId;
 
 	/* Superusers bypass all permission checking. */
@@ -4486,7 +4486,7 @@ recordExtObjInitPriv(Oid objoid, Oid classoid)
 	/* This will error on unsupported classoid. */
 	else if (get_object_attnum_acl(classoid) != InvalidAttrNumber)
 	{
-		int			cacheid;
+		SysCacheIdentifier cacheid;
 		Datum		aclDatum;
 		bool		isNull;
 		HeapTuple	tuple;
@@ -4870,7 +4870,7 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid)
 	ScanKeyData key[3];
 	SysScanDesc scan;
 	HeapTuple	oldtuple;
-	int			cacheid;
+	SysCacheIdentifier cacheid;
 	HeapTuple	objtuple;
 	Oid			ownerId;
 	Datum		oldAclDatum;
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index f89267f0342..7564965fa18 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -1238,7 +1238,7 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
 static void
 DropObjectById(const ObjectAddress *object)
 {
-	int			cacheId;
+	SysCacheIdentifier cacheId;
 	Relation	rel;
 	HeapTuple	tup;

 

 print $syscache_info_fh "};\n";
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index c3b79a2ba48..cb335afdf89 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -229,7 +229,7 @@ static void AccessTempTableNamespace(bool force);
 static void InitTempTableNamespace(void);
 static void RemoveTempRelations(Oid tempNamespaceId);
 static void RemoveTempRelationsCallback(int code, Datum arg);
-static void InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue);
+static void InvalidationCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
 						   bool include_out_arguments, int pronargs,
 						   int **argnumbers, int *fgc_flags);
@@ -4863,7 +4863,7 @@ InitializeSearchPath(void)
  *		Syscache inval callback function
  */
 static void
-InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue)
+InvalidationCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	/*
 	 * Force search path to be recomputed on next use, also invalidating the
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 02af64b82c6..0af390d9810 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -99,8 +99,8 @@ typedef struct
 								 * error messages */
 	Oid			class_oid;		/* oid of catalog */
 	Oid			oid_index_oid;	/* oid of index on system oid column */
-	int			oid_catcache_id;	/* id of catcache on system oid column	*/
-	int			name_catcache_id;	/* id of catcache on (name,namespace), or
+	SysCacheIdentifier oid_catcache_id;	/* id of catcache on system oid column	*/
+	SysCacheIdentifier name_catcache_id;	/* id of catcache on (name,namespace), or
 									 * (name) if the object does not live in a
 									 * namespace */
 	AttrNumber	attnum_oid;		/* attribute number of oid column */
@@ -2571,7 +2571,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 Oid
 get_object_namespace(const ObjectAddress *address)
 {
-	int			cache;
+	SysCacheIdentifier cache;
 	HeapTuple	tuple;
 	Oid			oid;
 	const ObjectPropertyType *property;
@@ -2640,7 +2640,7 @@ get_object_oid_index(Oid class_id)
 	return prop->oid_index_oid;
 }
 
-int
+SysCacheIdentifier
 get_object_catcache_oid(Oid class_id)
 {
 	const ObjectPropertyType *prop = get_object_property_data(class_id);
@@ -2648,7 +2648,7 @@ get_object_catcache_oid(Oid class_id)
 	return prop->oid_catcache_id;
 }
 
-int
+SysCacheIdentifier
 get_object_catcache_name(Oid class_id)
 {
 	const ObjectPropertyType *prop = get_object_property_data(class_id);
@@ -2806,7 +2806,7 @@ get_catalog_object_by_oid_extended(Relation catalog,
 {
 	HeapTuple	tuple;
 	Oid			classId = RelationGetRelid(catalog);
-	int			oidCacheId = get_object_catcache_oid(classId);
+	SysCacheIdentifier oidCacheId = get_object_catcache_oid(classId);
 
 	if (oidCacheId > 0)
 	{
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 08957104c70..c6f58d47be6 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -159,8 +159,8 @@ static void
 AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
 {
 	Oid			classId = RelationGetRelid(rel);
-	int			oidCacheId = get_object_catcache_oid(classId);
-	int			nameCacheId = get_object_catcache_name(classId);
+	SysCacheIdentifier oidCacheId = get_object_catcache_oid(classId);
+	SysCacheIdentifier nameCacheId = get_object_catcache_name(classId);
 	AttrNumber	Anum_name = get_object_attnum_name(classId);
 	AttrNumber	Anum_namespace = get_object_attnum_namespace(classId);
 	AttrNumber	Anum_owner = get_object_attnum_owner(classId);
@@ -686,8 +686,8 @@ static Oid
 AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
 {
 	Oid			classId = RelationGetRelid(rel);
-	int			oidCacheId = get_object_catcache_oid(classId);
-	int			nameCacheId = get_object_catcache_name(classId);
+	SysCacheIdentifier oidCacheId = get_object_catcache_oid(classId);
+	SysCacheIdentifier nameCacheId = get_object_catcache_name(classId);
 	AttrNumber	Anum_name = get_object_attnum_name(classId);
 	AttrNumber	Anum_namespace = get_object_attnum_namespace(classId);
 	AttrNumber	Anum_owner = get_object_attnum_owner(classId);
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 81f24615d51..93ce3ebabf8 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -162,7 +162,7 @@ typedef struct ExtensionSiblingCache
 static ExtensionSiblingCache *ext_sibling_list = NULL;
 
 /* Local functions */
-static void ext_sibling_callback(Datum arg, int cacheid, uint32 hashvalue);
+static void ext_sibling_callback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 static List *find_update_path(List *evi_list,
 							  ExtensionVersionInfo *evi_start,
 							  ExtensionVersionInfo *evi_target,
@@ -379,7 +379,7 @@ get_function_sibling_type(Oid funcoid, const char *typname)
  * looking for, could change without an extension update or drop/recreate.
  */
 static void
-ext_sibling_callback(Datum arg, int cacheid, uint32 hashvalue)
+ext_sibling_callback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	ExtensionSiblingCache *cache_entry;
 
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 26858d1d2b0..61a0ed195aa 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -109,7 +109,7 @@ static bool operator_same_subexprs_proof(Oid pred_op, Oid clause_op,
 static bool operator_same_subexprs_lookup(Oid pred_op, Oid clause_op,
 										  bool refute_it);
 static Oid	get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it);
-static void InvalidateOprProofCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
+static void InvalidateOprProofCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);

 /*
@@ -2343,7 +2343,7 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
  * Callback for pg_amop inval events
  */
 static void
-InvalidateOprProofCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateOprProofCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	OprProofCacheEntry *hentry;
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 768e4cff9c5..76cbdacf933 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -79,7 +79,7 @@ static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key,
 								int location);
 static Oid	find_oper_cache_entry(OprCacheKey *key);
 static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid);
-static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
+static void InvalidateOprCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);

 /*
@@ -1076,7 +1076,7 @@ make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
  * Callback for pg_operator and pg_cast inval events
  */
 static void
-InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateOprCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	OprCacheEntry *hentry;
diff --git a/src/backend/replication/logical/syncutils.c b/src/backend/replication/logical/syncutils.c
index 535ffb6f09e..8f0897beec1 100644
--- a/src/backend/replication/logical/syncutils.c
+++ b/src/backend/replication/logical/syncutils.c
@@ -98,7 +98,7 @@ FinishSyncWorker(void)
  * Callback from syscache invalidation.
  */
 void
-InvalidateSyncingRelStates(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateSyncingRelStates(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	relation_states_validity = SYNC_RELATIONS_STATE_NEEDS_REBUILD;
 }
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 32725c48623..8b93f48470c 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -5164,7 +5164,7 @@ maybe_reread_subscription(void)
  * Callback from subscription syscache invalidation.
  */
 static void
-subscription_change_cb(Datum arg, int cacheid, uint32 hashvalue)
+subscription_change_cb(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	MySubscriptionValid = false;
 }
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index e016f64e0b3..2aea20dca22 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -86,7 +86,7 @@ static void pgoutput_stream_prepare_txn(LogicalDecodingContext *ctx,
 static bool publications_valid;
 
 static List *LoadPublications(List *pubnames);
-static void publication_invalidation_cb(Datum arg, int cacheid,
+static void publication_invalidation_cb(Datum arg, SysCacheIdentifier cacheid,
 										uint32 hashvalue);
 static void send_repl_origin(LogicalDecodingContext *ctx,
 							 ReplOriginId origin_id, XLogRecPtr origin_lsn,
@@ -227,7 +227,7 @@ static void send_relation_and_attrs(Relation relation, TransactionId xid,
 									LogicalDecodingContext *ctx,
 									RelationSyncEntry *relentry);
 static void rel_sync_cache_relation_cb(Datum arg, Oid relid);
-static void rel_sync_cache_publication_cb(Datum arg, int cacheid,
+static void rel_sync_cache_publication_cb(Datum arg, SysCacheIdentifier cacheid,
 										  uint32 hashvalue);
 static void set_schema_sent_in_streamed_txn(RelationSyncEntry *entry,
 											TransactionId xid);
@@ -1828,7 +1828,7 @@ LoadPublications(List *pubnames)
  * Called for invalidations on pg_publication.
  */
 static void
-publication_invalidation_cb(Datum arg, int cacheid, uint32 hashvalue)
+publication_invalidation_cb(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	publications_valid = false;
 }
@@ -2431,7 +2431,7 @@ rel_sync_cache_relation_cb(Datum arg, Oid relid)
  * Called for invalidations on pg_namespace.
  */
 static void
-rel_sync_cache_publication_cb(Datum arg, int cacheid, uint32 hashvalue)
+rel_sync_cache_publication_cb(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	RelationSyncEntry *entry;
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 3a6905f9546..332152cfd2a 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -130,7 +130,7 @@ static AclMode convert_largeobject_priv_string(text *priv_type_text);
 static AclMode convert_role_priv_string(text *priv_type_text);
 static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
 
-static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue);
+static void RoleMembershipCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);

 /*
@@ -5067,7 +5067,7 @@ initialize_acl(void)
  *		Syscache inval callback function
  */
 static void
-RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
+RoleMembershipCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	if (cacheid == DATABASEOID &&
 		hashvalue != cached_db_hash &&
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index bbadecef5f9..57a511cc9e2 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -213,7 +213,7 @@ static bool ri_CompareWithCast(Oid eq_opr, Oid typeid, Oid collid,
 							   Datum lhs, Datum rhs);
 
 static void ri_InitHashTables(void);
-static void InvalidateConstraintCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
+static void InvalidateConstraintCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 static SPIPlanPtr ri_FetchPreparedPlan(RI_QueryKey *key);
 static void ri_HashPreparedPlan(RI_QueryKey *key, SPIPlanPtr plan);
 static RI_CompareHashEntry *ri_HashCompareOp(Oid eq_opr, Oid typeid);
@@ -2397,7 +2397,7 @@ get_ri_constraint_root(Oid constrOid)
  * data from changing under it --- but we may get cache flushes anyway.)
  */
 static void
-InvalidateConstraintCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateConstraintCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	dlist_mutable_iter iter;
 
diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c
index 72edc8f665b..4e0fc7f9112 100644
--- a/src/backend/utils/cache/attoptcache.c
+++ b/src/backend/utils/cache/attoptcache.c
@@ -50,7 +50,7 @@ typedef struct
  * for that attribute.
  */
 static void
-InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateAttoptCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	AttoptCacheEntry *attopt;
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index 2b4453e54a7..ac5c760efa7 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -49,7 +49,7 @@ static EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD;
 
 static void BuildEventTriggerCache(void);
 static void InvalidateEventCacheCallback(Datum arg,
-										 int cacheid, uint32 hashvalue);
+										 SysCacheIdentifier cacheid, uint32 hashvalue);
 static Bitmapset *DecodeTextArrayToBitmapset(Datum array);
 
 /*
@@ -254,7 +254,7 @@ DecodeTextArrayToBitmapset(Datum array)
  * memory leaks.
  */
 static void
-InvalidateEventCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateEventCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	/*
 	 * If the cache isn't valid, then there might be a rebuild in progress, so
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index bf465a295e3..d59216b28f1 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -1813,7 +1813,7 @@ CacheInvalidateRelmap(Oid databaseId)
  * flush all cached state anyway.
  */
 void
-CacheRegisterSyscacheCallback(int cacheid,
+CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid,
 							  SyscacheCallbackFunction func,
 							  Datum arg)
 {
@@ -1895,7 +1895,7 @@ CacheRegisterRelSyncCallback(RelSyncCallbackFunction func,
  * this module from knowing which catcache IDs correspond to which catalogs.
  */
 void
-CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
+CallSyscacheCallbacks(SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	int			i;
 
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 37d5d73b7fb..d93c3b8afe8 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -106,8 +106,8 @@ static void ScanQueryForLocks(Query *parsetree, bool acquire);
 static bool ScanQueryWalker(Node *node, bool *acquire);
 static TupleDesc PlanCacheComputeResultDesc(List *stmt_list);
 static void PlanCacheRelCallback(Datum arg, Oid relid);
-static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue);
-static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue);
+static void PlanCacheObjectCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
+static void PlanCacheSysCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 
 /* ResourceOwner callbacks to track plancache references */
 static void ResOwnerReleaseCachedPlan(Datum res);
@@ -2201,7 +2201,7 @@ PlanCacheRelCallback(Datum arg, Oid relid)
  * or all plans mentioning any member of this cache if hashvalue == 0.
  */
 static void
-PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
+PlanCacheObjectCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	dlist_iter	iter;
 
@@ -2310,7 +2310,7 @@ PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
  * Just invalidate everything...
  */
 static void
-PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
+PlanCacheSysCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	ResetPlanCache();
 }
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
index 8f1a5e69595..0d87fb2f4fc 100644
--- a/src/backend/utils/cache/spccache.c
+++ b/src/backend/utils/cache/spccache.c
@@ -52,7 +52,7 @@ typedef struct
  * tablespaces, nor do we expect them to be frequently modified.
  */
 static void
-InvalidateTableSpaceCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateTableSpaceCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	TableSpaceCacheEntry *spc;
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index ae3d18e0e74..007a9a15d71 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -109,7 +109,7 @@ static int	oid_compare(const void *a, const void *b);
 void
 InitCatalogCache(void)
 {
-	int			cacheId;
+	SysCacheIdentifier cacheId;

 

 HeapTuple
 
 HeapTuple
 
 HeapTuple
 
 HeapTuple
-SearchSysCache4(int cacheId,
+SearchSysCache4(SysCacheIdentifier cacheId,
 				Datum key1, Datum key2, Datum key3, Datum key4)
 {
 	Assert(cacheId >= 0 && cacheId < SysCacheSize && SysCache[cacheId]);
@@ -279,7 +279,7 @@ ReleaseSysCache(HeapTuple tuple)
  * doesn't prevent the "tuple concurrently updated" error.
  */
 HeapTuple
-SearchSysCacheLocked1(int cacheId,
+SearchSysCacheLocked1(SysCacheIdentifier cacheId,
 					  Datum key1)
 {
 	CatCache   *cache = SysCache[cacheId];
@@ -371,7 +371,7 @@ SearchSysCacheLocked1(int cacheId,
  * heap_freetuple() the result when done with it.
  */
 HeapTuple
-SearchSysCacheCopy(int cacheId,
+SearchSysCacheCopy(SysCacheIdentifier cacheId,
 				   Datum key1,
 				   Datum key2,
 				   Datum key3,
@@ -396,7 +396,7 @@ SearchSysCacheCopy(int cacheId,
  * heap_freetuple().
  */
 HeapTuple
-SearchSysCacheLockedCopy1(int cacheId,
+SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId,
 						  Datum key1)
 {
 	HeapTuple	tuple,
@@ -417,7 +417,7 @@ SearchSysCacheLockedCopy1(int cacheId,
  * No lock is retained on the syscache entry.
  */
 bool
-SearchSysCacheExists(int cacheId,
+SearchSysCacheExists(SysCacheIdentifier cacheId,
 					 Datum key1,
 					 Datum key2,
 					 Datum key3,
@@ -440,7 +440,7 @@ SearchSysCacheExists(int cacheId,
  * No lock is retained on the syscache entry.
  */
 Oid
-GetSysCacheOid(int cacheId,
+GetSysCacheOid(SysCacheIdentifier cacheId,
 			   AttrNumber oidcol,
 			   Datum key1,
 			   Datum key2,
@@ -592,7 +592,7 @@ SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
  * a different cache for the same catalog the tuple was fetched from.
  */
 Datum
-SysCacheGetAttr(int cacheId, HeapTuple tup,
+SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup,
 				AttrNumber attributeNumber,
 				bool *isNull)
 {
@@ -622,7 +622,7 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
  * be NULL.
  */
 Datum
-SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
+SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup,
 					   AttrNumber attributeNumber)
 {
 	bool		isnull;
@@ -652,7 +652,7 @@ SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
  * catcache code that need to be able to compute the hash values.
  */
 uint32
-GetSysCacheHashValue(int cacheId,
+GetSysCacheHashValue(SysCacheIdentifier cacheId,
 					 Datum key1,
 					 Datum key2,
 					 Datum key3,
@@ -668,7 +668,7 @@ GetSysCacheHashValue(int cacheId,
  * List-search interface
  */
 struct catclist *
-SearchSysCacheList(int cacheId, int nkeys,
+SearchSysCacheList(SysCacheIdentifier cacheId, int nkeys,
 				   Datum key1, Datum key2, Datum key3)
 {
 	if (cacheId < 0 || cacheId >= SysCacheSize || !SysCache[cacheId])
@@ -687,7 +687,7 @@ SearchSysCacheList(int cacheId, int nkeys,
  *	This routine is only quasi-public: it should only be used by inval.c.
  */
 void
-SysCacheInvalidate(int cacheId, uint32 hashValue)
+SysCacheInvalidate(SysCacheIdentifier cacheId, uint32 hashValue)
 {
 	if (cacheId < 0 || cacheId >= SysCacheSize)
 		elog(ERROR, "invalid cache ID: %d", cacheId);
diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c
index 71e49b2b919..744c8e71d71 100644
--- a/src/backend/utils/cache/ts_cache.c
+++ b/src/backend/utils/cache/ts_cache.c
@@ -91,7 +91,7 @@ static Oid	TSCurrentConfigCache = InvalidOid;
  * table address as the "arg".
  */
 static void
-InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
+InvalidateTSCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HTAB	   *hash = (HTAB *) DatumGetPointer(arg);
 	HASH_SEQ_STATUS status;
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index dc4b1a56414..c721e1c2874 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -337,9 +337,9 @@ static bool multirange_element_has_hashing(TypeCacheEntry *typentry);
 static bool multirange_element_has_extended_hashing(TypeCacheEntry *typentry);
 static void cache_multirange_element_properties(TypeCacheEntry *typentry);
 static void TypeCacheRelCallback(Datum arg, Oid relid);
-static void TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue);
-static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue);
-static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue);
+static void TypeCacheTypCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
+static void TypeCacheOpcCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
+static void TypeCacheConstrCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 static void load_enum_cache_data(TypeCacheEntry *tcache);
 static EnumItem *find_enumitem(TypeCacheEnumData *enumdata, Oid arg);
 static int	enum_oid_cmp(const void *left, const void *right);
@@ -2512,7 +2512,7 @@ TypeCacheRelCallback(Datum arg, Oid relid)
  * it as needing to be reloaded.
  */
 static void
-TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
+TypeCacheTypCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	TypeCacheEntry *typentry;
@@ -2569,7 +2569,7 @@ TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
  * of members are not going to get cached here.
  */
 static void
-TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
+TypeCacheOpcCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	HASH_SEQ_STATUS status;
 	TypeCacheEntry *typentry;
@@ -2607,7 +2607,7 @@ TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
  * approach to domain constraints.
  */
 static void
-TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
+TypeCacheConstrCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	TypeCacheEntry *typentry;
 
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 7821624687a..10759a9a37b 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -36,7 +36,7 @@ static Oid	last_roleid = InvalidOid;	/* InvalidOid == cache not valid */
 static bool last_roleid_is_super = false;
 static bool roleid_callback_registered = false;
 
-static void RoleidCallback(Datum arg, int cacheid, uint32 hashvalue);
+static void RoleidCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);

 /*
@@ -100,7 +100,7 @@ superuser_arg(Oid roleid)
  *		Syscache inval callback function
  */
 static void
-RoleidCallback(Datum arg, int cacheid, uint32 hashvalue)
+RoleidCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	/* Invalidate our local cache in case role's superuserness changed */
 	last_roleid = InvalidOid;
diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
index e2fe9db1161..b549be2d523 100644
--- a/src/include/catalog/objectaddress.h
+++ b/src/include/catalog/objectaddress.h
@@ -17,6 +17,7 @@
 #include "nodes/parsenodes.h"
 #include "storage/lockdefs.h"
 #include "utils/relcache.h"
+#include "utils/syscache.h"
 
 /*
  * An ObjectAddress represents a database object of any type.
@@ -57,8 +58,8 @@ extern Oid	get_object_namespace(const ObjectAddress *address);
 extern bool is_objectclass_supported(Oid class_id);
 extern const char *get_object_class_descr(Oid class_id);
 extern Oid	get_object_oid_index(Oid class_id);
-extern int	get_object_catcache_oid(Oid class_id);
-extern int	get_object_catcache_name(Oid class_id);
+extern SysCacheIdentifier get_object_catcache_oid(Oid class_id);
+extern SysCacheIdentifier get_object_catcache_name(Oid class_id);
 extern AttrNumber get_object_attnum_oid(Oid class_id);
 extern AttrNumber get_object_attnum_name(Oid class_id);
 extern AttrNumber get_object_attnum_namespace(Oid class_id);
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
index c1285fdd1bc..644c953c940 100644
--- a/src/include/replication/worker_internal.h
+++ b/src/include/replication/worker_internal.h
@@ -289,7 +289,7 @@ extern void ProcessSyncingTablesForApply(XLogRecPtr current_lsn);
 extern void ProcessSequencesForSync(void);
 
 pg_noreturn extern void FinishSyncWorker(void);
-extern void InvalidateSyncingRelStates(Datum arg, int cacheid, uint32 hashvalue);
+extern void InvalidateSyncingRelStates(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 extern void launch_sync_worker(LogicalRepWorkerType wtype, int nsyncworkers,
 							   Oid relid, TimestampTz *last_start_time);
 extern void ProcessSyncingRelations(XLogRecPtr current_lsn);
diff --git a/src/include/utils/inval.h b/src/include/utils/inval.h
index 0e937fec9e9..e9d8cdb75ff 100644
--- a/src/include/utils/inval.h
+++ b/src/include/utils/inval.h
@@ -17,6 +17,7 @@
 #include "access/htup.h"
 #include "storage/relfilelocator.h"
 #include "utils/relcache.h"
+#include "utils/syscache.h"
 
 extern PGDLLIMPORT int debug_discard_caches;
 
@@ -38,7 +39,7 @@ extern PGDLLIMPORT int debug_discard_caches;
 #endif							/* not DISCARD_CACHES_ENABLED */

-typedef void (*SyscacheCallbackFunction) (Datum arg, int cacheid, uint32 hashvalue);
+typedef void (*SyscacheCallbackFunction) (Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 typedef void (*RelcacheCallbackFunction) (Datum arg, Oid relid);
 typedef void (*RelSyncCallbackFunction) (Datum arg, Oid relid);
 
@@ -81,7 +82,7 @@ extern void CacheInvalidateSmgr(RelFileLocatorBackend rlocator);
 
 extern void CacheInvalidateRelmap(Oid databaseId);
 
-extern void CacheRegisterSyscacheCallback(int cacheid,
+extern void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid,
 										  SyscacheCallbackFunction func,
 										  Datum arg);
 
@@ -91,7 +92,7 @@ extern void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func,
 extern void CacheRegisterRelSyncCallback(RelSyncCallbackFunction func,
 										 Datum arg);
 
-extern void CallSyscacheCallbacks(int cacheid, uint32 hashvalue);
+extern void CallSyscacheCallbacks(SysCacheIdentifier cacheid, uint32 hashvalue);
 
 extern void CallRelSyncCallbacks(Oid relid);

 
 /*

---

From: Zsolt Parragi <[email-masked]>
Date: Fri, 13 Feb 2026 09:58:42 +0000

While it isn't strictly ABI, this made me wonder about the static
inline functions in public headers. Wouldn't extensions using those,
compiled with older minor versions have similar issues as issues
caused by actual ABI incompatibility?

I did a quick test with scripts about this in the REL 17 branch, and
there are several changes that could cause issues in theory.

See ffd9b8134658 for example introduced in 17.3. While technically
this is ABI compatible (nbanks is the same size as bank_mask in the
public struct, no binary change), part of the modified calculation is
in an inline function in the header, but part of it is in the C part.
Extensions compiled against 17.2 or earlier and using this
functionality will misbehave in 17.3 or later, as only part of the
code gets updated.

Similar issues could be caused by macro changes, for example COPYCHAR
was changed from memcpy to ts_copychar_cstr. That doesn't seem to be
an actual issue, but it could have been with a different change, and I
think similarly could go unnoticed.

There are also cases where something was simply removed from public
headers (firstbyte64(v) define from hashfn_unstable.h for example).
This again wouldn't cause any issues as long as the functions called
by it are still there, but it seems to break source compatibility
between minor versions.

---

From: Michael Paquier <[email-masked]>
Date: Mon, 16 Feb 2026 16:47:24 +0900

On Fri, Feb 13, 2026 at 10:36:41AM +0100, Andreas Karlsson wrote:
> It is a bit more code churn if I also include inval.c, but I still do not
> think it would be too bad.

The blast looks acceptable with inval.c in sight.  What's less
acceptable is the set of failures generated, like:
#3  0x00000000019e7ac4 in ExceptionalCondition
(conditionName=0x1e31ff0 "cacheId >= 0 && cacheId < SysCacheSize &&
SysCache[cacheId]", fileName=0x1e31e80 "syscache.c",
lineNumber=223) at assert.c:65
#4  0x00000000019d277e in SearchSysCache1 (cacheId=4294967295,
key1=16778) at syscache.c:223

I didn't look beyond that.
--
Michael

---

From: Michael Paquier <[email-masked]>
Date: Tue, 17 Feb 2026 15:58:38 +0900

> key1=16778) at syscache.c:223

The issue here is that we have three code paths that are perfectly OK
with dealing in negative syscache ID values:
- DropObjectById()@dependency.c
- AlterObjectRename_internal()@alter.c
- AlterObjectNamespace_internal()@alter.c

The best path moving forward on this one that I can think of in
objectaddress.c would be to add an extra "invalid" value in the enum
of SysCacheIdentifier and attach that to the ObjectProperty that we
can use to mark when we don't have an ID assigned.  That would have 
the advantage to self-document the behavior that we don't have a
syscache entry at all when using this invalid ID.

What do you think about the updated version attached?
--
Michael
From 612ffaf8fa9abab811b6878739e8393c78f495fc Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email-masked]>
Date: Tue, 17 Feb 2026 15:51:41 +0900
Subject: [PATCH v3] Use SysCacheIdentifier enum instead of int

This change makes the ABI checker happier, by forcing checks based on
this type.
---
 src/include/catalog/objectaddress.h         |  5 +-
 src/include/replication/worker_internal.h   |  2 +-
 src/include/utils/inval.h                   |  7 +-
 src/include/utils/syscache.h                | 30 ++++----
 src/backend/catalog/aclchk.c                | 10 +--
 src/backend/catalog/dependency.c            |  2 +-
 src/backend/catalog/genbki.pl               | 15 ++--
 src/backend/catalog/namespace.c             |  4 +-
 src/backend/catalog/objectaddress.c         | 77 +++++++++++----------
 src/backend/commands/alter.c                |  8 +--
 src/backend/commands/extension.c            |  4 +-
 src/backend/optimizer/util/predtest.c       |  4 +-
 src/backend/parser/parse_oper.c             |  4 +-
 src/backend/replication/logical/syncutils.c |  2 +-
 src/backend/replication/logical/worker.c    |  2 +-
 src/backend/replication/pgoutput/pgoutput.c |  8 +--
 src/backend/utils/adt/acl.c                 |  4 +-
 src/backend/utils/adt/ri_triggers.c         |  4 +-
 src/backend/utils/cache/attoptcache.c       |  2 +-
 src/backend/utils/cache/evtcache.c          |  4 +-
 src/backend/utils/cache/inval.c             |  4 +-
 src/backend/utils/cache/plancache.c         |  8 +--
 src/backend/utils/cache/spccache.c          |  2 +-
 src/backend/utils/cache/syscache.c          | 34 ++++-----
 src/backend/utils/cache/ts_cache.c          |  2 +-
 src/backend/utils/cache/typcache.c          | 12 ++--
 src/backend/utils/misc/superuser.c          |  4 +-
 contrib/postgres_fdw/connection.c           |  4 +-
 contrib/postgres_fdw/shippable.c            |  2 +-
 29 files changed, 140 insertions(+), 130 deletions(-)

index e2fe9db11617..b549be2d523e 100644
 
 /*
index c1285fdd1bc1..644c953c9407 100644
 
index 0e937fec9e9c..e9d8cdb75ff6 100644

 

 

 
index 13f49af9ed4e..81e5933708e1 100644

 /*

 

 

 
 
index a431fc0926ff..1dd6df71d14b 100644

index f89267f03428..7564965fa18d 100644
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index b2c1b1c57332..48c6805f7527 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -795,9 +795,9 @@ print $fk_info "};\n\n#endif\t\t\t\t\t\t\t/* SYSTEM_FK_INFO_H */\n";
 # Now generate syscache info
 
 print_boilerplate($syscache_ids_fh, "syscache_ids.h", "SysCache identifiers");
-print $syscache_ids_fh "enum SysCacheIdentifier
+print $syscache_ids_fh "typedef enum SysCacheIdentifier
 {
-";
+\tSYSCACHEID_INVALID = -1,\n";
 
 print_boilerplate($syscache_info_fh, "syscache_info.h",
 	"SysCache definitions");
@@ -812,7 +812,14 @@ print $syscache_info_fh "static const struct cachedesc cacheinfo[] = {\n";
 my $last_syscache;
 foreach my $syscache (sort keys %syscaches)
 {
-	print $syscache_ids_fh "\t$syscache,\n";
+	if (not defined $last_syscache)
+	{
+		print $syscache_ids_fh "\t$syscache = 0,\n";
+	}
+	else
+	{
+		print $syscache_ids_fh "\t$syscache,\n";
+	}
 	$last_syscache = $syscache;
 
 	print $syscache_info_fh "\t[$syscache] = {\n";
@@ -825,7 +832,7 @@ foreach my $syscache (sort keys %syscaches)
 	print $syscache_info_fh "\t},\n";
 }

 print $syscache_info_fh "};\n";
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index c3b79a2ba48f..cb335afdf896 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -229,7 +229,7 @@ static void AccessTempTableNamespace(bool force);
 static void InitTempTableNamespace(void);
 static void RemoveTempRelations(Oid tempNamespaceId);
 static void RemoveTempRelationsCallback(int code, Datum arg);
-static void InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue);
+static void InvalidationCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue);
 static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
 						   bool include_out_arguments, int pronargs,
 						   int **argnumbers, int *fgc_flags);
@@ -4863,7 +4863,7 @@ InitializeSearchPath(void)
  *		Syscache inval callback function
  */
 static void
-InvalidationCallback(Datum arg, int cacheid, uint32 hashvalue)
+InvalidationCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
 {
 	/*
 	 * Force search path to be recomputed on next use, also invalidating the
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 02af64b82c68..d41a4d629186 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -99,10 +99,11 @@ typedef struct
 								 * error messages */
 	Oid			class_oid;		/* oid of catalog */
 	Oid			oid_index_oid;	/* oid of index on system oid column */
-	int			oid_catcache_id;	/* id of catcache on system oid column	*/
-	int			name_catcache_id;	/* id of catcache on (name,namespace), or
-									 * (name) if the object does not live in a
-									 * namespace */
+	SysCacheIdentifier oid_catcache_id; /* id of catcache on system oid column	*/
+	SysCacheIdentifier name_catcache_id;	/* id of catcache on
+											 * (name,namespace), or (name) if
+											 * the object does not live in a
+											 * namespace */
 	AttrNumber	attnum_oid;		/* attribute number of oid column */
 	AttrNumber	attnum_name;	/* attnum of name field */
 	AttrNumber	attnum_namespace;	/* attnum of namespace field */
@@ -135,8 +136,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"access method operator",
 		AccessMethodOperatorRelationId,
 		AccessMethodOperatorOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_amop_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -149,8 +150,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"access method procedure",
 		AccessMethodProcedureRelationId,
 		AccessMethodProcedureOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_amproc_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -163,8 +164,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"cast",
 		CastRelationId,
 		CastOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_cast_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -178,7 +179,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		CollationRelationId,
 		CollationOidIndexId,
 		COLLOID,
-		-1,						/* COLLNAMEENCNSP also takes encoding */
+		SYSCACHEID_INVALID,		/* COLLNAMEENCNSP also takes encoding */
 		Anum_pg_collation_oid,
 		Anum_pg_collation_collname,
 		Anum_pg_collation_collnamespace,
@@ -192,7 +193,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		ConstraintRelationId,
 		ConstraintOidIndexId,
 		CONSTROID,
-		-1,
+		SYSCACHEID_INVALID,
 		Anum_pg_constraint_oid,
 		Anum_pg_constraint_conname,
 		Anum_pg_constraint_connamespace,
@@ -220,7 +221,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		DatabaseRelationId,
 		DatabaseOidIndexId,
 		DATABASEOID,
-		-1,
+		SYSCACHEID_INVALID,
 		Anum_pg_database_oid,
 		Anum_pg_database_datname,
 		InvalidAttrNumber,
@@ -233,8 +234,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"default ACL",
 		DefaultAclRelationId,
 		DefaultAclOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_default_acl_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -247,8 +248,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"extension",
 		ExtensionRelationId,
 		ExtensionOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_extension_oid,
 		Anum_pg_extension_extname,
 		InvalidAttrNumber,		/* extension doesn't belong to extnamespace */
@@ -290,7 +291,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		ProcedureRelationId,
 		ProcedureOidIndexId,
 		PROCOID,
-		-1,						/* PROCNAMEARGSNSP also takes argument types */
+		SYSCACHEID_INVALID,		/* PROCNAMEARGSNSP also takes argument types */
 		Anum_pg_proc_oid,
 		Anum_pg_proc_proname,
 		Anum_pg_proc_pronamespace,
@@ -317,8 +318,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"large object metadata",
 		LargeObjectMetadataRelationId,
 		LargeObjectMetadataOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_largeobject_metadata_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -332,7 +333,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		OperatorClassRelationId,
 		OpclassOidIndexId,
 		CLAOID,
-		-1,						/* CLAAMNAMENSP also takes opcmethod */
+		SYSCACHEID_INVALID,		/* CLAAMNAMENSP also takes opcmethod */
 		Anum_pg_opclass_oid,
 		Anum_pg_opclass_opcname,
 		Anum_pg_opclass_opcnamespace,
@@ -346,7 +347,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		OperatorRelationId,
 		OperatorOidIndexId,
 		OPEROID,
-		-1,						/* OPERNAMENSP also takes left and right type */
+		SYSCACHEID_INVALID,		/* OPERNAMENSP also takes left and right type */
 		Anum_pg_operator_oid,
 		Anum_pg_operator_oprname,
 		Anum_pg_operator_oprnamespace,
@@ -360,7 +361,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		OperatorFamilyRelationId,
 		OpfamilyOidIndexId,
 		OPFAMILYOID,
-		-1,						/* OPFAMILYAMNAMENSP also takes opfmethod */
+		SYSCACHEID_INVALID,		/* OPFAMILYAMNAMENSP also takes opfmethod */
 		Anum_pg_opfamily_oid,
 		Anum_pg_opfamily_opfname,
 		Anum_pg_opfamily_opfnamespace,
@@ -387,8 +388,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"role membership",
 		AuthMemRelationId,
 		AuthMemOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_auth_members_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -401,8 +402,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"rule",
 		RewriteRelationId,
 		RewriteOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_rewrite_oid,
 		Anum_pg_rewrite_rulename,
 		InvalidAttrNumber,
@@ -444,7 +445,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		TableSpaceRelationId,
 		TablespaceOidIndexId,
 		TABLESPACEOID,
-		-1,
+		SYSCACHEID_INVALID,
 		Anum_pg_tablespace_oid,
 		Anum_pg_tablespace_spcname,
 		InvalidAttrNumber,
@@ -458,7 +459,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		TransformRelationId,
 		TransformOidIndexId,
 		TRFOID,
-		-1,
+		SYSCACHEID_INVALID,
 		Anum_pg_transform_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -471,8 +472,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"trigger",
 		TriggerRelationId,
 		TriggerOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_trigger_oid,
 		Anum_pg_trigger_tgname,
 		InvalidAttrNumber,
@@ -485,8 +486,8 @@ static const ObjectPropertyType ObjectProperty[] =
 		"policy",
 		PolicyRelationId,
 		PolicyOidIndexId,
-		-1,
-		-1,
+		SYSCACHEID_INVALID,
+		SYSCACHEID_INVALID,
 		Anum_pg_policy_oid,
 		Anum_pg_policy_polname,
 		InvalidAttrNumber,
@@ -626,7 +627,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		UserMappingRelationId,
 		UserMappingOidIndexId,
 		USERMAPPINGOID,
-		-1,
+		SYSCACHEID_INVALID,
 		Anum_pg_user_mapping_oid,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
@@ -2571,7 +2572,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 Oid
 get_object_namespace(const ObjectAddress *address)
 {
-	int			cache;
+	SysCacheIdentifier cache;
 	HeapTuple	tuple;
 	Oid			oid;
 	const ObjectPropertyType *property;
@@ -2640,7 +2641,7 @@ get_object_oid_index(Oid class_id)
 	return prop->oid_index_oid;
 }
 
-int
+SysCacheIdentifier
 get_object_catcache_oid(Oid class_id)
 {
 	const ObjectPropertyType *prop = get_object_property_data(class_id);
@@ -2648,7 +2649,7 @@ get_object_catcache_oid(Oid class_id)
 	return prop->oid_catcache_id;
 }
 
-int
+SysCacheIdentifier
@@ -2806,7 +2807,7 @@ get_catalog_object_by_oid_extended(Relation catalog,
 
 	if (oidCacheId > 0)
 	{
index 08957104c70a..c6f58d47be62 100644
index 81f24615d51c..93ce3ebabf81 100644
 
 /* Local functions */
 
index 26858d1d2b07..61a0ed195aa5 100644

 /*
index 768e4cff9c50..76cbdacf9336 100644

 /*
index 535ffb6f09e3..8f0897beec14 100644
index 32725c48623b..8b93f48470c3 100644
index e016f64e0b37..2aea20dca227 100644
 
index 3a6905f9546e..332152cfd2a3 100644

 /*
index bbadecef5f92..57a511cc9e24 100644

index 72edc8f665b8..4e0fc7f91123 100644
index 2b4453e54a76..ac5c760efa74 100644

 /*
index bf465a295e3f..d59216b28f16 100644
 
index 37d5d73b7fb9..d93c3b8afe87 100644

index 8f1a5e695956..0d87fb2f4fcd 100644
index ae3d18e0e74a..007a9a15d71b 100644

 

 HeapTuple
 
 HeapTuple
 
 HeapTuple
 
 HeapTuple
index 71e49b2b9193..744c8e71d715 100644
index dc4b1a56414c..c721e1c28747 100644
 
index 7821624687af..10759a9a37bd 100644

 /*
index 487a1a231707..16e440715773 100644
index d32d3d0e4616..e07eadd36300 100644
2.53.0

---

From: Andreas Karlsson <[email-masked]>
Date: Tue, 17 Feb 2026 09:20:44 +0100

> What do you think about the updated version attached?

Yeah, that looks like a quite nice improvement. My only comment is that 
if it was me I would have split it into two patches, one introducing the 
invalid and one replacing int. But you are much more familiar than me 
with what granularity of commits the project prefers

Andreas

---

From: Michael Paquier <[email-masked]>
Date: Tue, 17 Feb 2026 17:59:31 +0900

On Tue, Feb 17, 2026 at 09:20:44AM +0100, Andreas Karlsson wrote:
> Yeah, that looks like a quite nice improvement. My only comment is that if
> it was me I would have split it into two patches, one introducing the
> invalid and one replacing int. But you are much more familiar than me with
> what granularity of commits the project prefers

Splitting that into two is probably better, yes.  Even if both changes
touch the same portions of perl script, it makes the introduction of
the two concepts cleaner.
--
Michael