generate syscache info automatically

Started by Peter Eisentrautover 2 years ago17 messages
#1Peter Eisentraut
peter@eisentraut.org
5 attachment(s)

I want to report on my on-the-plane-to-PGCon project.

The idea was mentioned in [0]/messages/by-id/CA+hUKGKdpDjKL2jgC-GpoL4DGZU1YPqnOFHbDqFkfRQcPaR5DQ@mail.gmail.com. genbki.pl already knows everything about
system catalog indexes. If we add a "please also make a syscache for
this one" flag to the catalog metadata, we can have genbki.pl produce
the tables in syscache.c and syscache.h automatically.

Aside from avoiding the cumbersome editing of those tables, I think this
layout is also conceptually cleaner, as you can more easily see which
system catalog indexes have syscaches and maybe ask questions about why
or why not.

As a possible follow-up, I have also started work on generating the
ObjectProperty structure in objectaddress.c. One of the things you need
for that is making genbki.pl aware of the syscache information. There
is some more work to be done there, but it's looking promising.

[0]: /messages/by-id/CA+hUKGKdpDjKL2jgC-GpoL4DGZU1YPqnOFHbDqFkfRQcPaR5DQ@mail.gmail.com
/messages/by-id/CA+hUKGKdpDjKL2jgC-GpoL4DGZU1YPqnOFHbDqFkfRQcPaR5DQ@mail.gmail.com

Attachments:

0001-Update-DECLARE_INDEX-documentation.patchtext/plain; charset=UTF-8; name=0001-Update-DECLARE_INDEX-documentation.patchDownload
From 27fbebc06378c97b9918e899564532146d618558 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Tue, 30 May 2023 08:27:56 -0400
Subject: [PATCH 1/5] Update DECLARE_INDEX documentation

should have been updated in 6a6389a08b
---
 src/include/catalog/genbki.h | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index 50518cbbf5..c42ba0cea5 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -71,12 +71,13 @@
  * DECLARE_UNIQUE_INDEX_PKEY.  ("PKEY" marks the index as being the catalog's
  * primary key; currently this is only cosmetically different from a regular
  * unique index.  By convention, we usually make a catalog's OID column its
- * pkey, if it has one.)  The first two arguments are the index's name and
- * OID, the rest is much like a standard 'create index' SQL command.
+ * pkey, if it has one.)
  *
- * For each index, we also provide a #define for its OID.  References to
- * the index in the C code should always use these #defines, not the actual
- * index name (much less the numeric OID).
+ * The first two arguments are the index's name and OID.  The third argument
+ * is the name of a #define to generate for its OID.  References to the index
+ * in the C code should always use these #defines, not the actual index name
+ * (much less the numeric OID).  The rest is much like a standard 'create
+ * index' SQL command.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */

base-commit: 0bcb3ca3b95b2b94de0b337a73aef333e0346c44
-- 
2.40.1

0002-Restructure-DECLARE_INDEX-arguments.patchtext/plain; charset=UTF-8; name=0002-Restructure-DECLARE_INDEX-arguments.patchDownload
From 8f47e5c37dad09a3011f678a859aaa1677ce5603 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 29 May 2023 17:12:28 +0200
Subject: [PATCH 2/5] Restructure DECLARE_INDEX arguments

Separate the table name from the index declaration.  We need that
anyway later for the ALTER TABLE / USING INDEX commands, so we might
as well structure the declarations like that to begin with.
---
 src/backend/catalog/Catalog.pm                 |  5 +++--
 src/backend/catalog/genbki.pl                  |  7 +++----
 src/include/catalog/genbki.h                   | 10 +++++-----
 src/include/catalog/pg_aggregate.h             |  2 +-
 src/include/catalog/pg_am.h                    |  4 ++--
 src/include/catalog/pg_amop.h                  |  6 +++---
 src/include/catalog/pg_amproc.h                |  4 ++--
 src/include/catalog/pg_attrdef.h               |  4 ++--
 src/include/catalog/pg_attribute.h             |  4 ++--
 src/include/catalog/pg_auth_members.h          |  8 ++++----
 src/include/catalog/pg_authid.h                |  4 ++--
 src/include/catalog/pg_cast.h                  |  4 ++--
 src/include/catalog/pg_class.h                 |  6 +++---
 src/include/catalog/pg_collation.h             |  4 ++--
 src/include/catalog/pg_constraint.h            | 10 +++++-----
 src/include/catalog/pg_conversion.h            |  6 +++---
 src/include/catalog/pg_database.h              |  4 ++--
 src/include/catalog/pg_db_role_setting.h       |  2 +-
 src/include/catalog/pg_default_acl.h           |  4 ++--
 src/include/catalog/pg_depend.h                |  4 ++--
 src/include/catalog/pg_description.h           |  2 +-
 src/include/catalog/pg_enum.h                  |  6 +++---
 src/include/catalog/pg_event_trigger.h         |  4 ++--
 src/include/catalog/pg_extension.h             |  4 ++--
 src/include/catalog/pg_foreign_data_wrapper.h  |  4 ++--
 src/include/catalog/pg_foreign_server.h        |  4 ++--
 src/include/catalog/pg_foreign_table.h         |  2 +-
 src/include/catalog/pg_index.h                 |  4 ++--
 src/include/catalog/pg_inherits.h              |  4 ++--
 src/include/catalog/pg_init_privs.h            |  2 +-
 src/include/catalog/pg_language.h              |  4 ++--
 src/include/catalog/pg_largeobject.h           |  2 +-
 src/include/catalog/pg_largeobject_metadata.h  |  2 +-
 src/include/catalog/pg_namespace.h             |  4 ++--
 src/include/catalog/pg_opclass.h               |  4 ++--
 src/include/catalog/pg_operator.h              |  4 ++--
 src/include/catalog/pg_opfamily.h              |  4 ++--
 src/include/catalog/pg_parameter_acl.h         |  4 ++--
 src/include/catalog/pg_partitioned_table.h     |  2 +-
 src/include/catalog/pg_policy.h                |  4 ++--
 src/include/catalog/pg_proc.h                  |  4 ++--
 src/include/catalog/pg_publication.h           |  4 ++--
 src/include/catalog/pg_publication_namespace.h |  4 ++--
 src/include/catalog/pg_publication_rel.h       |  6 +++---
 src/include/catalog/pg_range.h                 |  4 ++--
 src/include/catalog/pg_replication_origin.h    |  4 ++--
 src/include/catalog/pg_rewrite.h               |  4 ++--
 src/include/catalog/pg_seclabel.h              |  2 +-
 src/include/catalog/pg_sequence.h              |  2 +-
 src/include/catalog/pg_shdepend.h              |  4 ++--
 src/include/catalog/pg_shdescription.h         |  2 +-
 src/include/catalog/pg_shseclabel.h            |  2 +-
 src/include/catalog/pg_statistic.h             |  2 +-
 src/include/catalog/pg_statistic_ext.h         |  6 +++---
 src/include/catalog/pg_statistic_ext_data.h    |  2 +-
 src/include/catalog/pg_subscription.h          |  4 ++--
 src/include/catalog/pg_subscription_rel.h      |  2 +-
 src/include/catalog/pg_tablespace.h            |  4 ++--
 src/include/catalog/pg_transform.h             |  4 ++--
 src/include/catalog/pg_trigger.h               |  6 +++---
 src/include/catalog/pg_ts_config.h             |  4 ++--
 src/include/catalog/pg_ts_config_map.h         |  2 +-
 src/include/catalog/pg_ts_dict.h               |  4 ++--
 src/include/catalog/pg_ts_parser.h             |  4 ++--
 src/include/catalog/pg_ts_template.h           |  4 ++--
 src/include/catalog/pg_type.h                  |  4 ++--
 src/include/catalog/pg_user_mapping.h          |  4 ++--
 67 files changed, 135 insertions(+), 135 deletions(-)

diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 84aaeb002a..a727d692b7 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -110,7 +110,7 @@ sub ParseHeader
 			  };
 		}
 		elsif (
-			/^DECLARE_(UNIQUE_)?INDEX(_PKEY)?\(\s*(\w+),\s*(\d+),\s*(\w+),\s*(.+)\)/
+			/^DECLARE_(UNIQUE_)?INDEX(_PKEY)?\(\s*(\w+),\s*(\d+),\s*(\w+),\s*(\w+),\s*(.+)\)/
 		  )
 		{
 			push @{ $catalog{indexing} },
@@ -120,7 +120,8 @@ sub ParseHeader
 				index_name => $3,
 				index_oid => $4,
 				index_oid_macro => $5,
-				index_decl => $6
+				table_name => $6,
+				index_decl => $7
 			  };
 		}
 		elsif (/^DECLARE_OID_DEFINING_MACRO\(\s*(\w+),\s*(\d+)\)/)
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 4a7205472c..c7657cc47c 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -135,19 +135,18 @@
 	foreach my $index (@{ $catalog->{indexing} })
 	{
 		push @index_decls,
-		  sprintf "declare %sindex %s %s %s\n",
+		  sprintf "declare %sindex %s %s on %s using %s\n",
 		  $index->{is_unique} ? 'unique ' : '',
 		  $index->{index_name}, $index->{index_oid},
+		  $index->{table_name},
 		  $index->{index_decl};
 		$oidcounts{ $index->{index_oid} }++;
 
 		if ($index->{is_unique})
 		{
-			$index->{index_decl} =~ /on (\w+) using/;
-			my $tblname = $1;
 			push @system_constraints,
 			  sprintf "ALTER TABLE %s ADD %s USING INDEX %s;",
-			  $tblname,
+			  $index->{table_name},
 			  $index->{is_pkey} ? "PRIMARY KEY" : "UNIQUE",
 			  $index->{index_name};
 		}
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index c42ba0cea5..e22a6902fb 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -76,14 +76,14 @@
  * The first two arguments are the index's name and OID.  The third argument
  * is the name of a #define to generate for its OID.  References to the index
  * in the C code should always use these #defines, not the actual index name
- * (much less the numeric OID).  The rest is much like a standard 'create
- * index' SQL command.
+ * (much less the numeric OID).  The fourth argument is the table name.  The
+ * rest is much like a standard 'create index' SQL command.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */
-#define DECLARE_INDEX(name,oid,oidmacro,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,decl) extern int no_such_variable
+#define DECLARE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl) extern int no_such_variable
 
 /*
  * These lines inform genbki.pl about manually-assigned OIDs that do not
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 3112881193..085149e258 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -110,7 +110,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
 
 DECLARE_TOAST(pg_aggregate, 4159, 4160);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, on pg_aggregate using btree(aggfnoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index dab54be130..d5314bb38b 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -47,8 +47,8 @@ CATALOG(pg_am,2601,AccessMethodRelationId)
  */
 typedef FormData_pg_am *Form_pg_am;
 
-DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, on pg_am using btree(amname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, on pg_am using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index 4ca7321409..c9bb7b4787 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -87,9 +87,9 @@ CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
  */
 typedef FormData_pg_amop *Form_pg_amop;
 
-DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, on pg_amop using btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
-DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, on pg_amop using btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, on pg_amop using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, pg_amop, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 3307d5c844..5acf4efab9 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -67,7 +67,7 @@ CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
  */
 typedef FormData_pg_amproc *Form_pg_amproc;
 
-DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, on pg_amproc using btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, on pg_amproc using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, pg_amproc, btree(oid oid_ops));
 
 #endif							/* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h
index 9dc318ff93..04c5725045 100644
--- a/src/include/catalog/pg_attrdef.h
+++ b/src/include/catalog/pg_attrdef.h
@@ -50,8 +50,8 @@ typedef FormData_pg_attrdef *Form_pg_attrdef;
 
 DECLARE_TOAST(pg_attrdef, 2830, 2831);
 
-DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index, 2656, AttrDefaultIndexId, on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attrdef_oid_index, 2657, AttrDefaultOidIndexId, on pg_attrdef using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index, 2656, AttrDefaultIndexId, pg_attrdef, btree(adrelid oid_ops, adnum int2_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_attrdef_oid_index, 2657, AttrDefaultOidIndexId, pg_attrdef, btree(oid oid_ops));
 
 DECLARE_FOREIGN_KEY((adrelid, adnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index f8b4861b94..f0d6de7c1f 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -208,8 +208,8 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
  */
 typedef FormData_pg_attribute *Form_pg_attribute;
 
-DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, on pg_attribute using btree(attrelid oid_ops, attname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index df2b8b29e0..4ab8a9f7b7 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -45,9 +45,9 @@ CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_
  */
 typedef FormData_pg_auth_members *Form_pg_auth_members;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, on pg_auth_members using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, on pg_auth_members using btree(roleid oid_ops, member oid_ops, grantor oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, on pg_auth_members using btree(member oid_ops, roleid oid_ops, grantor oid_ops));
-DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, on pg_auth_members using btree(grantor oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, pg_auth_members, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops));
+DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, pg_auth_members, btree(grantor oid_ops));
 
 #endif							/* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index c70baf7887..0e7ddc56ea 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -57,7 +57,7 @@ typedef FormData_pg_authid *Form_pg_authid;
 
 DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, on pg_authid using btree(rolname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, on pg_authid using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops));
 
 #endif							/* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index 9ec2b5785b..a2518388b3 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -56,8 +56,8 @@ CATALOG(pg_cast,2605,CastRelationId)
  */
 typedef FormData_pg_cast *Form_pg_cast;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, on pg_cast using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, pg_cast, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 2d1bb7af3a..55dcd54100 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -152,9 +152,9 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat
  */
 typedef FormData_pg_class *Form_pg_class;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, on pg_class using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, on pg_class using btree(relname name_ops, relnamespace oid_ops));
-DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, on pg_class using btree(reltablespace oid_ops, relfilenode oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops));
+DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, pg_class, btree(reltablespace oid_ops, relfilenode oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index bfa3568451..2d7dcde183 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -59,8 +59,8 @@ typedef FormData_pg_collation *Form_pg_collation;
 
 DECLARE_TOAST(pg_collation, 6175, 6176);
 
-DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, on pg_collation using btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, on pg_collation using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 16bf5f5576..0d47c9b589 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -166,11 +166,11 @@ typedef FormData_pg_constraint *Form_pg_constraint;
 
 DECLARE_TOAST(pg_constraint, 2832, 2833);
 
-DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, on pg_constraint using btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, on pg_constraint using btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
-DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, on pg_constraint using btree(contypid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, on pg_constraint using btree(oid oid_ops));
-DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, on pg_constraint using btree(conparentid oid_ops));
+DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, pg_constraint, btree(conname name_ops, connamespace oid_ops));
+DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
+DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops));
+DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops));
 
 /* conkey can contain zero (InvalidAttrNumber) if a whole-row Var is used */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((conrelid, conkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index de40909dd3..42847fdf12 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -60,9 +60,9 @@ CATALOG(pg_conversion,2607,ConversionRelationId)
  */
 typedef FormData_pg_conversion *Form_pg_conversion;
 
-DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, on pg_conversion using btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, on pg_conversion using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops));
 
 
 extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index d004f4dc8a..44e2ed73cf 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -91,8 +91,8 @@ typedef FormData_pg_database *Form_pg_database;
 
 DECLARE_TOAST_WITH_MACRO(pg_database, 4177, 4178, PgDatabaseToastTable, PgDatabaseToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, on pg_database using btree(datname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, on pg_database using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, pg_database, btree(datname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops));
 
 /*
  * pg_database.dat contains an entry for template1, but not for the template0
diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h
index 4ba0d69e76..af025cc608 100644
--- a/src/include/catalog/pg_db_role_setting.h
+++ b/src/include/catalog/pg_db_role_setting.h
@@ -48,7 +48,7 @@ typedef FormData_pg_db_role_setting * Form_pg_db_role_setting;
 
 DECLARE_TOAST_WITH_MACRO(pg_db_role_setting, 2966, 2967, PgDbRoleSettingToastTable, PgDbRoleSettingToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_db_role_setting_databaseid_rol_index, 2965, DbRoleSettingDatidRolidIndexId, on pg_db_role_setting using btree(setdatabase oid_ops, setrole oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_db_role_setting_databaseid_rol_index, 2965, DbRoleSettingDatidRolidIndexId, pg_db_role_setting, btree(setdatabase oid_ops, setrole oid_ops));
 
 /*
  * prototypes for functions in pg_db_role_setting.c
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index d6d0a03f0c..803ce3eab8 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -51,8 +51,8 @@ typedef FormData_pg_default_acl *Form_pg_default_acl;
 
 DECLARE_TOAST(pg_default_acl, 4143, 4144);
 
-DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, on pg_default_acl using btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, on pg_default_acl using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, pg_default_acl, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h
index 30dde6f8aa..67ea968beb 100644
--- a/src/include/catalog/pg_depend.h
+++ b/src/include/catalog/pg_depend.h
@@ -71,7 +71,7 @@ CATALOG(pg_depend,2608,DependRelationId)
  */
 typedef FormData_pg_depend *Form_pg_depend;
 
-DECLARE_INDEX(pg_depend_depender_index, 2673, DependDependerIndexId, on pg_depend using btree(classid oid_ops, objid oid_ops, objsubid int4_ops));
-DECLARE_INDEX(pg_depend_reference_index, 2674, DependReferenceIndexId, on pg_depend using btree(refclassid oid_ops, refobjid oid_ops, refobjsubid int4_ops));
+DECLARE_INDEX(pg_depend_depender_index, 2673, DependDependerIndexId, pg_depend, btree(classid oid_ops, objid oid_ops, objsubid int4_ops));
+DECLARE_INDEX(pg_depend_reference_index, 2674, DependReferenceIndexId, pg_depend, btree(refclassid oid_ops, refobjid oid_ops, refobjsubid int4_ops));
 
 #endif							/* PG_DEPEND_H */
diff --git a/src/include/catalog/pg_description.h b/src/include/catalog/pg_description.h
index 7545b92a15..10026152e7 100644
--- a/src/include/catalog/pg_description.h
+++ b/src/include/catalog/pg_description.h
@@ -65,7 +65,7 @@ typedef FormData_pg_description * Form_pg_description;
 
 DECLARE_TOAST(pg_description, 2834, 2835);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_description_o_c_o_index, 2675, DescriptionObjIndexId, on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_description_o_c_o_index, 2675, DescriptionObjIndexId, pg_description, btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
 
 /* We do not use BKI_LOOKUP here because it causes problems for genbki.pl */
 DECLARE_FOREIGN_KEY((classoid), pg_class, (oid));
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index 83a0668233..c483cb1042 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -43,9 +43,9 @@ CATALOG(pg_enum,3501,EnumRelationId)
  */
 typedef FormData_pg_enum *Form_pg_enum;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, on pg_enum using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, on pg_enum using btree(enumtypid oid_ops, enumlabel name_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, on pg_enum using btree(enumtypid oid_ops, enumsortorder float4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops));
+DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, pg_enum, btree(enumtypid oid_ops, enumsortorder float4_ops));
 
 /*
  * prototypes for functions in pg_enum.c
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index e30550f6e1..0ec42edff6 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -51,7 +51,7 @@ typedef FormData_pg_event_trigger *Form_pg_event_trigger;
 
 DECLARE_TOAST(pg_event_trigger, 4145, 4146);
 
-DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, on pg_event_trigger using btree(evtname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, on pg_event_trigger using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops));
 
 #endif							/* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index 799c8ed9d0..8c7174e23c 100644
--- a/src/include/catalog/pg_extension.h
+++ b/src/include/catalog/pg_extension.h
@@ -53,7 +53,7 @@ typedef FormData_pg_extension *Form_pg_extension;
 
 DECLARE_TOAST(pg_extension, 4147, 4148);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_extension_oid_index, 3080, ExtensionOidIndexId, on pg_extension using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, ExtensionNameIndexId, on pg_extension using btree(extname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_extension_oid_index, 3080, ExtensionOidIndexId, pg_extension, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, ExtensionNameIndexId, pg_extension, btree(extname name_ops));
 
 #endif							/* PG_EXTENSION_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index e7833ec883..37387f9355 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -52,7 +52,7 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
 
 DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, on pg_foreign_data_wrapper using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, on pg_foreign_data_wrapper using btree(fdwname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops));
 
 #endif							/* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 2a14871d74..5993967c6e 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -49,7 +49,7 @@ typedef FormData_pg_foreign_server *Form_pg_foreign_server;
 
 DECLARE_TOAST(pg_foreign_server, 4151, 4152);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, on pg_foreign_server using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, on pg_foreign_server using btree(srvname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops));
 
 #endif							/* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index cfa570a88c..2420e23401 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -44,6 +44,6 @@ typedef FormData_pg_foreign_table *Form_pg_foreign_table;
 
 DECLARE_TOAST(pg_foreign_table, 4153, 4154);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, on pg_foreign_table using btree(ftrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops));
 
 #endif							/* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index b0592571da..32930411b6 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -69,8 +69,8 @@ CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
  */
 typedef FormData_pg_index *Form_pg_index;
 
-DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, on pg_index using btree(indrelid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, on pg_index using btree(indexrelid oid_ops));
+DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops));
 
 /* indkey can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((indrelid, indkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h
index ce154ab943..65562b8c3e 100644
--- a/src/include/catalog/pg_inherits.h
+++ b/src/include/catalog/pg_inherits.h
@@ -44,8 +44,8 @@ CATALOG(pg_inherits,2611,InheritsRelationId)
  */
 typedef FormData_pg_inherits *Form_pg_inherits;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_inherits_relid_seqno_index, 2680, InheritsRelidSeqnoIndexId, on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops));
-DECLARE_INDEX(pg_inherits_parent_index, 2187, InheritsParentIndexId, on pg_inherits using btree(inhparent oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_inherits_relid_seqno_index, 2680, InheritsRelidSeqnoIndexId, pg_inherits, btree(inhrelid oid_ops, inhseqno int4_ops));
+DECLARE_INDEX(pg_inherits_parent_index, 2187, InheritsParentIndexId, pg_inherits, btree(inhparent oid_ops));
 
 
 extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode);
diff --git a/src/include/catalog/pg_init_privs.h b/src/include/catalog/pg_init_privs.h
index 34fe2b4d0e..3f3df954a8 100644
--- a/src/include/catalog/pg_init_privs.h
+++ b/src/include/catalog/pg_init_privs.h
@@ -65,7 +65,7 @@ typedef FormData_pg_init_privs * Form_pg_init_privs;
 
 DECLARE_TOAST(pg_init_privs, 4155, 4156);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_init_privs_o_c_o_index, 3395, InitPrivsObjIndexId, on pg_init_privs using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_init_privs_o_c_o_index, 3395, InitPrivsObjIndexId, pg_init_privs, btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
 
 /*
  * It is important to know if the initial privileges are from initdb or from an
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index 02003b4627..d666ea2044 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -66,7 +66,7 @@ typedef FormData_pg_language *Form_pg_language;
 
 DECLARE_TOAST(pg_language, 4157, 4158);
 
-DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, on pg_language using btree(lanname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, on pg_language using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops));
 
 #endif							/* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h
index 95471073a8..c073e10e40 100644
--- a/src/include/catalog/pg_largeobject.h
+++ b/src/include/catalog/pg_largeobject.h
@@ -44,7 +44,7 @@ CATALOG(pg_largeobject,2613,LargeObjectRelationId)
  */
 typedef FormData_pg_largeobject *Form_pg_largeobject;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_loid_pn_index, 2683, LargeObjectLOidPNIndexId, on pg_largeobject using btree(loid oid_ops, pageno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_loid_pn_index, 2683, LargeObjectLOidPNIndexId, pg_largeobject, btree(loid oid_ops, pageno int4_ops));
 
 extern Oid	LargeObjectCreate(Oid loid);
 extern void LargeObjectDrop(Oid loid);
diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h
index 80db926079..0481244845 100644
--- a/src/include/catalog/pg_largeobject_metadata.h
+++ b/src/include/catalog/pg_largeobject_metadata.h
@@ -46,6 +46,6 @@ CATALOG(pg_largeobject_metadata,2995,LargeObjectMetadataRelationId)
  */
 typedef FormData_pg_largeobject_metadata *Form_pg_largeobject_metadata;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_metadata_oid_index, 2996, LargeObjectMetadataOidIndexId, on pg_largeobject_metadata using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_metadata_oid_index, 2996, LargeObjectMetadataOidIndexId, pg_largeobject_metadata, btree(oid oid_ops));
 
 #endif							/* PG_LARGEOBJECT_METADATA_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 2b0c243178..fc74a14c37 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -53,8 +53,8 @@ typedef FormData_pg_namespace *Form_pg_namespace;
 
 DECLARE_TOAST(pg_namespace, 4163, 4164);
 
-DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, on pg_namespace using btree(nspname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, on pg_namespace using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops));
 
 /*
  * prototypes for functions in pg_namespace.c
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index b4b6325c06..a5d09faf1f 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -82,7 +82,7 @@ CATALOG(pg_opclass,2616,OperatorClassRelationId)
  */
 typedef FormData_pg_opclass *Form_pg_opclass;
 
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, on pg_opclass using btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, on pg_opclass using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops));
 
 #endif							/* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index e60cf782a6..aff372b4bb 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -82,8 +82,8 @@ CATALOG(pg_operator,2617,OperatorRelationId)
  */
 typedef FormData_pg_operator *Form_pg_operator;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, on pg_operator using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
 
 
 extern ObjectAddress OperatorCreate(const char *operatorName,
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 39b8d7c219..88940de916 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -50,8 +50,8 @@ CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
  */
 typedef FormData_pg_opfamily *Form_pg_opfamily;
 
-DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, on pg_opfamily using btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, on pg_opfamily using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h
index 1612cebd0e..f46cdd1524 100644
--- a/src/include/catalog/pg_parameter_acl.h
+++ b/src/include/catalog/pg_parameter_acl.h
@@ -50,8 +50,8 @@ typedef FormData_pg_parameter_acl * Form_pg_parameter_acl;
 
 DECLARE_TOAST_WITH_MACRO(pg_parameter_acl, 6244, 6245, PgParameterAclToastTable, PgParameterAclToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, on pg_parameter_acl using btree(parname text_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, on pg_parameter_acl using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops));
 
 
 extern Oid	ParameterAclLookup(const char *parameter, bool missing_ok);
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index eb867ad62b..0cf512e1c8 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -66,7 +66,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
 
 DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, on pg_partitioned_table using btree(partrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops));
 
 /* partattrs can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((partrelid, partattrs), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h
index c9525ece74..feaeedbbe6 100644
--- a/src/include/catalog/pg_policy.h
+++ b/src/include/catalog/pg_policy.h
@@ -52,7 +52,7 @@ typedef FormData_pg_policy *Form_pg_policy;
 
 DECLARE_TOAST(pg_policy, 4167, 4168);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_policy_oid_index, 3257, PolicyOidIndexId, on pg_policy using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_policy_polrelid_polname_index, 3258, PolicyPolrelidPolnameIndexId, on pg_policy using btree(polrelid oid_ops, polname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_policy_oid_index, 3257, PolicyOidIndexId, pg_policy, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_policy_polrelid_polname_index, 3258, PolicyPolrelidPolnameIndexId, pg_policy, btree(polrelid oid_ops, polname name_ops));
 
 #endif							/* PG_POLICY_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index e7abe0b497..fdb39d4001 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -137,8 +137,8 @@ typedef FormData_pg_proc *Form_pg_proc;
 
 DECLARE_TOAST(pg_proc, 2836, 2837);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, on pg_proc using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 6ecaa2a01e..d929c9a188 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -63,8 +63,8 @@ CATALOG(pg_publication,6104,PublicationRelationId)
  */
 typedef FormData_pg_publication *Form_pg_publication;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, on pg_publication using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, on pg_publication using btree(pubname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops));
 
 typedef struct PublicationActions
 {
diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h
index f1abcb9f16..b361c8ab5e 100644
--- a/src/include/catalog/pg_publication_namespace.h
+++ b/src/include/catalog/pg_publication_namespace.h
@@ -41,7 +41,7 @@ CATALOG(pg_publication_namespace,6237,PublicationNamespaceRelationId)
  */
 typedef FormData_pg_publication_namespace *Form_pg_publication_namespace;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, on pg_publication_namespace using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, on pg_publication_namespace using btree(pnnspid oid_ops, pnpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_NAMESPACE_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index 613e9747c2..bef508764a 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -47,8 +47,8 @@ typedef FormData_pg_publication_rel *Form_pg_publication_rel;
 
 DECLARE_TOAST(pg_publication_rel, 6228, 6229);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, on pg_publication_rel using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, on pg_publication_rel using btree(prrelid oid_ops, prpubid oid_ops));
-DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, on pg_publication_rel using btree(prpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops));
+DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, pg_publication_rel, btree(prpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index d03ef18851..1247fa7c77 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -57,8 +57,8 @@ CATALOG(pg_range,3541,RangeRelationId)
  */
 typedef FormData_pg_range *Form_pg_range;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, on pg_range using btree(rngtypid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, on pg_range using btree(rngmultitypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops));
 
 /*
  * prototypes for functions in pg_range.c
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index fa54f120e6..83ff36dcba 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -56,7 +56,7 @@ typedef FormData_pg_replication_origin *Form_pg_replication_origin;
 
 DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, on pg_replication_origin using btree(roident oid_ops));
-DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, on pg_replication_origin using btree(roname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops));
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops));
 
 #endif							/* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 21f24e6d7e..60d642b595 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -53,7 +53,7 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
 
 DECLARE_TOAST(pg_rewrite, 2838, 2839);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, on pg_rewrite using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, pg_rewrite, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops));
 
 #endif							/* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
index 74299cf85d..a3a601f6fe 100644
--- a/src/include/catalog/pg_seclabel.h
+++ b/src/include/catalog/pg_seclabel.h
@@ -40,6 +40,6 @@ CATALOG(pg_seclabel,3596,SecLabelRelationId)
 
 DECLARE_TOAST(pg_seclabel, 3598, 3599);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_seclabel_object_index, 3597, SecLabelObjectIndexId, on pg_seclabel using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_seclabel_object_index, 3597, SecLabelObjectIndexId, pg_seclabel, btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops));
 
 #endif							/* PG_SECLABEL_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index d528c9122f..fdfc27bbd9 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -39,6 +39,6 @@ CATALOG(pg_sequence,2224,SequenceRelationId)
  */
 typedef FormData_pg_sequence *Form_pg_sequence;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, on pg_sequence using btree(seqrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops));
 
 #endif							/* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_shdepend.h b/src/include/catalog/pg_shdepend.h
index 35ba911a22..3834d07f78 100644
--- a/src/include/catalog/pg_shdepend.h
+++ b/src/include/catalog/pg_shdepend.h
@@ -72,7 +72,7 @@ CATALOG(pg_shdepend,1214,SharedDependRelationId) BKI_SHARED_RELATION
  */
 typedef FormData_pg_shdepend *Form_pg_shdepend;
 
-DECLARE_INDEX(pg_shdepend_depender_index, 1232, SharedDependDependerIndexId, on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
-DECLARE_INDEX(pg_shdepend_reference_index, 1233, SharedDependReferenceIndexId, on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops));
+DECLARE_INDEX(pg_shdepend_depender_index, 1232, SharedDependDependerIndexId, pg_shdepend, btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
+DECLARE_INDEX(pg_shdepend_reference_index, 1233, SharedDependReferenceIndexId, pg_shdepend, btree(refclassid oid_ops, refobjid oid_ops));
 
 #endif							/* PG_SHDEPEND_H */
diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h
index 7b66c12224..c7b66d95d5 100644
--- a/src/include/catalog/pg_shdescription.h
+++ b/src/include/catalog/pg_shdescription.h
@@ -57,7 +57,7 @@ typedef FormData_pg_shdescription * Form_pg_shdescription;
 
 DECLARE_TOAST_WITH_MACRO(pg_shdescription, 2846, 2847, PgShdescriptionToastTable, PgShdescriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_shdescription_o_c_index, 2397, SharedDescriptionObjIndexId, on pg_shdescription using btree(objoid oid_ops, classoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_shdescription_o_c_index, 2397, SharedDescriptionObjIndexId, pg_shdescription, btree(objoid oid_ops, classoid oid_ops));
 
 /* We do not use BKI_LOOKUP here because it causes problems for genbki.pl */
 DECLARE_FOREIGN_KEY((classoid), pg_class, (oid));
diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h
index 32b03de952..e252b75688 100644
--- a/src/include/catalog/pg_shseclabel.h
+++ b/src/include/catalog/pg_shseclabel.h
@@ -41,6 +41,6 @@ typedef FormData_pg_shseclabel * Form_pg_shseclabel;
 
 DECLARE_TOAST_WITH_MACRO(pg_shseclabel, 4060, 4061, PgShseclabelToastTable, PgShseclabelToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_shseclabel_object_index, 3593, SharedSecLabelObjectIndexId, on pg_shseclabel using btree(objoid oid_ops, classoid oid_ops, provider text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_shseclabel_object_index, 3593, SharedSecLabelObjectIndexId, pg_shseclabel, btree(objoid oid_ops, classoid oid_ops, provider text_ops));
 
 #endif							/* PG_SHSECLABEL_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 8770c5b4c6..864cb54a51 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -136,7 +136,7 @@ typedef FormData_pg_statistic *Form_pg_statistic;
 
 DECLARE_TOAST(pg_statistic, 2840, 2841);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, on pg_statistic using btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
 
 DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index 53eec9025a..85e56feb80 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -70,9 +70,9 @@ typedef FormData_pg_statistic_ext *Form_pg_statistic_ext;
 
 DECLARE_TOAST(pg_statistic_ext, 3439, 3440);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, on pg_statistic_ext using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, on pg_statistic_ext using btree(stxname name_ops, stxnamespace oid_ops));
-DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, on pg_statistic_ext using btree(stxrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops));
+DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, pg_statistic_ext, btree(stxrelid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((stxrelid, stxkeys), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
index 64d11a9c58..19a00705e6 100644
--- a/src/include/catalog/pg_statistic_ext_data.h
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -54,7 +54,7 @@ typedef FormData_pg_statistic_ext_data *Form_pg_statistic_ext_data;
 
 DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, on pg_statistic_ext_data using btree(stxoid oid_ops, stxdinherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops));
 
 
 #endif							/* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index 1d40eebc78..be36c4a820 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -115,8 +115,8 @@ typedef FormData_pg_subscription *Form_pg_subscription;
 
 DECLARE_TOAST_WITH_MACRO(pg_subscription, 4183, 4184, PgSubscriptionToastTable, PgSubscriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, on pg_subscription using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, on pg_subscription using btree(subdbid oid_ops, subname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops));
 
 typedef struct Subscription
 {
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index 60a2bcca23..f5324b710d 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -49,7 +49,7 @@ CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
 
 typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, on pg_subscription_rel using btree(srrelid oid_ops, srsubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index ea1593d874..ea8665e83a 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -49,7 +49,7 @@ typedef FormData_pg_tablespace *Form_pg_tablespace;
 
 DECLARE_TOAST_WITH_MACRO(pg_tablespace, 4185, 4186, PgTablespaceToastTable, PgTablespaceToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, on pg_tablespace using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, on pg_tablespace using btree(spcname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, pg_tablespace, btree(spcname name_ops));
 
 #endif							/* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index 6273b0a491..8eb189784d 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -42,7 +42,7 @@ CATALOG(pg_transform,3576,TransformRelationId)
  */
 typedef FormData_pg_transform *Form_pg_transform;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, on pg_transform using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, on pg_transform using btree(trftype oid_ops, trflang oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops));
 
 #endif							/* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
index 3679b0395f..61c9353fff 100644
--- a/src/include/catalog/pg_trigger.h
+++ b/src/include/catalog/pg_trigger.h
@@ -81,9 +81,9 @@ typedef FormData_pg_trigger *Form_pg_trigger;
 
 DECLARE_TOAST(pg_trigger, 2336, 2337);
 
-DECLARE_INDEX(pg_trigger_tgconstraint_index, 2699, TriggerConstraintIndexId, on pg_trigger using btree(tgconstraint oid_ops));
-DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, TriggerRelidNameIndexId, on pg_trigger using btree(tgrelid oid_ops, tgname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_trigger_oid_index, 2702, TriggerOidIndexId, on pg_trigger using btree(oid oid_ops));
+DECLARE_INDEX(pg_trigger_tgconstraint_index, 2699, TriggerConstraintIndexId, pg_trigger, btree(tgconstraint oid_ops));
+DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, TriggerRelidNameIndexId, pg_trigger, btree(tgrelid oid_ops, tgname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_trigger_oid_index, 2702, TriggerOidIndexId, pg_trigger, btree(oid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((tgrelid, tgattr), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index aee0bf71af..e52720387d 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -47,7 +47,7 @@ CATALOG(pg_ts_config,3602,TSConfigRelationId)
 
 typedef FormData_pg_ts_config *Form_pg_ts_config;
 
-DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, on pg_ts_config using btree(cfgname name_ops, cfgnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, on pg_ts_config using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops));
 
 #endif							/* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index 359368ecd6..91f092ca48 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -44,6 +44,6 @@ CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
 
 typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, on pg_ts_config_map using btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
 
 #endif							/* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 476325f010..10a6490213 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -53,7 +53,7 @@ typedef FormData_pg_ts_dict *Form_pg_ts_dict;
 
 DECLARE_TOAST(pg_ts_dict, 4169, 4170);
 
-DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, on pg_ts_dict using btree(dictname name_ops, dictnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, on pg_ts_dict using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops));
 
 #endif							/* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index 283de252b4..57d9e8428a 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -54,7 +54,7 @@ CATALOG(pg_ts_parser,3601,TSParserRelationId)
 
 typedef FormData_pg_ts_parser *Form_pg_ts_parser;
 
-DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, on pg_ts_parser using btree(prsname name_ops, prsnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, on pg_ts_parser using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops));
 
 #endif							/* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index f4e510c8f9..f3bdc7b200 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -45,7 +45,7 @@ CATALOG(pg_ts_template,3764,TSTemplateRelationId)
 
 typedef FormData_pg_ts_template *Form_pg_ts_template;
 
-DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, on pg_ts_template using btree(tmplname name_ops, tmplnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, on pg_ts_template using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops));
 
 #endif							/* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 519e570c8c..508ba7b0f7 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -262,8 +262,8 @@ typedef FormData_pg_type *Form_pg_type;
 
 DECLARE_TOAST(pg_type, 4171, 4172);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, on pg_type using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, on pg_type using btree(typname name_ops, typnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index 528c94a7c4..eca33f4cb4 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -49,7 +49,7 @@ typedef FormData_pg_user_mapping *Form_pg_user_mapping;
 
 DECLARE_TOAST(pg_user_mapping, 4173, 4174);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, on pg_user_mapping using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, on pg_user_mapping using btree(umuser oid_ops, umserver oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops));
 
 #endif							/* PG_USER_MAPPING_H */
-- 
2.40.1

0003-genbki.pl-Factor-out-boilerplate-generation.patchtext/plain; charset=UTF-8; name=0003-genbki.pl-Factor-out-boilerplate-generation.patchDownload
From 2fffa7e60cd46c820b2b8be90eeb1d3dc54eddc1 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 29 May 2023 20:11:18 +0200
Subject: [PATCH 3/5] genbki.pl: Factor out boilerplate generation

---
 src/backend/catalog/genbki.pl | 84 ++++++++++++-----------------------
 1 file changed, 29 insertions(+), 55 deletions(-)

diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index c7657cc47c..851bae14f0 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -439,25 +439,8 @@
 	open my $def, '>', $def_file . $tmpext
 	  or die "can't open $def_file$tmpext: $!";
 
-	# Opening boilerplate for pg_*_d.h
-	printf $def <<EOM, $catname, $catname, uc $catname, uc $catname;
-/*-------------------------------------------------------------------------
- *
- * %s_d.h
- *    Macro definitions for %s
- *
- * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * NOTES
- *  ******************************
- *  *** DO NOT EDIT THIS FILE! ***
- *  ******************************
- *
- *  It has been GENERATED by src/backend/catalog/genbki.pl
- *
- *-------------------------------------------------------------------------
- */
+	print_boilerplate($def, "${catname}_d.h", "Macro definitions for $catname");
+	printf $def <<EOM, uc $catname, uc $catname;
 #ifndef %s_D_H
 #define %s_D_H
 
@@ -705,25 +688,8 @@
 
 # Now generate schemapg.h
 
-# Opening boilerplate for schemapg.h
+print_boilerplate($schemapg, "schemapg.h", "Schema_pg_xxx macros for use by relcache.c");
 print $schemapg <<EOM;
-/*-------------------------------------------------------------------------
- *
- * schemapg.h
- *    Schema_pg_xxx macros for use by relcache.c
- *
- * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * NOTES
- *  ******************************
- *  *** DO NOT EDIT THIS FILE! ***
- *  ******************************
- *
- *  It has been GENERATED by src/backend/catalog/genbki.pl
- *
- *-------------------------------------------------------------------------
- */
 #ifndef SCHEMAPG_H
 #define SCHEMAPG_H
 EOM
@@ -741,25 +707,9 @@
 
 # Now generate system_fk_info.h
 
-# Opening boilerplate for system_fk_info.h
+print_boilerplate($fk_info, "system_fk_info.h",
+	"Data about the foreign-key relationships in the system catalogs");
 print $fk_info <<EOM;
-/*-------------------------------------------------------------------------
- *
- * system_fk_info.h
- *    Data about the foreign-key relationships in the system catalogs
- *
- * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * NOTES
- *  ******************************
- *  *** DO NOT EDIT THIS FILE! ***
- *  ******************************
- *
- *  It has been GENERATED by src/backend/catalog/genbki.pl
- *
- *-------------------------------------------------------------------------
- */
 #ifndef SYSTEM_FK_INFO_H
 #define SYSTEM_FK_INFO_H
 
@@ -1121,6 +1071,30 @@ sub assign_next_oid
 	return $result;
 }
 
+sub print_boilerplate
+{
+	my ($fh, $fname, $descr) = @_;
+	printf $fh <<EOM, $fname, $descr;
+/*-------------------------------------------------------------------------
+ *
+ * %s
+ *    %s
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ *  ******************************
+ *  *** DO NOT EDIT THIS FILE! ***
+ *  ******************************
+ *
+ *  It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+EOM
+}
+
 sub usage
 {
 	die <<EOM;
-- 
2.40.1

0004-Generate-syscache-info-from-catalog-files.patchtext/plain; charset=UTF-8; name=0004-Generate-syscache-info-from-catalog-files.patchDownload
From d75a13dd8c32951f537966cf8efa93dcdc0a8bda Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 29 May 2023 20:19:57 +0200
Subject: [PATCH 4/5] Generate syscache info from catalog files

DECLARE_UNIQUE_INDEX gets two additional arguments with the syscache
ID macro and the number of buckets.  From that, we can generate the
existing tables in syscache.h and syscache.c via genbki.pl.
---
 src/backend/catalog/.gitignore                |   2 +
 src/backend/catalog/Catalog.pm                |   6 +-
 src/backend/catalog/Makefile                  |   2 +-
 src/backend/catalog/genbki.pl                 |  55 ++
 src/backend/utils/cache/syscache.c            | 572 +-----------------
 src/include/catalog/.gitignore                |   2 +
 src/include/catalog/genbki.h                  |   7 +-
 src/include/catalog/meson.build               |  18 +-
 src/include/catalog/pg_aggregate.h            |   2 +-
 src/include/catalog/pg_am.h                   |   4 +-
 src/include/catalog/pg_amop.h                 |   4 +-
 src/include/catalog/pg_amproc.h               |   2 +-
 src/include/catalog/pg_attribute.h            |   4 +-
 src/include/catalog/pg_auth_members.h         |   4 +-
 src/include/catalog/pg_authid.h               |   4 +-
 src/include/catalog/pg_cast.h                 |   2 +-
 src/include/catalog/pg_class.h                |   4 +-
 src/include/catalog/pg_collation.h            |   4 +-
 src/include/catalog/pg_constraint.h           |   2 +-
 src/include/catalog/pg_conversion.h           |   6 +-
 src/include/catalog/pg_database.h             |   2 +-
 src/include/catalog/pg_default_acl.h          |   2 +-
 src/include/catalog/pg_enum.h                 |   4 +-
 src/include/catalog/pg_event_trigger.h        |   4 +-
 src/include/catalog/pg_foreign_data_wrapper.h |   4 +-
 src/include/catalog/pg_foreign_server.h       |   4 +-
 src/include/catalog/pg_foreign_table.h        |   2 +-
 src/include/catalog/pg_index.h                |   2 +-
 src/include/catalog/pg_language.h             |   4 +-
 src/include/catalog/pg_namespace.h            |   4 +-
 src/include/catalog/pg_opclass.h              |   4 +-
 src/include/catalog/pg_operator.h             |   4 +-
 src/include/catalog/pg_opfamily.h             |   4 +-
 src/include/catalog/pg_parameter_acl.h        |   4 +-
 src/include/catalog/pg_partitioned_table.h    |   2 +-
 src/include/catalog/pg_proc.h                 |   4 +-
 src/include/catalog/pg_publication.h          |   4 +-
 .../catalog/pg_publication_namespace.h        |   4 +-
 src/include/catalog/pg_publication_rel.h      |   4 +-
 src/include/catalog/pg_range.h                |   4 +-
 src/include/catalog/pg_replication_origin.h   |   4 +-
 src/include/catalog/pg_rewrite.h              |   2 +-
 src/include/catalog/pg_sequence.h             |   2 +-
 src/include/catalog/pg_statistic.h            |   2 +-
 src/include/catalog/pg_statistic_ext.h        |   4 +-
 src/include/catalog/pg_statistic_ext_data.h   |   2 +-
 src/include/catalog/pg_subscription.h         |   4 +-
 src/include/catalog/pg_subscription_rel.h     |   2 +-
 src/include/catalog/pg_tablespace.h           |   2 +-
 src/include/catalog/pg_transform.h            |   4 +-
 src/include/catalog/pg_ts_config.h            |   4 +-
 src/include/catalog/pg_ts_config_map.h        |   2 +-
 src/include/catalog/pg_ts_dict.h              |   4 +-
 src/include/catalog/pg_ts_parser.h            |   4 +-
 src/include/catalog/pg_ts_template.h          |   4 +-
 src/include/catalog/pg_type.h                 |   4 +-
 src/include/catalog/pg_user_mapping.h         |   4 +-
 src/include/utils/syscache.h                  |  98 +--
 src/tools/pginclude/cpluspluscheck            |   5 +
 src/tools/pginclude/headerscheck              |   5 +
 60 files changed, 186 insertions(+), 752 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index 237ff54165..ff65560379 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,5 +1,7 @@
 /postgres.bki
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /system_constraints.sql
 /pg_*_d.h
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index a727d692b7..89c2a0a7b8 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -110,7 +110,7 @@ sub ParseHeader
 			  };
 		}
 		elsif (
-			/^DECLARE_(UNIQUE_)?INDEX(_PKEY)?\(\s*(\w+),\s*(\d+),\s*(\w+),\s*(\w+),\s*(.+)\)/
+			/^DECLARE_(UNIQUE_)?INDEX(_PKEY)?\(\s*(\w+),\s*(\d+),\s*(\w+),\s*(\w+),\s*(\w+\s*\([\w\s,]+\))(?:,\s*(\w+),\s*(\w+))?\)/
 		  )
 		{
 			push @{ $catalog{indexing} },
@@ -121,7 +121,9 @@ sub ParseHeader
 				index_oid => $4,
 				index_oid_macro => $5,
 				table_name => $6,
-				index_decl => $7
+				index_decl => $7,
+				syscache_name => $8,
+				syscache_nbuckets => $9,
 			  };
 		}
 		elsif (/^DECLARE_OID_DEFINING_MACRO\(\s*(\w+),\s*(\d+)\)/)
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index a60107bf94..0dfefae28e 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -74,7 +74,7 @@ CATALOG_HEADERS := \
 	pg_sequence.h pg_publication.h pg_publication_namespace.h \
 	pg_publication_rel.h pg_subscription.h pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 851bae14f0..80a7828d6c 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -56,6 +56,7 @@
 my %catalog_data;
 my @toast_decls;
 my @index_decls;
+my %syscaches;
 my %oidcounts;
 my @system_constraints;
 
@@ -150,6 +151,21 @@
 			  $index->{is_pkey} ? "PRIMARY KEY" : "UNIQUE",
 			  $index->{index_name};
 		}
+
+		if ($index->{syscache_name})
+		{
+			my $tbl = $index->{table_name};
+			my $key = $index->{index_decl};
+			$key =~ s/^\w+\(//;
+			$key =~ s/\)$//;
+			$key =~ s/(\w+)\s+\w+/Anum_${tbl}_$1/g;
+			$syscaches{$index->{syscache_name}} = {
+				table_oid_macro => $catalogs{$tbl}->{relation_oid_macro},
+				index_oid_macro => $index->{index_oid_macro},
+				key => $key,
+				nbuckets => $index->{syscache_nbuckets},
+			};
+		}
 	}
 }
 
@@ -419,6 +435,12 @@
 my $constraints_file = $output_path . 'system_constraints.sql';
 open my $constraints, '>', $constraints_file . $tmpext
   or die "can't open $constraints_file$tmpext: $!";
+my $syscache_info_h = $output_path . 'syscache_info.h';
+open my $syscache_info_h_fh, '>', $syscache_info_h . $tmpext
+  or die "can't open $syscache_info_h$tmpext: $!";
+my $syscache_info_c = $output_path . 'syscache_info.c.h';
+open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
+  or die "can't open $syscache_info_c$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -751,17 +773,50 @@
 # Closing boilerplate for system_fk_info.h
 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_info_h_fh, "syscache_info.h", "SysCache identifiers");
+print $syscache_info_h_fh "enum SysCacheIdentifier
+{
+";
+
+print_boilerplate($syscache_info_c_fh, "syscache_info.c.h", "SysCache definitions");
+print $syscache_info_c_fh "static const struct cachedesc cacheinfo[] = {\n";
+
+my $last_syscache;
+foreach my $syscache (sort keys %syscaches)
+{
+	print $syscache_info_h_fh "\t$syscache,\n";
+	$last_syscache = $syscache;
+
+	print $syscache_info_c_fh "\t[$syscache] = {\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{table_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{index_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\tKEY(", $syscaches{$syscache}{key}, "),\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{nbuckets}, "\n";
+	print $syscache_info_c_fh "\t},\n";
+}
+
+print $syscache_info_h_fh "};\n";
+print $syscache_info_h_fh "#define SysCacheSize ($last_syscache + 1)\n";
+
+print $syscache_info_c_fh "};\n";
+
 # We're done emitting data
 close $bki;
 close $schemapg;
 close $fk_info;
 close $constraints;
+close $syscache_info_h_fh;
+close $syscache_info_c_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
 Catalog::RenameTempFile($schemafile, $tmpext);
 Catalog::RenameTempFile($fk_info_file, $tmpext);
 Catalog::RenameTempFile($constraints_file, $tmpext);
+Catalog::RenameTempFile($syscache_info_h, $tmpext);
+Catalog::RenameTempFile($syscache_info_c, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 4e4a34bde8..6daa81ca83 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -85,18 +85,6 @@
 
 	Adding system caches:
 
-	Add your new cache to the list in include/utils/syscache.h.
-	Keep the list sorted alphabetically.
-
-	Add your entry to the cacheinfo[] array below. All cache lists are
-	alphabetical, so add it in the proper place.  Specify the relation OID,
-	index OID, number of keys, key attribute numbers, and initial number of
-	hash buckets.
-
-	The number of hash buckets must be a power of 2.  It's reasonable to
-	set this to the number of entries that might be in the particular cache
-	in a medium-size database.
-
 	There must be a unique index underlying each syscache (ie, an index
 	whose key is the same as that of the cache).  If there is not one
 	already, add the definition for it to include/catalog/pg_*.h using
@@ -104,6 +92,13 @@
 	(Adding an index requires a catversion.h update, while simply
 	adding/deleting caches only requires a recompile.)
 
+	Then add the name of your name cache and the initial number of hash
+	buckets as arguments of DECLARE_UNIQUE_INDEX.
+
+	The number of hash buckets must be a power of 2.  It's reasonable to
+	set this to the number of entries that might be in the particular cache
+	in a medium-size database.
+
 	Finally, any place your relation gets heap_insert() or
 	heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
 	instead, which also update indexes.  The heap_* calls do not do that.
@@ -126,558 +121,7 @@ struct cachedesc
 /* Macro to provide nkeys and key array with convenient syntax. */
 #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
 
-static const struct cachedesc cacheinfo[] = {
-	[AGGFNOID] = {
-		AggregateRelationId,
-		AggregateFnoidIndexId,
-		KEY(Anum_pg_aggregate_aggfnoid),
-		16
-	},
-	[AMNAME] = {
-		AccessMethodRelationId,
-		AmNameIndexId,
-		KEY(Anum_pg_am_amname),
-		4
-	},
-	[AMOID] = {
-		AccessMethodRelationId,
-		AmOidIndexId,
-		KEY(Anum_pg_am_oid),
-		4
-	},
-	[AMOPOPID] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodOperatorIndexId,
-		KEY(Anum_pg_amop_amopopr,
-			Anum_pg_amop_amoppurpose,
-			Anum_pg_amop_amopfamily),
-		64
-	},
-	[AMOPSTRATEGY] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodStrategyIndexId,
-		KEY(Anum_pg_amop_amopfamily,
-			Anum_pg_amop_amoplefttype,
-			Anum_pg_amop_amoprighttype,
-			Anum_pg_amop_amopstrategy),
-		64
-	},
-	[AMPROCNUM] = {
-		AccessMethodProcedureRelationId,
-		AccessMethodProcedureIndexId,
-		KEY(Anum_pg_amproc_amprocfamily,
-			Anum_pg_amproc_amproclefttype,
-			Anum_pg_amproc_amprocrighttype,
-			Anum_pg_amproc_amprocnum),
-		16
-	},
-	[ATTNAME] = {
-		AttributeRelationId,
-		AttributeRelidNameIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attname),
-		32
-	},
-	[ATTNUM] = {
-		AttributeRelationId,
-		AttributeRelidNumIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attnum),
-		128
-	},
-	[AUTHMEMMEMROLE] = {
-		AuthMemRelationId,
-		AuthMemMemRoleIndexId,
-		KEY(Anum_pg_auth_members_member,
-			Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHMEMROLEMEM] = {
-		AuthMemRelationId,
-		AuthMemRoleMemIndexId,
-		KEY(Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_member,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHNAME] = {
-		AuthIdRelationId,
-		AuthIdRolnameIndexId,
-		KEY(Anum_pg_authid_rolname),
-		8
-	},
-	[AUTHOID] = {
-		AuthIdRelationId,
-		AuthIdOidIndexId,
-		KEY(Anum_pg_authid_oid),
-		8
-	},
-	[CASTSOURCETARGET] = {
-		CastRelationId,
-		CastSourceTargetIndexId,
-		KEY(Anum_pg_cast_castsource,
-			Anum_pg_cast_casttarget),
-		256
-	},
-	[CLAAMNAMENSP] = {
-		OperatorClassRelationId,
-		OpclassAmNameNspIndexId,
-		KEY(Anum_pg_opclass_opcmethod,
-			Anum_pg_opclass_opcname,
-			Anum_pg_opclass_opcnamespace),
-		8
-	},
-	[CLAOID] = {
-		OperatorClassRelationId,
-		OpclassOidIndexId,
-		KEY(Anum_pg_opclass_oid),
-		8
-	},
-	[COLLNAMEENCNSP] = {
-		CollationRelationId,
-		CollationNameEncNspIndexId,
-		KEY(Anum_pg_collation_collname,
-			Anum_pg_collation_collencoding,
-			Anum_pg_collation_collnamespace),
-		8
-	},
-	[COLLOID] = {
-		CollationRelationId,
-		CollationOidIndexId,
-		KEY(Anum_pg_collation_oid),
-		8
-	},
-	[CONDEFAULT] = {
-		ConversionRelationId,
-		ConversionDefaultIndexId,
-		KEY(Anum_pg_conversion_connamespace,
-			Anum_pg_conversion_conforencoding,
-			Anum_pg_conversion_contoencoding,
-			Anum_pg_conversion_oid),
-		8
-	},
-	[CONNAMENSP] = {
-		ConversionRelationId,
-		ConversionNameNspIndexId,
-		KEY(Anum_pg_conversion_conname,
-			Anum_pg_conversion_connamespace),
-		8
-	},
-	[CONSTROID] = {
-		ConstraintRelationId,
-		ConstraintOidIndexId,
-		KEY(Anum_pg_constraint_oid),
-		16
-	},
-	[CONVOID] = {
-		ConversionRelationId,
-		ConversionOidIndexId,
-		KEY(Anum_pg_conversion_oid),
-		8
-	},
-	[DATABASEOID] = {
-		DatabaseRelationId,
-		DatabaseOidIndexId,
-		KEY(Anum_pg_database_oid),
-		4
-	},
-	[DEFACLROLENSPOBJ] = {
-		DefaultAclRelationId,
-		DefaultAclRoleNspObjIndexId,
-		KEY(Anum_pg_default_acl_defaclrole,
-			Anum_pg_default_acl_defaclnamespace,
-			Anum_pg_default_acl_defaclobjtype),
-		8
-	},
-	[ENUMOID] = {
-		EnumRelationId,
-		EnumOidIndexId,
-		KEY(Anum_pg_enum_oid),
-		8
-	},
-	[ENUMTYPOIDNAME] = {
-		EnumRelationId,
-		EnumTypIdLabelIndexId,
-		KEY(Anum_pg_enum_enumtypid,
-			Anum_pg_enum_enumlabel),
-		8
-	},
-	[EVENTTRIGGERNAME] = {
-		EventTriggerRelationId,
-		EventTriggerNameIndexId,
-		KEY(Anum_pg_event_trigger_evtname),
-		8
-	},
-	[EVENTTRIGGEROID] = {
-		EventTriggerRelationId,
-		EventTriggerOidIndexId,
-		KEY(Anum_pg_event_trigger_oid),
-		8
-	},
-	[FOREIGNDATAWRAPPERNAME] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperNameIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_fdwname),
-		2
-	},
-	[FOREIGNDATAWRAPPEROID] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperOidIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_oid),
-		2
-	},
-	[FOREIGNSERVERNAME] = {
-		ForeignServerRelationId,
-		ForeignServerNameIndexId,
-		KEY(Anum_pg_foreign_server_srvname),
-		2
-	},
-	[FOREIGNSERVEROID] = {
-		ForeignServerRelationId,
-		ForeignServerOidIndexId,
-		KEY(Anum_pg_foreign_server_oid),
-		2
-	},
-	[FOREIGNTABLEREL] = {
-		ForeignTableRelationId,
-		ForeignTableRelidIndexId,
-		KEY(Anum_pg_foreign_table_ftrelid),
-		4
-	},
-	[INDEXRELID] = {
-		IndexRelationId,
-		IndexRelidIndexId,
-		KEY(Anum_pg_index_indexrelid),
-		64
-	},
-	[LANGNAME] = {
-		LanguageRelationId,
-		LanguageNameIndexId,
-		KEY(Anum_pg_language_lanname),
-		4
-	},
-	[LANGOID] = {
-		LanguageRelationId,
-		LanguageOidIndexId,
-		KEY(Anum_pg_language_oid),
-		4
-	},
-	[NAMESPACENAME] = {
-		NamespaceRelationId,
-		NamespaceNameIndexId,
-		KEY(Anum_pg_namespace_nspname),
-		4
-	},
-	[NAMESPACEOID] = {
-		NamespaceRelationId,
-		NamespaceOidIndexId,
-		KEY(Anum_pg_namespace_oid),
-		16
-	},
-	[OPERNAMENSP] = {
-		OperatorRelationId,
-		OperatorNameNspIndexId,
-		KEY(Anum_pg_operator_oprname,
-			Anum_pg_operator_oprleft,
-			Anum_pg_operator_oprright,
-			Anum_pg_operator_oprnamespace),
-		256
-	},
-	[OPEROID] = {
-		OperatorRelationId,
-		OperatorOidIndexId,
-		KEY(Anum_pg_operator_oid),
-		32
-	},
-	[OPFAMILYAMNAMENSP] = {
-		OperatorFamilyRelationId,
-		OpfamilyAmNameNspIndexId,
-		KEY(Anum_pg_opfamily_opfmethod,
-			Anum_pg_opfamily_opfname,
-			Anum_pg_opfamily_opfnamespace),
-		8
-	},
-	[OPFAMILYOID] = {
-		OperatorFamilyRelationId,
-		OpfamilyOidIndexId,
-		KEY(Anum_pg_opfamily_oid),
-		8
-	},
-	[PARAMETERACLNAME] = {
-		ParameterAclRelationId,
-		ParameterAclParnameIndexId,
-		KEY(Anum_pg_parameter_acl_parname),
-		4
-	},
-	[PARAMETERACLOID] = {
-		ParameterAclRelationId,
-		ParameterAclOidIndexId,
-		KEY(Anum_pg_parameter_acl_oid),
-		4
-	},
-	[PARTRELID] = {
-		PartitionedRelationId,
-		PartitionedRelidIndexId,
-		KEY(Anum_pg_partitioned_table_partrelid),
-		32
-	},
-	[PROCNAMEARGSNSP] = {
-		ProcedureRelationId,
-		ProcedureNameArgsNspIndexId,
-		KEY(Anum_pg_proc_proname,
-			Anum_pg_proc_proargtypes,
-			Anum_pg_proc_pronamespace),
-		128
-	},
-	[PROCOID] = {
-		ProcedureRelationId,
-		ProcedureOidIndexId,
-		KEY(Anum_pg_proc_oid),
-		128
-	},
-	[PUBLICATIONNAME] = {
-		PublicationRelationId,
-		PublicationNameIndexId,
-		KEY(Anum_pg_publication_pubname),
-		8
-	},
-	[PUBLICATIONNAMESPACE] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespaceObjectIndexId,
-		KEY(Anum_pg_publication_namespace_oid),
-		64
-	},
-	[PUBLICATIONNAMESPACEMAP] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespacePnnspidPnpubidIndexId,
-		KEY(Anum_pg_publication_namespace_pnnspid,
-			Anum_pg_publication_namespace_pnpubid),
-		64
-	},
-	[PUBLICATIONOID] = {
-		PublicationRelationId,
-		PublicationObjectIndexId,
-		KEY(Anum_pg_publication_oid),
-		8
-	},
-	[PUBLICATIONREL] = {
-		PublicationRelRelationId,
-		PublicationRelObjectIndexId,
-		KEY(Anum_pg_publication_rel_oid),
-		64
-	},
-	[PUBLICATIONRELMAP] = {
-		PublicationRelRelationId,
-		PublicationRelPrrelidPrpubidIndexId,
-		KEY(Anum_pg_publication_rel_prrelid,
-			Anum_pg_publication_rel_prpubid),
-		64
-	},
-	[RANGEMULTIRANGE] = {
-		RangeRelationId,
-		RangeMultirangeTypidIndexId,
-		KEY(Anum_pg_range_rngmultitypid),
-		4
-	},
-	[RANGETYPE] = {
-		RangeRelationId,
-		RangeTypidIndexId,
-		KEY(Anum_pg_range_rngtypid),
-		4
-	},
-	[RELNAMENSP] = {
-		RelationRelationId,
-		ClassNameNspIndexId,
-		KEY(Anum_pg_class_relname,
-			Anum_pg_class_relnamespace),
-		128
-	},
-	[RELOID] = {
-		RelationRelationId,
-		ClassOidIndexId,
-		KEY(Anum_pg_class_oid),
-		128
-	},
-	[REPLORIGIDENT] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginIdentIndex,
-		KEY(Anum_pg_replication_origin_roident),
-		16
-	},
-	[REPLORIGNAME] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginNameIndex,
-		KEY(Anum_pg_replication_origin_roname),
-		16
-	},
-	[RULERELNAME] = {
-		RewriteRelationId,
-		RewriteRelRulenameIndexId,
-		KEY(Anum_pg_rewrite_ev_class,
-			Anum_pg_rewrite_rulename),
-		8
-	},
-	[SEQRELID] = {
-		SequenceRelationId,
-		SequenceRelidIndexId,
-		KEY(Anum_pg_sequence_seqrelid),
-		32
-	},
-	[STATEXTDATASTXOID] = {
-		StatisticExtDataRelationId,
-		StatisticExtDataStxoidInhIndexId,
-		KEY(Anum_pg_statistic_ext_data_stxoid,
-			Anum_pg_statistic_ext_data_stxdinherit),
-		4
-	},
-	[STATEXTNAMENSP] = {
-		StatisticExtRelationId,
-		StatisticExtNameIndexId,
-		KEY(Anum_pg_statistic_ext_stxname,
-			Anum_pg_statistic_ext_stxnamespace),
-		4
-	},
-	[STATEXTOID] = {
-		StatisticExtRelationId,
-		StatisticExtOidIndexId,
-		KEY(Anum_pg_statistic_ext_oid),
-		4
-	},
-	[STATRELATTINH] = {
-		StatisticRelationId,
-		StatisticRelidAttnumInhIndexId,
-		KEY(Anum_pg_statistic_starelid,
-			Anum_pg_statistic_staattnum,
-			Anum_pg_statistic_stainherit),
-		128
-	},
-	[SUBSCRIPTIONNAME] = {
-		SubscriptionRelationId,
-		SubscriptionNameIndexId,
-		KEY(Anum_pg_subscription_subdbid,
-			Anum_pg_subscription_subname),
-		4
-	},
-	[SUBSCRIPTIONOID] = {
-		SubscriptionRelationId,
-		SubscriptionObjectIndexId,
-		KEY(Anum_pg_subscription_oid),
-		4
-	},
-	[SUBSCRIPTIONRELMAP] = {
-		SubscriptionRelRelationId,
-		SubscriptionRelSrrelidSrsubidIndexId,
-		KEY(Anum_pg_subscription_rel_srrelid,
-			Anum_pg_subscription_rel_srsubid),
-		64
-	},
-	[TABLESPACEOID] = {
-		TableSpaceRelationId,
-		TablespaceOidIndexId,
-		KEY(Anum_pg_tablespace_oid),
-		4
-	},
-	[TRFOID] = {
-		TransformRelationId,
-		TransformOidIndexId,
-		KEY(Anum_pg_transform_oid),
-		16
-	},
-	[TRFTYPELANG] = {
-		TransformRelationId,
-		TransformTypeLangIndexId,
-		KEY(Anum_pg_transform_trftype,
-			Anum_pg_transform_trflang),
-		16
-	},
-	[TSCONFIGMAP] = {
-		TSConfigMapRelationId,
-		TSConfigMapIndexId,
-		KEY(Anum_pg_ts_config_map_mapcfg,
-			Anum_pg_ts_config_map_maptokentype,
-			Anum_pg_ts_config_map_mapseqno),
-		2
-	},
-	[TSCONFIGNAMENSP] = {
-		TSConfigRelationId,
-		TSConfigNameNspIndexId,
-		KEY(Anum_pg_ts_config_cfgname,
-			Anum_pg_ts_config_cfgnamespace),
-		2
-	},
-	[TSCONFIGOID] = {
-		TSConfigRelationId,
-		TSConfigOidIndexId,
-		KEY(Anum_pg_ts_config_oid),
-		2
-	},
-	[TSDICTNAMENSP] = {
-		TSDictionaryRelationId,
-		TSDictionaryNameNspIndexId,
-		KEY(Anum_pg_ts_dict_dictname,
-			Anum_pg_ts_dict_dictnamespace),
-		2
-	},
-	[TSDICTOID] = {
-		TSDictionaryRelationId,
-		TSDictionaryOidIndexId,
-		KEY(Anum_pg_ts_dict_oid),
-		2
-	},
-	[TSPARSERNAMENSP] = {
-		TSParserRelationId,
-		TSParserNameNspIndexId,
-		KEY(Anum_pg_ts_parser_prsname,
-			Anum_pg_ts_parser_prsnamespace),
-		2
-	},
-	[TSPARSEROID] = {
-		TSParserRelationId,
-		TSParserOidIndexId,
-		KEY(Anum_pg_ts_parser_oid),
-		2
-	},
-	[TSTEMPLATENAMENSP] = {
-		TSTemplateRelationId,
-		TSTemplateNameNspIndexId,
-		KEY(Anum_pg_ts_template_tmplname,
-			Anum_pg_ts_template_tmplnamespace),
-		2
-	},
-	[TSTEMPLATEOID] = {
-		TSTemplateRelationId,
-		TSTemplateOidIndexId,
-		KEY(Anum_pg_ts_template_oid),
-		2
-	},
-	[TYPENAMENSP] = {
-		TypeRelationId,
-		TypeNameNspIndexId,
-		KEY(Anum_pg_type_typname,
-			Anum_pg_type_typnamespace),
-		64
-	},
-	[TYPEOID] = {
-		TypeRelationId,
-		TypeOidIndexId,
-		KEY(Anum_pg_type_oid),
-		64
-	},
-	[USERMAPPINGOID] = {
-		UserMappingRelationId,
-		UserMappingOidIndexId,
-		KEY(Anum_pg_user_mapping_oid),
-		2
-	},
-	[USERMAPPINGUSERSERVER] = {
-		UserMappingRelationId,
-		UserMappingUserServerIndexId,
-		KEY(Anum_pg_user_mapping_umuser,
-			Anum_pg_user_mapping_umserver),
-		2
-	}
-};
+#include "catalog/syscache_info.c.h"
 
 StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
 				 "SysCacheSize does not match syscache.c's array");
diff --git a/src/include/catalog/.gitignore b/src/include/catalog/.gitignore
index 6b83d4c7e6..f7ddf2554b 100644
--- a/src/include/catalog/.gitignore
+++ b/src/include/catalog/.gitignore
@@ -1,4 +1,6 @@
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /pg_*_d.h
 /header-stamp
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index e22a6902fb..2d5bd38cde 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -77,13 +77,14 @@
  * is the name of a #define to generate for its OID.  References to the index
  * in the C code should always use these #defines, not the actual index name
  * (much less the numeric OID).  The fourth argument is the table name.  The
- * rest is much like a standard 'create index' SQL command.
+ * decl argument is much like a standard 'create index' SQL command.
+ * Optionally, specify the syscache ID and bucket size.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */
 #define DECLARE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
 
 /*
  * These lines inform genbki.pl about manually-assigned OIDs that do not
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index 3179be09d3..1fa22d925d 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -97,8 +97,22 @@ bki_data_f = files(bki_data)
 
 
 input = []
-output_files = ['postgres.bki', 'system_constraints.sql', 'schemapg.h', 'system_fk_info.h']
-output_install = [dir_data, dir_data, dir_include_server / 'catalog', dir_include_server / 'catalog']
+output_files = [
+  'postgres.bki',
+  'system_constraints.sql',
+  'schemapg.h',
+  'syscache_info.c.h',
+  'syscache_info.h',
+  'system_fk_info.h',
+]
+output_install = [
+  dir_data,
+  dir_data,
+  dir_include_server / 'catalog',
+  false,
+  dir_include_server / 'catalog',
+  dir_include_server / 'catalog',
+]
 
 foreach h : catalog_headers
   fname = h.split('.h')[0] + '_d.h'
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 085149e258..e6f6f4ccb5 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -110,7 +110,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
 
 DECLARE_TOAST(pg_aggregate, 4159, 4160);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops), AGGFNOID, 16);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index d5314bb38b..e3a1313e6c 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -47,8 +47,8 @@ CATALOG(pg_am,2601,AccessMethodRelationId)
  */
 typedef FormData_pg_am *Form_pg_am;
 
-DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops), AMNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops), AMOID, 4);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index c9bb7b4787..3449166507 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -87,8 +87,8 @@ CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
  */
 typedef FormData_pg_amop *Form_pg_amop;
 
-DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
-DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops), AMOPSTRATEGY, 64);
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops), AMOPOPID, 64);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, pg_amop, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 5acf4efab9..31e67be344 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -67,7 +67,7 @@ CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
  */
 typedef FormData_pg_amproc *Form_pg_amproc;
 
-DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops), AMPROCNUM, 16);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, pg_amproc, btree(oid oid_ops));
 
 #endif							/* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index f0d6de7c1f..9e99237f56 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -208,8 +208,8 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
  */
 typedef FormData_pg_attribute *Form_pg_attribute;
 
-DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops), ATTNAME, 32);
+DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops), ATTNUM, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index 4ab8a9f7b7..37104cf20f 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -46,8 +46,8 @@ CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_
 typedef FormData_pg_auth_members *Form_pg_auth_members;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, pg_auth_members, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops), AUTHMEMROLEMEM, 8);
+DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops), AUTHMEMMEMROLE, 8);
 DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, pg_auth_members, btree(grantor oid_ops));
 
 #endif							/* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index 0e7ddc56ea..748ab95fad 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -57,7 +57,7 @@ typedef FormData_pg_authid *Form_pg_authid;
 
 DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops), AUTHNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops), AUTHOID, 8);
 
 #endif							/* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index a2518388b3..32235776ce 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -57,7 +57,7 @@ CATALOG(pg_cast,2605,CastRelationId)
 typedef FormData_pg_cast *Form_pg_cast;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, pg_cast, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops), CASTSOURCETARGET, 256);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 55dcd54100..52edbf0229 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -152,8 +152,8 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat
  */
 typedef FormData_pg_class *Form_pg_class;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops), RELOID, 128);
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops), RELNAMENSP, 128);
 DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, pg_class, btree(reltablespace oid_ops, relfilenode oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index 2d7dcde183..6cf59f479a 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -59,8 +59,8 @@ typedef FormData_pg_collation *Form_pg_collation;
 
 DECLARE_TOAST(pg_collation, 6175, 6176);
 
-DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops), COLLNAMEENCNSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops), COLLOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 0d47c9b589..de1b7bcd57 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -169,7 +169,7 @@ DECLARE_TOAST(pg_constraint, 2832, 2833);
 DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, pg_constraint, btree(conname name_ops, connamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
 DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops), CONSTROID, 16);
 DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops));
 
 /* conkey can contain zero (InvalidAttrNumber) if a whole-row Var is used */
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index 42847fdf12..acd944a4ae 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -60,9 +60,9 @@ CATALOG(pg_conversion,2607,ConversionRelationId)
  */
 typedef FormData_pg_conversion *Form_pg_conversion;
 
-DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops), CONDEFAULT, 8);
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops), CONNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops), CONVOID, 8);
 
 
 extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 44e2ed73cf..1eceb52174 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -92,7 +92,7 @@ typedef FormData_pg_database *Form_pg_database;
 DECLARE_TOAST_WITH_MACRO(pg_database, 4177, 4178, PgDatabaseToastTable, PgDatabaseToastIndex);
 
 DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, pg_database, btree(datname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops), DATABASEOID, 4);
 
 /*
  * pg_database.dat contains an entry for template1, but not for the template0
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index 803ce3eab8..b526af26a6 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -51,7 +51,7 @@ typedef FormData_pg_default_acl *Form_pg_default_acl;
 
 DECLARE_TOAST(pg_default_acl, 4143, 4144);
 
-DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
+DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops), DEFACLROLENSPOBJ, 8);
 DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, pg_default_acl, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index c483cb1042..4ea20aeabe 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -43,8 +43,8 @@ CATALOG(pg_enum,3501,EnumRelationId)
  */
 typedef FormData_pg_enum *Form_pg_enum;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops), ENUMOID, 8);
+DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops), ENUMTYPOIDNAME, 8);
 DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, pg_enum, btree(enumtypid oid_ops, enumsortorder float4_ops));
 
 /*
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index 0ec42edff6..ca1c5bd728 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -51,7 +51,7 @@ typedef FormData_pg_event_trigger *Form_pg_event_trigger;
 
 DECLARE_TOAST(pg_event_trigger, 4145, 4146);
 
-DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops), EVENTTRIGGERNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops), EVENTTRIGGEROID, 8);
 
 #endif							/* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 37387f9355..8674eb261a 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -52,7 +52,7 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
 
 DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops), FOREIGNDATAWRAPPEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops), FOREIGNDATAWRAPPERNAME, 2);
 
 #endif							/* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 5993967c6e..fb77abe36f 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -49,7 +49,7 @@ typedef FormData_pg_foreign_server *Form_pg_foreign_server;
 
 DECLARE_TOAST(pg_foreign_server, 4151, 4152);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops), FOREIGNSERVEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops), FOREIGNSERVERNAME, 2);
 
 #endif							/* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 2420e23401..8a10130cc0 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -44,6 +44,6 @@ typedef FormData_pg_foreign_table *Form_pg_foreign_table;
 
 DECLARE_TOAST(pg_foreign_table, 4153, 4154);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops), FOREIGNTABLEREL, 4);
 
 #endif							/* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 32930411b6..9352d8a9ed 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -70,7 +70,7 @@ CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
 typedef FormData_pg_index *Form_pg_index;
 
 DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops), INDEXRELID, 64);
 
 /* indkey can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((indrelid, indkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index d666ea2044..070094edb8 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -66,7 +66,7 @@ typedef FormData_pg_language *Form_pg_language;
 
 DECLARE_TOAST(pg_language, 4157, 4158);
 
-DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops), LANGNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops), LANGOID, 4);
 
 #endif							/* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index fc74a14c37..b70073d456 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -53,8 +53,8 @@ typedef FormData_pg_namespace *Form_pg_namespace;
 
 DECLARE_TOAST(pg_namespace, 4163, 4164);
 
-DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops), NAMESPACENAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops), NAMESPACEOID, 16);
 
 /*
  * prototypes for functions in pg_namespace.c
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index a5d09faf1f..18ecd56ada 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -82,7 +82,7 @@ CATALOG(pg_opclass,2616,OperatorClassRelationId)
  */
 typedef FormData_pg_opclass *Form_pg_opclass;
 
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops), CLAAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops), CLAOID, 8);
 
 #endif							/* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index aff372b4bb..3daa79cfae 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -82,8 +82,8 @@ CATALOG(pg_operator,2617,OperatorRelationId)
  */
 typedef FormData_pg_operator *Form_pg_operator;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops), OPEROID, 32);
+DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops), OPERNAMENSP, 256);
 
 
 extern ObjectAddress OperatorCreate(const char *operatorName,
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 88940de916..fe2b5c60c4 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -50,8 +50,8 @@ CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
  */
 typedef FormData_pg_opfamily *Form_pg_opfamily;
 
-DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops), OPFAMILYAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops), OPFAMILYOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h
index f46cdd1524..aef18ff4a7 100644
--- a/src/include/catalog/pg_parameter_acl.h
+++ b/src/include/catalog/pg_parameter_acl.h
@@ -50,8 +50,8 @@ typedef FormData_pg_parameter_acl * Form_pg_parameter_acl;
 
 DECLARE_TOAST_WITH_MACRO(pg_parameter_acl, 6244, 6245, PgParameterAclToastTable, PgParameterAclToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops), PARAMETERACLNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops), PARAMETERACLOID, 4);
 
 
 extern Oid	ParameterAclLookup(const char *parameter, bool missing_ok);
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index 0cf512e1c8..a137f031f7 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -66,7 +66,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
 
 DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops), PARTRELID, 32);
 
 /* partattrs can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((partrelid, partattrs), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index fdb39d4001..29ef344cc2 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -137,8 +137,8 @@ typedef FormData_pg_proc *Form_pg_proc;
 
 DECLARE_TOAST(pg_proc, 2836, 2837);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops), PROCOID, 128);
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops), PROCNAMEARGSNSP, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index d929c9a188..c17be5ed88 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -63,8 +63,8 @@ CATALOG(pg_publication,6104,PublicationRelationId)
  */
 typedef FormData_pg_publication *Form_pg_publication;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops), PUBLICATIONOID, 8);
+DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops), PUBLICATIONNAME, 8);
 
 typedef struct PublicationActions
 {
diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h
index b361c8ab5e..b6326c7730 100644
--- a/src/include/catalog/pg_publication_namespace.h
+++ b/src/include/catalog/pg_publication_namespace.h
@@ -41,7 +41,7 @@ CATALOG(pg_publication_namespace,6237,PublicationNamespaceRelationId)
  */
 typedef FormData_pg_publication_namespace *Form_pg_publication_namespace;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops), PUBLICATIONNAMESPACE, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops), PUBLICATIONNAMESPACEMAP, 64);
 
 #endif							/* PG_PUBLICATION_NAMESPACE_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index bef508764a..19cad0a344 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -47,8 +47,8 @@ typedef FormData_pg_publication_rel *Form_pg_publication_rel;
 
 DECLARE_TOAST(pg_publication_rel, 6228, 6229);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops), PUBLICATIONREL, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops), PUBLICATIONRELMAP, 64);
 DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, pg_publication_rel, btree(prpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index 1247fa7c77..ce662c6a03 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -57,8 +57,8 @@ CATALOG(pg_range,3541,RangeRelationId)
  */
 typedef FormData_pg_range *Form_pg_range;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops), RANGETYPE, 4);
+DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops), RANGEMULTIRANGE, 4);
 
 /*
  * prototypes for functions in pg_range.c
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index 83ff36dcba..49824dbc07 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -56,7 +56,7 @@ typedef FormData_pg_replication_origin *Form_pg_replication_origin;
 
 DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops));
-DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops), REPLORIGIDENT, 16);
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops), REPLORIGNAME, 16);
 
 #endif							/* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 60d642b595..8148e3568b 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -54,6 +54,6 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
 DECLARE_TOAST(pg_rewrite, 2838, 2839);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, pg_rewrite, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops));
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops), RULERELNAME, 8);
 
 #endif							/* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index fdfc27bbd9..efd441c339 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -39,6 +39,6 @@ CATALOG(pg_sequence,2224,SequenceRelationId)
  */
 typedef FormData_pg_sequence *Form_pg_sequence;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops), SEQRELID, 32);
 
 #endif							/* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 864cb54a51..53bb3d1936 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -136,7 +136,7 @@ typedef FormData_pg_statistic *Form_pg_statistic;
 
 DECLARE_TOAST(pg_statistic, 2840, 2841);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops), STATRELATTINH, 128);
 
 DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index 85e56feb80..cb16044e08 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -70,8 +70,8 @@ typedef FormData_pg_statistic_ext *Form_pg_statistic_ext;
 
 DECLARE_TOAST(pg_statistic_ext, 3439, 3440);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops), STATEXTOID, 4);
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops), STATEXTNAMENSP, 4);
 DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, pg_statistic_ext, btree(stxrelid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((stxrelid, stxkeys), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
index 19a00705e6..0f09883e12 100644
--- a/src/include/catalog/pg_statistic_ext_data.h
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -54,7 +54,7 @@ typedef FormData_pg_statistic_ext_data *Form_pg_statistic_ext_data;
 
 DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops), STATEXTDATASTXOID, 4);
 
 
 #endif							/* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index be36c4a820..fff35ebf83 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -115,8 +115,8 @@ typedef FormData_pg_subscription *Form_pg_subscription;
 
 DECLARE_TOAST_WITH_MACRO(pg_subscription, 4183, 4184, PgSubscriptionToastTable, PgSubscriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops), SUBSCRIPTIONOID, 4);
+DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops), SUBSCRIPTIONNAME, 4);
 
 typedef struct Subscription
 {
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index f5324b710d..638f0d5447 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -49,7 +49,7 @@ CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
 
 typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops), SUBSCRIPTIONRELMAP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index ea8665e83a..8910fe362c 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -49,7 +49,7 @@ typedef FormData_pg_tablespace *Form_pg_tablespace;
 
 DECLARE_TOAST_WITH_MACRO(pg_tablespace, 4185, 4186, PgTablespaceToastTable, PgTablespaceToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops), TABLESPACEOID, 4);
 DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, pg_tablespace, btree(spcname name_ops));
 
 #endif							/* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index 8eb189784d..2660d7a706 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -42,7 +42,7 @@ CATALOG(pg_transform,3576,TransformRelationId)
  */
 typedef FormData_pg_transform *Form_pg_transform;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops), TRFOID, 16);
+DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops), TRFTYPELANG, 16);
 
 #endif							/* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index e52720387d..3699551f0f 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -47,7 +47,7 @@ CATALOG(pg_ts_config,3602,TSConfigRelationId)
 
 typedef FormData_pg_ts_config *Form_pg_ts_config;
 
-DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops), TSCONFIGNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops), TSCONFIGOID, 2);
 
 #endif							/* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index 91f092ca48..437b34a20c 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -44,6 +44,6 @@ CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
 
 typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops), TSCONFIGMAP, 2);
 
 #endif							/* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 10a6490213..34e22d9434 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -53,7 +53,7 @@ typedef FormData_pg_ts_dict *Form_pg_ts_dict;
 
 DECLARE_TOAST(pg_ts_dict, 4169, 4170);
 
-DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops), TSDICTNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops), TSDICTOID, 2);
 
 #endif							/* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index 57d9e8428a..7885c2555e 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -54,7 +54,7 @@ CATALOG(pg_ts_parser,3601,TSParserRelationId)
 
 typedef FormData_pg_ts_parser *Form_pg_ts_parser;
 
-DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops), TSPARSERNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops), TSPARSEROID, 2);
 
 #endif							/* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index f3bdc7b200..cd569a700e 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -45,7 +45,7 @@ CATALOG(pg_ts_template,3764,TSTemplateRelationId)
 
 typedef FormData_pg_ts_template *Form_pg_ts_template;
 
-DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops), TSTEMPLATENAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops), TSTEMPLATEOID, 2);
 
 #endif							/* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 508ba7b0f7..9d00be8dbb 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -262,8 +262,8 @@ typedef FormData_pg_type *Form_pg_type;
 
 DECLARE_TOAST(pg_type, 4171, 4172);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops), TYPEOID, 64);
+DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops), TYPENAMENSP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index eca33f4cb4..94bc93a83f 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -49,7 +49,7 @@ typedef FormData_pg_user_mapping *Form_pg_user_mapping;
 
 DECLARE_TOAST(pg_user_mapping, 4173, 4174);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops), USERMAPPINGOID, 2);
+DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops), USERMAPPINGUSERSERVER, 2);
 
 #endif							/* PG_USER_MAPPING_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 67ea6e4945..68827fba50 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -20,103 +20,7 @@
 #include "access/htup.h"
 /* we intentionally do not include utils/catcache.h here */
 
-/*
- *		SysCache identifiers.
- *
- *		The order of these identifiers must match the order
- *		of the entries in the array cacheinfo[] in syscache.c.
- *		Keep them in alphabetical order (renumbering only costs a
- *		backend rebuild).
- */
-
-enum SysCacheIdentifier
-{
-	AGGFNOID = 0,
-	AMNAME,
-	AMOID,
-	AMOPOPID,
-	AMOPSTRATEGY,
-	AMPROCNUM,
-	ATTNAME,
-	ATTNUM,
-	AUTHMEMMEMROLE,
-	AUTHMEMROLEMEM,
-	AUTHNAME,
-	AUTHOID,
-	CASTSOURCETARGET,
-	CLAAMNAMENSP,
-	CLAOID,
-	COLLNAMEENCNSP,
-	COLLOID,
-	CONDEFAULT,
-	CONNAMENSP,
-	CONSTROID,
-	CONVOID,
-	DATABASEOID,
-	DEFACLROLENSPOBJ,
-	ENUMOID,
-	ENUMTYPOIDNAME,
-	EVENTTRIGGERNAME,
-	EVENTTRIGGEROID,
-	FOREIGNDATAWRAPPERNAME,
-	FOREIGNDATAWRAPPEROID,
-	FOREIGNSERVERNAME,
-	FOREIGNSERVEROID,
-	FOREIGNTABLEREL,
-	INDEXRELID,
-	LANGNAME,
-	LANGOID,
-	NAMESPACENAME,
-	NAMESPACEOID,
-	OPERNAMENSP,
-	OPEROID,
-	OPFAMILYAMNAMENSP,
-	OPFAMILYOID,
-	PARAMETERACLNAME,
-	PARAMETERACLOID,
-	PARTRELID,
-	PROCNAMEARGSNSP,
-	PROCOID,
-	PUBLICATIONNAME,
-	PUBLICATIONNAMESPACE,
-	PUBLICATIONNAMESPACEMAP,
-	PUBLICATIONOID,
-	PUBLICATIONREL,
-	PUBLICATIONRELMAP,
-	RANGEMULTIRANGE,
-	RANGETYPE,
-	RELNAMENSP,
-	RELOID,
-	REPLORIGIDENT,
-	REPLORIGNAME,
-	RULERELNAME,
-	SEQRELID,
-	STATEXTDATASTXOID,
-	STATEXTNAMENSP,
-	STATEXTOID,
-	STATRELATTINH,
-	SUBSCRIPTIONNAME,
-	SUBSCRIPTIONOID,
-	SUBSCRIPTIONRELMAP,
-	TABLESPACEOID,
-	TRFOID,
-	TRFTYPELANG,
-	TSCONFIGMAP,
-	TSCONFIGNAMENSP,
-	TSCONFIGOID,
-	TSDICTNAMENSP,
-	TSDICTOID,
-	TSPARSERNAMENSP,
-	TSPARSEROID,
-	TSTEMPLATENAMENSP,
-	TSTEMPLATEOID,
-	TYPENAMENSP,
-	TYPEOID,
-	USERMAPPINGOID,
-	USERMAPPINGUSERSERVER
-
-#define SysCacheSize (USERMAPPINGUSERSERVER + 1)
-};
+#include "catalog/syscache_info.h"
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 4e09c4686b..56ed423567 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 8dee1b5670..477e4dd7e6 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
-- 
2.40.1

0005-WIP-Generate-ObjectProperty-from-catalog-files.patchtext/plain; charset=UTF-8; name=0005-WIP-Generate-ObjectProperty-from-catalog-files.patchDownload
From 881e9f1254376c0877ad562f98ee112eab47ac33 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 29 May 2023 19:56:31 -0400
Subject: [PATCH 5/5] WIP: Generate ObjectProperty from catalog files

---
 src/backend/catalog/.gitignore     |  1 +
 src/backend/catalog/genbki.pl      | 81 ++++++++++++++++++++++++++++++
 src/tools/pginclude/cpluspluscheck |  3 ++
 src/tools/pginclude/headerscheck   |  3 ++
 4 files changed, 88 insertions(+)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index ff65560379..d817798dc0 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,3 +1,4 @@
+/objectproperty_info.c.h
 /postgres.bki
 /schemapg.h
 /syscache_info.c.h
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 80a7828d6c..e0813d1286 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -19,8 +19,10 @@
 
 use FindBin;
 use lib $FindBin::RealBin;
+use lib "$FindBin::RealBin/../../tools";
 
 use Catalog;
+use PerfectHash;
 
 my $output_path = '';
 my $major_version;
@@ -59,6 +61,7 @@
 my %syscaches;
 my %oidcounts;
 my @system_constraints;
+my @object_properties;
 
 foreach my $header (@ARGV)
 {
@@ -133,6 +136,7 @@
 		$oidcounts{ $toast->{toast_oid} }++;
 		$oidcounts{ $toast->{toast_index_oid} }++;
 	}
+	my ($oid_index, $oid_syscache, $name_syscache, $is_nsp_name_unique);
 	foreach my $index (@{ $catalog->{indexing} })
 	{
 		push @index_decls,
@@ -142,6 +146,7 @@
 		  $index->{table_name},
 		  $index->{index_decl};
 		$oidcounts{ $index->{index_oid} }++;
+		$oid_index = $index->{index_oid_macro} if $index->{index_decl} eq 'btree(oid oid_ops)';
 
 		if ($index->{is_unique})
 		{
@@ -152,6 +157,11 @@
 			  $index->{index_name};
 		}
 
+		if ($index->{is_unique} && $index->{index_decl} =~ /\(\w+name name_ops, \w+namespace oid_ops\)/)
+		{
+			$is_nsp_name_unique = 1;
+		}
+
 		if ($index->{syscache_name})
 		{
 			my $tbl = $index->{table_name};
@@ -165,8 +175,51 @@
 				key => $key,
 				nbuckets => $index->{syscache_nbuckets},
 			};
+
+			$oid_syscache = $index->{syscache_name} if $index->{index_decl} eq 'btree(oid oid_ops)';
+			$name_syscache = $index->{syscache_name} if $index->{index_decl} =~ /^btree\(\w+name name_ops\)$/;
+		}
+	}
+
+	my ($attnum_oid, $attnum_name, $attnum_namespace, $attnum_owner, $attnum_acl);
+	foreach my $att (@$schema)
+	{
+		if ($att->{name} eq 'oid' && $att->{type} eq 'oid')
+		{
+			$attnum_oid = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /name$/ && $att->{type} eq 'name')
+		{
+			$attnum_name = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /namespace$/ && $att->{type} eq 'oid')
+		{
+			$attnum_namespace = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /owner$/ && $att->{type} eq 'oid')
+		{
+			$attnum_owner = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /acl$/ && $att->{type} eq '_aclitem')
+		{
+			$attnum_acl = "Anum_${catname}_" . $att->{name};
 		}
 	}
+	push @object_properties, {
+		#class_descr => q{"TODO"},
+		class_oid => $catalog->{relation_oid_macro},
+		_class_oid => $catalog->{relation_oid},
+		oid_index_oid => $oid_index,
+		oid_catcache_id => $oid_syscache || '-1',
+		name_catcache_id => $name_syscache || '-1',
+		attnum_oid => $attnum_oid,
+		attnum_name => $attnum_name,
+		attnum_namespace => $attnum_namespace,
+		attnum_owner => $attnum_owner,
+		attnum_acl => $attnum_acl,
+		#objtype => TODO,
+		is_nsp_name_unique => $is_nsp_name_unique ? 'true' : 'false',
+	};
 }
 
 # Complain and exit if we found any duplicate OIDs.
@@ -441,6 +494,9 @@
 my $syscache_info_c = $output_path . 'syscache_info.c.h';
 open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
   or die "can't open $syscache_info_c$tmpext: $!";
+my $objectproperty_info = $output_path . 'objectproperty_info.c.h';
+open my $objectproperty_info_fh, '>', $objectproperty_info . $tmpext
+  or die "can't open $objectproperty_info$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -802,6 +858,29 @@
 
 print $syscache_info_c_fh "};\n";
 
+# Now generate objectproperty_info
+
+print_boilerplate($objectproperty_info_fh, "objectproperty_info.h", "object property data");
+print $objectproperty_info_fh "static const ObjectPropertyType ObjectProperty[] =
+{
+";
+
+my @class_oids;
+foreach my $op (@object_properties)
+{
+	print $objectproperty_info_fh "\t{\n";
+	foreach my $p (sort keys %{$op})
+	{
+		printf $objectproperty_info_fh "\t\t%s = %s,\n", $p, ${$op}{$p} if $p !~ /^_/ && ${$op}{$p};
+	}
+	push @class_oids, pack('N', ${$op}{_class_oid});
+	print $objectproperty_info_fh "\t},\n";
+}
+
+print $objectproperty_info_fh "};\n";
+
+print $objectproperty_info_fh "\nstatic " . PerfectHash::generate_hash_function(\@class_oids, 'objectproperty_hash_func', fixed_key_length => 4);
+
 # We're done emitting data
 close $bki;
 close $schemapg;
@@ -809,6 +888,7 @@
 close $constraints;
 close $syscache_info_h_fh;
 close $syscache_info_c_fh;
+close $objectproperty_info_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
@@ -817,6 +897,7 @@
 Catalog::RenameTempFile($constraints_file, $tmpext);
 Catalog::RenameTempFile($syscache_info_h, $tmpext);
 Catalog::RenameTempFile($syscache_info_c, $tmpext);
+Catalog::RenameTempFile($objectproperty_info, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 56ed423567..49e3ca7a7b 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 477e4dd7e6..a1ea2ef692 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
-- 
2.40.1

In reply to: Peter Eisentraut (#1)
Re: generate syscache info automatically

Peter Eisentraut <peter@eisentraut.org> writes:

The idea was mentioned in [0]. genbki.pl already knows everything about
system catalog indexes. If we add a "please also make a syscache for
this one" flag to the catalog metadata, we can have genbki.pl produce
the tables in syscache.c and syscache.h automatically.

+1 on this worthwhile reduction of manual work. Tangentially, it
reminded me of one of my least favourite parts of Catalog.pm, the
regexes in ParseHeader():

diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 84aaeb002a..a727d692b7 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -110,7 +110,7 @@ sub ParseHeader
};
}
elsif (
-			/^DECLARE_(UNIQUE_)?INDEX(_PKEY)?\(\s*(\w+),\s*(\d+),\s*(\w+),\s*(.+)\)/
+			/^DECLARE_(UNIQUE_)?INDEX(_PKEY)?\(\s*(\w+),\s*(\d+),\s*(\w+),\s*(\w+),\s*(.+)\)/
)
{
push @{ $catalog{indexing} },
@@ -120,7 +120,8 @@ sub ParseHeader
index_name => $3,
index_oid => $4,
index_oid_macro => $5,
-				index_decl => $6
+				table_name => $6,
+				index_decl => $7
};
}
elsif (/^DECLARE_OID_DEFINING_MACRO\(\s*(\w+),\s*(\d+)\)/)

Now that we require Perl 5.14, we could replace this parenthesis-
counting nightmare with named captures (introduced in Perl 5.10), which
would make the above change look like this instead (context expanded to
show the whole elsif block):

elsif (
/^DECLARE_(UNIQUE_)?INDEX(_PKEY)?\(\s*
(?<index_name>\w+),\s*
(?<index_oid>\d+),\s*
(?<index_oid_macro>\w+),\s*
+ (?<table_name>\w+),\s*
(?<index_decl>.+)
\)/x
)
{
push @{ $catalog{indexing} },
{
is_unique => $1 ? 1 : 0,
is_pkey => $2 ? 1 : 0,
%+,
};
}

For other patterns without the optional bits in the keyword, it becomes
even simpler, e.g.

if (/^DECLARE_TOAST\(\s*
(?<parent_table>\w+),\s*
(?<toast_oid>\d+),\s*
(?<toast_index_oid>\d+)\s*
\)/x
)
{
push @{ $catalog{toasting} }, {%+};
}

I'd be happy to submit a patch to do this for all the ParseHeader()
regexes (in a separate thread) if others agree this is an improvement.

- ilmari

#3Peter Eisentraut
peter@eisentraut.org
In reply to: Dagfinn Ilmari Mannsåker (#2)
Re: generate syscache info automatically

On 31.05.23 13:02, Dagfinn Ilmari Mannsåker wrote:

For other patterns without the optional bits in the keyword, it becomes
even simpler, e.g.

if (/^DECLARE_TOAST\(\s*
(?<parent_table>\w+),\s*
(?<toast_oid>\d+),\s*
(?<toast_index_oid>\d+)\s*
\)/x
)
{
push @{ $catalog{toasting} }, {%+};
}

I'd be happy to submit a patch to do this for all the ParseHeader()
regexes (in a separate thread) if others agree this is an improvement.

I would welcome such a patch.

#4John Naylor
john.naylor@enterprisedb.com
In reply to: Peter Eisentraut (#1)
Re: generate syscache info automatically

On Wed, May 31, 2023 at 4:58 AM Peter Eisentraut <peter@eisentraut.org>
wrote:

I want to report on my on-the-plane-to-PGCon project.

The idea was mentioned in [0]. genbki.pl already knows everything about
system catalog indexes. If we add a "please also make a syscache for
this one" flag to the catalog metadata, we can have genbki.pl produce
the tables in syscache.c and syscache.h automatically.

Aside from avoiding the cumbersome editing of those tables, I think this
layout is also conceptually cleaner, as you can more easily see which
system catalog indexes have syscaches and maybe ask questions about why
or why not.

When this has come up before, one objection was that index declarations
shouldn't know about cache names and bucket sizes [1]/messages/by-id/12460.1570734874@sss.pgh.pa.us. The second paragraph
above makes a reasonable case for that, however. I believe one alternative
idea was for a script to read the enum, which would look something like
this:

#define DECLARE_SYSCACHE(cacheid,indexname,numbuckets) cacheid

enum SysCacheIdentifier
{
DECLARE_SYSCACHE(AGGFNOID, pg_aggregate_fnoid_index, 16) = 0,
...
};

...which would then look up the other info in the usual way from Catalog.pm.

As a possible follow-up, I have also started work on generating the
ObjectProperty structure in objectaddress.c. One of the things you need
for that is making genbki.pl aware of the syscache information. There
is some more work to be done there, but it's looking promising.

I haven't studied this, but it seems interesting.

One other possible improvement: syscache.c has a bunch of #include's, one
for each catalog with a cache, so there's still a bit of manual work in
adding a cache, and the current #include list is a bit cumbersome. Perhaps
it's worth it to have the script emit them as well?

I also wonder if at some point it will make sense to split off a separate
script(s) for some things that are unrelated to the bootstrap data.
genbki.pl is getting pretty large, and there are additional things that
could be done with syscaches, e.g. inlined eq/hash functions for cache
lookup [2]/messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de.

[1]: /messages/by-id/12460.1570734874@sss.pgh.pa.us
[2]: /messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de
/messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de

--
John Naylor
EDB: http://www.enterprisedb.com

#5Peter Eisentraut
peter@eisentraut.org
In reply to: John Naylor (#4)
6 attachment(s)
Re: generate syscache info automatically

Here is an updated patch set that adjusts for the recently introduced
named captures. I will address the other issues later. I think the
first few patches in the series can be considered nonetheless.

Show quoted text

On 15.06.23 09:45, John Naylor wrote:

On Wed, May 31, 2023 at 4:58 AM Peter Eisentraut <peter@eisentraut.org
<mailto:peter@eisentraut.org>> wrote:

I want to report on my on-the-plane-to-PGCon project.

The idea was mentioned in [0]. genbki.pl <http://genbki.pl&gt; already

knows everything about

system catalog indexes.  If we add a "please also make a syscache for
this one" flag to the catalog metadata, we can have genbki.pl

<http://genbki.pl&gt; produce

the tables in syscache.c and syscache.h automatically.

Aside from avoiding the cumbersome editing of those tables, I think this
layout is also conceptually cleaner, as you can more easily see which
system catalog indexes have syscaches and maybe ask questions about why
or why not.

When this has come up before, one objection was that index declarations
shouldn't know about cache names and bucket sizes [1]. The second
paragraph above makes a reasonable case for that, however. I believe one
alternative idea was for a script to read the enum, which would look
something like this:

#define DECLARE_SYSCACHE(cacheid,indexname,numbuckets) cacheid

enum SysCacheIdentifier
{
DECLARE_SYSCACHE(AGGFNOID, pg_aggregate_fnoid_index, 16) = 0,
...
};

...which would then look up the other info in the usual way from Catalog.pm.

As a possible follow-up, I have also started work on generating the
ObjectProperty structure in objectaddress.c.  One of the things you need
for that is making genbki.pl <http://genbki.pl&gt; aware of the syscache

information.  There

is some more work to be done there, but it's looking promising.

I haven't studied this, but it seems interesting.

One other possible improvement: syscache.c has a bunch of #include's,
one for each catalog with a cache, so there's still a bit of manual work
in adding a cache, and the current #include list is a bit cumbersome.
Perhaps it's worth it to have the script emit them as well?

I also wonder if at some point it will make sense to split off a
separate script(s) for some things that are unrelated to the bootstrap
data. genbki.pl <http://genbki.pl&gt; is getting pretty large, and there
are additional things that could be done with syscaches, e.g. inlined
eq/hash functions for cache lookup [2].

[1] /messages/by-id/12460.1570734874@sss.pgh.pa.us
</messages/by-id/12460.1570734874@sss.pgh.pa.us&gt;
[2]
/messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de </messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de&gt;

--
John Naylor
EDB: http://www.enterprisedb.com <http://www.enterprisedb.com&gt;

Attachments:

v2-0001-Update-DECLARE_INDEX-documentation.patchtext/plain; charset=UTF-8; name=v2-0001-Update-DECLARE_INDEX-documentation.patchDownload
From 4c70e5acf932668efebf64dc60b8d29524e25e2b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v2 1/6] Update DECLARE_INDEX documentation

should have been updated in 6a6389a08b
---
 src/include/catalog/genbki.h | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index 50518cbbf5..c42ba0cea5 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -71,12 +71,13 @@
  * DECLARE_UNIQUE_INDEX_PKEY.  ("PKEY" marks the index as being the catalog's
  * primary key; currently this is only cosmetically different from a regular
  * unique index.  By convention, we usually make a catalog's OID column its
- * pkey, if it has one.)  The first two arguments are the index's name and
- * OID, the rest is much like a standard 'create index' SQL command.
+ * pkey, if it has one.)
  *
- * For each index, we also provide a #define for its OID.  References to
- * the index in the C code should always use these #defines, not the actual
- * index name (much less the numeric OID).
+ * The first two arguments are the index's name and OID.  The third argument
+ * is the name of a #define to generate for its OID.  References to the index
+ * in the C code should always use these #defines, not the actual index name
+ * (much less the numeric OID).  The rest is much like a standard 'create
+ * index' SQL command.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */

base-commit: c951e9042dd12db80cac4e9a50f198a1eead2036
-- 
2.41.0

v2-0002-Restructure-DECLARE_INDEX-arguments.patchtext/plain; charset=UTF-8; name=v2-0002-Restructure-DECLARE_INDEX-arguments.patchDownload
From e5f9dc1855a8d28839cf58ea5332de0029d586ab Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v2 2/6] Restructure DECLARE_INDEX arguments

Separate the table name from the index declaration.  We need that
anyway later for the ALTER TABLE / USING INDEX commands, so we might
as well structure the declarations like that to begin with.
---
 src/backend/catalog/Catalog.pm                 |  1 +
 src/backend/catalog/genbki.pl                  |  7 +++----
 src/include/catalog/genbki.h                   | 10 +++++-----
 src/include/catalog/pg_aggregate.h             |  2 +-
 src/include/catalog/pg_am.h                    |  4 ++--
 src/include/catalog/pg_amop.h                  |  6 +++---
 src/include/catalog/pg_amproc.h                |  4 ++--
 src/include/catalog/pg_attrdef.h               |  4 ++--
 src/include/catalog/pg_attribute.h             |  4 ++--
 src/include/catalog/pg_auth_members.h          |  8 ++++----
 src/include/catalog/pg_authid.h                |  4 ++--
 src/include/catalog/pg_cast.h                  |  4 ++--
 src/include/catalog/pg_class.h                 |  6 +++---
 src/include/catalog/pg_collation.h             |  4 ++--
 src/include/catalog/pg_constraint.h            | 10 +++++-----
 src/include/catalog/pg_conversion.h            |  6 +++---
 src/include/catalog/pg_database.h              |  4 ++--
 src/include/catalog/pg_db_role_setting.h       |  2 +-
 src/include/catalog/pg_default_acl.h           |  4 ++--
 src/include/catalog/pg_depend.h                |  4 ++--
 src/include/catalog/pg_description.h           |  2 +-
 src/include/catalog/pg_enum.h                  |  6 +++---
 src/include/catalog/pg_event_trigger.h         |  4 ++--
 src/include/catalog/pg_extension.h             |  4 ++--
 src/include/catalog/pg_foreign_data_wrapper.h  |  4 ++--
 src/include/catalog/pg_foreign_server.h        |  4 ++--
 src/include/catalog/pg_foreign_table.h         |  2 +-
 src/include/catalog/pg_index.h                 |  4 ++--
 src/include/catalog/pg_inherits.h              |  4 ++--
 src/include/catalog/pg_init_privs.h            |  2 +-
 src/include/catalog/pg_language.h              |  4 ++--
 src/include/catalog/pg_largeobject.h           |  2 +-
 src/include/catalog/pg_largeobject_metadata.h  |  2 +-
 src/include/catalog/pg_namespace.h             |  4 ++--
 src/include/catalog/pg_opclass.h               |  4 ++--
 src/include/catalog/pg_operator.h              |  4 ++--
 src/include/catalog/pg_opfamily.h              |  4 ++--
 src/include/catalog/pg_parameter_acl.h         |  4 ++--
 src/include/catalog/pg_partitioned_table.h     |  2 +-
 src/include/catalog/pg_policy.h                |  4 ++--
 src/include/catalog/pg_proc.h                  |  4 ++--
 src/include/catalog/pg_publication.h           |  4 ++--
 src/include/catalog/pg_publication_namespace.h |  4 ++--
 src/include/catalog/pg_publication_rel.h       |  6 +++---
 src/include/catalog/pg_range.h                 |  4 ++--
 src/include/catalog/pg_replication_origin.h    |  4 ++--
 src/include/catalog/pg_rewrite.h               |  4 ++--
 src/include/catalog/pg_seclabel.h              |  2 +-
 src/include/catalog/pg_sequence.h              |  2 +-
 src/include/catalog/pg_shdepend.h              |  4 ++--
 src/include/catalog/pg_shdescription.h         |  2 +-
 src/include/catalog/pg_shseclabel.h            |  2 +-
 src/include/catalog/pg_statistic.h             |  2 +-
 src/include/catalog/pg_statistic_ext.h         |  6 +++---
 src/include/catalog/pg_statistic_ext_data.h    |  2 +-
 src/include/catalog/pg_subscription.h          |  4 ++--
 src/include/catalog/pg_subscription_rel.h      |  2 +-
 src/include/catalog/pg_tablespace.h            |  4 ++--
 src/include/catalog/pg_transform.h             |  4 ++--
 src/include/catalog/pg_trigger.h               |  6 +++---
 src/include/catalog/pg_ts_config.h             |  4 ++--
 src/include/catalog/pg_ts_config_map.h         |  2 +-
 src/include/catalog/pg_ts_dict.h               |  4 ++--
 src/include/catalog/pg_ts_parser.h             |  4 ++--
 src/include/catalog/pg_ts_template.h           |  4 ++--
 src/include/catalog/pg_type.h                  |  4 ++--
 src/include/catalog/pg_user_mapping.h          |  4 ++--
 67 files changed, 133 insertions(+), 133 deletions(-)

diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index b15f513183..be56cc153f 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -117,6 +117,7 @@ sub ParseHeader
 			 (?<index_name>\w+),\s*
 			 (?<index_oid>\d+),\s*
 			 (?<index_oid_macro>\w+),\s*
+			 (?<table_name>\w+),\s*
 			 (?<index_decl>.+)\s*
 			 \)/x
 		  )
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 4a7205472c..c7657cc47c 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -135,19 +135,18 @@
 	foreach my $index (@{ $catalog->{indexing} })
 	{
 		push @index_decls,
-		  sprintf "declare %sindex %s %s %s\n",
+		  sprintf "declare %sindex %s %s on %s using %s\n",
 		  $index->{is_unique} ? 'unique ' : '',
 		  $index->{index_name}, $index->{index_oid},
+		  $index->{table_name},
 		  $index->{index_decl};
 		$oidcounts{ $index->{index_oid} }++;
 
 		if ($index->{is_unique})
 		{
-			$index->{index_decl} =~ /on (\w+) using/;
-			my $tblname = $1;
 			push @system_constraints,
 			  sprintf "ALTER TABLE %s ADD %s USING INDEX %s;",
-			  $tblname,
+			  $index->{table_name},
 			  $index->{is_pkey} ? "PRIMARY KEY" : "UNIQUE",
 			  $index->{index_name};
 		}
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index c42ba0cea5..e22a6902fb 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -76,14 +76,14 @@
  * The first two arguments are the index's name and OID.  The third argument
  * is the name of a #define to generate for its OID.  References to the index
  * in the C code should always use these #defines, not the actual index name
- * (much less the numeric OID).  The rest is much like a standard 'create
- * index' SQL command.
+ * (much less the numeric OID).  The fourth argument is the table name.  The
+ * rest is much like a standard 'create index' SQL command.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */
-#define DECLARE_INDEX(name,oid,oidmacro,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,decl) extern int no_such_variable
+#define DECLARE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl) extern int no_such_variable
 
 /*
  * These lines inform genbki.pl about manually-assigned OIDs that do not
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 3112881193..085149e258 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -110,7 +110,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
 
 DECLARE_TOAST(pg_aggregate, 4159, 4160);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, on pg_aggregate using btree(aggfnoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index dab54be130..d5314bb38b 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -47,8 +47,8 @@ CATALOG(pg_am,2601,AccessMethodRelationId)
  */
 typedef FormData_pg_am *Form_pg_am;
 
-DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, on pg_am using btree(amname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, on pg_am using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index 4ca7321409..c9bb7b4787 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -87,9 +87,9 @@ CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
  */
 typedef FormData_pg_amop *Form_pg_amop;
 
-DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, on pg_amop using btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
-DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, on pg_amop using btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, on pg_amop using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, pg_amop, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 3307d5c844..5acf4efab9 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -67,7 +67,7 @@ CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
  */
 typedef FormData_pg_amproc *Form_pg_amproc;
 
-DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, on pg_amproc using btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, on pg_amproc using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, pg_amproc, btree(oid oid_ops));
 
 #endif							/* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h
index 9dc318ff93..04c5725045 100644
--- a/src/include/catalog/pg_attrdef.h
+++ b/src/include/catalog/pg_attrdef.h
@@ -50,8 +50,8 @@ typedef FormData_pg_attrdef *Form_pg_attrdef;
 
 DECLARE_TOAST(pg_attrdef, 2830, 2831);
 
-DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index, 2656, AttrDefaultIndexId, on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attrdef_oid_index, 2657, AttrDefaultOidIndexId, on pg_attrdef using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index, 2656, AttrDefaultIndexId, pg_attrdef, btree(adrelid oid_ops, adnum int2_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_attrdef_oid_index, 2657, AttrDefaultOidIndexId, pg_attrdef, btree(oid oid_ops));
 
 DECLARE_FOREIGN_KEY((adrelid, adnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index f8b4861b94..f0d6de7c1f 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -208,8 +208,8 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
  */
 typedef FormData_pg_attribute *Form_pg_attribute;
 
-DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, on pg_attribute using btree(attrelid oid_ops, attname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index df2b8b29e0..4ab8a9f7b7 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -45,9 +45,9 @@ CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_
  */
 typedef FormData_pg_auth_members *Form_pg_auth_members;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, on pg_auth_members using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, on pg_auth_members using btree(roleid oid_ops, member oid_ops, grantor oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, on pg_auth_members using btree(member oid_ops, roleid oid_ops, grantor oid_ops));
-DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, on pg_auth_members using btree(grantor oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, pg_auth_members, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops));
+DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, pg_auth_members, btree(grantor oid_ops));
 
 #endif							/* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index c70baf7887..0e7ddc56ea 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -57,7 +57,7 @@ typedef FormData_pg_authid *Form_pg_authid;
 
 DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, on pg_authid using btree(rolname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, on pg_authid using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops));
 
 #endif							/* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index 9ec2b5785b..a2518388b3 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -56,8 +56,8 @@ CATALOG(pg_cast,2605,CastRelationId)
  */
 typedef FormData_pg_cast *Form_pg_cast;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, on pg_cast using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, pg_cast, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 2d1bb7af3a..55dcd54100 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -152,9 +152,9 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat
  */
 typedef FormData_pg_class *Form_pg_class;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, on pg_class using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, on pg_class using btree(relname name_ops, relnamespace oid_ops));
-DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, on pg_class using btree(reltablespace oid_ops, relfilenode oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops));
+DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, pg_class, btree(reltablespace oid_ops, relfilenode oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index bfa3568451..2d7dcde183 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -59,8 +59,8 @@ typedef FormData_pg_collation *Form_pg_collation;
 
 DECLARE_TOAST(pg_collation, 6175, 6176);
 
-DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, on pg_collation using btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, on pg_collation using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 16bf5f5576..0d47c9b589 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -166,11 +166,11 @@ typedef FormData_pg_constraint *Form_pg_constraint;
 
 DECLARE_TOAST(pg_constraint, 2832, 2833);
 
-DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, on pg_constraint using btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, on pg_constraint using btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
-DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, on pg_constraint using btree(contypid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, on pg_constraint using btree(oid oid_ops));
-DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, on pg_constraint using btree(conparentid oid_ops));
+DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, pg_constraint, btree(conname name_ops, connamespace oid_ops));
+DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
+DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops));
+DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops));
 
 /* conkey can contain zero (InvalidAttrNumber) if a whole-row Var is used */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((conrelid, conkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index de40909dd3..42847fdf12 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -60,9 +60,9 @@ CATALOG(pg_conversion,2607,ConversionRelationId)
  */
 typedef FormData_pg_conversion *Form_pg_conversion;
 
-DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, on pg_conversion using btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, on pg_conversion using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops));
 
 
 extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index d004f4dc8a..44e2ed73cf 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -91,8 +91,8 @@ typedef FormData_pg_database *Form_pg_database;
 
 DECLARE_TOAST_WITH_MACRO(pg_database, 4177, 4178, PgDatabaseToastTable, PgDatabaseToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, on pg_database using btree(datname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, on pg_database using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, pg_database, btree(datname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops));
 
 /*
  * pg_database.dat contains an entry for template1, but not for the template0
diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h
index 4ba0d69e76..af025cc608 100644
--- a/src/include/catalog/pg_db_role_setting.h
+++ b/src/include/catalog/pg_db_role_setting.h
@@ -48,7 +48,7 @@ typedef FormData_pg_db_role_setting * Form_pg_db_role_setting;
 
 DECLARE_TOAST_WITH_MACRO(pg_db_role_setting, 2966, 2967, PgDbRoleSettingToastTable, PgDbRoleSettingToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_db_role_setting_databaseid_rol_index, 2965, DbRoleSettingDatidRolidIndexId, on pg_db_role_setting using btree(setdatabase oid_ops, setrole oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_db_role_setting_databaseid_rol_index, 2965, DbRoleSettingDatidRolidIndexId, pg_db_role_setting, btree(setdatabase oid_ops, setrole oid_ops));
 
 /*
  * prototypes for functions in pg_db_role_setting.c
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index d6d0a03f0c..803ce3eab8 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -51,8 +51,8 @@ typedef FormData_pg_default_acl *Form_pg_default_acl;
 
 DECLARE_TOAST(pg_default_acl, 4143, 4144);
 
-DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, on pg_default_acl using btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, on pg_default_acl using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, pg_default_acl, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h
index 30dde6f8aa..67ea968beb 100644
--- a/src/include/catalog/pg_depend.h
+++ b/src/include/catalog/pg_depend.h
@@ -71,7 +71,7 @@ CATALOG(pg_depend,2608,DependRelationId)
  */
 typedef FormData_pg_depend *Form_pg_depend;
 
-DECLARE_INDEX(pg_depend_depender_index, 2673, DependDependerIndexId, on pg_depend using btree(classid oid_ops, objid oid_ops, objsubid int4_ops));
-DECLARE_INDEX(pg_depend_reference_index, 2674, DependReferenceIndexId, on pg_depend using btree(refclassid oid_ops, refobjid oid_ops, refobjsubid int4_ops));
+DECLARE_INDEX(pg_depend_depender_index, 2673, DependDependerIndexId, pg_depend, btree(classid oid_ops, objid oid_ops, objsubid int4_ops));
+DECLARE_INDEX(pg_depend_reference_index, 2674, DependReferenceIndexId, pg_depend, btree(refclassid oid_ops, refobjid oid_ops, refobjsubid int4_ops));
 
 #endif							/* PG_DEPEND_H */
diff --git a/src/include/catalog/pg_description.h b/src/include/catalog/pg_description.h
index 7545b92a15..10026152e7 100644
--- a/src/include/catalog/pg_description.h
+++ b/src/include/catalog/pg_description.h
@@ -65,7 +65,7 @@ typedef FormData_pg_description * Form_pg_description;
 
 DECLARE_TOAST(pg_description, 2834, 2835);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_description_o_c_o_index, 2675, DescriptionObjIndexId, on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_description_o_c_o_index, 2675, DescriptionObjIndexId, pg_description, btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
 
 /* We do not use BKI_LOOKUP here because it causes problems for genbki.pl */
 DECLARE_FOREIGN_KEY((classoid), pg_class, (oid));
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index 83a0668233..c483cb1042 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -43,9 +43,9 @@ CATALOG(pg_enum,3501,EnumRelationId)
  */
 typedef FormData_pg_enum *Form_pg_enum;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, on pg_enum using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, on pg_enum using btree(enumtypid oid_ops, enumlabel name_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, on pg_enum using btree(enumtypid oid_ops, enumsortorder float4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops));
+DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, pg_enum, btree(enumtypid oid_ops, enumsortorder float4_ops));
 
 /*
  * prototypes for functions in pg_enum.c
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index e30550f6e1..0ec42edff6 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -51,7 +51,7 @@ typedef FormData_pg_event_trigger *Form_pg_event_trigger;
 
 DECLARE_TOAST(pg_event_trigger, 4145, 4146);
 
-DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, on pg_event_trigger using btree(evtname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, on pg_event_trigger using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops));
 
 #endif							/* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index 799c8ed9d0..8c7174e23c 100644
--- a/src/include/catalog/pg_extension.h
+++ b/src/include/catalog/pg_extension.h
@@ -53,7 +53,7 @@ typedef FormData_pg_extension *Form_pg_extension;
 
 DECLARE_TOAST(pg_extension, 4147, 4148);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_extension_oid_index, 3080, ExtensionOidIndexId, on pg_extension using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, ExtensionNameIndexId, on pg_extension using btree(extname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_extension_oid_index, 3080, ExtensionOidIndexId, pg_extension, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, ExtensionNameIndexId, pg_extension, btree(extname name_ops));
 
 #endif							/* PG_EXTENSION_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index e7833ec883..37387f9355 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -52,7 +52,7 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
 
 DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, on pg_foreign_data_wrapper using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, on pg_foreign_data_wrapper using btree(fdwname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops));
 
 #endif							/* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 2a14871d74..5993967c6e 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -49,7 +49,7 @@ typedef FormData_pg_foreign_server *Form_pg_foreign_server;
 
 DECLARE_TOAST(pg_foreign_server, 4151, 4152);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, on pg_foreign_server using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, on pg_foreign_server using btree(srvname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops));
 
 #endif							/* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index cfa570a88c..2420e23401 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -44,6 +44,6 @@ typedef FormData_pg_foreign_table *Form_pg_foreign_table;
 
 DECLARE_TOAST(pg_foreign_table, 4153, 4154);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, on pg_foreign_table using btree(ftrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops));
 
 #endif							/* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index b0592571da..32930411b6 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -69,8 +69,8 @@ CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
  */
 typedef FormData_pg_index *Form_pg_index;
 
-DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, on pg_index using btree(indrelid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, on pg_index using btree(indexrelid oid_ops));
+DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops));
 
 /* indkey can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((indrelid, indkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h
index ce154ab943..65562b8c3e 100644
--- a/src/include/catalog/pg_inherits.h
+++ b/src/include/catalog/pg_inherits.h
@@ -44,8 +44,8 @@ CATALOG(pg_inherits,2611,InheritsRelationId)
  */
 typedef FormData_pg_inherits *Form_pg_inherits;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_inherits_relid_seqno_index, 2680, InheritsRelidSeqnoIndexId, on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops));
-DECLARE_INDEX(pg_inherits_parent_index, 2187, InheritsParentIndexId, on pg_inherits using btree(inhparent oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_inherits_relid_seqno_index, 2680, InheritsRelidSeqnoIndexId, pg_inherits, btree(inhrelid oid_ops, inhseqno int4_ops));
+DECLARE_INDEX(pg_inherits_parent_index, 2187, InheritsParentIndexId, pg_inherits, btree(inhparent oid_ops));
 
 
 extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode);
diff --git a/src/include/catalog/pg_init_privs.h b/src/include/catalog/pg_init_privs.h
index 34fe2b4d0e..3f3df954a8 100644
--- a/src/include/catalog/pg_init_privs.h
+++ b/src/include/catalog/pg_init_privs.h
@@ -65,7 +65,7 @@ typedef FormData_pg_init_privs * Form_pg_init_privs;
 
 DECLARE_TOAST(pg_init_privs, 4155, 4156);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_init_privs_o_c_o_index, 3395, InitPrivsObjIndexId, on pg_init_privs using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_init_privs_o_c_o_index, 3395, InitPrivsObjIndexId, pg_init_privs, btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
 
 /*
  * It is important to know if the initial privileges are from initdb or from an
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index 02003b4627..d666ea2044 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -66,7 +66,7 @@ typedef FormData_pg_language *Form_pg_language;
 
 DECLARE_TOAST(pg_language, 4157, 4158);
 
-DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, on pg_language using btree(lanname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, on pg_language using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops));
 
 #endif							/* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h
index 95471073a8..c073e10e40 100644
--- a/src/include/catalog/pg_largeobject.h
+++ b/src/include/catalog/pg_largeobject.h
@@ -44,7 +44,7 @@ CATALOG(pg_largeobject,2613,LargeObjectRelationId)
  */
 typedef FormData_pg_largeobject *Form_pg_largeobject;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_loid_pn_index, 2683, LargeObjectLOidPNIndexId, on pg_largeobject using btree(loid oid_ops, pageno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_loid_pn_index, 2683, LargeObjectLOidPNIndexId, pg_largeobject, btree(loid oid_ops, pageno int4_ops));
 
 extern Oid	LargeObjectCreate(Oid loid);
 extern void LargeObjectDrop(Oid loid);
diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h
index 80db926079..0481244845 100644
--- a/src/include/catalog/pg_largeobject_metadata.h
+++ b/src/include/catalog/pg_largeobject_metadata.h
@@ -46,6 +46,6 @@ CATALOG(pg_largeobject_metadata,2995,LargeObjectMetadataRelationId)
  */
 typedef FormData_pg_largeobject_metadata *Form_pg_largeobject_metadata;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_metadata_oid_index, 2996, LargeObjectMetadataOidIndexId, on pg_largeobject_metadata using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_metadata_oid_index, 2996, LargeObjectMetadataOidIndexId, pg_largeobject_metadata, btree(oid oid_ops));
 
 #endif							/* PG_LARGEOBJECT_METADATA_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 2b0c243178..fc74a14c37 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -53,8 +53,8 @@ typedef FormData_pg_namespace *Form_pg_namespace;
 
 DECLARE_TOAST(pg_namespace, 4163, 4164);
 
-DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, on pg_namespace using btree(nspname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, on pg_namespace using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops));
 
 /*
  * prototypes for functions in pg_namespace.c
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index b4b6325c06..a5d09faf1f 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -82,7 +82,7 @@ CATALOG(pg_opclass,2616,OperatorClassRelationId)
  */
 typedef FormData_pg_opclass *Form_pg_opclass;
 
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, on pg_opclass using btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, on pg_opclass using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops));
 
 #endif							/* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index e60cf782a6..aff372b4bb 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -82,8 +82,8 @@ CATALOG(pg_operator,2617,OperatorRelationId)
  */
 typedef FormData_pg_operator *Form_pg_operator;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, on pg_operator using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
 
 
 extern ObjectAddress OperatorCreate(const char *operatorName,
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 39b8d7c219..88940de916 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -50,8 +50,8 @@ CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
  */
 typedef FormData_pg_opfamily *Form_pg_opfamily;
 
-DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, on pg_opfamily using btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, on pg_opfamily using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h
index 1612cebd0e..f46cdd1524 100644
--- a/src/include/catalog/pg_parameter_acl.h
+++ b/src/include/catalog/pg_parameter_acl.h
@@ -50,8 +50,8 @@ typedef FormData_pg_parameter_acl * Form_pg_parameter_acl;
 
 DECLARE_TOAST_WITH_MACRO(pg_parameter_acl, 6244, 6245, PgParameterAclToastTable, PgParameterAclToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, on pg_parameter_acl using btree(parname text_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, on pg_parameter_acl using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops));
 
 
 extern Oid	ParameterAclLookup(const char *parameter, bool missing_ok);
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index eb867ad62b..0cf512e1c8 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -66,7 +66,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
 
 DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, on pg_partitioned_table using btree(partrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops));
 
 /* partattrs can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((partrelid, partattrs), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h
index c9525ece74..feaeedbbe6 100644
--- a/src/include/catalog/pg_policy.h
+++ b/src/include/catalog/pg_policy.h
@@ -52,7 +52,7 @@ typedef FormData_pg_policy *Form_pg_policy;
 
 DECLARE_TOAST(pg_policy, 4167, 4168);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_policy_oid_index, 3257, PolicyOidIndexId, on pg_policy using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_policy_polrelid_polname_index, 3258, PolicyPolrelidPolnameIndexId, on pg_policy using btree(polrelid oid_ops, polname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_policy_oid_index, 3257, PolicyOidIndexId, pg_policy, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_policy_polrelid_polname_index, 3258, PolicyPolrelidPolnameIndexId, pg_policy, btree(polrelid oid_ops, polname name_ops));
 
 #endif							/* PG_POLICY_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index e7abe0b497..fdb39d4001 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -137,8 +137,8 @@ typedef FormData_pg_proc *Form_pg_proc;
 
 DECLARE_TOAST(pg_proc, 2836, 2837);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, on pg_proc using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 6ecaa2a01e..d929c9a188 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -63,8 +63,8 @@ CATALOG(pg_publication,6104,PublicationRelationId)
  */
 typedef FormData_pg_publication *Form_pg_publication;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, on pg_publication using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, on pg_publication using btree(pubname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops));
 
 typedef struct PublicationActions
 {
diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h
index f1abcb9f16..b361c8ab5e 100644
--- a/src/include/catalog/pg_publication_namespace.h
+++ b/src/include/catalog/pg_publication_namespace.h
@@ -41,7 +41,7 @@ CATALOG(pg_publication_namespace,6237,PublicationNamespaceRelationId)
  */
 typedef FormData_pg_publication_namespace *Form_pg_publication_namespace;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, on pg_publication_namespace using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, on pg_publication_namespace using btree(pnnspid oid_ops, pnpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_NAMESPACE_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index 613e9747c2..bef508764a 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -47,8 +47,8 @@ typedef FormData_pg_publication_rel *Form_pg_publication_rel;
 
 DECLARE_TOAST(pg_publication_rel, 6228, 6229);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, on pg_publication_rel using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, on pg_publication_rel using btree(prrelid oid_ops, prpubid oid_ops));
-DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, on pg_publication_rel using btree(prpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops));
+DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, pg_publication_rel, btree(prpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index d03ef18851..1247fa7c77 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -57,8 +57,8 @@ CATALOG(pg_range,3541,RangeRelationId)
  */
 typedef FormData_pg_range *Form_pg_range;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, on pg_range using btree(rngtypid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, on pg_range using btree(rngmultitypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops));
 
 /*
  * prototypes for functions in pg_range.c
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index fa54f120e6..83ff36dcba 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -56,7 +56,7 @@ typedef FormData_pg_replication_origin *Form_pg_replication_origin;
 
 DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, on pg_replication_origin using btree(roident oid_ops));
-DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, on pg_replication_origin using btree(roname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops));
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops));
 
 #endif							/* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 21f24e6d7e..60d642b595 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -53,7 +53,7 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
 
 DECLARE_TOAST(pg_rewrite, 2838, 2839);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, on pg_rewrite using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, pg_rewrite, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops));
 
 #endif							/* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
index 74299cf85d..a3a601f6fe 100644
--- a/src/include/catalog/pg_seclabel.h
+++ b/src/include/catalog/pg_seclabel.h
@@ -40,6 +40,6 @@ CATALOG(pg_seclabel,3596,SecLabelRelationId)
 
 DECLARE_TOAST(pg_seclabel, 3598, 3599);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_seclabel_object_index, 3597, SecLabelObjectIndexId, on pg_seclabel using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_seclabel_object_index, 3597, SecLabelObjectIndexId, pg_seclabel, btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops));
 
 #endif							/* PG_SECLABEL_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index d528c9122f..fdfc27bbd9 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -39,6 +39,6 @@ CATALOG(pg_sequence,2224,SequenceRelationId)
  */
 typedef FormData_pg_sequence *Form_pg_sequence;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, on pg_sequence using btree(seqrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops));
 
 #endif							/* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_shdepend.h b/src/include/catalog/pg_shdepend.h
index 35ba911a22..3834d07f78 100644
--- a/src/include/catalog/pg_shdepend.h
+++ b/src/include/catalog/pg_shdepend.h
@@ -72,7 +72,7 @@ CATALOG(pg_shdepend,1214,SharedDependRelationId) BKI_SHARED_RELATION
  */
 typedef FormData_pg_shdepend *Form_pg_shdepend;
 
-DECLARE_INDEX(pg_shdepend_depender_index, 1232, SharedDependDependerIndexId, on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
-DECLARE_INDEX(pg_shdepend_reference_index, 1233, SharedDependReferenceIndexId, on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops));
+DECLARE_INDEX(pg_shdepend_depender_index, 1232, SharedDependDependerIndexId, pg_shdepend, btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
+DECLARE_INDEX(pg_shdepend_reference_index, 1233, SharedDependReferenceIndexId, pg_shdepend, btree(refclassid oid_ops, refobjid oid_ops));
 
 #endif							/* PG_SHDEPEND_H */
diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h
index 7b66c12224..c7b66d95d5 100644
--- a/src/include/catalog/pg_shdescription.h
+++ b/src/include/catalog/pg_shdescription.h
@@ -57,7 +57,7 @@ typedef FormData_pg_shdescription * Form_pg_shdescription;
 
 DECLARE_TOAST_WITH_MACRO(pg_shdescription, 2846, 2847, PgShdescriptionToastTable, PgShdescriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_shdescription_o_c_index, 2397, SharedDescriptionObjIndexId, on pg_shdescription using btree(objoid oid_ops, classoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_shdescription_o_c_index, 2397, SharedDescriptionObjIndexId, pg_shdescription, btree(objoid oid_ops, classoid oid_ops));
 
 /* We do not use BKI_LOOKUP here because it causes problems for genbki.pl */
 DECLARE_FOREIGN_KEY((classoid), pg_class, (oid));
diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h
index 32b03de952..e252b75688 100644
--- a/src/include/catalog/pg_shseclabel.h
+++ b/src/include/catalog/pg_shseclabel.h
@@ -41,6 +41,6 @@ typedef FormData_pg_shseclabel * Form_pg_shseclabel;
 
 DECLARE_TOAST_WITH_MACRO(pg_shseclabel, 4060, 4061, PgShseclabelToastTable, PgShseclabelToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_shseclabel_object_index, 3593, SharedSecLabelObjectIndexId, on pg_shseclabel using btree(objoid oid_ops, classoid oid_ops, provider text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_shseclabel_object_index, 3593, SharedSecLabelObjectIndexId, pg_shseclabel, btree(objoid oid_ops, classoid oid_ops, provider text_ops));
 
 #endif							/* PG_SHSECLABEL_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 8770c5b4c6..864cb54a51 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -136,7 +136,7 @@ typedef FormData_pg_statistic *Form_pg_statistic;
 
 DECLARE_TOAST(pg_statistic, 2840, 2841);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, on pg_statistic using btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
 
 DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index 53eec9025a..85e56feb80 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -70,9 +70,9 @@ typedef FormData_pg_statistic_ext *Form_pg_statistic_ext;
 
 DECLARE_TOAST(pg_statistic_ext, 3439, 3440);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, on pg_statistic_ext using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, on pg_statistic_ext using btree(stxname name_ops, stxnamespace oid_ops));
-DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, on pg_statistic_ext using btree(stxrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops));
+DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, pg_statistic_ext, btree(stxrelid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((stxrelid, stxkeys), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
index 64d11a9c58..19a00705e6 100644
--- a/src/include/catalog/pg_statistic_ext_data.h
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -54,7 +54,7 @@ typedef FormData_pg_statistic_ext_data *Form_pg_statistic_ext_data;
 
 DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, on pg_statistic_ext_data using btree(stxoid oid_ops, stxdinherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops));
 
 
 #endif							/* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index 1d40eebc78..be36c4a820 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -115,8 +115,8 @@ typedef FormData_pg_subscription *Form_pg_subscription;
 
 DECLARE_TOAST_WITH_MACRO(pg_subscription, 4183, 4184, PgSubscriptionToastTable, PgSubscriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, on pg_subscription using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, on pg_subscription using btree(subdbid oid_ops, subname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops));
 
 typedef struct Subscription
 {
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index 60a2bcca23..f5324b710d 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -49,7 +49,7 @@ CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
 
 typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, on pg_subscription_rel using btree(srrelid oid_ops, srsubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index ea1593d874..ea8665e83a 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -49,7 +49,7 @@ typedef FormData_pg_tablespace *Form_pg_tablespace;
 
 DECLARE_TOAST_WITH_MACRO(pg_tablespace, 4185, 4186, PgTablespaceToastTable, PgTablespaceToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, on pg_tablespace using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, on pg_tablespace using btree(spcname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, pg_tablespace, btree(spcname name_ops));
 
 #endif							/* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index 6273b0a491..8eb189784d 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -42,7 +42,7 @@ CATALOG(pg_transform,3576,TransformRelationId)
  */
 typedef FormData_pg_transform *Form_pg_transform;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, on pg_transform using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, on pg_transform using btree(trftype oid_ops, trflang oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops));
 
 #endif							/* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
index 3679b0395f..61c9353fff 100644
--- a/src/include/catalog/pg_trigger.h
+++ b/src/include/catalog/pg_trigger.h
@@ -81,9 +81,9 @@ typedef FormData_pg_trigger *Form_pg_trigger;
 
 DECLARE_TOAST(pg_trigger, 2336, 2337);
 
-DECLARE_INDEX(pg_trigger_tgconstraint_index, 2699, TriggerConstraintIndexId, on pg_trigger using btree(tgconstraint oid_ops));
-DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, TriggerRelidNameIndexId, on pg_trigger using btree(tgrelid oid_ops, tgname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_trigger_oid_index, 2702, TriggerOidIndexId, on pg_trigger using btree(oid oid_ops));
+DECLARE_INDEX(pg_trigger_tgconstraint_index, 2699, TriggerConstraintIndexId, pg_trigger, btree(tgconstraint oid_ops));
+DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, TriggerRelidNameIndexId, pg_trigger, btree(tgrelid oid_ops, tgname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_trigger_oid_index, 2702, TriggerOidIndexId, pg_trigger, btree(oid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((tgrelid, tgattr), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index aee0bf71af..e52720387d 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -47,7 +47,7 @@ CATALOG(pg_ts_config,3602,TSConfigRelationId)
 
 typedef FormData_pg_ts_config *Form_pg_ts_config;
 
-DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, on pg_ts_config using btree(cfgname name_ops, cfgnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, on pg_ts_config using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops));
 
 #endif							/* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index 359368ecd6..91f092ca48 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -44,6 +44,6 @@ CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
 
 typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, on pg_ts_config_map using btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
 
 #endif							/* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 476325f010..10a6490213 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -53,7 +53,7 @@ typedef FormData_pg_ts_dict *Form_pg_ts_dict;
 
 DECLARE_TOAST(pg_ts_dict, 4169, 4170);
 
-DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, on pg_ts_dict using btree(dictname name_ops, dictnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, on pg_ts_dict using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops));
 
 #endif							/* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index 283de252b4..57d9e8428a 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -54,7 +54,7 @@ CATALOG(pg_ts_parser,3601,TSParserRelationId)
 
 typedef FormData_pg_ts_parser *Form_pg_ts_parser;
 
-DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, on pg_ts_parser using btree(prsname name_ops, prsnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, on pg_ts_parser using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops));
 
 #endif							/* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index f4e510c8f9..f3bdc7b200 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -45,7 +45,7 @@ CATALOG(pg_ts_template,3764,TSTemplateRelationId)
 
 typedef FormData_pg_ts_template *Form_pg_ts_template;
 
-DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, on pg_ts_template using btree(tmplname name_ops, tmplnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, on pg_ts_template using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops));
 
 #endif							/* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 519e570c8c..508ba7b0f7 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -262,8 +262,8 @@ typedef FormData_pg_type *Form_pg_type;
 
 DECLARE_TOAST(pg_type, 4171, 4172);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, on pg_type using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, on pg_type using btree(typname name_ops, typnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index 528c94a7c4..eca33f4cb4 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -49,7 +49,7 @@ typedef FormData_pg_user_mapping *Form_pg_user_mapping;
 
 DECLARE_TOAST(pg_user_mapping, 4173, 4174);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, on pg_user_mapping using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, on pg_user_mapping using btree(umuser oid_ops, umserver oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops));
 
 #endif							/* PG_USER_MAPPING_H */
-- 
2.41.0

v2-0003-genbki.pl-Factor-out-boilerplate-generation.patchtext/plain; charset=UTF-8; name=v2-0003-genbki.pl-Factor-out-boilerplate-generation.patchDownload
From 349e2844b0e8eac0caee7d4a7293b81bb877d5ed Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v2 3/6] genbki.pl: Factor out boilerplate generation

---
 src/backend/catalog/genbki.pl | 84 ++++++++++++-----------------------
 1 file changed, 29 insertions(+), 55 deletions(-)

diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index c7657cc47c..851bae14f0 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -439,25 +439,8 @@
 	open my $def, '>', $def_file . $tmpext
 	  or die "can't open $def_file$tmpext: $!";
 
-	# Opening boilerplate for pg_*_d.h
-	printf $def <<EOM, $catname, $catname, uc $catname, uc $catname;
-/*-------------------------------------------------------------------------
- *
- * %s_d.h
- *    Macro definitions for %s
- *
- * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * NOTES
- *  ******************************
- *  *** DO NOT EDIT THIS FILE! ***
- *  ******************************
- *
- *  It has been GENERATED by src/backend/catalog/genbki.pl
- *
- *-------------------------------------------------------------------------
- */
+	print_boilerplate($def, "${catname}_d.h", "Macro definitions for $catname");
+	printf $def <<EOM, uc $catname, uc $catname;
 #ifndef %s_D_H
 #define %s_D_H
 
@@ -705,25 +688,8 @@
 
 # Now generate schemapg.h
 
-# Opening boilerplate for schemapg.h
+print_boilerplate($schemapg, "schemapg.h", "Schema_pg_xxx macros for use by relcache.c");
 print $schemapg <<EOM;
-/*-------------------------------------------------------------------------
- *
- * schemapg.h
- *    Schema_pg_xxx macros for use by relcache.c
- *
- * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * NOTES
- *  ******************************
- *  *** DO NOT EDIT THIS FILE! ***
- *  ******************************
- *
- *  It has been GENERATED by src/backend/catalog/genbki.pl
- *
- *-------------------------------------------------------------------------
- */
 #ifndef SCHEMAPG_H
 #define SCHEMAPG_H
 EOM
@@ -741,25 +707,9 @@
 
 # Now generate system_fk_info.h
 
-# Opening boilerplate for system_fk_info.h
+print_boilerplate($fk_info, "system_fk_info.h",
+	"Data about the foreign-key relationships in the system catalogs");
 print $fk_info <<EOM;
-/*-------------------------------------------------------------------------
- *
- * system_fk_info.h
- *    Data about the foreign-key relationships in the system catalogs
- *
- * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * NOTES
- *  ******************************
- *  *** DO NOT EDIT THIS FILE! ***
- *  ******************************
- *
- *  It has been GENERATED by src/backend/catalog/genbki.pl
- *
- *-------------------------------------------------------------------------
- */
 #ifndef SYSTEM_FK_INFO_H
 #define SYSTEM_FK_INFO_H
 
@@ -1121,6 +1071,30 @@ sub assign_next_oid
 	return $result;
 }
 
+sub print_boilerplate
+{
+	my ($fh, $fname, $descr) = @_;
+	printf $fh <<EOM, $fname, $descr;
+/*-------------------------------------------------------------------------
+ *
+ * %s
+ *    %s
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ *  ******************************
+ *  *** DO NOT EDIT THIS FILE! ***
+ *  ******************************
+ *
+ *  It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+EOM
+}
+
 sub usage
 {
 	die <<EOM;
-- 
2.41.0

v2-0004-Generate-syscache-info-from-catalog-files.patchtext/plain; charset=UTF-8; name=v2-0004-Generate-syscache-info-from-catalog-files.patchDownload
From 6f36e4648f4dce809d82d68b5dba333810783d09 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v2 4/6] Generate syscache info from catalog files

DECLARE_UNIQUE_INDEX gets two additional arguments with the syscache
ID macro and the number of buckets.  From that, we can generate the
existing tables in syscache.h and syscache.c via genbki.pl.
---
 src/backend/catalog/.gitignore                |   2 +
 src/backend/catalog/Catalog.pm                |   6 +-
 src/backend/catalog/Makefile                  |   2 +-
 src/backend/catalog/genbki.pl                 |  55 ++
 src/backend/utils/cache/syscache.c            | 572 +-----------------
 src/include/catalog/.gitignore                |   2 +
 src/include/catalog/genbki.h                  |   7 +-
 src/include/catalog/meson.build               |  18 +-
 src/include/catalog/pg_aggregate.h            |   2 +-
 src/include/catalog/pg_am.h                   |   4 +-
 src/include/catalog/pg_amop.h                 |   4 +-
 src/include/catalog/pg_amproc.h               |   2 +-
 src/include/catalog/pg_attribute.h            |   4 +-
 src/include/catalog/pg_auth_members.h         |   4 +-
 src/include/catalog/pg_authid.h               |   4 +-
 src/include/catalog/pg_cast.h                 |   2 +-
 src/include/catalog/pg_class.h                |   4 +-
 src/include/catalog/pg_collation.h            |   4 +-
 src/include/catalog/pg_constraint.h           |   2 +-
 src/include/catalog/pg_conversion.h           |   6 +-
 src/include/catalog/pg_database.h             |   2 +-
 src/include/catalog/pg_default_acl.h          |   2 +-
 src/include/catalog/pg_enum.h                 |   4 +-
 src/include/catalog/pg_event_trigger.h        |   4 +-
 src/include/catalog/pg_foreign_data_wrapper.h |   4 +-
 src/include/catalog/pg_foreign_server.h       |   4 +-
 src/include/catalog/pg_foreign_table.h        |   2 +-
 src/include/catalog/pg_index.h                |   2 +-
 src/include/catalog/pg_language.h             |   4 +-
 src/include/catalog/pg_namespace.h            |   4 +-
 src/include/catalog/pg_opclass.h              |   4 +-
 src/include/catalog/pg_operator.h             |   4 +-
 src/include/catalog/pg_opfamily.h             |   4 +-
 src/include/catalog/pg_parameter_acl.h        |   4 +-
 src/include/catalog/pg_partitioned_table.h    |   2 +-
 src/include/catalog/pg_proc.h                 |   4 +-
 src/include/catalog/pg_publication.h          |   4 +-
 .../catalog/pg_publication_namespace.h        |   4 +-
 src/include/catalog/pg_publication_rel.h      |   4 +-
 src/include/catalog/pg_range.h                |   4 +-
 src/include/catalog/pg_replication_origin.h   |   4 +-
 src/include/catalog/pg_rewrite.h              |   2 +-
 src/include/catalog/pg_sequence.h             |   2 +-
 src/include/catalog/pg_statistic.h            |   2 +-
 src/include/catalog/pg_statistic_ext.h        |   4 +-
 src/include/catalog/pg_statistic_ext_data.h   |   2 +-
 src/include/catalog/pg_subscription.h         |   4 +-
 src/include/catalog/pg_subscription_rel.h     |   2 +-
 src/include/catalog/pg_tablespace.h           |   2 +-
 src/include/catalog/pg_transform.h            |   4 +-
 src/include/catalog/pg_ts_config.h            |   4 +-
 src/include/catalog/pg_ts_config_map.h        |   2 +-
 src/include/catalog/pg_ts_dict.h              |   4 +-
 src/include/catalog/pg_ts_parser.h            |   4 +-
 src/include/catalog/pg_ts_template.h          |   4 +-
 src/include/catalog/pg_type.h                 |   4 +-
 src/include/catalog/pg_user_mapping.h         |   4 +-
 src/include/utils/syscache.h                  |  98 +--
 src/tools/pginclude/cpluspluscheck            |   5 +
 src/tools/pginclude/headerscheck              |   5 +
 60 files changed, 187 insertions(+), 751 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index 237ff54165..ff65560379 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,5 +1,7 @@
 /postgres.bki
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /system_constraints.sql
 /pg_*_d.h
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index be56cc153f..de67632793 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -118,7 +118,11 @@ sub ParseHeader
 			 (?<index_oid>\d+),\s*
 			 (?<index_oid_macro>\w+),\s*
 			 (?<table_name>\w+),\s*
-			 (?<index_decl>.+)\s*
+			 (?<index_decl>\w+\s*\([\w\s,]+\))\s*
+			 (?:,\s*
+			   (?<syscache_name>\w+),\s*
+			   (?<syscache_nbuckets>\w+)
+			 )?
 			 \)/x
 		  )
 		{
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index a60107bf94..0dfefae28e 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -74,7 +74,7 @@ CATALOG_HEADERS := \
 	pg_sequence.h pg_publication.h pg_publication_namespace.h \
 	pg_publication_rel.h pg_subscription.h pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 851bae14f0..80a7828d6c 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -56,6 +56,7 @@
 my %catalog_data;
 my @toast_decls;
 my @index_decls;
+my %syscaches;
 my %oidcounts;
 my @system_constraints;
 
@@ -150,6 +151,21 @@
 			  $index->{is_pkey} ? "PRIMARY KEY" : "UNIQUE",
 			  $index->{index_name};
 		}
+
+		if ($index->{syscache_name})
+		{
+			my $tbl = $index->{table_name};
+			my $key = $index->{index_decl};
+			$key =~ s/^\w+\(//;
+			$key =~ s/\)$//;
+			$key =~ s/(\w+)\s+\w+/Anum_${tbl}_$1/g;
+			$syscaches{$index->{syscache_name}} = {
+				table_oid_macro => $catalogs{$tbl}->{relation_oid_macro},
+				index_oid_macro => $index->{index_oid_macro},
+				key => $key,
+				nbuckets => $index->{syscache_nbuckets},
+			};
+		}
 	}
 }
 
@@ -419,6 +435,12 @@
 my $constraints_file = $output_path . 'system_constraints.sql';
 open my $constraints, '>', $constraints_file . $tmpext
   or die "can't open $constraints_file$tmpext: $!";
+my $syscache_info_h = $output_path . 'syscache_info.h';
+open my $syscache_info_h_fh, '>', $syscache_info_h . $tmpext
+  or die "can't open $syscache_info_h$tmpext: $!";
+my $syscache_info_c = $output_path . 'syscache_info.c.h';
+open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
+  or die "can't open $syscache_info_c$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -751,17 +773,50 @@
 # Closing boilerplate for system_fk_info.h
 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_info_h_fh, "syscache_info.h", "SysCache identifiers");
+print $syscache_info_h_fh "enum SysCacheIdentifier
+{
+";
+
+print_boilerplate($syscache_info_c_fh, "syscache_info.c.h", "SysCache definitions");
+print $syscache_info_c_fh "static const struct cachedesc cacheinfo[] = {\n";
+
+my $last_syscache;
+foreach my $syscache (sort keys %syscaches)
+{
+	print $syscache_info_h_fh "\t$syscache,\n";
+	$last_syscache = $syscache;
+
+	print $syscache_info_c_fh "\t[$syscache] = {\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{table_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{index_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\tKEY(", $syscaches{$syscache}{key}, "),\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{nbuckets}, "\n";
+	print $syscache_info_c_fh "\t},\n";
+}
+
+print $syscache_info_h_fh "};\n";
+print $syscache_info_h_fh "#define SysCacheSize ($last_syscache + 1)\n";
+
+print $syscache_info_c_fh "};\n";
+
 # We're done emitting data
 close $bki;
 close $schemapg;
 close $fk_info;
 close $constraints;
+close $syscache_info_h_fh;
+close $syscache_info_c_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
 Catalog::RenameTempFile($schemafile, $tmpext);
 Catalog::RenameTempFile($fk_info_file, $tmpext);
 Catalog::RenameTempFile($constraints_file, $tmpext);
+Catalog::RenameTempFile($syscache_info_h, $tmpext);
+Catalog::RenameTempFile($syscache_info_c, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 4e4a34bde8..6daa81ca83 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -85,18 +85,6 @@
 
 	Adding system caches:
 
-	Add your new cache to the list in include/utils/syscache.h.
-	Keep the list sorted alphabetically.
-
-	Add your entry to the cacheinfo[] array below. All cache lists are
-	alphabetical, so add it in the proper place.  Specify the relation OID,
-	index OID, number of keys, key attribute numbers, and initial number of
-	hash buckets.
-
-	The number of hash buckets must be a power of 2.  It's reasonable to
-	set this to the number of entries that might be in the particular cache
-	in a medium-size database.
-
 	There must be a unique index underlying each syscache (ie, an index
 	whose key is the same as that of the cache).  If there is not one
 	already, add the definition for it to include/catalog/pg_*.h using
@@ -104,6 +92,13 @@
 	(Adding an index requires a catversion.h update, while simply
 	adding/deleting caches only requires a recompile.)
 
+	Then add the name of your name cache and the initial number of hash
+	buckets as arguments of DECLARE_UNIQUE_INDEX.
+
+	The number of hash buckets must be a power of 2.  It's reasonable to
+	set this to the number of entries that might be in the particular cache
+	in a medium-size database.
+
 	Finally, any place your relation gets heap_insert() or
 	heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
 	instead, which also update indexes.  The heap_* calls do not do that.
@@ -126,558 +121,7 @@ struct cachedesc
 /* Macro to provide nkeys and key array with convenient syntax. */
 #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
 
-static const struct cachedesc cacheinfo[] = {
-	[AGGFNOID] = {
-		AggregateRelationId,
-		AggregateFnoidIndexId,
-		KEY(Anum_pg_aggregate_aggfnoid),
-		16
-	},
-	[AMNAME] = {
-		AccessMethodRelationId,
-		AmNameIndexId,
-		KEY(Anum_pg_am_amname),
-		4
-	},
-	[AMOID] = {
-		AccessMethodRelationId,
-		AmOidIndexId,
-		KEY(Anum_pg_am_oid),
-		4
-	},
-	[AMOPOPID] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodOperatorIndexId,
-		KEY(Anum_pg_amop_amopopr,
-			Anum_pg_amop_amoppurpose,
-			Anum_pg_amop_amopfamily),
-		64
-	},
-	[AMOPSTRATEGY] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodStrategyIndexId,
-		KEY(Anum_pg_amop_amopfamily,
-			Anum_pg_amop_amoplefttype,
-			Anum_pg_amop_amoprighttype,
-			Anum_pg_amop_amopstrategy),
-		64
-	},
-	[AMPROCNUM] = {
-		AccessMethodProcedureRelationId,
-		AccessMethodProcedureIndexId,
-		KEY(Anum_pg_amproc_amprocfamily,
-			Anum_pg_amproc_amproclefttype,
-			Anum_pg_amproc_amprocrighttype,
-			Anum_pg_amproc_amprocnum),
-		16
-	},
-	[ATTNAME] = {
-		AttributeRelationId,
-		AttributeRelidNameIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attname),
-		32
-	},
-	[ATTNUM] = {
-		AttributeRelationId,
-		AttributeRelidNumIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attnum),
-		128
-	},
-	[AUTHMEMMEMROLE] = {
-		AuthMemRelationId,
-		AuthMemMemRoleIndexId,
-		KEY(Anum_pg_auth_members_member,
-			Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHMEMROLEMEM] = {
-		AuthMemRelationId,
-		AuthMemRoleMemIndexId,
-		KEY(Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_member,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHNAME] = {
-		AuthIdRelationId,
-		AuthIdRolnameIndexId,
-		KEY(Anum_pg_authid_rolname),
-		8
-	},
-	[AUTHOID] = {
-		AuthIdRelationId,
-		AuthIdOidIndexId,
-		KEY(Anum_pg_authid_oid),
-		8
-	},
-	[CASTSOURCETARGET] = {
-		CastRelationId,
-		CastSourceTargetIndexId,
-		KEY(Anum_pg_cast_castsource,
-			Anum_pg_cast_casttarget),
-		256
-	},
-	[CLAAMNAMENSP] = {
-		OperatorClassRelationId,
-		OpclassAmNameNspIndexId,
-		KEY(Anum_pg_opclass_opcmethod,
-			Anum_pg_opclass_opcname,
-			Anum_pg_opclass_opcnamespace),
-		8
-	},
-	[CLAOID] = {
-		OperatorClassRelationId,
-		OpclassOidIndexId,
-		KEY(Anum_pg_opclass_oid),
-		8
-	},
-	[COLLNAMEENCNSP] = {
-		CollationRelationId,
-		CollationNameEncNspIndexId,
-		KEY(Anum_pg_collation_collname,
-			Anum_pg_collation_collencoding,
-			Anum_pg_collation_collnamespace),
-		8
-	},
-	[COLLOID] = {
-		CollationRelationId,
-		CollationOidIndexId,
-		KEY(Anum_pg_collation_oid),
-		8
-	},
-	[CONDEFAULT] = {
-		ConversionRelationId,
-		ConversionDefaultIndexId,
-		KEY(Anum_pg_conversion_connamespace,
-			Anum_pg_conversion_conforencoding,
-			Anum_pg_conversion_contoencoding,
-			Anum_pg_conversion_oid),
-		8
-	},
-	[CONNAMENSP] = {
-		ConversionRelationId,
-		ConversionNameNspIndexId,
-		KEY(Anum_pg_conversion_conname,
-			Anum_pg_conversion_connamespace),
-		8
-	},
-	[CONSTROID] = {
-		ConstraintRelationId,
-		ConstraintOidIndexId,
-		KEY(Anum_pg_constraint_oid),
-		16
-	},
-	[CONVOID] = {
-		ConversionRelationId,
-		ConversionOidIndexId,
-		KEY(Anum_pg_conversion_oid),
-		8
-	},
-	[DATABASEOID] = {
-		DatabaseRelationId,
-		DatabaseOidIndexId,
-		KEY(Anum_pg_database_oid),
-		4
-	},
-	[DEFACLROLENSPOBJ] = {
-		DefaultAclRelationId,
-		DefaultAclRoleNspObjIndexId,
-		KEY(Anum_pg_default_acl_defaclrole,
-			Anum_pg_default_acl_defaclnamespace,
-			Anum_pg_default_acl_defaclobjtype),
-		8
-	},
-	[ENUMOID] = {
-		EnumRelationId,
-		EnumOidIndexId,
-		KEY(Anum_pg_enum_oid),
-		8
-	},
-	[ENUMTYPOIDNAME] = {
-		EnumRelationId,
-		EnumTypIdLabelIndexId,
-		KEY(Anum_pg_enum_enumtypid,
-			Anum_pg_enum_enumlabel),
-		8
-	},
-	[EVENTTRIGGERNAME] = {
-		EventTriggerRelationId,
-		EventTriggerNameIndexId,
-		KEY(Anum_pg_event_trigger_evtname),
-		8
-	},
-	[EVENTTRIGGEROID] = {
-		EventTriggerRelationId,
-		EventTriggerOidIndexId,
-		KEY(Anum_pg_event_trigger_oid),
-		8
-	},
-	[FOREIGNDATAWRAPPERNAME] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperNameIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_fdwname),
-		2
-	},
-	[FOREIGNDATAWRAPPEROID] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperOidIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_oid),
-		2
-	},
-	[FOREIGNSERVERNAME] = {
-		ForeignServerRelationId,
-		ForeignServerNameIndexId,
-		KEY(Anum_pg_foreign_server_srvname),
-		2
-	},
-	[FOREIGNSERVEROID] = {
-		ForeignServerRelationId,
-		ForeignServerOidIndexId,
-		KEY(Anum_pg_foreign_server_oid),
-		2
-	},
-	[FOREIGNTABLEREL] = {
-		ForeignTableRelationId,
-		ForeignTableRelidIndexId,
-		KEY(Anum_pg_foreign_table_ftrelid),
-		4
-	},
-	[INDEXRELID] = {
-		IndexRelationId,
-		IndexRelidIndexId,
-		KEY(Anum_pg_index_indexrelid),
-		64
-	},
-	[LANGNAME] = {
-		LanguageRelationId,
-		LanguageNameIndexId,
-		KEY(Anum_pg_language_lanname),
-		4
-	},
-	[LANGOID] = {
-		LanguageRelationId,
-		LanguageOidIndexId,
-		KEY(Anum_pg_language_oid),
-		4
-	},
-	[NAMESPACENAME] = {
-		NamespaceRelationId,
-		NamespaceNameIndexId,
-		KEY(Anum_pg_namespace_nspname),
-		4
-	},
-	[NAMESPACEOID] = {
-		NamespaceRelationId,
-		NamespaceOidIndexId,
-		KEY(Anum_pg_namespace_oid),
-		16
-	},
-	[OPERNAMENSP] = {
-		OperatorRelationId,
-		OperatorNameNspIndexId,
-		KEY(Anum_pg_operator_oprname,
-			Anum_pg_operator_oprleft,
-			Anum_pg_operator_oprright,
-			Anum_pg_operator_oprnamespace),
-		256
-	},
-	[OPEROID] = {
-		OperatorRelationId,
-		OperatorOidIndexId,
-		KEY(Anum_pg_operator_oid),
-		32
-	},
-	[OPFAMILYAMNAMENSP] = {
-		OperatorFamilyRelationId,
-		OpfamilyAmNameNspIndexId,
-		KEY(Anum_pg_opfamily_opfmethod,
-			Anum_pg_opfamily_opfname,
-			Anum_pg_opfamily_opfnamespace),
-		8
-	},
-	[OPFAMILYOID] = {
-		OperatorFamilyRelationId,
-		OpfamilyOidIndexId,
-		KEY(Anum_pg_opfamily_oid),
-		8
-	},
-	[PARAMETERACLNAME] = {
-		ParameterAclRelationId,
-		ParameterAclParnameIndexId,
-		KEY(Anum_pg_parameter_acl_parname),
-		4
-	},
-	[PARAMETERACLOID] = {
-		ParameterAclRelationId,
-		ParameterAclOidIndexId,
-		KEY(Anum_pg_parameter_acl_oid),
-		4
-	},
-	[PARTRELID] = {
-		PartitionedRelationId,
-		PartitionedRelidIndexId,
-		KEY(Anum_pg_partitioned_table_partrelid),
-		32
-	},
-	[PROCNAMEARGSNSP] = {
-		ProcedureRelationId,
-		ProcedureNameArgsNspIndexId,
-		KEY(Anum_pg_proc_proname,
-			Anum_pg_proc_proargtypes,
-			Anum_pg_proc_pronamespace),
-		128
-	},
-	[PROCOID] = {
-		ProcedureRelationId,
-		ProcedureOidIndexId,
-		KEY(Anum_pg_proc_oid),
-		128
-	},
-	[PUBLICATIONNAME] = {
-		PublicationRelationId,
-		PublicationNameIndexId,
-		KEY(Anum_pg_publication_pubname),
-		8
-	},
-	[PUBLICATIONNAMESPACE] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespaceObjectIndexId,
-		KEY(Anum_pg_publication_namespace_oid),
-		64
-	},
-	[PUBLICATIONNAMESPACEMAP] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespacePnnspidPnpubidIndexId,
-		KEY(Anum_pg_publication_namespace_pnnspid,
-			Anum_pg_publication_namespace_pnpubid),
-		64
-	},
-	[PUBLICATIONOID] = {
-		PublicationRelationId,
-		PublicationObjectIndexId,
-		KEY(Anum_pg_publication_oid),
-		8
-	},
-	[PUBLICATIONREL] = {
-		PublicationRelRelationId,
-		PublicationRelObjectIndexId,
-		KEY(Anum_pg_publication_rel_oid),
-		64
-	},
-	[PUBLICATIONRELMAP] = {
-		PublicationRelRelationId,
-		PublicationRelPrrelidPrpubidIndexId,
-		KEY(Anum_pg_publication_rel_prrelid,
-			Anum_pg_publication_rel_prpubid),
-		64
-	},
-	[RANGEMULTIRANGE] = {
-		RangeRelationId,
-		RangeMultirangeTypidIndexId,
-		KEY(Anum_pg_range_rngmultitypid),
-		4
-	},
-	[RANGETYPE] = {
-		RangeRelationId,
-		RangeTypidIndexId,
-		KEY(Anum_pg_range_rngtypid),
-		4
-	},
-	[RELNAMENSP] = {
-		RelationRelationId,
-		ClassNameNspIndexId,
-		KEY(Anum_pg_class_relname,
-			Anum_pg_class_relnamespace),
-		128
-	},
-	[RELOID] = {
-		RelationRelationId,
-		ClassOidIndexId,
-		KEY(Anum_pg_class_oid),
-		128
-	},
-	[REPLORIGIDENT] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginIdentIndex,
-		KEY(Anum_pg_replication_origin_roident),
-		16
-	},
-	[REPLORIGNAME] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginNameIndex,
-		KEY(Anum_pg_replication_origin_roname),
-		16
-	},
-	[RULERELNAME] = {
-		RewriteRelationId,
-		RewriteRelRulenameIndexId,
-		KEY(Anum_pg_rewrite_ev_class,
-			Anum_pg_rewrite_rulename),
-		8
-	},
-	[SEQRELID] = {
-		SequenceRelationId,
-		SequenceRelidIndexId,
-		KEY(Anum_pg_sequence_seqrelid),
-		32
-	},
-	[STATEXTDATASTXOID] = {
-		StatisticExtDataRelationId,
-		StatisticExtDataStxoidInhIndexId,
-		KEY(Anum_pg_statistic_ext_data_stxoid,
-			Anum_pg_statistic_ext_data_stxdinherit),
-		4
-	},
-	[STATEXTNAMENSP] = {
-		StatisticExtRelationId,
-		StatisticExtNameIndexId,
-		KEY(Anum_pg_statistic_ext_stxname,
-			Anum_pg_statistic_ext_stxnamespace),
-		4
-	},
-	[STATEXTOID] = {
-		StatisticExtRelationId,
-		StatisticExtOidIndexId,
-		KEY(Anum_pg_statistic_ext_oid),
-		4
-	},
-	[STATRELATTINH] = {
-		StatisticRelationId,
-		StatisticRelidAttnumInhIndexId,
-		KEY(Anum_pg_statistic_starelid,
-			Anum_pg_statistic_staattnum,
-			Anum_pg_statistic_stainherit),
-		128
-	},
-	[SUBSCRIPTIONNAME] = {
-		SubscriptionRelationId,
-		SubscriptionNameIndexId,
-		KEY(Anum_pg_subscription_subdbid,
-			Anum_pg_subscription_subname),
-		4
-	},
-	[SUBSCRIPTIONOID] = {
-		SubscriptionRelationId,
-		SubscriptionObjectIndexId,
-		KEY(Anum_pg_subscription_oid),
-		4
-	},
-	[SUBSCRIPTIONRELMAP] = {
-		SubscriptionRelRelationId,
-		SubscriptionRelSrrelidSrsubidIndexId,
-		KEY(Anum_pg_subscription_rel_srrelid,
-			Anum_pg_subscription_rel_srsubid),
-		64
-	},
-	[TABLESPACEOID] = {
-		TableSpaceRelationId,
-		TablespaceOidIndexId,
-		KEY(Anum_pg_tablespace_oid),
-		4
-	},
-	[TRFOID] = {
-		TransformRelationId,
-		TransformOidIndexId,
-		KEY(Anum_pg_transform_oid),
-		16
-	},
-	[TRFTYPELANG] = {
-		TransformRelationId,
-		TransformTypeLangIndexId,
-		KEY(Anum_pg_transform_trftype,
-			Anum_pg_transform_trflang),
-		16
-	},
-	[TSCONFIGMAP] = {
-		TSConfigMapRelationId,
-		TSConfigMapIndexId,
-		KEY(Anum_pg_ts_config_map_mapcfg,
-			Anum_pg_ts_config_map_maptokentype,
-			Anum_pg_ts_config_map_mapseqno),
-		2
-	},
-	[TSCONFIGNAMENSP] = {
-		TSConfigRelationId,
-		TSConfigNameNspIndexId,
-		KEY(Anum_pg_ts_config_cfgname,
-			Anum_pg_ts_config_cfgnamespace),
-		2
-	},
-	[TSCONFIGOID] = {
-		TSConfigRelationId,
-		TSConfigOidIndexId,
-		KEY(Anum_pg_ts_config_oid),
-		2
-	},
-	[TSDICTNAMENSP] = {
-		TSDictionaryRelationId,
-		TSDictionaryNameNspIndexId,
-		KEY(Anum_pg_ts_dict_dictname,
-			Anum_pg_ts_dict_dictnamespace),
-		2
-	},
-	[TSDICTOID] = {
-		TSDictionaryRelationId,
-		TSDictionaryOidIndexId,
-		KEY(Anum_pg_ts_dict_oid),
-		2
-	},
-	[TSPARSERNAMENSP] = {
-		TSParserRelationId,
-		TSParserNameNspIndexId,
-		KEY(Anum_pg_ts_parser_prsname,
-			Anum_pg_ts_parser_prsnamespace),
-		2
-	},
-	[TSPARSEROID] = {
-		TSParserRelationId,
-		TSParserOidIndexId,
-		KEY(Anum_pg_ts_parser_oid),
-		2
-	},
-	[TSTEMPLATENAMENSP] = {
-		TSTemplateRelationId,
-		TSTemplateNameNspIndexId,
-		KEY(Anum_pg_ts_template_tmplname,
-			Anum_pg_ts_template_tmplnamespace),
-		2
-	},
-	[TSTEMPLATEOID] = {
-		TSTemplateRelationId,
-		TSTemplateOidIndexId,
-		KEY(Anum_pg_ts_template_oid),
-		2
-	},
-	[TYPENAMENSP] = {
-		TypeRelationId,
-		TypeNameNspIndexId,
-		KEY(Anum_pg_type_typname,
-			Anum_pg_type_typnamespace),
-		64
-	},
-	[TYPEOID] = {
-		TypeRelationId,
-		TypeOidIndexId,
-		KEY(Anum_pg_type_oid),
-		64
-	},
-	[USERMAPPINGOID] = {
-		UserMappingRelationId,
-		UserMappingOidIndexId,
-		KEY(Anum_pg_user_mapping_oid),
-		2
-	},
-	[USERMAPPINGUSERSERVER] = {
-		UserMappingRelationId,
-		UserMappingUserServerIndexId,
-		KEY(Anum_pg_user_mapping_umuser,
-			Anum_pg_user_mapping_umserver),
-		2
-	}
-};
+#include "catalog/syscache_info.c.h"
 
 StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
 				 "SysCacheSize does not match syscache.c's array");
diff --git a/src/include/catalog/.gitignore b/src/include/catalog/.gitignore
index 6b83d4c7e6..f7ddf2554b 100644
--- a/src/include/catalog/.gitignore
+++ b/src/include/catalog/.gitignore
@@ -1,4 +1,6 @@
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /pg_*_d.h
 /header-stamp
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index e22a6902fb..2d5bd38cde 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -77,13 +77,14 @@
  * is the name of a #define to generate for its OID.  References to the index
  * in the C code should always use these #defines, not the actual index name
  * (much less the numeric OID).  The fourth argument is the table name.  The
- * rest is much like a standard 'create index' SQL command.
+ * decl argument is much like a standard 'create index' SQL command.
+ * Optionally, specify the syscache ID and bucket size.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */
 #define DECLARE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
 
 /*
  * These lines inform genbki.pl about manually-assigned OIDs that do not
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index c3fd05d027..f0398c09df 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -97,8 +97,22 @@ bki_data_f = files(bki_data)
 
 
 input = []
-output_files = ['postgres.bki', 'system_constraints.sql', 'schemapg.h', 'system_fk_info.h']
-output_install = [dir_data, dir_data, dir_include_server / 'catalog', dir_include_server / 'catalog']
+output_files = [
+  'postgres.bki',
+  'system_constraints.sql',
+  'schemapg.h',
+  'syscache_info.c.h',
+  'syscache_info.h',
+  'system_fk_info.h',
+]
+output_install = [
+  dir_data,
+  dir_data,
+  dir_include_server / 'catalog',
+  false,
+  dir_include_server / 'catalog',
+  dir_include_server / 'catalog',
+]
 
 foreach h : catalog_headers
   fname = h.split('.h')[0] + '_d.h'
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 085149e258..e6f6f4ccb5 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -110,7 +110,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
 
 DECLARE_TOAST(pg_aggregate, 4159, 4160);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops), AGGFNOID, 16);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index d5314bb38b..e3a1313e6c 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -47,8 +47,8 @@ CATALOG(pg_am,2601,AccessMethodRelationId)
  */
 typedef FormData_pg_am *Form_pg_am;
 
-DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops), AMNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops), AMOID, 4);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index c9bb7b4787..3449166507 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -87,8 +87,8 @@ CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
  */
 typedef FormData_pg_amop *Form_pg_amop;
 
-DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
-DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops), AMOPSTRATEGY, 64);
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops), AMOPOPID, 64);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, pg_amop, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 5acf4efab9..31e67be344 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -67,7 +67,7 @@ CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
  */
 typedef FormData_pg_amproc *Form_pg_amproc;
 
-DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops), AMPROCNUM, 16);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, pg_amproc, btree(oid oid_ops));
 
 #endif							/* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index f0d6de7c1f..9e99237f56 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -208,8 +208,8 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
  */
 typedef FormData_pg_attribute *Form_pg_attribute;
 
-DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops), ATTNAME, 32);
+DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops), ATTNUM, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index 4ab8a9f7b7..37104cf20f 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -46,8 +46,8 @@ CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_
 typedef FormData_pg_auth_members *Form_pg_auth_members;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, pg_auth_members, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops), AUTHMEMROLEMEM, 8);
+DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops), AUTHMEMMEMROLE, 8);
 DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, pg_auth_members, btree(grantor oid_ops));
 
 #endif							/* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index 0e7ddc56ea..748ab95fad 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -57,7 +57,7 @@ typedef FormData_pg_authid *Form_pg_authid;
 
 DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops), AUTHNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops), AUTHOID, 8);
 
 #endif							/* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index a2518388b3..32235776ce 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -57,7 +57,7 @@ CATALOG(pg_cast,2605,CastRelationId)
 typedef FormData_pg_cast *Form_pg_cast;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, pg_cast, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops), CASTSOURCETARGET, 256);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 55dcd54100..52edbf0229 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -152,8 +152,8 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat
  */
 typedef FormData_pg_class *Form_pg_class;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops), RELOID, 128);
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops), RELNAMENSP, 128);
 DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, pg_class, btree(reltablespace oid_ops, relfilenode oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index 2d7dcde183..6cf59f479a 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -59,8 +59,8 @@ typedef FormData_pg_collation *Form_pg_collation;
 
 DECLARE_TOAST(pg_collation, 6175, 6176);
 
-DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops), COLLNAMEENCNSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops), COLLOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 0d47c9b589..de1b7bcd57 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -169,7 +169,7 @@ DECLARE_TOAST(pg_constraint, 2832, 2833);
 DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, pg_constraint, btree(conname name_ops, connamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
 DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops), CONSTROID, 16);
 DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops));
 
 /* conkey can contain zero (InvalidAttrNumber) if a whole-row Var is used */
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index 42847fdf12..acd944a4ae 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -60,9 +60,9 @@ CATALOG(pg_conversion,2607,ConversionRelationId)
  */
 typedef FormData_pg_conversion *Form_pg_conversion;
 
-DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops), CONDEFAULT, 8);
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops), CONNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops), CONVOID, 8);
 
 
 extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 44e2ed73cf..1eceb52174 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -92,7 +92,7 @@ typedef FormData_pg_database *Form_pg_database;
 DECLARE_TOAST_WITH_MACRO(pg_database, 4177, 4178, PgDatabaseToastTable, PgDatabaseToastIndex);
 
 DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, pg_database, btree(datname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops), DATABASEOID, 4);
 
 /*
  * pg_database.dat contains an entry for template1, but not for the template0
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index 803ce3eab8..b526af26a6 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -51,7 +51,7 @@ typedef FormData_pg_default_acl *Form_pg_default_acl;
 
 DECLARE_TOAST(pg_default_acl, 4143, 4144);
 
-DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
+DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops), DEFACLROLENSPOBJ, 8);
 DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, pg_default_acl, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index c483cb1042..4ea20aeabe 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -43,8 +43,8 @@ CATALOG(pg_enum,3501,EnumRelationId)
  */
 typedef FormData_pg_enum *Form_pg_enum;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops), ENUMOID, 8);
+DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops), ENUMTYPOIDNAME, 8);
 DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, pg_enum, btree(enumtypid oid_ops, enumsortorder float4_ops));
 
 /*
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index 0ec42edff6..ca1c5bd728 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -51,7 +51,7 @@ typedef FormData_pg_event_trigger *Form_pg_event_trigger;
 
 DECLARE_TOAST(pg_event_trigger, 4145, 4146);
 
-DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops), EVENTTRIGGERNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops), EVENTTRIGGEROID, 8);
 
 #endif							/* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 37387f9355..8674eb261a 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -52,7 +52,7 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
 
 DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops), FOREIGNDATAWRAPPEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops), FOREIGNDATAWRAPPERNAME, 2);
 
 #endif							/* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 5993967c6e..fb77abe36f 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -49,7 +49,7 @@ typedef FormData_pg_foreign_server *Form_pg_foreign_server;
 
 DECLARE_TOAST(pg_foreign_server, 4151, 4152);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops), FOREIGNSERVEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops), FOREIGNSERVERNAME, 2);
 
 #endif							/* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 2420e23401..8a10130cc0 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -44,6 +44,6 @@ typedef FormData_pg_foreign_table *Form_pg_foreign_table;
 
 DECLARE_TOAST(pg_foreign_table, 4153, 4154);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops), FOREIGNTABLEREL, 4);
 
 #endif							/* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 32930411b6..9352d8a9ed 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -70,7 +70,7 @@ CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
 typedef FormData_pg_index *Form_pg_index;
 
 DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops), INDEXRELID, 64);
 
 /* indkey can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((indrelid, indkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index d666ea2044..070094edb8 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -66,7 +66,7 @@ typedef FormData_pg_language *Form_pg_language;
 
 DECLARE_TOAST(pg_language, 4157, 4158);
 
-DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops), LANGNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops), LANGOID, 4);
 
 #endif							/* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index fc74a14c37..b70073d456 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -53,8 +53,8 @@ typedef FormData_pg_namespace *Form_pg_namespace;
 
 DECLARE_TOAST(pg_namespace, 4163, 4164);
 
-DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops), NAMESPACENAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops), NAMESPACEOID, 16);
 
 /*
  * prototypes for functions in pg_namespace.c
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index a5d09faf1f..18ecd56ada 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -82,7 +82,7 @@ CATALOG(pg_opclass,2616,OperatorClassRelationId)
  */
 typedef FormData_pg_opclass *Form_pg_opclass;
 
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops), CLAAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops), CLAOID, 8);
 
 #endif							/* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index aff372b4bb..3daa79cfae 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -82,8 +82,8 @@ CATALOG(pg_operator,2617,OperatorRelationId)
  */
 typedef FormData_pg_operator *Form_pg_operator;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops), OPEROID, 32);
+DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops), OPERNAMENSP, 256);
 
 
 extern ObjectAddress OperatorCreate(const char *operatorName,
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 88940de916..fe2b5c60c4 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -50,8 +50,8 @@ CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
  */
 typedef FormData_pg_opfamily *Form_pg_opfamily;
 
-DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops), OPFAMILYAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops), OPFAMILYOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h
index f46cdd1524..aef18ff4a7 100644
--- a/src/include/catalog/pg_parameter_acl.h
+++ b/src/include/catalog/pg_parameter_acl.h
@@ -50,8 +50,8 @@ typedef FormData_pg_parameter_acl * Form_pg_parameter_acl;
 
 DECLARE_TOAST_WITH_MACRO(pg_parameter_acl, 6244, 6245, PgParameterAclToastTable, PgParameterAclToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops), PARAMETERACLNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops), PARAMETERACLOID, 4);
 
 
 extern Oid	ParameterAclLookup(const char *parameter, bool missing_ok);
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index 0cf512e1c8..a137f031f7 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -66,7 +66,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
 
 DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops), PARTRELID, 32);
 
 /* partattrs can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((partrelid, partattrs), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index fdb39d4001..29ef344cc2 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -137,8 +137,8 @@ typedef FormData_pg_proc *Form_pg_proc;
 
 DECLARE_TOAST(pg_proc, 2836, 2837);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops), PROCOID, 128);
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops), PROCNAMEARGSNSP, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index d929c9a188..c17be5ed88 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -63,8 +63,8 @@ CATALOG(pg_publication,6104,PublicationRelationId)
  */
 typedef FormData_pg_publication *Form_pg_publication;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops), PUBLICATIONOID, 8);
+DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops), PUBLICATIONNAME, 8);
 
 typedef struct PublicationActions
 {
diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h
index b361c8ab5e..b6326c7730 100644
--- a/src/include/catalog/pg_publication_namespace.h
+++ b/src/include/catalog/pg_publication_namespace.h
@@ -41,7 +41,7 @@ CATALOG(pg_publication_namespace,6237,PublicationNamespaceRelationId)
  */
 typedef FormData_pg_publication_namespace *Form_pg_publication_namespace;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops), PUBLICATIONNAMESPACE, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops), PUBLICATIONNAMESPACEMAP, 64);
 
 #endif							/* PG_PUBLICATION_NAMESPACE_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index bef508764a..19cad0a344 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -47,8 +47,8 @@ typedef FormData_pg_publication_rel *Form_pg_publication_rel;
 
 DECLARE_TOAST(pg_publication_rel, 6228, 6229);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops), PUBLICATIONREL, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops), PUBLICATIONRELMAP, 64);
 DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, pg_publication_rel, btree(prpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index 1247fa7c77..ce662c6a03 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -57,8 +57,8 @@ CATALOG(pg_range,3541,RangeRelationId)
  */
 typedef FormData_pg_range *Form_pg_range;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops), RANGETYPE, 4);
+DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops), RANGEMULTIRANGE, 4);
 
 /*
  * prototypes for functions in pg_range.c
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index 83ff36dcba..49824dbc07 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -56,7 +56,7 @@ typedef FormData_pg_replication_origin *Form_pg_replication_origin;
 
 DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops));
-DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops), REPLORIGIDENT, 16);
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops), REPLORIGNAME, 16);
 
 #endif							/* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 60d642b595..8148e3568b 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -54,6 +54,6 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
 DECLARE_TOAST(pg_rewrite, 2838, 2839);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, pg_rewrite, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops));
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops), RULERELNAME, 8);
 
 #endif							/* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index fdfc27bbd9..efd441c339 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -39,6 +39,6 @@ CATALOG(pg_sequence,2224,SequenceRelationId)
  */
 typedef FormData_pg_sequence *Form_pg_sequence;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops), SEQRELID, 32);
 
 #endif							/* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 864cb54a51..53bb3d1936 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -136,7 +136,7 @@ typedef FormData_pg_statistic *Form_pg_statistic;
 
 DECLARE_TOAST(pg_statistic, 2840, 2841);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops), STATRELATTINH, 128);
 
 DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index 85e56feb80..cb16044e08 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -70,8 +70,8 @@ typedef FormData_pg_statistic_ext *Form_pg_statistic_ext;
 
 DECLARE_TOAST(pg_statistic_ext, 3439, 3440);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops), STATEXTOID, 4);
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops), STATEXTNAMENSP, 4);
 DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, pg_statistic_ext, btree(stxrelid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((stxrelid, stxkeys), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
index 19a00705e6..0f09883e12 100644
--- a/src/include/catalog/pg_statistic_ext_data.h
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -54,7 +54,7 @@ typedef FormData_pg_statistic_ext_data *Form_pg_statistic_ext_data;
 
 DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops), STATEXTDATASTXOID, 4);
 
 
 #endif							/* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index be36c4a820..fff35ebf83 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -115,8 +115,8 @@ typedef FormData_pg_subscription *Form_pg_subscription;
 
 DECLARE_TOAST_WITH_MACRO(pg_subscription, 4183, 4184, PgSubscriptionToastTable, PgSubscriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops), SUBSCRIPTIONOID, 4);
+DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops), SUBSCRIPTIONNAME, 4);
 
 typedef struct Subscription
 {
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index f5324b710d..638f0d5447 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -49,7 +49,7 @@ CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
 
 typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops), SUBSCRIPTIONRELMAP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index ea8665e83a..8910fe362c 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -49,7 +49,7 @@ typedef FormData_pg_tablespace *Form_pg_tablespace;
 
 DECLARE_TOAST_WITH_MACRO(pg_tablespace, 4185, 4186, PgTablespaceToastTable, PgTablespaceToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops), TABLESPACEOID, 4);
 DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, pg_tablespace, btree(spcname name_ops));
 
 #endif							/* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index 8eb189784d..2660d7a706 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -42,7 +42,7 @@ CATALOG(pg_transform,3576,TransformRelationId)
  */
 typedef FormData_pg_transform *Form_pg_transform;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops), TRFOID, 16);
+DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops), TRFTYPELANG, 16);
 
 #endif							/* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index e52720387d..3699551f0f 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -47,7 +47,7 @@ CATALOG(pg_ts_config,3602,TSConfigRelationId)
 
 typedef FormData_pg_ts_config *Form_pg_ts_config;
 
-DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops), TSCONFIGNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops), TSCONFIGOID, 2);
 
 #endif							/* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index 91f092ca48..437b34a20c 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -44,6 +44,6 @@ CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
 
 typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops), TSCONFIGMAP, 2);
 
 #endif							/* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 10a6490213..34e22d9434 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -53,7 +53,7 @@ typedef FormData_pg_ts_dict *Form_pg_ts_dict;
 
 DECLARE_TOAST(pg_ts_dict, 4169, 4170);
 
-DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops), TSDICTNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops), TSDICTOID, 2);
 
 #endif							/* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index 57d9e8428a..7885c2555e 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -54,7 +54,7 @@ CATALOG(pg_ts_parser,3601,TSParserRelationId)
 
 typedef FormData_pg_ts_parser *Form_pg_ts_parser;
 
-DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops), TSPARSERNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops), TSPARSEROID, 2);
 
 #endif							/* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index f3bdc7b200..cd569a700e 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -45,7 +45,7 @@ CATALOG(pg_ts_template,3764,TSTemplateRelationId)
 
 typedef FormData_pg_ts_template *Form_pg_ts_template;
 
-DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops), TSTEMPLATENAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops), TSTEMPLATEOID, 2);
 
 #endif							/* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 508ba7b0f7..9d00be8dbb 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -262,8 +262,8 @@ typedef FormData_pg_type *Form_pg_type;
 
 DECLARE_TOAST(pg_type, 4171, 4172);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops), TYPEOID, 64);
+DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops), TYPENAMENSP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index eca33f4cb4..94bc93a83f 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -49,7 +49,7 @@ typedef FormData_pg_user_mapping *Form_pg_user_mapping;
 
 DECLARE_TOAST(pg_user_mapping, 4173, 4174);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops), USERMAPPINGOID, 2);
+DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops), USERMAPPINGUSERSERVER, 2);
 
 #endif							/* PG_USER_MAPPING_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 67ea6e4945..68827fba50 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -20,103 +20,7 @@
 #include "access/htup.h"
 /* we intentionally do not include utils/catcache.h here */
 
-/*
- *		SysCache identifiers.
- *
- *		The order of these identifiers must match the order
- *		of the entries in the array cacheinfo[] in syscache.c.
- *		Keep them in alphabetical order (renumbering only costs a
- *		backend rebuild).
- */
-
-enum SysCacheIdentifier
-{
-	AGGFNOID = 0,
-	AMNAME,
-	AMOID,
-	AMOPOPID,
-	AMOPSTRATEGY,
-	AMPROCNUM,
-	ATTNAME,
-	ATTNUM,
-	AUTHMEMMEMROLE,
-	AUTHMEMROLEMEM,
-	AUTHNAME,
-	AUTHOID,
-	CASTSOURCETARGET,
-	CLAAMNAMENSP,
-	CLAOID,
-	COLLNAMEENCNSP,
-	COLLOID,
-	CONDEFAULT,
-	CONNAMENSP,
-	CONSTROID,
-	CONVOID,
-	DATABASEOID,
-	DEFACLROLENSPOBJ,
-	ENUMOID,
-	ENUMTYPOIDNAME,
-	EVENTTRIGGERNAME,
-	EVENTTRIGGEROID,
-	FOREIGNDATAWRAPPERNAME,
-	FOREIGNDATAWRAPPEROID,
-	FOREIGNSERVERNAME,
-	FOREIGNSERVEROID,
-	FOREIGNTABLEREL,
-	INDEXRELID,
-	LANGNAME,
-	LANGOID,
-	NAMESPACENAME,
-	NAMESPACEOID,
-	OPERNAMENSP,
-	OPEROID,
-	OPFAMILYAMNAMENSP,
-	OPFAMILYOID,
-	PARAMETERACLNAME,
-	PARAMETERACLOID,
-	PARTRELID,
-	PROCNAMEARGSNSP,
-	PROCOID,
-	PUBLICATIONNAME,
-	PUBLICATIONNAMESPACE,
-	PUBLICATIONNAMESPACEMAP,
-	PUBLICATIONOID,
-	PUBLICATIONREL,
-	PUBLICATIONRELMAP,
-	RANGEMULTIRANGE,
-	RANGETYPE,
-	RELNAMENSP,
-	RELOID,
-	REPLORIGIDENT,
-	REPLORIGNAME,
-	RULERELNAME,
-	SEQRELID,
-	STATEXTDATASTXOID,
-	STATEXTNAMENSP,
-	STATEXTOID,
-	STATRELATTINH,
-	SUBSCRIPTIONNAME,
-	SUBSCRIPTIONOID,
-	SUBSCRIPTIONRELMAP,
-	TABLESPACEOID,
-	TRFOID,
-	TRFTYPELANG,
-	TSCONFIGMAP,
-	TSCONFIGNAMENSP,
-	TSCONFIGOID,
-	TSDICTNAMENSP,
-	TSDICTOID,
-	TSPARSERNAMENSP,
-	TSPARSEROID,
-	TSTEMPLATENAMENSP,
-	TSTEMPLATEOID,
-	TYPENAMENSP,
-	TYPEOID,
-	USERMAPPINGOID,
-	USERMAPPINGUSERSERVER
-
-#define SysCacheSize (USERMAPPINGUSERSERVER + 1)
-};
+#include "catalog/syscache_info.h"
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 4e09c4686b..56ed423567 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 8dee1b5670..477e4dd7e6 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
-- 
2.41.0

v2-0005-Fill-in-more-of-ObjectProperty.patchtext/plain; charset=UTF-8; name=v2-0005-Fill-in-more-of-ObjectProperty.patchDownload
From 35090c543090c4a93582cd4570f7793f3db31181 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v2 5/6] Fill in more of ObjectProperty

---
 src/backend/catalog/objectaddress.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 95fefc7565..bb4efcad20 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -132,7 +132,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_ACCESS_METHOD,
 		true
 	},
 	{
@@ -174,7 +174,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_CAST,
 		false
 	},
 	{
@@ -384,7 +384,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_ROLE,
 		true
 	},
 	{
@@ -412,7 +412,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_RULE,
 		false
 	},
 	{
@@ -462,8 +462,14 @@ static const ObjectPropertyType ObjectProperty[] =
 		TransformRelationId,
 		TransformOidIndexId,
 		TRFOID,
+		-1,
+		Anum_pg_transform_oid,
+		InvalidAttrNumber,
+		InvalidAttrNumber,
 		InvalidAttrNumber,
-		Anum_pg_transform_oid
+		InvalidAttrNumber,
+		OBJECT_TRANSFORM,
+		false
 	},
 	{
 		"trigger",
@@ -476,7 +482,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_TRIGGER,
 		false
 	},
 	{
@@ -490,7 +496,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_POLICY,
 		false
 	},
 	{
@@ -546,7 +552,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		Anum_pg_ts_parser_prsnamespace,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_TSPARSER,
 		true
 	},
 	{
@@ -560,7 +566,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		Anum_pg_ts_template_tmplnamespace,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_TSTEMPLATE,
 		true,
 	},
 	{
-- 
2.41.0

v2-0006-WIP-Generate-ObjectProperty-from-catalog-files.patchtext/plain; charset=UTF-8; name=v2-0006-WIP-Generate-ObjectProperty-from-catalog-files.patchDownload
From 2d8f4f58bd42696fe9db2039039bab1c94d8a72d Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v2 6/6] WIP: Generate ObjectProperty from catalog files

---
 src/backend/catalog/.gitignore     |  1 +
 src/backend/catalog/genbki.pl      | 81 ++++++++++++++++++++++++++++++
 src/tools/pginclude/cpluspluscheck |  3 ++
 src/tools/pginclude/headerscheck   |  3 ++
 4 files changed, 88 insertions(+)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index ff65560379..d817798dc0 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,3 +1,4 @@
+/objectproperty_info.c.h
 /postgres.bki
 /schemapg.h
 /syscache_info.c.h
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 80a7828d6c..e0813d1286 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -19,8 +19,10 @@
 
 use FindBin;
 use lib $FindBin::RealBin;
+use lib "$FindBin::RealBin/../../tools";
 
 use Catalog;
+use PerfectHash;
 
 my $output_path = '';
 my $major_version;
@@ -59,6 +61,7 @@
 my %syscaches;
 my %oidcounts;
 my @system_constraints;
+my @object_properties;
 
 foreach my $header (@ARGV)
 {
@@ -133,6 +136,7 @@
 		$oidcounts{ $toast->{toast_oid} }++;
 		$oidcounts{ $toast->{toast_index_oid} }++;
 	}
+	my ($oid_index, $oid_syscache, $name_syscache, $is_nsp_name_unique);
 	foreach my $index (@{ $catalog->{indexing} })
 	{
 		push @index_decls,
@@ -142,6 +146,7 @@
 		  $index->{table_name},
 		  $index->{index_decl};
 		$oidcounts{ $index->{index_oid} }++;
+		$oid_index = $index->{index_oid_macro} if $index->{index_decl} eq 'btree(oid oid_ops)';
 
 		if ($index->{is_unique})
 		{
@@ -152,6 +157,11 @@
 			  $index->{index_name};
 		}
 
+		if ($index->{is_unique} && $index->{index_decl} =~ /\(\w+name name_ops, \w+namespace oid_ops\)/)
+		{
+			$is_nsp_name_unique = 1;
+		}
+
 		if ($index->{syscache_name})
 		{
 			my $tbl = $index->{table_name};
@@ -165,8 +175,51 @@
 				key => $key,
 				nbuckets => $index->{syscache_nbuckets},
 			};
+
+			$oid_syscache = $index->{syscache_name} if $index->{index_decl} eq 'btree(oid oid_ops)';
+			$name_syscache = $index->{syscache_name} if $index->{index_decl} =~ /^btree\(\w+name name_ops\)$/;
+		}
+	}
+
+	my ($attnum_oid, $attnum_name, $attnum_namespace, $attnum_owner, $attnum_acl);
+	foreach my $att (@$schema)
+	{
+		if ($att->{name} eq 'oid' && $att->{type} eq 'oid')
+		{
+			$attnum_oid = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /name$/ && $att->{type} eq 'name')
+		{
+			$attnum_name = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /namespace$/ && $att->{type} eq 'oid')
+		{
+			$attnum_namespace = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /owner$/ && $att->{type} eq 'oid')
+		{
+			$attnum_owner = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /acl$/ && $att->{type} eq '_aclitem')
+		{
+			$attnum_acl = "Anum_${catname}_" . $att->{name};
 		}
 	}
+	push @object_properties, {
+		#class_descr => q{"TODO"},
+		class_oid => $catalog->{relation_oid_macro},
+		_class_oid => $catalog->{relation_oid},
+		oid_index_oid => $oid_index,
+		oid_catcache_id => $oid_syscache || '-1',
+		name_catcache_id => $name_syscache || '-1',
+		attnum_oid => $attnum_oid,
+		attnum_name => $attnum_name,
+		attnum_namespace => $attnum_namespace,
+		attnum_owner => $attnum_owner,
+		attnum_acl => $attnum_acl,
+		#objtype => TODO,
+		is_nsp_name_unique => $is_nsp_name_unique ? 'true' : 'false',
+	};
 }
 
 # Complain and exit if we found any duplicate OIDs.
@@ -441,6 +494,9 @@
 my $syscache_info_c = $output_path . 'syscache_info.c.h';
 open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
   or die "can't open $syscache_info_c$tmpext: $!";
+my $objectproperty_info = $output_path . 'objectproperty_info.c.h';
+open my $objectproperty_info_fh, '>', $objectproperty_info . $tmpext
+  or die "can't open $objectproperty_info$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -802,6 +858,29 @@
 
 print $syscache_info_c_fh "};\n";
 
+# Now generate objectproperty_info
+
+print_boilerplate($objectproperty_info_fh, "objectproperty_info.h", "object property data");
+print $objectproperty_info_fh "static const ObjectPropertyType ObjectProperty[] =
+{
+";
+
+my @class_oids;
+foreach my $op (@object_properties)
+{
+	print $objectproperty_info_fh "\t{\n";
+	foreach my $p (sort keys %{$op})
+	{
+		printf $objectproperty_info_fh "\t\t%s = %s,\n", $p, ${$op}{$p} if $p !~ /^_/ && ${$op}{$p};
+	}
+	push @class_oids, pack('N', ${$op}{_class_oid});
+	print $objectproperty_info_fh "\t},\n";
+}
+
+print $objectproperty_info_fh "};\n";
+
+print $objectproperty_info_fh "\nstatic " . PerfectHash::generate_hash_function(\@class_oids, 'objectproperty_hash_func', fixed_key_length => 4);
+
 # We're done emitting data
 close $bki;
 close $schemapg;
@@ -809,6 +888,7 @@
 close $constraints;
 close $syscache_info_h_fh;
 close $syscache_info_c_fh;
+close $objectproperty_info_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
@@ -817,6 +897,7 @@
 Catalog::RenameTempFile($constraints_file, $tmpext);
 Catalog::RenameTempFile($syscache_info_h, $tmpext);
 Catalog::RenameTempFile($syscache_info_c, $tmpext);
+Catalog::RenameTempFile($objectproperty_info, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 56ed423567..49e3ca7a7b 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 477e4dd7e6..a1ea2ef692 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
-- 
2.41.0

#6Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#5)
Re: generate syscache info automatically

On 03.07.23 07:45, Peter Eisentraut wrote:

Here is an updated patch set that adjusts for the recently introduced
named captures.  I will address the other issues later.  I think the
first few patches in the series can be considered nonetheless.

I have committed the 0001 patch, which was really a (code comment) bug fix.

I think the patches 0002 and 0003 should be uncontroversial, so I'd like
to commit them if no one objects.

The remaining patches are still WIP.

Show quoted text

On 15.06.23 09:45, John Naylor wrote:

On Wed, May 31, 2023 at 4:58 AM Peter Eisentraut <peter@eisentraut.org
<mailto:peter@eisentraut.org>> wrote:
 >
 > I want to report on my on-the-plane-to-PGCon project.
 >
 > The idea was mentioned in [0]. genbki.pl <http://genbki.pl&gt; already
knows everything about
 > system catalog indexes.  If we add a "please also make a syscache for
 > this one" flag to the catalog metadata, we can have genbki.pl
<http://genbki.pl&gt; produce
 > the tables in syscache.c and syscache.h automatically.
 >
 > Aside from avoiding the cumbersome editing of those tables, I think
this
 > layout is also conceptually cleaner, as you can more easily see which
 > system catalog indexes have syscaches and maybe ask questions about
why
 > or why not.

When this has come up before, one objection was that index
declarations shouldn't know about cache names and bucket sizes [1].
The second paragraph above makes a reasonable case for that, however.
I believe one alternative idea was for a script to read the enum,
which would look something like this:

#define DECLARE_SYSCACHE(cacheid,indexname,numbuckets) cacheid

enum SysCacheIdentifier
{
DECLARE_SYSCACHE(AGGFNOID, pg_aggregate_fnoid_index, 16) = 0,
...
};

...which would then look up the other info in the usual way from
Catalog.pm.

 > As a possible follow-up, I have also started work on generating the
 > ObjectProperty structure in objectaddress.c.  One of the things you
need
 > for that is making genbki.pl <http://genbki.pl&gt; aware of the
syscache information.  There
 > is some more work to be done there, but it's looking promising.

I haven't studied this, but it seems interesting.

One other possible improvement: syscache.c has a bunch of #include's,
one for each catalog with a cache, so there's still a bit of manual
work in adding a cache, and the current #include list is a bit
cumbersome. Perhaps it's worth it to have the script emit them as well?

I also wonder if at some point it will make sense to split off a
separate script(s) for some things that are unrelated to the bootstrap
data. genbki.pl <http://genbki.pl&gt; is getting pretty large, and there
are additional things that could be done with syscaches, e.g. inlined
eq/hash functions for cache lookup [2].

[1]
/messages/by-id/12460.1570734874@sss.pgh.pa.us
</messages/by-id/12460.1570734874@sss.pgh.pa.us&gt;
[2]
/messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de </messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de&gt;

--
John Naylor
EDB: http://www.enterprisedb.com <http://www.enterprisedb.com&gt;

#7Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#6)
3 attachment(s)
Re: generate syscache info automatically

I have committed 0002 and 0003, and also a small bug fix in the
ObjectProperty entry for "transforms".

I have also gotten the automatic generation of the ObjectProperty lookup
table working (with some warts).

Attached is an updated patch set.

One win here is that the ObjectProperty lookup now uses a hash function
instead of a linear search. So hopefully the performance is better (to
be confirmed) and it could now be used for things like [0]/messages/by-id/12f1b1d2-f8cf-c4a2-72ec-441bd79546cb@enterprisedb.com.

[0]: /messages/by-id/12f1b1d2-f8cf-c4a2-72ec-441bd79546cb@enterprisedb.com
/messages/by-id/12f1b1d2-f8cf-c4a2-72ec-441bd79546cb@enterprisedb.com

There was some discussion about whether the catalog files are the right
place to keep syscache information. Personally, I would find that more
convenient. (Note that we also recently moved the definitions of
indexes and toast tables from files with the whole list into the various
catalog files.) But we can also keep it somewhere else. The important
thing is that Catalog.pm can find it somewhere in a structured form.

To finish up the ObjectProperty generation, we also need to store some
more data, namely the OBJECT_* mappings. We probably do not want to
store those in the catalog headers; that looks like a layering violation
to me.

So, there is some discussion to be had about where to put all this
across various use cases.

Show quoted text

On 24.08.23 16:03, Peter Eisentraut wrote:

On 03.07.23 07:45, Peter Eisentraut wrote:

Here is an updated patch set that adjusts for the recently introduced
named captures.  I will address the other issues later.  I think the
first few patches in the series can be considered nonetheless.

I have committed the 0001 patch, which was really a (code comment) bug fix.

I think the patches 0002 and 0003 should be uncontroversial, so I'd like
to commit them if no one objects.

The remaining patches are still WIP.

On 15.06.23 09:45, John Naylor wrote:

On Wed, May 31, 2023 at 4:58 AM Peter Eisentraut
<peter@eisentraut.org <mailto:peter@eisentraut.org>> wrote:
 >
 > I want to report on my on-the-plane-to-PGCon project.
 >
 > The idea was mentioned in [0]. genbki.pl <http://genbki.pl&gt;
already knows everything about
 > system catalog indexes.  If we add a "please also make a syscache for
 > this one" flag to the catalog metadata, we can have genbki.pl
<http://genbki.pl&gt; produce
 > the tables in syscache.c and syscache.h automatically.
 >
 > Aside from avoiding the cumbersome editing of those tables, I
think this
 > layout is also conceptually cleaner, as you can more easily see which
 > system catalog indexes have syscaches and maybe ask questions
about why
 > or why not.

When this has come up before, one objection was that index
declarations shouldn't know about cache names and bucket sizes [1].
The second paragraph above makes a reasonable case for that, however.
I believe one alternative idea was for a script to read the enum,
which would look something like this:

#define DECLARE_SYSCACHE(cacheid,indexname,numbuckets) cacheid

enum SysCacheIdentifier
{
DECLARE_SYSCACHE(AGGFNOID, pg_aggregate_fnoid_index, 16) = 0,
...
};

...which would then look up the other info in the usual way from
Catalog.pm.

 > As a possible follow-up, I have also started work on generating the
 > ObjectProperty structure in objectaddress.c.  One of the things
you need
 > for that is making genbki.pl <http://genbki.pl&gt; aware of the
syscache information.  There
 > is some more work to be done there, but it's looking promising.

I haven't studied this, but it seems interesting.

One other possible improvement: syscache.c has a bunch of #include's,
one for each catalog with a cache, so there's still a bit of manual
work in adding a cache, and the current #include list is a bit
cumbersome. Perhaps it's worth it to have the script emit them as well?

I also wonder if at some point it will make sense to split off a
separate script(s) for some things that are unrelated to the
bootstrap data. genbki.pl <http://genbki.pl&gt; is getting pretty large,
and there are additional things that could be done with syscaches,
e.g. inlined eq/hash functions for cache lookup [2].

[1]
/messages/by-id/12460.1570734874@sss.pgh.pa.us
</messages/by-id/12460.1570734874@sss.pgh.pa.us&gt;
[2]
/messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de </messages/by-id/20210831205906.4wk3s4lvgzkdaqpi@alap3.anarazel.de&gt;

--
John Naylor
EDB: http://www.enterprisedb.com <http://www.enterprisedb.com&gt;

Attachments:

v3-0001-Fill-in-more-of-ObjectProperty.patchtext/plain; charset=UTF-8; name=v3-0001-Fill-in-more-of-ObjectProperty.patchDownload
From 399b6add1e775083317b60f51dfd7e6c41209421 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v3 1/3] Fill in more of ObjectProperty

Fill in .objtype field where an appropriate value exists.

These cases are currently not used (see also comments at
get_object_type()), but we might as well fill in what's possible in
case additional uses arise.

Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
 src/backend/catalog/objectaddress.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 715201f5a2..bb4efcad20 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -132,7 +132,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_ACCESS_METHOD,
 		true
 	},
 	{
@@ -174,7 +174,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_CAST,
 		false
 	},
 	{
@@ -384,7 +384,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_ROLE,
 		true
 	},
 	{
@@ -412,7 +412,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_RULE,
 		false
 	},
 	{
@@ -468,7 +468,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_TRANSFORM,
 		false
 	},
 	{
@@ -482,7 +482,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_TRIGGER,
 		false
 	},
 	{
@@ -496,7 +496,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_POLICY,
 		false
 	},
 	{
@@ -552,7 +552,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		Anum_pg_ts_parser_prsnamespace,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_TSPARSER,
 		true
 	},
 	{
@@ -566,7 +566,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		Anum_pg_ts_template_tmplnamespace,
 		InvalidAttrNumber,
 		InvalidAttrNumber,
-		-1,
+		OBJECT_TSTEMPLATE,
 		true,
 	},
 	{
-- 
2.41.0

v3-0002-Generate-syscache-info-from-catalog-files.patchtext/plain; charset=UTF-8; name=v3-0002-Generate-syscache-info-from-catalog-files.patchDownload
From dd888bd6f70ee0a25fa8c3f8e905f98a5b73cf2d Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v3 2/3] Generate syscache info from catalog files

DECLARE_UNIQUE_INDEX gets two additional arguments with the syscache
ID macro and the number of buckets.  From that, we can generate the
existing tables in syscache.h and syscache.c via genbki.pl.

Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
 src/backend/catalog/.gitignore                |   2 +
 src/backend/catalog/Catalog.pm                |   6 +-
 src/backend/catalog/Makefile                  |   2 +-
 src/backend/catalog/genbki.pl                 |  61 ++
 src/backend/utils/cache/syscache.c            | 625 +-----------------
 src/include/catalog/.gitignore                |   2 +
 src/include/catalog/genbki.h                  |   7 +-
 src/include/catalog/meson.build               |  18 +-
 src/include/catalog/pg_aggregate.h            |   2 +-
 src/include/catalog/pg_am.h                   |   4 +-
 src/include/catalog/pg_amop.h                 |   4 +-
 src/include/catalog/pg_amproc.h               |   2 +-
 src/include/catalog/pg_attribute.h            |   4 +-
 src/include/catalog/pg_auth_members.h         |   4 +-
 src/include/catalog/pg_authid.h               |   4 +-
 src/include/catalog/pg_cast.h                 |   2 +-
 src/include/catalog/pg_class.h                |   4 +-
 src/include/catalog/pg_collation.h            |   4 +-
 src/include/catalog/pg_constraint.h           |   2 +-
 src/include/catalog/pg_conversion.h           |   6 +-
 src/include/catalog/pg_database.h             |   2 +-
 src/include/catalog/pg_default_acl.h          |   2 +-
 src/include/catalog/pg_enum.h                 |   4 +-
 src/include/catalog/pg_event_trigger.h        |   4 +-
 src/include/catalog/pg_foreign_data_wrapper.h |   4 +-
 src/include/catalog/pg_foreign_server.h       |   4 +-
 src/include/catalog/pg_foreign_table.h        |   2 +-
 src/include/catalog/pg_index.h                |   2 +-
 src/include/catalog/pg_language.h             |   4 +-
 src/include/catalog/pg_namespace.h            |   4 +-
 src/include/catalog/pg_opclass.h              |   4 +-
 src/include/catalog/pg_operator.h             |   4 +-
 src/include/catalog/pg_opfamily.h             |   4 +-
 src/include/catalog/pg_parameter_acl.h        |   4 +-
 src/include/catalog/pg_partitioned_table.h    |   2 +-
 src/include/catalog/pg_proc.h                 |   4 +-
 src/include/catalog/pg_publication.h          |   4 +-
 .../catalog/pg_publication_namespace.h        |   4 +-
 src/include/catalog/pg_publication_rel.h      |   4 +-
 src/include/catalog/pg_range.h                |   4 +-
 src/include/catalog/pg_replication_origin.h   |   4 +-
 src/include/catalog/pg_rewrite.h              |   2 +-
 src/include/catalog/pg_sequence.h             |   2 +-
 src/include/catalog/pg_statistic.h            |   2 +-
 src/include/catalog/pg_statistic_ext.h        |   4 +-
 src/include/catalog/pg_statistic_ext_data.h   |   2 +-
 src/include/catalog/pg_subscription.h         |   4 +-
 src/include/catalog/pg_subscription_rel.h     |   2 +-
 src/include/catalog/pg_tablespace.h           |   2 +-
 src/include/catalog/pg_transform.h            |   4 +-
 src/include/catalog/pg_ts_config.h            |   4 +-
 src/include/catalog/pg_ts_config_map.h        |   2 +-
 src/include/catalog/pg_ts_dict.h              |   4 +-
 src/include/catalog/pg_ts_parser.h            |   4 +-
 src/include/catalog/pg_ts_template.h          |   4 +-
 src/include/catalog/pg_type.h                 |   4 +-
 src/include/catalog/pg_user_mapping.h         |   4 +-
 src/include/utils/syscache.h                  |  98 +--
 src/tools/pginclude/cpluspluscheck            |   5 +
 src/tools/pginclude/headerscheck              |   5 +
 60 files changed, 193 insertions(+), 804 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index 237ff54165..ff65560379 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,5 +1,7 @@
 /postgres.bki
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /system_constraints.sql
 /pg_*_d.h
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index be56cc153f..de67632793 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -118,7 +118,11 @@ sub ParseHeader
 			 (?<index_oid>\d+),\s*
 			 (?<index_oid_macro>\w+),\s*
 			 (?<table_name>\w+),\s*
-			 (?<index_decl>.+)\s*
+			 (?<index_decl>\w+\s*\([\w\s,]+\))\s*
+			 (?:,\s*
+			   (?<syscache_name>\w+),\s*
+			   (?<syscache_nbuckets>\w+)
+			 )?
 			 \)/x
 		  )
 		{
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 3e9994793d..2c94126ec5 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -120,7 +120,7 @@ CATALOG_HEADERS := \
 	pg_subscription.h \
 	pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 380bc23c82..78f2da690e 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -56,6 +56,7 @@
 my %catalog_data;
 my @toast_decls;
 my @index_decls;
+my %syscaches;
 my %oidcounts;
 my @system_constraints;
 
@@ -150,6 +151,21 @@
 			  $index->{is_pkey} ? "PRIMARY KEY" : "UNIQUE",
 			  $index->{index_name};
 		}
+
+		if ($index->{syscache_name})
+		{
+			my $tbl = $index->{table_name};
+			my $key = $index->{index_decl};
+			$key =~ s/^\w+\(//;
+			$key =~ s/\)$//;
+			$key =~ s/(\w+)\s+\w+/Anum_${tbl}_$1/g;
+			$syscaches{$index->{syscache_name}} = {
+				table_oid_macro => $catalogs{$tbl}->{relation_oid_macro},
+				index_oid_macro => $index->{index_oid_macro},
+				key => $key,
+				nbuckets => $index->{syscache_nbuckets},
+			};
+		}
 	}
 }
 
@@ -419,6 +435,12 @@
 my $constraints_file = $output_path . 'system_constraints.sql';
 open my $constraints, '>', $constraints_file . $tmpext
   or die "can't open $constraints_file$tmpext: $!";
+my $syscache_info_h = $output_path . 'syscache_info.h';
+open my $syscache_info_h_fh, '>', $syscache_info_h . $tmpext
+  or die "can't open $syscache_info_h$tmpext: $!";
+my $syscache_info_c = $output_path . 'syscache_info.c.h';
+open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
+  or die "can't open $syscache_info_c$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -753,17 +775,56 @@
 # Closing boilerplate for system_fk_info.h
 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_info_h_fh, "syscache_info.h", "SysCache identifiers");
+print $syscache_info_h_fh "enum SysCacheIdentifier
+{
+";
+
+print_boilerplate($syscache_info_c_fh, "syscache_info.c.h", "SysCache definitions");
+print $syscache_info_c_fh "\n";
+foreach my $catname (@catnames)
+{
+	print $syscache_info_c_fh qq{#include "catalog/${catname}_d.h"\n};
+}
+print $syscache_info_c_fh "\n";
+print $syscache_info_c_fh "static const struct cachedesc cacheinfo[] = {\n";
+
+my $last_syscache;
+foreach my $syscache (sort keys %syscaches)
+{
+	print $syscache_info_h_fh "\t$syscache,\n";
+	$last_syscache = $syscache;
+
+	print $syscache_info_c_fh "\t[$syscache] = {\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{table_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{index_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\tKEY(", $syscaches{$syscache}{key}, "),\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{nbuckets}, "\n";
+	print $syscache_info_c_fh "\t},\n";
+}
+
+print $syscache_info_h_fh "};\n";
+print $syscache_info_h_fh "#define SysCacheSize ($last_syscache + 1)\n";
+
+print $syscache_info_c_fh "};\n";
+
 # We're done emitting data
 close $bki;
 close $schemapg;
 close $fk_info;
 close $constraints;
+close $syscache_info_h_fh;
+close $syscache_info_c_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
 Catalog::RenameTempFile($schemafile, $tmpext);
 Catalog::RenameTempFile($fk_info_file, $tmpext);
 Catalog::RenameTempFile($constraints_file, $tmpext);
+Catalog::RenameTempFile($syscache_info_h, $tmpext);
+Catalog::RenameTempFile($syscache_info_c, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 8dbda0024f..072fa9ef47 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -22,59 +22,6 @@
 
 #include "access/htup_details.h"
 #include "access/sysattr.h"
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_am.h"
-#include "catalog/pg_amop.h"
-#include "catalog/pg_amproc.h"
-#include "catalog/pg_auth_members.h"
-#include "catalog/pg_authid.h"
-#include "catalog/pg_cast.h"
-#include "catalog/pg_collation.h"
-#include "catalog/pg_constraint.h"
-#include "catalog/pg_conversion.h"
-#include "catalog/pg_database.h"
-#include "catalog/pg_db_role_setting.h"
-#include "catalog/pg_default_acl.h"
-#include "catalog/pg_depend.h"
-#include "catalog/pg_description.h"
-#include "catalog/pg_enum.h"
-#include "catalog/pg_event_trigger.h"
-#include "catalog/pg_foreign_data_wrapper.h"
-#include "catalog/pg_foreign_server.h"
-#include "catalog/pg_foreign_table.h"
-#include "catalog/pg_language.h"
-#include "catalog/pg_namespace.h"
-#include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
-#include "catalog/pg_opfamily.h"
-#include "catalog/pg_parameter_acl.h"
-#include "catalog/pg_partitioned_table.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_publication.h"
-#include "catalog/pg_publication_namespace.h"
-#include "catalog/pg_publication_rel.h"
-#include "catalog/pg_range.h"
-#include "catalog/pg_replication_origin.h"
-#include "catalog/pg_rewrite.h"
-#include "catalog/pg_seclabel.h"
-#include "catalog/pg_sequence.h"
-#include "catalog/pg_shdepend.h"
-#include "catalog/pg_shdescription.h"
-#include "catalog/pg_shseclabel.h"
-#include "catalog/pg_statistic.h"
-#include "catalog/pg_statistic_ext.h"
-#include "catalog/pg_statistic_ext_data.h"
-#include "catalog/pg_subscription.h"
-#include "catalog/pg_subscription_rel.h"
-#include "catalog/pg_tablespace.h"
-#include "catalog/pg_transform.h"
-#include "catalog/pg_ts_config.h"
-#include "catalog/pg_ts_config_map.h"
-#include "catalog/pg_ts_dict.h"
-#include "catalog/pg_ts_parser.h"
-#include "catalog/pg_ts_template.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_user_mapping.h"
 #include "lib/qunique.h"
 #include "utils/catcache.h"
 #include "utils/lsyscache.h"
@@ -85,18 +32,6 @@
 
 	Adding system caches:
 
-	Add your new cache to the list in include/utils/syscache.h.
-	Keep the list sorted alphabetically.
-
-	Add your entry to the cacheinfo[] array below. All cache lists are
-	alphabetical, so add it in the proper place.  Specify the relation OID,
-	index OID, number of keys, key attribute numbers, and initial number of
-	hash buckets.
-
-	The number of hash buckets must be a power of 2.  It's reasonable to
-	set this to the number of entries that might be in the particular cache
-	in a medium-size database.
-
 	There must be a unique index underlying each syscache (ie, an index
 	whose key is the same as that of the cache).  If there is not one
 	already, add the definition for it to include/catalog/pg_*.h using
@@ -104,6 +39,13 @@
 	(Adding an index requires a catversion.h update, while simply
 	adding/deleting caches only requires a recompile.)
 
+	Then add the name of your name cache and the initial number of hash
+	buckets as arguments of DECLARE_UNIQUE_INDEX.
+
+	The number of hash buckets must be a power of 2.  It's reasonable to
+	set this to the number of entries that might be in the particular cache
+	in a medium-size database.
+
 	Finally, any place your relation gets heap_insert() or
 	heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
 	instead, which also update indexes.  The heap_* calls do not do that.
@@ -126,558 +68,7 @@ struct cachedesc
 /* Macro to provide nkeys and key array with convenient syntax. */
 #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
 
-static const struct cachedesc cacheinfo[] = {
-	[AGGFNOID] = {
-		AggregateRelationId,
-		AggregateFnoidIndexId,
-		KEY(Anum_pg_aggregate_aggfnoid),
-		16
-	},
-	[AMNAME] = {
-		AccessMethodRelationId,
-		AmNameIndexId,
-		KEY(Anum_pg_am_amname),
-		4
-	},
-	[AMOID] = {
-		AccessMethodRelationId,
-		AmOidIndexId,
-		KEY(Anum_pg_am_oid),
-		4
-	},
-	[AMOPOPID] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodOperatorIndexId,
-		KEY(Anum_pg_amop_amopopr,
-			Anum_pg_amop_amoppurpose,
-			Anum_pg_amop_amopfamily),
-		64
-	},
-	[AMOPSTRATEGY] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodStrategyIndexId,
-		KEY(Anum_pg_amop_amopfamily,
-			Anum_pg_amop_amoplefttype,
-			Anum_pg_amop_amoprighttype,
-			Anum_pg_amop_amopstrategy),
-		64
-	},
-	[AMPROCNUM] = {
-		AccessMethodProcedureRelationId,
-		AccessMethodProcedureIndexId,
-		KEY(Anum_pg_amproc_amprocfamily,
-			Anum_pg_amproc_amproclefttype,
-			Anum_pg_amproc_amprocrighttype,
-			Anum_pg_amproc_amprocnum),
-		16
-	},
-	[ATTNAME] = {
-		AttributeRelationId,
-		AttributeRelidNameIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attname),
-		32
-	},
-	[ATTNUM] = {
-		AttributeRelationId,
-		AttributeRelidNumIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attnum),
-		128
-	},
-	[AUTHMEMMEMROLE] = {
-		AuthMemRelationId,
-		AuthMemMemRoleIndexId,
-		KEY(Anum_pg_auth_members_member,
-			Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHMEMROLEMEM] = {
-		AuthMemRelationId,
-		AuthMemRoleMemIndexId,
-		KEY(Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_member,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHNAME] = {
-		AuthIdRelationId,
-		AuthIdRolnameIndexId,
-		KEY(Anum_pg_authid_rolname),
-		8
-	},
-	[AUTHOID] = {
-		AuthIdRelationId,
-		AuthIdOidIndexId,
-		KEY(Anum_pg_authid_oid),
-		8
-	},
-	[CASTSOURCETARGET] = {
-		CastRelationId,
-		CastSourceTargetIndexId,
-		KEY(Anum_pg_cast_castsource,
-			Anum_pg_cast_casttarget),
-		256
-	},
-	[CLAAMNAMENSP] = {
-		OperatorClassRelationId,
-		OpclassAmNameNspIndexId,
-		KEY(Anum_pg_opclass_opcmethod,
-			Anum_pg_opclass_opcname,
-			Anum_pg_opclass_opcnamespace),
-		8
-	},
-	[CLAOID] = {
-		OperatorClassRelationId,
-		OpclassOidIndexId,
-		KEY(Anum_pg_opclass_oid),
-		8
-	},
-	[COLLNAMEENCNSP] = {
-		CollationRelationId,
-		CollationNameEncNspIndexId,
-		KEY(Anum_pg_collation_collname,
-			Anum_pg_collation_collencoding,
-			Anum_pg_collation_collnamespace),
-		8
-	},
-	[COLLOID] = {
-		CollationRelationId,
-		CollationOidIndexId,
-		KEY(Anum_pg_collation_oid),
-		8
-	},
-	[CONDEFAULT] = {
-		ConversionRelationId,
-		ConversionDefaultIndexId,
-		KEY(Anum_pg_conversion_connamespace,
-			Anum_pg_conversion_conforencoding,
-			Anum_pg_conversion_contoencoding,
-			Anum_pg_conversion_oid),
-		8
-	},
-	[CONNAMENSP] = {
-		ConversionRelationId,
-		ConversionNameNspIndexId,
-		KEY(Anum_pg_conversion_conname,
-			Anum_pg_conversion_connamespace),
-		8
-	},
-	[CONSTROID] = {
-		ConstraintRelationId,
-		ConstraintOidIndexId,
-		KEY(Anum_pg_constraint_oid),
-		16
-	},
-	[CONVOID] = {
-		ConversionRelationId,
-		ConversionOidIndexId,
-		KEY(Anum_pg_conversion_oid),
-		8
-	},
-	[DATABASEOID] = {
-		DatabaseRelationId,
-		DatabaseOidIndexId,
-		KEY(Anum_pg_database_oid),
-		4
-	},
-	[DEFACLROLENSPOBJ] = {
-		DefaultAclRelationId,
-		DefaultAclRoleNspObjIndexId,
-		KEY(Anum_pg_default_acl_defaclrole,
-			Anum_pg_default_acl_defaclnamespace,
-			Anum_pg_default_acl_defaclobjtype),
-		8
-	},
-	[ENUMOID] = {
-		EnumRelationId,
-		EnumOidIndexId,
-		KEY(Anum_pg_enum_oid),
-		8
-	},
-	[ENUMTYPOIDNAME] = {
-		EnumRelationId,
-		EnumTypIdLabelIndexId,
-		KEY(Anum_pg_enum_enumtypid,
-			Anum_pg_enum_enumlabel),
-		8
-	},
-	[EVENTTRIGGERNAME] = {
-		EventTriggerRelationId,
-		EventTriggerNameIndexId,
-		KEY(Anum_pg_event_trigger_evtname),
-		8
-	},
-	[EVENTTRIGGEROID] = {
-		EventTriggerRelationId,
-		EventTriggerOidIndexId,
-		KEY(Anum_pg_event_trigger_oid),
-		8
-	},
-	[FOREIGNDATAWRAPPERNAME] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperNameIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_fdwname),
-		2
-	},
-	[FOREIGNDATAWRAPPEROID] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperOidIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_oid),
-		2
-	},
-	[FOREIGNSERVERNAME] = {
-		ForeignServerRelationId,
-		ForeignServerNameIndexId,
-		KEY(Anum_pg_foreign_server_srvname),
-		2
-	},
-	[FOREIGNSERVEROID] = {
-		ForeignServerRelationId,
-		ForeignServerOidIndexId,
-		KEY(Anum_pg_foreign_server_oid),
-		2
-	},
-	[FOREIGNTABLEREL] = {
-		ForeignTableRelationId,
-		ForeignTableRelidIndexId,
-		KEY(Anum_pg_foreign_table_ftrelid),
-		4
-	},
-	[INDEXRELID] = {
-		IndexRelationId,
-		IndexRelidIndexId,
-		KEY(Anum_pg_index_indexrelid),
-		64
-	},
-	[LANGNAME] = {
-		LanguageRelationId,
-		LanguageNameIndexId,
-		KEY(Anum_pg_language_lanname),
-		4
-	},
-	[LANGOID] = {
-		LanguageRelationId,
-		LanguageOidIndexId,
-		KEY(Anum_pg_language_oid),
-		4
-	},
-	[NAMESPACENAME] = {
-		NamespaceRelationId,
-		NamespaceNameIndexId,
-		KEY(Anum_pg_namespace_nspname),
-		4
-	},
-	[NAMESPACEOID] = {
-		NamespaceRelationId,
-		NamespaceOidIndexId,
-		KEY(Anum_pg_namespace_oid),
-		16
-	},
-	[OPERNAMENSP] = {
-		OperatorRelationId,
-		OperatorNameNspIndexId,
-		KEY(Anum_pg_operator_oprname,
-			Anum_pg_operator_oprleft,
-			Anum_pg_operator_oprright,
-			Anum_pg_operator_oprnamespace),
-		256
-	},
-	[OPEROID] = {
-		OperatorRelationId,
-		OperatorOidIndexId,
-		KEY(Anum_pg_operator_oid),
-		32
-	},
-	[OPFAMILYAMNAMENSP] = {
-		OperatorFamilyRelationId,
-		OpfamilyAmNameNspIndexId,
-		KEY(Anum_pg_opfamily_opfmethod,
-			Anum_pg_opfamily_opfname,
-			Anum_pg_opfamily_opfnamespace),
-		8
-	},
-	[OPFAMILYOID] = {
-		OperatorFamilyRelationId,
-		OpfamilyOidIndexId,
-		KEY(Anum_pg_opfamily_oid),
-		8
-	},
-	[PARAMETERACLNAME] = {
-		ParameterAclRelationId,
-		ParameterAclParnameIndexId,
-		KEY(Anum_pg_parameter_acl_parname),
-		4
-	},
-	[PARAMETERACLOID] = {
-		ParameterAclRelationId,
-		ParameterAclOidIndexId,
-		KEY(Anum_pg_parameter_acl_oid),
-		4
-	},
-	[PARTRELID] = {
-		PartitionedRelationId,
-		PartitionedRelidIndexId,
-		KEY(Anum_pg_partitioned_table_partrelid),
-		32
-	},
-	[PROCNAMEARGSNSP] = {
-		ProcedureRelationId,
-		ProcedureNameArgsNspIndexId,
-		KEY(Anum_pg_proc_proname,
-			Anum_pg_proc_proargtypes,
-			Anum_pg_proc_pronamespace),
-		128
-	},
-	[PROCOID] = {
-		ProcedureRelationId,
-		ProcedureOidIndexId,
-		KEY(Anum_pg_proc_oid),
-		128
-	},
-	[PUBLICATIONNAME] = {
-		PublicationRelationId,
-		PublicationNameIndexId,
-		KEY(Anum_pg_publication_pubname),
-		8
-	},
-	[PUBLICATIONNAMESPACE] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespaceObjectIndexId,
-		KEY(Anum_pg_publication_namespace_oid),
-		64
-	},
-	[PUBLICATIONNAMESPACEMAP] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespacePnnspidPnpubidIndexId,
-		KEY(Anum_pg_publication_namespace_pnnspid,
-			Anum_pg_publication_namespace_pnpubid),
-		64
-	},
-	[PUBLICATIONOID] = {
-		PublicationRelationId,
-		PublicationObjectIndexId,
-		KEY(Anum_pg_publication_oid),
-		8
-	},
-	[PUBLICATIONREL] = {
-		PublicationRelRelationId,
-		PublicationRelObjectIndexId,
-		KEY(Anum_pg_publication_rel_oid),
-		64
-	},
-	[PUBLICATIONRELMAP] = {
-		PublicationRelRelationId,
-		PublicationRelPrrelidPrpubidIndexId,
-		KEY(Anum_pg_publication_rel_prrelid,
-			Anum_pg_publication_rel_prpubid),
-		64
-	},
-	[RANGEMULTIRANGE] = {
-		RangeRelationId,
-		RangeMultirangeTypidIndexId,
-		KEY(Anum_pg_range_rngmultitypid),
-		4
-	},
-	[RANGETYPE] = {
-		RangeRelationId,
-		RangeTypidIndexId,
-		KEY(Anum_pg_range_rngtypid),
-		4
-	},
-	[RELNAMENSP] = {
-		RelationRelationId,
-		ClassNameNspIndexId,
-		KEY(Anum_pg_class_relname,
-			Anum_pg_class_relnamespace),
-		128
-	},
-	[RELOID] = {
-		RelationRelationId,
-		ClassOidIndexId,
-		KEY(Anum_pg_class_oid),
-		128
-	},
-	[REPLORIGIDENT] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginIdentIndex,
-		KEY(Anum_pg_replication_origin_roident),
-		16
-	},
-	[REPLORIGNAME] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginNameIndex,
-		KEY(Anum_pg_replication_origin_roname),
-		16
-	},
-	[RULERELNAME] = {
-		RewriteRelationId,
-		RewriteRelRulenameIndexId,
-		KEY(Anum_pg_rewrite_ev_class,
-			Anum_pg_rewrite_rulename),
-		8
-	},
-	[SEQRELID] = {
-		SequenceRelationId,
-		SequenceRelidIndexId,
-		KEY(Anum_pg_sequence_seqrelid),
-		32
-	},
-	[STATEXTDATASTXOID] = {
-		StatisticExtDataRelationId,
-		StatisticExtDataStxoidInhIndexId,
-		KEY(Anum_pg_statistic_ext_data_stxoid,
-			Anum_pg_statistic_ext_data_stxdinherit),
-		4
-	},
-	[STATEXTNAMENSP] = {
-		StatisticExtRelationId,
-		StatisticExtNameIndexId,
-		KEY(Anum_pg_statistic_ext_stxname,
-			Anum_pg_statistic_ext_stxnamespace),
-		4
-	},
-	[STATEXTOID] = {
-		StatisticExtRelationId,
-		StatisticExtOidIndexId,
-		KEY(Anum_pg_statistic_ext_oid),
-		4
-	},
-	[STATRELATTINH] = {
-		StatisticRelationId,
-		StatisticRelidAttnumInhIndexId,
-		KEY(Anum_pg_statistic_starelid,
-			Anum_pg_statistic_staattnum,
-			Anum_pg_statistic_stainherit),
-		128
-	},
-	[SUBSCRIPTIONNAME] = {
-		SubscriptionRelationId,
-		SubscriptionNameIndexId,
-		KEY(Anum_pg_subscription_subdbid,
-			Anum_pg_subscription_subname),
-		4
-	},
-	[SUBSCRIPTIONOID] = {
-		SubscriptionRelationId,
-		SubscriptionObjectIndexId,
-		KEY(Anum_pg_subscription_oid),
-		4
-	},
-	[SUBSCRIPTIONRELMAP] = {
-		SubscriptionRelRelationId,
-		SubscriptionRelSrrelidSrsubidIndexId,
-		KEY(Anum_pg_subscription_rel_srrelid,
-			Anum_pg_subscription_rel_srsubid),
-		64
-	},
-	[TABLESPACEOID] = {
-		TableSpaceRelationId,
-		TablespaceOidIndexId,
-		KEY(Anum_pg_tablespace_oid),
-		4
-	},
-	[TRFOID] = {
-		TransformRelationId,
-		TransformOidIndexId,
-		KEY(Anum_pg_transform_oid),
-		16
-	},
-	[TRFTYPELANG] = {
-		TransformRelationId,
-		TransformTypeLangIndexId,
-		KEY(Anum_pg_transform_trftype,
-			Anum_pg_transform_trflang),
-		16
-	},
-	[TSCONFIGMAP] = {
-		TSConfigMapRelationId,
-		TSConfigMapIndexId,
-		KEY(Anum_pg_ts_config_map_mapcfg,
-			Anum_pg_ts_config_map_maptokentype,
-			Anum_pg_ts_config_map_mapseqno),
-		2
-	},
-	[TSCONFIGNAMENSP] = {
-		TSConfigRelationId,
-		TSConfigNameNspIndexId,
-		KEY(Anum_pg_ts_config_cfgname,
-			Anum_pg_ts_config_cfgnamespace),
-		2
-	},
-	[TSCONFIGOID] = {
-		TSConfigRelationId,
-		TSConfigOidIndexId,
-		KEY(Anum_pg_ts_config_oid),
-		2
-	},
-	[TSDICTNAMENSP] = {
-		TSDictionaryRelationId,
-		TSDictionaryNameNspIndexId,
-		KEY(Anum_pg_ts_dict_dictname,
-			Anum_pg_ts_dict_dictnamespace),
-		2
-	},
-	[TSDICTOID] = {
-		TSDictionaryRelationId,
-		TSDictionaryOidIndexId,
-		KEY(Anum_pg_ts_dict_oid),
-		2
-	},
-	[TSPARSERNAMENSP] = {
-		TSParserRelationId,
-		TSParserNameNspIndexId,
-		KEY(Anum_pg_ts_parser_prsname,
-			Anum_pg_ts_parser_prsnamespace),
-		2
-	},
-	[TSPARSEROID] = {
-		TSParserRelationId,
-		TSParserOidIndexId,
-		KEY(Anum_pg_ts_parser_oid),
-		2
-	},
-	[TSTEMPLATENAMENSP] = {
-		TSTemplateRelationId,
-		TSTemplateNameNspIndexId,
-		KEY(Anum_pg_ts_template_tmplname,
-			Anum_pg_ts_template_tmplnamespace),
-		2
-	},
-	[TSTEMPLATEOID] = {
-		TSTemplateRelationId,
-		TSTemplateOidIndexId,
-		KEY(Anum_pg_ts_template_oid),
-		2
-	},
-	[TYPENAMENSP] = {
-		TypeRelationId,
-		TypeNameNspIndexId,
-		KEY(Anum_pg_type_typname,
-			Anum_pg_type_typnamespace),
-		64
-	},
-	[TYPEOID] = {
-		TypeRelationId,
-		TypeOidIndexId,
-		KEY(Anum_pg_type_oid),
-		64
-	},
-	[USERMAPPINGOID] = {
-		UserMappingRelationId,
-		UserMappingOidIndexId,
-		KEY(Anum_pg_user_mapping_oid),
-		2
-	},
-	[USERMAPPINGUSERSERVER] = {
-		UserMappingRelationId,
-		UserMappingUserServerIndexId,
-		KEY(Anum_pg_user_mapping_umuser,
-			Anum_pg_user_mapping_umserver),
-		2
-	}
-};
+#include "catalog/syscache_info.c.h"
 
 StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
 				 "SysCacheSize does not match syscache.c's array");
diff --git a/src/include/catalog/.gitignore b/src/include/catalog/.gitignore
index 6b83d4c7e6..f7ddf2554b 100644
--- a/src/include/catalog/.gitignore
+++ b/src/include/catalog/.gitignore
@@ -1,4 +1,6 @@
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /pg_*_d.h
 /header-stamp
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index e22a6902fb..2d5bd38cde 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -77,13 +77,14 @@
  * is the name of a #define to generate for its OID.  References to the index
  * in the C code should always use these #defines, not the actual index name
  * (much less the numeric OID).  The fourth argument is the table name.  The
- * rest is much like a standard 'create index' SQL command.
+ * decl argument is much like a standard 'create index' SQL command.
+ * Optionally, specify the syscache ID and bucket size.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */
 #define DECLARE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
 
 /*
  * These lines inform genbki.pl about manually-assigned OIDs that do not
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index dcb3c5f766..39d8e94ae2 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -102,8 +102,22 @@ bki_data_f = files(bki_data)
 
 
 input = []
-output_files = ['postgres.bki', 'system_constraints.sql', 'schemapg.h', 'system_fk_info.h']
-output_install = [dir_data, dir_data, dir_include_server / 'catalog', dir_include_server / 'catalog']
+output_files = [
+  'postgres.bki',
+  'system_constraints.sql',
+  'schemapg.h',
+  'syscache_info.c.h',
+  'syscache_info.h',
+  'system_fk_info.h',
+]
+output_install = [
+  dir_data,
+  dir_data,
+  dir_include_server / 'catalog',
+  false,
+  dir_include_server / 'catalog',
+  dir_include_server / 'catalog',
+]
 
 foreach h : catalog_headers
   fname = h.split('.h')[0] + '_d.h'
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 085149e258..e6f6f4ccb5 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -110,7 +110,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
 
 DECLARE_TOAST(pg_aggregate, 4159, 4160);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops), AGGFNOID, 16);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index d5314bb38b..e3a1313e6c 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -47,8 +47,8 @@ CATALOG(pg_am,2601,AccessMethodRelationId)
  */
 typedef FormData_pg_am *Form_pg_am;
 
-DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops), AMNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops), AMOID, 4);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index c9bb7b4787..3449166507 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -87,8 +87,8 @@ CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
  */
 typedef FormData_pg_amop *Form_pg_amop;
 
-DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
-DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops), AMOPSTRATEGY, 64);
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops), AMOPOPID, 64);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, pg_amop, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 5acf4efab9..31e67be344 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -67,7 +67,7 @@ CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
  */
 typedef FormData_pg_amproc *Form_pg_amproc;
 
-DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops), AMPROCNUM, 16);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, pg_amproc, btree(oid oid_ops));
 
 #endif							/* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 672a5a16ff..84759175de 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -208,8 +208,8 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
  */
 typedef FormData_pg_attribute *Form_pg_attribute;
 
-DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops), ATTNAME, 32);
+DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops), ATTNUM, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index 4ab8a9f7b7..37104cf20f 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -46,8 +46,8 @@ CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_
 typedef FormData_pg_auth_members *Form_pg_auth_members;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, pg_auth_members, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops), AUTHMEMROLEMEM, 8);
+DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops), AUTHMEMMEMROLE, 8);
 DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, pg_auth_members, btree(grantor oid_ops));
 
 #endif							/* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index 0e7ddc56ea..748ab95fad 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -57,7 +57,7 @@ typedef FormData_pg_authid *Form_pg_authid;
 
 DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops), AUTHNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops), AUTHOID, 8);
 
 #endif							/* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index a2518388b3..32235776ce 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -57,7 +57,7 @@ CATALOG(pg_cast,2605,CastRelationId)
 typedef FormData_pg_cast *Form_pg_cast;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, pg_cast, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops), CASTSOURCETARGET, 256);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 55dcd54100..52edbf0229 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -152,8 +152,8 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat
  */
 typedef FormData_pg_class *Form_pg_class;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops), RELOID, 128);
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops), RELNAMENSP, 128);
 DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, pg_class, btree(reltablespace oid_ops, relfilenode oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index 2d7dcde183..6cf59f479a 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -59,8 +59,8 @@ typedef FormData_pg_collation *Form_pg_collation;
 
 DECLARE_TOAST(pg_collation, 6175, 6176);
 
-DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops), COLLNAMEENCNSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops), COLLOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 9b9d8faf35..8a3694599d 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -169,7 +169,7 @@ DECLARE_TOAST(pg_constraint, 2832, 2833);
 DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, pg_constraint, btree(conname name_ops, connamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
 DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops), CONSTROID, 16);
 DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops));
 
 /* conkey can contain zero (InvalidAttrNumber) if a whole-row Var is used */
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index 42847fdf12..acd944a4ae 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -60,9 +60,9 @@ CATALOG(pg_conversion,2607,ConversionRelationId)
  */
 typedef FormData_pg_conversion *Form_pg_conversion;
 
-DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops), CONDEFAULT, 8);
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops), CONNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops), CONVOID, 8);
 
 
 extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index e9eb06b2e5..b247336456 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -95,7 +95,7 @@ typedef FormData_pg_database *Form_pg_database;
 DECLARE_TOAST_WITH_MACRO(pg_database, 4177, 4178, PgDatabaseToastTable, PgDatabaseToastIndex);
 
 DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, pg_database, btree(datname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops), DATABASEOID, 4);
 
 /*
  * pg_database.dat contains an entry for template1, but not for the template0
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index 803ce3eab8..b526af26a6 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -51,7 +51,7 @@ typedef FormData_pg_default_acl *Form_pg_default_acl;
 
 DECLARE_TOAST(pg_default_acl, 4143, 4144);
 
-DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
+DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops), DEFACLROLENSPOBJ, 8);
 DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, pg_default_acl, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index c483cb1042..4ea20aeabe 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -43,8 +43,8 @@ CATALOG(pg_enum,3501,EnumRelationId)
  */
 typedef FormData_pg_enum *Form_pg_enum;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops), ENUMOID, 8);
+DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops), ENUMTYPOIDNAME, 8);
 DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, pg_enum, btree(enumtypid oid_ops, enumsortorder float4_ops));
 
 /*
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index 0ec42edff6..ca1c5bd728 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -51,7 +51,7 @@ typedef FormData_pg_event_trigger *Form_pg_event_trigger;
 
 DECLARE_TOAST(pg_event_trigger, 4145, 4146);
 
-DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops), EVENTTRIGGERNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops), EVENTTRIGGEROID, 8);
 
 #endif							/* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 37387f9355..8674eb261a 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -52,7 +52,7 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
 
 DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops), FOREIGNDATAWRAPPEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops), FOREIGNDATAWRAPPERNAME, 2);
 
 #endif							/* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 5993967c6e..fb77abe36f 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -49,7 +49,7 @@ typedef FormData_pg_foreign_server *Form_pg_foreign_server;
 
 DECLARE_TOAST(pg_foreign_server, 4151, 4152);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops), FOREIGNSERVEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops), FOREIGNSERVERNAME, 2);
 
 #endif							/* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 2420e23401..8a10130cc0 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -44,6 +44,6 @@ typedef FormData_pg_foreign_table *Form_pg_foreign_table;
 
 DECLARE_TOAST(pg_foreign_table, 4153, 4154);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops), FOREIGNTABLEREL, 4);
 
 #endif							/* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 32930411b6..9352d8a9ed 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -70,7 +70,7 @@ CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
 typedef FormData_pg_index *Form_pg_index;
 
 DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops), INDEXRELID, 64);
 
 /* indkey can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((indrelid, indkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index d666ea2044..070094edb8 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -66,7 +66,7 @@ typedef FormData_pg_language *Form_pg_language;
 
 DECLARE_TOAST(pg_language, 4157, 4158);
 
-DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops), LANGNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops), LANGOID, 4);
 
 #endif							/* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index fc74a14c37..b70073d456 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -53,8 +53,8 @@ typedef FormData_pg_namespace *Form_pg_namespace;
 
 DECLARE_TOAST(pg_namespace, 4163, 4164);
 
-DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops), NAMESPACENAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops), NAMESPACEOID, 16);
 
 /*
  * prototypes for functions in pg_namespace.c
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index a5d09faf1f..18ecd56ada 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -82,7 +82,7 @@ CATALOG(pg_opclass,2616,OperatorClassRelationId)
  */
 typedef FormData_pg_opclass *Form_pg_opclass;
 
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops), CLAAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops), CLAOID, 8);
 
 #endif							/* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index aff372b4bb..3daa79cfae 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -82,8 +82,8 @@ CATALOG(pg_operator,2617,OperatorRelationId)
  */
 typedef FormData_pg_operator *Form_pg_operator;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops), OPEROID, 32);
+DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops), OPERNAMENSP, 256);
 
 
 extern ObjectAddress OperatorCreate(const char *operatorName,
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 88940de916..fe2b5c60c4 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -50,8 +50,8 @@ CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
  */
 typedef FormData_pg_opfamily *Form_pg_opfamily;
 
-DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops), OPFAMILYAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops), OPFAMILYOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h
index f46cdd1524..aef18ff4a7 100644
--- a/src/include/catalog/pg_parameter_acl.h
+++ b/src/include/catalog/pg_parameter_acl.h
@@ -50,8 +50,8 @@ typedef FormData_pg_parameter_acl * Form_pg_parameter_acl;
 
 DECLARE_TOAST_WITH_MACRO(pg_parameter_acl, 6244, 6245, PgParameterAclToastTable, PgParameterAclToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops), PARAMETERACLNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops), PARAMETERACLOID, 4);
 
 
 extern Oid	ParameterAclLookup(const char *parameter, bool missing_ok);
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index 0cf512e1c8..a137f031f7 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -66,7 +66,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
 
 DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops), PARTRELID, 32);
 
 /* partattrs can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((partrelid, partattrs), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index fdb39d4001..29ef344cc2 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -137,8 +137,8 @@ typedef FormData_pg_proc *Form_pg_proc;
 
 DECLARE_TOAST(pg_proc, 2836, 2837);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops), PROCOID, 128);
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops), PROCNAMEARGSNSP, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index d929c9a188..c17be5ed88 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -63,8 +63,8 @@ CATALOG(pg_publication,6104,PublicationRelationId)
  */
 typedef FormData_pg_publication *Form_pg_publication;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops), PUBLICATIONOID, 8);
+DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops), PUBLICATIONNAME, 8);
 
 typedef struct PublicationActions
 {
diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h
index b361c8ab5e..b6326c7730 100644
--- a/src/include/catalog/pg_publication_namespace.h
+++ b/src/include/catalog/pg_publication_namespace.h
@@ -41,7 +41,7 @@ CATALOG(pg_publication_namespace,6237,PublicationNamespaceRelationId)
  */
 typedef FormData_pg_publication_namespace *Form_pg_publication_namespace;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops), PUBLICATIONNAMESPACE, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops), PUBLICATIONNAMESPACEMAP, 64);
 
 #endif							/* PG_PUBLICATION_NAMESPACE_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index bef508764a..19cad0a344 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -47,8 +47,8 @@ typedef FormData_pg_publication_rel *Form_pg_publication_rel;
 
 DECLARE_TOAST(pg_publication_rel, 6228, 6229);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops), PUBLICATIONREL, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops), PUBLICATIONRELMAP, 64);
 DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, pg_publication_rel, btree(prpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index 1247fa7c77..ce662c6a03 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -57,8 +57,8 @@ CATALOG(pg_range,3541,RangeRelationId)
  */
 typedef FormData_pg_range *Form_pg_range;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops), RANGETYPE, 4);
+DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops), RANGEMULTIRANGE, 4);
 
 /*
  * prototypes for functions in pg_range.c
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index 83ff36dcba..49824dbc07 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -56,7 +56,7 @@ typedef FormData_pg_replication_origin *Form_pg_replication_origin;
 
 DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops));
-DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops), REPLORIGIDENT, 16);
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops), REPLORIGNAME, 16);
 
 #endif							/* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 60d642b595..8148e3568b 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -54,6 +54,6 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
 DECLARE_TOAST(pg_rewrite, 2838, 2839);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, pg_rewrite, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops));
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops), RULERELNAME, 8);
 
 #endif							/* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index fdfc27bbd9..efd441c339 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -39,6 +39,6 @@ CATALOG(pg_sequence,2224,SequenceRelationId)
  */
 typedef FormData_pg_sequence *Form_pg_sequence;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops), SEQRELID, 32);
 
 #endif							/* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 864cb54a51..53bb3d1936 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -136,7 +136,7 @@ typedef FormData_pg_statistic *Form_pg_statistic;
 
 DECLARE_TOAST(pg_statistic, 2840, 2841);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops), STATRELATTINH, 128);
 
 DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index a136ceffc6..9576fe723e 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -70,8 +70,8 @@ typedef FormData_pg_statistic_ext *Form_pg_statistic_ext;
 
 DECLARE_TOAST(pg_statistic_ext, 3439, 3440);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops), STATEXTOID, 4);
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops), STATEXTNAMENSP, 4);
 DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, pg_statistic_ext, btree(stxrelid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((stxrelid, stxkeys), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
index 19a00705e6..0f09883e12 100644
--- a/src/include/catalog/pg_statistic_ext_data.h
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -54,7 +54,7 @@ typedef FormData_pg_statistic_ext_data *Form_pg_statistic_ext_data;
 
 DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops), STATEXTDATASTXOID, 4);
 
 
 #endif							/* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index be36c4a820..fff35ebf83 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -115,8 +115,8 @@ typedef FormData_pg_subscription *Form_pg_subscription;
 
 DECLARE_TOAST_WITH_MACRO(pg_subscription, 4183, 4184, PgSubscriptionToastTable, PgSubscriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops), SUBSCRIPTIONOID, 4);
+DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops), SUBSCRIPTIONNAME, 4);
 
 typedef struct Subscription
 {
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index f5324b710d..638f0d5447 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -49,7 +49,7 @@ CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
 
 typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops), SUBSCRIPTIONRELMAP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index ea8665e83a..8910fe362c 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -49,7 +49,7 @@ typedef FormData_pg_tablespace *Form_pg_tablespace;
 
 DECLARE_TOAST_WITH_MACRO(pg_tablespace, 4185, 4186, PgTablespaceToastTable, PgTablespaceToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops), TABLESPACEOID, 4);
 DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, pg_tablespace, btree(spcname name_ops));
 
 #endif							/* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index 8eb189784d..2660d7a706 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -42,7 +42,7 @@ CATALOG(pg_transform,3576,TransformRelationId)
  */
 typedef FormData_pg_transform *Form_pg_transform;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops), TRFOID, 16);
+DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops), TRFTYPELANG, 16);
 
 #endif							/* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index e52720387d..3699551f0f 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -47,7 +47,7 @@ CATALOG(pg_ts_config,3602,TSConfigRelationId)
 
 typedef FormData_pg_ts_config *Form_pg_ts_config;
 
-DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops), TSCONFIGNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops), TSCONFIGOID, 2);
 
 #endif							/* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index 91f092ca48..437b34a20c 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -44,6 +44,6 @@ CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
 
 typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops), TSCONFIGMAP, 2);
 
 #endif							/* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 10a6490213..34e22d9434 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -53,7 +53,7 @@ typedef FormData_pg_ts_dict *Form_pg_ts_dict;
 
 DECLARE_TOAST(pg_ts_dict, 4169, 4170);
 
-DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops), TSDICTNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops), TSDICTOID, 2);
 
 #endif							/* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index 57d9e8428a..7885c2555e 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -54,7 +54,7 @@ CATALOG(pg_ts_parser,3601,TSParserRelationId)
 
 typedef FormData_pg_ts_parser *Form_pg_ts_parser;
 
-DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops), TSPARSERNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops), TSPARSEROID, 2);
 
 #endif							/* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index f3bdc7b200..cd569a700e 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -45,7 +45,7 @@ CATALOG(pg_ts_template,3764,TSTemplateRelationId)
 
 typedef FormData_pg_ts_template *Form_pg_ts_template;
 
-DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops), TSTEMPLATENAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops), TSTEMPLATEOID, 2);
 
 #endif							/* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 508ba7b0f7..9d00be8dbb 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -262,8 +262,8 @@ typedef FormData_pg_type *Form_pg_type;
 
 DECLARE_TOAST(pg_type, 4171, 4172);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops), TYPEOID, 64);
+DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops), TYPENAMENSP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index eca33f4cb4..94bc93a83f 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -49,7 +49,7 @@ typedef FormData_pg_user_mapping *Form_pg_user_mapping;
 
 DECLARE_TOAST(pg_user_mapping, 4173, 4174);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops), USERMAPPINGOID, 2);
+DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops), USERMAPPINGUSERSERVER, 2);
 
 #endif							/* PG_USER_MAPPING_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 67ea6e4945..68827fba50 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -20,103 +20,7 @@
 #include "access/htup.h"
 /* we intentionally do not include utils/catcache.h here */
 
-/*
- *		SysCache identifiers.
- *
- *		The order of these identifiers must match the order
- *		of the entries in the array cacheinfo[] in syscache.c.
- *		Keep them in alphabetical order (renumbering only costs a
- *		backend rebuild).
- */
-
-enum SysCacheIdentifier
-{
-	AGGFNOID = 0,
-	AMNAME,
-	AMOID,
-	AMOPOPID,
-	AMOPSTRATEGY,
-	AMPROCNUM,
-	ATTNAME,
-	ATTNUM,
-	AUTHMEMMEMROLE,
-	AUTHMEMROLEMEM,
-	AUTHNAME,
-	AUTHOID,
-	CASTSOURCETARGET,
-	CLAAMNAMENSP,
-	CLAOID,
-	COLLNAMEENCNSP,
-	COLLOID,
-	CONDEFAULT,
-	CONNAMENSP,
-	CONSTROID,
-	CONVOID,
-	DATABASEOID,
-	DEFACLROLENSPOBJ,
-	ENUMOID,
-	ENUMTYPOIDNAME,
-	EVENTTRIGGERNAME,
-	EVENTTRIGGEROID,
-	FOREIGNDATAWRAPPERNAME,
-	FOREIGNDATAWRAPPEROID,
-	FOREIGNSERVERNAME,
-	FOREIGNSERVEROID,
-	FOREIGNTABLEREL,
-	INDEXRELID,
-	LANGNAME,
-	LANGOID,
-	NAMESPACENAME,
-	NAMESPACEOID,
-	OPERNAMENSP,
-	OPEROID,
-	OPFAMILYAMNAMENSP,
-	OPFAMILYOID,
-	PARAMETERACLNAME,
-	PARAMETERACLOID,
-	PARTRELID,
-	PROCNAMEARGSNSP,
-	PROCOID,
-	PUBLICATIONNAME,
-	PUBLICATIONNAMESPACE,
-	PUBLICATIONNAMESPACEMAP,
-	PUBLICATIONOID,
-	PUBLICATIONREL,
-	PUBLICATIONRELMAP,
-	RANGEMULTIRANGE,
-	RANGETYPE,
-	RELNAMENSP,
-	RELOID,
-	REPLORIGIDENT,
-	REPLORIGNAME,
-	RULERELNAME,
-	SEQRELID,
-	STATEXTDATASTXOID,
-	STATEXTNAMENSP,
-	STATEXTOID,
-	STATRELATTINH,
-	SUBSCRIPTIONNAME,
-	SUBSCRIPTIONOID,
-	SUBSCRIPTIONRELMAP,
-	TABLESPACEOID,
-	TRFOID,
-	TRFTYPELANG,
-	TSCONFIGMAP,
-	TSCONFIGNAMENSP,
-	TSCONFIGOID,
-	TSDICTNAMENSP,
-	TSDICTOID,
-	TSPARSERNAMENSP,
-	TSPARSEROID,
-	TSTEMPLATENAMENSP,
-	TSTEMPLATEOID,
-	TYPENAMENSP,
-	TYPEOID,
-	USERMAPPINGOID,
-	USERMAPPINGUSERSERVER
-
-#define SysCacheSize (USERMAPPINGUSERSERVER + 1)
-};
+#include "catalog/syscache_info.h"
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 4e09c4686b..56ed423567 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 8dee1b5670..477e4dd7e6 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
-- 
2.41.0

v3-0003-Generate-ObjectProperty-from-catalog-files.patchtext/plain; charset=UTF-8; name=v3-0003-Generate-ObjectProperty-from-catalog-files.patchDownload
From a17faafd7c55f446bd3eb99e3451e23f74a06873 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 31 Aug 2023 09:51:28 +0200
Subject: [PATCH v3 3/3] Generate ObjectProperty from catalog files

Most of the information can be extracted from catalog files and
generated automatically.

TODO: Currently missing: object type and class description.  There are
some workarounds in place.

We also now replace the linear search with a hash function generated
using PerfectHash.  This would allow this lookup table to be used in
more performance-sensitive situations.

Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
 src/backend/catalog/.gitignore      |   1 +
 src/backend/catalog/Makefile        |   2 +-
 src/backend/catalog/genbki.pl       | 167 ++++++++++++++++++++++++++++
 src/backend/catalog/objectaddress.c |  22 ++--
 src/include/catalog/meson.build     |   2 +
 src/tools/pginclude/cpluspluscheck  |   3 +
 src/tools/pginclude/headerscheck    |   3 +
 7 files changed, 188 insertions(+), 12 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index ff65560379..d817798dc0 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,3 +1,4 @@
+/objectproperty_info.c.h
 /postgres.bki
 /schemapg.h
 /syscache_info.c.h
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 2c94126ec5..e6c5878e99 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -120,7 +120,7 @@ CATALOG_HEADERS := \
 	pg_subscription.h \
 	pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) objectproperty_info.c.h schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 78f2da690e..199091305c 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -19,8 +19,10 @@
 
 use FindBin;
 use lib $FindBin::RealBin;
+use lib "$FindBin::RealBin/../../tools";
 
 use Catalog;
+use PerfectHash;
 
 my $output_path = '';
 my $major_version;
@@ -59,6 +61,7 @@
 my %syscaches;
 my %oidcounts;
 my @system_constraints;
+my @object_properties;
 
 foreach my $header (@ARGV)
 {
@@ -133,6 +136,7 @@
 		$oidcounts{ $toast->{toast_oid} }++;
 		$oidcounts{ $toast->{toast_index_oid} }++;
 	}
+	my ($oid_index, $oid_syscache, $name_syscache, $is_nsp_name_unique);
 	foreach my $index (@{ $catalog->{indexing} })
 	{
 		push @index_decls,
@@ -166,7 +170,136 @@
 				nbuckets => $index->{syscache_nbuckets},
 			};
 		}
+
+		if ($index->{index_decl} eq 'btree(oid oid_ops)')
+		{
+			$oid_index = $index->{index_oid_macro};
+			$oid_syscache = $index->{syscache_name};
+		}
+		if ($index->{index_decl} =~ /\(\w+name name_ops(, \w+namespace oid_ops)?\)/)
+		{
+			$name_syscache = $index->{syscache_name};
+			$is_nsp_name_unique = 1 if $index->{is_unique};
+		}
+	}
+
+	my ($attnum_oid, $attnum_name, $attnum_namespace, $attnum_owner, $attnum_acl);
+	foreach my $att (@$schema)
+	{
+		if ($att->{name} eq 'oid' && $att->{type} eq 'oid')
+		{
+			$attnum_oid = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}name$/ && $att->{type} eq 'name')
+		{
+			$attnum_name = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}namespace$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_namespace')
+		{
+			$attnum_namespace = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}owner$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_authid')
+		{
+			$attnum_owner = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}acl$/ && $att->{type} eq '_aclitem')
+		{
+			$attnum_acl = "Anum_${catname}_" . $att->{name};
+		}
+	}
+
+	# XXX hardcoded exceptions
+	# extension doesn't belong to extnamespace
+	$attnum_namespace = undef if $catname eq 'pg_extension';
+	# pg_database owner is spelled datdba
+	$attnum_owner = "Anum_pg_database_datdba" if $catname eq 'pg_database';
+	# XXX?
+	$name_syscache = "SUBSCRIPTIONNAME" if $catname eq 'pg_subscription';
+	# XXX?
+	$is_nsp_name_unique = 1 if $catname eq 'pg_collation';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_opclass';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_opfamily';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_subscription';
+
+	# XXX These catalogs were not covered by the previous hand-maintained table.
+	my @skip = qw(
+		AttrDefaultRelationId EnumRelationId IndexRelationId
+		LargeObjectRelationId ParameterAclRelationId
+		PublicationNamespaceRelationId PublicationRelRelationId
+		InheritsRelationId AggregateRelationId StatisticRelationId
+		StatisticExtDataRelationId DescriptionRelationId
+		DependRelationId DbRoleSettingRelationId
+		SharedDependRelationId SharedDescriptionRelationId
+		TSConfigMapRelationId ForeignTableRelationId
+		ReplicationOriginRelationId InitPrivsRelationId
+		SecLabelRelationId SharedSecLabelRelationId
+		PartitionedRelationId RangeRelationId SequenceRelationId
+		SubscriptionRelRelationId);
+	# XXX This one neither, but if I add it to @skip, PerfectHash will fail. (???)
+	#FIXME: AttributeRelationId
+
+	# XXX hardcoded ObjectType mapping -- where to put this?
+	my %objtypes = (
+		'AccessMethodRelationId' => 'OBJECT_ACCESS_METHOD',
+		'AccessMethodOperatorRelationId' => 'OBJECT_AMOP',
+		'AccessMethodProcedureRelationId' => 'OBJECT_AMPROC',
+		'CastRelationId' => 'OBJECT_CAST',
+		'CollationRelationId' => 'OBJECT_COLLATION',
+		'ConversionRelationId' => 'OBJECT_CONVERSION',
+		'DatabaseRelationId' => 'OBJECT_DATABASE',
+		'DefaultAclRelationId' => 'OBJECT_DEFACL',
+		'ExtensionRelationId' => 'OBJECT_EXTENSION',
+		'ForeignDataWrapperRelationId' => 'OBJECT_FDW',
+		'ForeignServerRelationId' => 'OBJECT_FOREIGN_SERVER',
+		'ProcedureRelationId' => 'OBJECT_FUNCTION',
+		'LanguageRelationId' => 'OBJECT_LANGUAGE',
+		'LargeObjectMetadataRelationId' => 'OBJECT_LARGEOBJECT',
+		'OperatorClassRelationId' => 'OBJECT_OPCLASS',
+		'OperatorRelationId' => 'OBJECT_OPERATOR',
+		'OperatorFamilyRelationId' => 'OBJECT_OPFAMILY',
+		'AuthIdRelationId' => 'OBJECT_ROLE',
+		'RewriteRelationId' => 'OBJECT_RULE',
+		'NamespaceRelationId' => 'OBJECT_SCHEMA',
+		'RelationRelationId' => 'OBJECT_TABLE',
+		'TableSpaceRelationId' => 'OBJECT_TABLESPACE',
+		'TransformRelationId' => 'OBJECT_TRANSFORM',
+		'TriggerRelationId' => 'OBJECT_TRIGGER',
+		'PolicyRelationId' => 'OBJECT_POLICY',
+		'EventTriggerRelationId' => 'OBJECT_EVENT_TRIGGER',
+		'TSConfigRelationId' => 'OBJECT_TSCONFIGURATION',
+		'TSDictionaryRelationId' => 'OBJECT_TSDICTIONARY',
+		'TSParserRelationId' => 'OBJECT_TSPARSER',
+		'TSTemplateRelationId' => 'OBJECT_TSTEMPLATE',
+		'TypeRelationId' => 'OBJECT_TYPE',
+		'PublicationRelationId' => 'OBJECT_PUBLICATION',
+		'SubscriptionRelationId' => 'OBJECT_SUBSCRIPTION',
+		'StatisticExtRelationId' => 'OBJECT_STATISTIC_EXT',
+		'UserMappingRelationId' => 'OBJECT_USER_MAPPING',
+	);
+	my $objtype = $objtypes{$catalog->{relation_oid_macro}};
+
+	# XXX This just uses the catalog name as a string rather than the
+	# previous natural-language description.  This could be changed if
+	# we decide on a place to store this.  But maybe for what we are
+	# using it, this is actually better.
+	my $class_descr = qq{"${catname}"};
+
+	push @object_properties, {
+		class_descr => $class_descr,
+		class_oid => $catalog->{relation_oid_macro},
+		_class_oid => $catalog->{relation_oid},
+		oid_index_oid => $oid_index,
+		oid_catcache_id => $oid_syscache || '-1',
+		name_catcache_id => $name_syscache || '-1',
+		attnum_oid => $attnum_oid,
+		attnum_name => $attnum_name,
+		attnum_namespace => $attnum_namespace,
+		attnum_owner => $attnum_owner,
+		attnum_acl => $attnum_acl,
+		objtype => $objtype,
+		is_nsp_name_unique => $is_nsp_name_unique ? 'true' : 'false',
 	}
+	unless grep { $_ eq $catalog->{relation_oid_macro} } @skip;
 }
 
 # Complain and exit if we found any duplicate OIDs.
@@ -441,6 +574,9 @@
 my $syscache_info_c = $output_path . 'syscache_info.c.h';
 open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
   or die "can't open $syscache_info_c$tmpext: $!";
+my $objectproperty_info = $output_path . 'objectproperty_info.c.h';
+open my $objectproperty_info_fh, '>', $objectproperty_info . $tmpext
+  or die "can't open $objectproperty_info$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -810,6 +946,35 @@
 
 print $syscache_info_c_fh "};\n";
 
+# Now generate objectproperty_info
+
+print_boilerplate($objectproperty_info_fh, "objectproperty_info.h", "object property data");
+print $objectproperty_info_fh "\n";
+foreach my $catname (@catnames)
+{
+	print $objectproperty_info_fh qq{#include "catalog/${catname}_d.h"\n};
+}
+print $objectproperty_info_fh "\n";
+print $objectproperty_info_fh "static const ObjectPropertyType ObjectProperty[] =
+{
+";
+
+my @class_oids;
+foreach my $op (@object_properties)
+{
+	print $objectproperty_info_fh "\t{\n";
+	foreach my $p (sort keys %{$op})
+	{
+		printf $objectproperty_info_fh "\t\t.%s = %s,\n", $p, ${$op}{$p} if $p !~ /^_/ && ${$op}{$p};
+	}
+	push @class_oids, pack('N', ${$op}{_class_oid});
+	print $objectproperty_info_fh "\t},\n";
+}
+
+print $objectproperty_info_fh "};\n";
+
+print $objectproperty_info_fh "\nstatic " . PerfectHash::generate_hash_function(\@class_oids, 'objectproperty_hash_func', fixed_key_length => 4);
+
 # We're done emitting data
 close $bki;
 close $schemapg;
@@ -817,6 +982,7 @@
 close $constraints;
 close $syscache_info_h_fh;
 close $syscache_info_c_fh;
+close $objectproperty_info_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
@@ -825,6 +991,7 @@
 Catalog::RenameTempFile($constraints_file, $tmpext);
 Catalog::RenameTempFile($syscache_info_h, $tmpext);
 Catalog::RenameTempFile($syscache_info_c, $tmpext);
+Catalog::RenameTempFile($objectproperty_info, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index bb4efcad20..6ba84ee86c 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -32,19 +32,10 @@
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_conversion.h"
-#include "catalog/pg_database.h"
 #include "catalog/pg_default_acl.h"
-#include "catalog/pg_enum.h"
-#include "catalog/pg_event_trigger.h"
-#include "catalog/pg_extension.h"
-#include "catalog/pg_foreign_data_wrapper.h"
-#include "catalog/pg_foreign_server.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_largeobject.h"
-#include "catalog/pg_largeobject_metadata.h"
-#include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_parameter_acl.h"
 #include "catalog/pg_policy.h"
@@ -54,8 +45,6 @@
 #include "catalog/pg_publication_rel.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_statistic_ext.h"
-#include "catalog/pg_subscription.h"
-#include "catalog/pg_tablespace.h"
 #include "catalog/pg_transform.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_ts_config.h"
@@ -119,6 +108,9 @@ typedef struct
 									 * object of this class? */
 } ObjectPropertyType;
 
+#if 1
+#include "catalog/objectproperty_info.c.h"
+#else
 static const ObjectPropertyType ObjectProperty[] =
 {
 	{
@@ -640,6 +632,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		false
 	},
 };
+#endif
 
 /*
  * This struct maps the string object types as returned by
@@ -2791,6 +2784,7 @@ get_object_property_data(Oid class_id)
 {
 	static const ObjectPropertyType *prop_last = NULL;
 	int			index;
+	uint32      hashkey;
 
 	/*
 	 * A shortcut to speed up multiple consecutive lookups of a particular
@@ -2799,7 +2793,13 @@ get_object_property_data(Oid class_id)
 	if (prop_last && prop_last->class_oid == class_id)
 		return prop_last;
 
+#if 1
+	hashkey = pg_hton32(class_id);
+	index = objectproperty_hash_func(&hashkey);
+	if (index >= 0 && index < lengthof(ObjectProperty))
+#else
 	for (index = 0; index < lengthof(ObjectProperty); index++)
+#endif
 	{
 		if (ObjectProperty[index].class_oid == class_id)
 		{
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index 39d8e94ae2..3362733b5a 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -103,6 +103,7 @@ bki_data_f = files(bki_data)
 
 input = []
 output_files = [
+  'objectproperty_info.c.h',
   'postgres.bki',
   'system_constraints.sql',
   'schemapg.h',
@@ -111,6 +112,7 @@ output_files = [
   'system_fk_info.h',
 ]
 output_install = [
+  dir_data,
   dir_data,
   dir_data,
   dir_include_server / 'catalog',
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 56ed423567..49e3ca7a7b 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 477e4dd7e6..a1ea2ef692 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
-- 
2.41.0

#8John Naylor
john.naylor@enterprisedb.com
In reply to: Peter Eisentraut (#7)
1 attachment(s)
Re: generate syscache info automatically

On Thu, Aug 31, 2023 at 6:23 PM Peter Eisentraut <peter@eisentraut.org>
wrote:

Attached is an updated patch set.

One win here is that the ObjectProperty lookup now uses a hash function
instead of a linear search. So hopefully the performance is better (to
be confirmed) and it could now be used for things like [0].

+ # XXX This one neither, but if I add it to @skip, PerfectHash will fail.
(???)
+ #FIXME: AttributeRelationId

I took a quick look at this, and attached is the least invasive way to get
it working for now, which is to bump the table size slightly. The comment
says doing this isn't reliable, but it happens to work in this case.
Playing around with the functions is hit-or-miss, and when that fails,
somehow the larger table saves the day.

--
John Naylor
EDB: http://www.enterprisedb.com

Attachments:

quick-hack-fix-hash.patch.txttext/plain; charset=US-ASCII; name=quick-hack-fix-hash.patch.txtDownload
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 199091305c..3640ee154b 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -223,6 +223,7 @@ foreach my $header (@ARGV)
 
 	# XXX These catalogs were not covered by the previous hand-maintained table.
 	my @skip = qw(
+		AttributeRelationId
 		AttrDefaultRelationId EnumRelationId IndexRelationId
 		LargeObjectRelationId ParameterAclRelationId
 		PublicationNamespaceRelationId PublicationRelRelationId
@@ -235,8 +236,6 @@ foreach my $header (@ARGV)
 		SecLabelRelationId SharedSecLabelRelationId
 		PartitionedRelationId RangeRelationId SequenceRelationId
 		SubscriptionRelRelationId);
-	# XXX This one neither, but if I add it to @skip, PerfectHash will fail. (???)
-	#FIXME: AttributeRelationId
 
 	# XXX hardcoded ObjectType mapping -- where to put this?
 	my %objtypes = (
diff --git a/src/tools/PerfectHash.pm b/src/tools/PerfectHash.pm
index e54905a3ef..f343661859 100644
--- a/src/tools/PerfectHash.pm
+++ b/src/tools/PerfectHash.pm
@@ -200,7 +200,8 @@ sub _construct_hash_table
 	# can be rejected due to touching unused hashtable entries.  In practice,
 	# neither effect seems strong enough to justify using a larger table.)
 	my $nedges = scalar @keys;       # number of edges
-	my $nverts = 2 * $nedges + 1;    # number of vertices
+	# WIP for object properties
+	my $nverts = 2 * $nedges + 3;    # number of vertices
 
 	# However, it would be very bad if $nverts were exactly equal to either
 	# $hash_mult1 or $hash_mult2: effectively, that hash function would be
#9John Naylor
john.naylor@enterprisedb.com
In reply to: John Naylor (#8)
2 attachment(s)
Re: generate syscache info automatically

I wrote:

+ # XXX This one neither, but if I add it to @skip, PerfectHash will

fail. (???)

+ #FIXME: AttributeRelationId

I took a quick look at this, and attached is the least invasive way to

get it working for now, which is to bump the table size slightly. The
comment says doing this isn't reliable, but it happens to work in this
case. Playing around with the functions is hit-or-miss, and when that
fails, somehow the larger table saves the day.

To while away a rainy day, I poked at this a bit more and found the input
is pathological with our current methods. Even with a large-ish exhaustive
search, the two success are strange in that they only succeeded by
accidentally bumping the table size up to where I got it to work before
(77):

With multipliers (5, 19), it recognizes that the initial table size (75) is
a multiple of 5, so increases the table size to 76, which is a multiple of
19, so it increases it again to 77 and succeeds.

Same with (3, 76): 75 is a multiple of 3, so up to 76, which of course
divides 76, so bumps it to 77 likewise.

Turning the loop into

a = (a ^ c) * 257;
b = (b ^ c) * X;

...seems to work very well.

In fact, now trying some powers-of-two for X before the primes works most
of the time with our inputs, even for some unicode normalization functions,
on the first seed iteration. That likely won't make any difference in
practice, but it's an interesting demo. I've attached these two draft ideas
as text.

--
John Naylor
EDB: http://www.enterprisedb.com

Attachments:

v301-0001-Use-XOR-for-combining-and-do-it-before-mixing.patch.txttext/plain; charset=US-ASCII; name=v301-0001-Use-XOR-for-combining-and-do-it-before-mixing.patch.txtDownload
From c72fa746108ed853f0219b10e7368b6e833e5fc5 Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Sat, 2 Sep 2023 16:25:23 +0700
Subject: [PATCH v301 1/2] Use XOR for combining and do it before mixing

Previously, we mixed first and then combined the input
character via addition. This failed on a small set of
OIDs, per report from Peter Eisentraut.
---
 src/tools/PerfectHash.pm | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/tools/PerfectHash.pm b/src/tools/PerfectHash.pm
index e54905a3ef..0d6826141f 100644
--- a/src/tools/PerfectHash.pm
+++ b/src/tools/PerfectHash.pm
@@ -144,8 +144,8 @@ sub generate_hash_function
 	$f .= sprintf "\t\tunsigned char c = *k++";
 	$f .= sprintf " | 0x20" if $case_fold;                 # see comment below
 	$f .= sprintf ";\n\n";
-	$f .= sprintf "\t\ta = a * %d + c;\n", $hash_mult1;
-	$f .= sprintf "\t\tb = b * %d + c;\n", $hash_mult2;
+	$f .= sprintf "\t\ta = (a ^ c) * %d;\n", $hash_mult1;
+	$f .= sprintf "\t\tb = (b ^ c) * %d;\n", $hash_mult2;
 	$f .= sprintf "\t}\n";
 	$f .= sprintf "\treturn h[a %% %d] + h[b %% %d];\n", $nhash, $nhash;
 	$f .= sprintf "}\n";
@@ -171,7 +171,7 @@ sub _calc_hash
 	{
 		my $cn = ord($c);
 		$cn |= 0x20 if $case_fold;
-		$result = ($result * $mult + $cn) % 4294967296;
+		$result = (($result ^ $cn) * $mult) % 4294967296;
 	}
 	return $result;
 }
@@ -203,8 +203,8 @@ sub _construct_hash_table
 	my $nverts = 2 * $nedges + 1;    # number of vertices
 
 	# However, it would be very bad if $nverts were exactly equal to either
-	# $hash_mult1 or $hash_mult2: effectively, that hash function would be
-	# sensitive to only the last byte of each key.  Cases where $nverts is a
+	# $hash_mult1 or $hash_mult2: the corresponding hash function would
+	# always have a modulus of zero.  Cases where $nverts is a
 	# multiple of either multiplier likewise lose information.  (But $nverts
 	# can't actually divide them, if they've been intelligently chosen as
 	# primes.)  We can avoid such problems by adjusting the table size.
-- 
2.41.0

v301-0002-Use-powers-of-two-when-choosing-multipliers-for.patch.txttext/plain; charset=US-ASCII; name=v301-0002-Use-powers-of-two-when-choosing-multipliers-for.patch.txtDownload
From a407ee7138c597403be5e0521416e4bf5a9c2e46 Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Sat, 2 Sep 2023 16:07:53 +0700
Subject: [PATCH v301 2/2] Use powers of two when choosing multipliers for
 perfect hash functions

---
 src/tools/PerfectHash.pm | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/tools/PerfectHash.pm b/src/tools/PerfectHash.pm
index 0d6826141f..dc5a9b4427 100644
--- a/src/tools/PerfectHash.pm
+++ b/src/tools/PerfectHash.pm
@@ -77,8 +77,10 @@ sub generate_hash_function
 	$case_fold = $options{case_fold} || 0;
 
 	# Try different hash function parameters until we find a set that works
-	# for these keys.  The multipliers are chosen to be primes that are cheap
-	# to calculate via shift-and-add, so don't change them without care.
+	# for these keys.  The multipliers are chosen to be numbers that are cheap
+	# to calculate, so don't change them without care.
+	# Currently they are either powers-of-two (which reduce to a shift),
+	# or adjacent primes (which reduce to shift-and-add).
 	# (Commonly, random seeds are tried, but we want reproducible results
 	# from this program so we don't do that.)
 	my $hash_mult1 = 257;
@@ -89,12 +91,12 @@ sub generate_hash_function
   FIND_PARAMS:
 	for ($hash_seed1 = 0; $hash_seed1 < 10; $hash_seed1++)
 	{
-
 		for ($hash_seed2 = 0; $hash_seed2 < 10; $hash_seed2++)
 		{
-			foreach (17, 31, 127, 8191)
+			foreach (16, 32, 64, 128, 512, 1024, 2048, 4096, 8192, 17, 31, 127, 8191)
 			{
 				$hash_mult2 = $_;    # "foreach $hash_mult2" doesn't work
+
 				@subresult = _construct_hash_table(
 					$keys_ref, $hash_mult1, $hash_mult2,
 					$hash_seed1, $hash_seed2);
@@ -205,11 +207,12 @@ sub _construct_hash_table
 	# However, it would be very bad if $nverts were exactly equal to either
 	# $hash_mult1 or $hash_mult2: the corresponding hash function would
 	# always have a modulus of zero.  Cases where $nverts is a
-	# multiple of either multiplier likewise lose information.  (But $nverts
-	# can't actually divide them, if they've been intelligently chosen as
-	# primes.)  We can avoid such problems by adjusting the table size.
+	# multiple or divisor of either multiplier likewise lose information.
+	# We can avoid such problems by adjusting the table size.
 	while ($nverts % $hash_mult1 == 0
-		|| $nverts % $hash_mult2 == 0)
+		|| $nverts % $hash_mult2 == 0
+		|| $hash_mult1 % $nverts == 0
+		|| $hash_mult2 % $nverts == 0)
 	{
 		$nverts++;
 	}
-- 
2.41.0

#10John Naylor
john.naylor@enterprisedb.com
In reply to: Peter Eisentraut (#7)
Re: generate syscache info automatically

On Thu, Aug 31, 2023 at 6:23 PM Peter Eisentraut <peter@eisentraut.org>
wrote:

Attached is an updated patch set.

There was some discussion about whether the catalog files are the right
place to keep syscache information. Personally, I would find that more
convenient. (Note that we also recently moved the definitions of
indexes and toast tables from files with the whole list into the various
catalog files.) But we can also keep it somewhere else. The important
thing is that Catalog.pm can find it somewhere in a structured form.

I don't have anything further to say on how to fit it together, but I'll go
ahead share some other comments from a quick read of v3-0003:

+ # XXX hardcoded exceptions
+ # extension doesn't belong to extnamespace
+ $attnum_namespace = undef if $catname eq 'pg_extension';
+ # pg_database owner is spelled datdba
+ $attnum_owner = "Anum_pg_database_datdba" if $catname eq 'pg_database';

These exceptions seem like true exceptions...

+ # XXX?
+ $name_syscache = "SUBSCRIPTIONNAME" if $catname eq 'pg_subscription';
+ # XXX?
+ $is_nsp_name_unique = 1 if $catname eq 'pg_collation';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_opclass';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_opfamily';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_subscription';

... but as the XXX conveys, these indicate a failure to do the right thing.
Trying to derive this info from the index declarations is currently
fragile. E.g. making one small change to this regex:

-               if ($index->{index_decl} =~ /\(\w+name name_ops(,
\w+namespace oid_ops)?\)/)
+               if ($index->{index_decl} =~ /\w+name name_ops(,
\w+namespace oid_ops)?\)/)

...causes "is_nsp_name_unique" to flip from false to true, and/or sets
"name_catcache_id" where it wasn't before, for several entries. It's not
quite clear what the "rule" is intended to be, or whether it's robust going
forward.

That being the case, perhaps some effort should also be made to make it
easy to verify the output matches HEAD (or rather, v3-0001). This is now
difficult because of the C99 ".foo = bar" syntax, plus the alphabetical
ordering.

+foreach my $catname (@catnames)
+{
+ print $objectproperty_info_fh qq{#include "catalog/${catname}_d.h"\n};
+}

Assuming we have a better way to know which catalogs need
object properties, is there a todo to only #include those?

To finish up the ObjectProperty generation, we also need to store some
more data, namely the OBJECT_* mappings. We probably do not want to
store those in the catalog headers; that looks like a layering violation
to me.

Possibly, but it's also convenient and, one could argue, more
straightforward than storing syscache id and num_buckets in the index info.

One last thing: I did try to make the hash function use uint16 for the key
(to reduce loop iterations on nul bytes), and that didn't help, so we are
left with the ideas I mentioned earlier.

(not changing CF status, because nothing specific is really required to
change at the moment, some things up in the air)

--
John Naylor
EDB: http://www.enterprisedb.com

#11Peter Eisentraut
peter@eisentraut.org
In reply to: John Naylor (#10)
2 attachment(s)
Re: generate syscache info automatically

Here is a rebased patch set, along with a summary of the questions I
have about these patches:

v4-0001-Generate-syscache-info-from-catalog-files.patch

What's a good syntax to declare a syscache? Currently, I have, for example

-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, 
pg_type, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, 
pg_type, btree(oid oid_ops), TYPEOID, 64);

I suppose a sensible alternative could be to leave the
DECLARE_..._INDEX... alone and make a separate statement, like

MAKE_SYSCACHE(pg_type_oid_index, TYPEOID, 64);

That's at least visually easier, because some of those
DECLARE_... lines are getting pretty long.

I would like to keep those MAKE_SYSCACHE lines in the catalog files.
That just makes it easier to reference everything together.

v4-0002-Generate-ObjectProperty-from-catalog-files.patch

Several questions here:

* What's a good way to declare the mapping between catalog and object
type?

* How to select which catalogs have ObjectProperty entries generated?

* Where to declare class descriptions? Or just keep the current hack in
the patch.

* How to declare the purpose of a catalog column, like "this is the ACL
column for this catalog". This is currently done by name, but maybe
it should be more explicit.

* Question about how to pick the correct value for is_nsp_name_unique?

This second patch is clearly still WIP. I hope the first patch can be
finished soon, however.

I was also amused to find the original commit fa351d5a0db that
introduced ObjectProperty, which contains the following comment:

Performance isn't critical here, so there's no need to be smart
about how we do the search.

which I'm now trying to amend.

Show quoted text

On 11.09.23 07:02, John Naylor wrote:

On Thu, Aug 31, 2023 at 6:23 PM Peter Eisentraut <peter@eisentraut.org
<mailto:peter@eisentraut.org>> wrote:

Attached is an updated patch set.

There was some discussion about whether the catalog files are the right
place to keep syscache information.  Personally, I would find that more
convenient.  (Note that we also recently moved the definitions of
indexes and toast tables from files with the whole list into the various
catalog files.)  But we can also keep it somewhere else.  The important
thing is that Catalog.pm can find it somewhere in a structured form.

I don't have anything further to say on how to fit it together, but I'll
go ahead share some other comments from a quick read of v3-0003:

+ # XXX hardcoded exceptions
+ # extension doesn't belong to extnamespace
+ $attnum_namespace = undef if $catname eq 'pg_extension';
+ # pg_database owner is spelled datdba
+ $attnum_owner = "Anum_pg_database_datdba" if $catname eq 'pg_database';

These exceptions seem like true exceptions...

+ # XXX?
+ $name_syscache = "SUBSCRIPTIONNAME" if $catname eq 'pg_subscription';
+ # XXX?
+ $is_nsp_name_unique = 1 if $catname eq 'pg_collation';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_opclass';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_opfamily';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_subscription';

... but as the XXX conveys, these indicate a failure to do the right
thing. Trying to derive this info from the index declarations is
currently fragile. E.g. making one small change to this regex:

-               if ($index->{index_decl} =~ /\(\w+name name_ops(, 
\w+namespace oid_ops)?\)/)
+               if ($index->{index_decl} =~ /\w+name name_ops(, 
\w+namespace oid_ops)?\)/)

...causes "is_nsp_name_unique" to flip from false to true, and/or sets
"name_catcache_id" where it wasn't before, for several entries. It's not
quite clear what the "rule" is intended to be, or whether it's robust
going forward.

That being the case, perhaps some effort should also be made to make it
easy to verify the output matches HEAD (or rather, v3-0001). This is now
difficult because of the C99 ".foo = bar" syntax, plus the alphabetical
ordering.

+foreach my $catname (@catnames)
+{
+ print $objectproperty_info_fh qq{#include "catalog/${catname}_d.h"\n};
+}

Assuming we have a better way to know which catalogs need
object properties, is there a todo to only #include those?

To finish up the ObjectProperty generation, we also need to store some
more data, namely the OBJECT_* mappings.  We probably do not want to
store those in the catalog headers; that looks like a layering violation
to me.

Possibly, but it's also convenient and, one could argue, more
straightforward than storing syscache id and num_buckets in the index info.

One last thing: I did try to make the hash function use uint16 for the
key (to reduce loop iterations on nul bytes), and that didn't help, so
we are left with the ideas I mentioned earlier.

(not changing CF status, because nothing specific is really required to
change at the moment, some things up in the air)

--
John Naylor
EDB: http://www.enterprisedb.com <http://www.enterprisedb.com&gt;

Attachments:

v4-0001-Generate-syscache-info-from-catalog-files.patchtext/plain; charset=UTF-8; name=v4-0001-Generate-syscache-info-from-catalog-files.patchDownload
From 5b6abb26d4cf2b1803697a03c80d59aff1aaf6af Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 1 Nov 2023 16:56:50 -0400
Subject: [PATCH v4 1/2] Generate syscache info from catalog files

DECLARE_UNIQUE_INDEX gets two additional arguments with the syscache
ID macro and the number of buckets.  From that, we can generate the
existing tables in syscache.h and syscache.c via genbki.pl.

Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
 src/backend/catalog/.gitignore                |   2 +
 src/backend/catalog/Catalog.pm                |   6 +-
 src/backend/catalog/Makefile                  |   2 +-
 src/backend/catalog/genbki.pl                 |  61 ++
 src/backend/utils/cache/syscache.c            | 625 +-----------------
 src/include/catalog/.gitignore                |   2 +
 src/include/catalog/genbki.h                  |   7 +-
 src/include/catalog/meson.build               |  18 +-
 src/include/catalog/pg_aggregate.h            |   2 +-
 src/include/catalog/pg_am.h                   |   4 +-
 src/include/catalog/pg_amop.h                 |   4 +-
 src/include/catalog/pg_amproc.h               |   2 +-
 src/include/catalog/pg_attribute.h            |   4 +-
 src/include/catalog/pg_auth_members.h         |   4 +-
 src/include/catalog/pg_authid.h               |   4 +-
 src/include/catalog/pg_cast.h                 |   2 +-
 src/include/catalog/pg_class.h                |   4 +-
 src/include/catalog/pg_collation.h            |   4 +-
 src/include/catalog/pg_constraint.h           |   2 +-
 src/include/catalog/pg_conversion.h           |   6 +-
 src/include/catalog/pg_database.h             |   2 +-
 src/include/catalog/pg_default_acl.h          |   2 +-
 src/include/catalog/pg_enum.h                 |   4 +-
 src/include/catalog/pg_event_trigger.h        |   4 +-
 src/include/catalog/pg_foreign_data_wrapper.h |   4 +-
 src/include/catalog/pg_foreign_server.h       |   4 +-
 src/include/catalog/pg_foreign_table.h        |   2 +-
 src/include/catalog/pg_index.h                |   2 +-
 src/include/catalog/pg_language.h             |   4 +-
 src/include/catalog/pg_namespace.h            |   4 +-
 src/include/catalog/pg_opclass.h              |   4 +-
 src/include/catalog/pg_operator.h             |   4 +-
 src/include/catalog/pg_opfamily.h             |   4 +-
 src/include/catalog/pg_parameter_acl.h        |   4 +-
 src/include/catalog/pg_partitioned_table.h    |   2 +-
 src/include/catalog/pg_proc.h                 |   4 +-
 src/include/catalog/pg_publication.h          |   4 +-
 .../catalog/pg_publication_namespace.h        |   4 +-
 src/include/catalog/pg_publication_rel.h      |   4 +-
 src/include/catalog/pg_range.h                |   4 +-
 src/include/catalog/pg_replication_origin.h   |   4 +-
 src/include/catalog/pg_rewrite.h              |   2 +-
 src/include/catalog/pg_sequence.h             |   2 +-
 src/include/catalog/pg_statistic.h            |   2 +-
 src/include/catalog/pg_statistic_ext.h        |   4 +-
 src/include/catalog/pg_statistic_ext_data.h   |   2 +-
 src/include/catalog/pg_subscription.h         |   4 +-
 src/include/catalog/pg_subscription_rel.h     |   2 +-
 src/include/catalog/pg_tablespace.h           |   2 +-
 src/include/catalog/pg_transform.h            |   4 +-
 src/include/catalog/pg_ts_config.h            |   4 +-
 src/include/catalog/pg_ts_config_map.h        |   2 +-
 src/include/catalog/pg_ts_dict.h              |   4 +-
 src/include/catalog/pg_ts_parser.h            |   4 +-
 src/include/catalog/pg_ts_template.h          |   4 +-
 src/include/catalog/pg_type.h                 |   4 +-
 src/include/catalog/pg_user_mapping.h         |   4 +-
 src/include/utils/syscache.h                  |  98 +--
 src/tools/pginclude/cpluspluscheck            |   5 +
 src/tools/pginclude/headerscheck              |   5 +
 60 files changed, 193 insertions(+), 804 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index 237ff541659..ff655603792 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,5 +1,7 @@
 /postgres.bki
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /system_constraints.sql
 /pg_*_d.h
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index be56cc153f9..de676327933 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -118,7 +118,11 @@ sub ParseHeader
 			 (?<index_oid>\d+),\s*
 			 (?<index_oid_macro>\w+),\s*
 			 (?<table_name>\w+),\s*
-			 (?<index_decl>.+)\s*
+			 (?<index_decl>\w+\s*\([\w\s,]+\))\s*
+			 (?:,\s*
+			   (?<syscache_name>\w+),\s*
+			   (?<syscache_nbuckets>\w+)
+			 )?
 			 \)/x
 		  )
 		{
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 3e9994793d6..2c94126ec5c 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -120,7 +120,7 @@ CATALOG_HEADERS := \
 	pg_subscription.h \
 	pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 380bc23c82e..78f2da690ec 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -56,6 +56,7 @@
 my %catalog_data;
 my @toast_decls;
 my @index_decls;
+my %syscaches;
 my %oidcounts;
 my @system_constraints;
 
@@ -150,6 +151,21 @@
 			  $index->{is_pkey} ? "PRIMARY KEY" : "UNIQUE",
 			  $index->{index_name};
 		}
+
+		if ($index->{syscache_name})
+		{
+			my $tbl = $index->{table_name};
+			my $key = $index->{index_decl};
+			$key =~ s/^\w+\(//;
+			$key =~ s/\)$//;
+			$key =~ s/(\w+)\s+\w+/Anum_${tbl}_$1/g;
+			$syscaches{$index->{syscache_name}} = {
+				table_oid_macro => $catalogs{$tbl}->{relation_oid_macro},
+				index_oid_macro => $index->{index_oid_macro},
+				key => $key,
+				nbuckets => $index->{syscache_nbuckets},
+			};
+		}
 	}
 }
 
@@ -419,6 +435,12 @@
 my $constraints_file = $output_path . 'system_constraints.sql';
 open my $constraints, '>', $constraints_file . $tmpext
   or die "can't open $constraints_file$tmpext: $!";
+my $syscache_info_h = $output_path . 'syscache_info.h';
+open my $syscache_info_h_fh, '>', $syscache_info_h . $tmpext
+  or die "can't open $syscache_info_h$tmpext: $!";
+my $syscache_info_c = $output_path . 'syscache_info.c.h';
+open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
+  or die "can't open $syscache_info_c$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -753,17 +775,56 @@
 # Closing boilerplate for system_fk_info.h
 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_info_h_fh, "syscache_info.h", "SysCache identifiers");
+print $syscache_info_h_fh "enum SysCacheIdentifier
+{
+";
+
+print_boilerplate($syscache_info_c_fh, "syscache_info.c.h", "SysCache definitions");
+print $syscache_info_c_fh "\n";
+foreach my $catname (@catnames)
+{
+	print $syscache_info_c_fh qq{#include "catalog/${catname}_d.h"\n};
+}
+print $syscache_info_c_fh "\n";
+print $syscache_info_c_fh "static const struct cachedesc cacheinfo[] = {\n";
+
+my $last_syscache;
+foreach my $syscache (sort keys %syscaches)
+{
+	print $syscache_info_h_fh "\t$syscache,\n";
+	$last_syscache = $syscache;
+
+	print $syscache_info_c_fh "\t[$syscache] = {\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{table_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{index_oid_macro}, ",\n";
+	print $syscache_info_c_fh "\t\tKEY(", $syscaches{$syscache}{key}, "),\n";
+	print $syscache_info_c_fh "\t\t", $syscaches{$syscache}{nbuckets}, "\n";
+	print $syscache_info_c_fh "\t},\n";
+}
+
+print $syscache_info_h_fh "};\n";
+print $syscache_info_h_fh "#define SysCacheSize ($last_syscache + 1)\n";
+
+print $syscache_info_c_fh "};\n";
+
 # We're done emitting data
 close $bki;
 close $schemapg;
 close $fk_info;
 close $constraints;
+close $syscache_info_h_fh;
+close $syscache_info_c_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
 Catalog::RenameTempFile($schemafile, $tmpext);
 Catalog::RenameTempFile($fk_info_file, $tmpext);
 Catalog::RenameTempFile($constraints_file, $tmpext);
+Catalog::RenameTempFile($syscache_info_h, $tmpext);
+Catalog::RenameTempFile($syscache_info_c, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 8dbda0024f9..072fa9ef471 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -22,59 +22,6 @@
 
 #include "access/htup_details.h"
 #include "access/sysattr.h"
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_am.h"
-#include "catalog/pg_amop.h"
-#include "catalog/pg_amproc.h"
-#include "catalog/pg_auth_members.h"
-#include "catalog/pg_authid.h"
-#include "catalog/pg_cast.h"
-#include "catalog/pg_collation.h"
-#include "catalog/pg_constraint.h"
-#include "catalog/pg_conversion.h"
-#include "catalog/pg_database.h"
-#include "catalog/pg_db_role_setting.h"
-#include "catalog/pg_default_acl.h"
-#include "catalog/pg_depend.h"
-#include "catalog/pg_description.h"
-#include "catalog/pg_enum.h"
-#include "catalog/pg_event_trigger.h"
-#include "catalog/pg_foreign_data_wrapper.h"
-#include "catalog/pg_foreign_server.h"
-#include "catalog/pg_foreign_table.h"
-#include "catalog/pg_language.h"
-#include "catalog/pg_namespace.h"
-#include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
-#include "catalog/pg_opfamily.h"
-#include "catalog/pg_parameter_acl.h"
-#include "catalog/pg_partitioned_table.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_publication.h"
-#include "catalog/pg_publication_namespace.h"
-#include "catalog/pg_publication_rel.h"
-#include "catalog/pg_range.h"
-#include "catalog/pg_replication_origin.h"
-#include "catalog/pg_rewrite.h"
-#include "catalog/pg_seclabel.h"
-#include "catalog/pg_sequence.h"
-#include "catalog/pg_shdepend.h"
-#include "catalog/pg_shdescription.h"
-#include "catalog/pg_shseclabel.h"
-#include "catalog/pg_statistic.h"
-#include "catalog/pg_statistic_ext.h"
-#include "catalog/pg_statistic_ext_data.h"
-#include "catalog/pg_subscription.h"
-#include "catalog/pg_subscription_rel.h"
-#include "catalog/pg_tablespace.h"
-#include "catalog/pg_transform.h"
-#include "catalog/pg_ts_config.h"
-#include "catalog/pg_ts_config_map.h"
-#include "catalog/pg_ts_dict.h"
-#include "catalog/pg_ts_parser.h"
-#include "catalog/pg_ts_template.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_user_mapping.h"
 #include "lib/qunique.h"
 #include "utils/catcache.h"
 #include "utils/lsyscache.h"
@@ -85,18 +32,6 @@
 
 	Adding system caches:
 
-	Add your new cache to the list in include/utils/syscache.h.
-	Keep the list sorted alphabetically.
-
-	Add your entry to the cacheinfo[] array below. All cache lists are
-	alphabetical, so add it in the proper place.  Specify the relation OID,
-	index OID, number of keys, key attribute numbers, and initial number of
-	hash buckets.
-
-	The number of hash buckets must be a power of 2.  It's reasonable to
-	set this to the number of entries that might be in the particular cache
-	in a medium-size database.
-
 	There must be a unique index underlying each syscache (ie, an index
 	whose key is the same as that of the cache).  If there is not one
 	already, add the definition for it to include/catalog/pg_*.h using
@@ -104,6 +39,13 @@
 	(Adding an index requires a catversion.h update, while simply
 	adding/deleting caches only requires a recompile.)
 
+	Then add the name of your name cache and the initial number of hash
+	buckets as arguments of DECLARE_UNIQUE_INDEX.
+
+	The number of hash buckets must be a power of 2.  It's reasonable to
+	set this to the number of entries that might be in the particular cache
+	in a medium-size database.
+
 	Finally, any place your relation gets heap_insert() or
 	heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
 	instead, which also update indexes.  The heap_* calls do not do that.
@@ -126,558 +68,7 @@ struct cachedesc
 /* Macro to provide nkeys and key array with convenient syntax. */
 #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
 
-static const struct cachedesc cacheinfo[] = {
-	[AGGFNOID] = {
-		AggregateRelationId,
-		AggregateFnoidIndexId,
-		KEY(Anum_pg_aggregate_aggfnoid),
-		16
-	},
-	[AMNAME] = {
-		AccessMethodRelationId,
-		AmNameIndexId,
-		KEY(Anum_pg_am_amname),
-		4
-	},
-	[AMOID] = {
-		AccessMethodRelationId,
-		AmOidIndexId,
-		KEY(Anum_pg_am_oid),
-		4
-	},
-	[AMOPOPID] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodOperatorIndexId,
-		KEY(Anum_pg_amop_amopopr,
-			Anum_pg_amop_amoppurpose,
-			Anum_pg_amop_amopfamily),
-		64
-	},
-	[AMOPSTRATEGY] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodStrategyIndexId,
-		KEY(Anum_pg_amop_amopfamily,
-			Anum_pg_amop_amoplefttype,
-			Anum_pg_amop_amoprighttype,
-			Anum_pg_amop_amopstrategy),
-		64
-	},
-	[AMPROCNUM] = {
-		AccessMethodProcedureRelationId,
-		AccessMethodProcedureIndexId,
-		KEY(Anum_pg_amproc_amprocfamily,
-			Anum_pg_amproc_amproclefttype,
-			Anum_pg_amproc_amprocrighttype,
-			Anum_pg_amproc_amprocnum),
-		16
-	},
-	[ATTNAME] = {
-		AttributeRelationId,
-		AttributeRelidNameIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attname),
-		32
-	},
-	[ATTNUM] = {
-		AttributeRelationId,
-		AttributeRelidNumIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attnum),
-		128
-	},
-	[AUTHMEMMEMROLE] = {
-		AuthMemRelationId,
-		AuthMemMemRoleIndexId,
-		KEY(Anum_pg_auth_members_member,
-			Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHMEMROLEMEM] = {
-		AuthMemRelationId,
-		AuthMemRoleMemIndexId,
-		KEY(Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_member,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHNAME] = {
-		AuthIdRelationId,
-		AuthIdRolnameIndexId,
-		KEY(Anum_pg_authid_rolname),
-		8
-	},
-	[AUTHOID] = {
-		AuthIdRelationId,
-		AuthIdOidIndexId,
-		KEY(Anum_pg_authid_oid),
-		8
-	},
-	[CASTSOURCETARGET] = {
-		CastRelationId,
-		CastSourceTargetIndexId,
-		KEY(Anum_pg_cast_castsource,
-			Anum_pg_cast_casttarget),
-		256
-	},
-	[CLAAMNAMENSP] = {
-		OperatorClassRelationId,
-		OpclassAmNameNspIndexId,
-		KEY(Anum_pg_opclass_opcmethod,
-			Anum_pg_opclass_opcname,
-			Anum_pg_opclass_opcnamespace),
-		8
-	},
-	[CLAOID] = {
-		OperatorClassRelationId,
-		OpclassOidIndexId,
-		KEY(Anum_pg_opclass_oid),
-		8
-	},
-	[COLLNAMEENCNSP] = {
-		CollationRelationId,
-		CollationNameEncNspIndexId,
-		KEY(Anum_pg_collation_collname,
-			Anum_pg_collation_collencoding,
-			Anum_pg_collation_collnamespace),
-		8
-	},
-	[COLLOID] = {
-		CollationRelationId,
-		CollationOidIndexId,
-		KEY(Anum_pg_collation_oid),
-		8
-	},
-	[CONDEFAULT] = {
-		ConversionRelationId,
-		ConversionDefaultIndexId,
-		KEY(Anum_pg_conversion_connamespace,
-			Anum_pg_conversion_conforencoding,
-			Anum_pg_conversion_contoencoding,
-			Anum_pg_conversion_oid),
-		8
-	},
-	[CONNAMENSP] = {
-		ConversionRelationId,
-		ConversionNameNspIndexId,
-		KEY(Anum_pg_conversion_conname,
-			Anum_pg_conversion_connamespace),
-		8
-	},
-	[CONSTROID] = {
-		ConstraintRelationId,
-		ConstraintOidIndexId,
-		KEY(Anum_pg_constraint_oid),
-		16
-	},
-	[CONVOID] = {
-		ConversionRelationId,
-		ConversionOidIndexId,
-		KEY(Anum_pg_conversion_oid),
-		8
-	},
-	[DATABASEOID] = {
-		DatabaseRelationId,
-		DatabaseOidIndexId,
-		KEY(Anum_pg_database_oid),
-		4
-	},
-	[DEFACLROLENSPOBJ] = {
-		DefaultAclRelationId,
-		DefaultAclRoleNspObjIndexId,
-		KEY(Anum_pg_default_acl_defaclrole,
-			Anum_pg_default_acl_defaclnamespace,
-			Anum_pg_default_acl_defaclobjtype),
-		8
-	},
-	[ENUMOID] = {
-		EnumRelationId,
-		EnumOidIndexId,
-		KEY(Anum_pg_enum_oid),
-		8
-	},
-	[ENUMTYPOIDNAME] = {
-		EnumRelationId,
-		EnumTypIdLabelIndexId,
-		KEY(Anum_pg_enum_enumtypid,
-			Anum_pg_enum_enumlabel),
-		8
-	},
-	[EVENTTRIGGERNAME] = {
-		EventTriggerRelationId,
-		EventTriggerNameIndexId,
-		KEY(Anum_pg_event_trigger_evtname),
-		8
-	},
-	[EVENTTRIGGEROID] = {
-		EventTriggerRelationId,
-		EventTriggerOidIndexId,
-		KEY(Anum_pg_event_trigger_oid),
-		8
-	},
-	[FOREIGNDATAWRAPPERNAME] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperNameIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_fdwname),
-		2
-	},
-	[FOREIGNDATAWRAPPEROID] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperOidIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_oid),
-		2
-	},
-	[FOREIGNSERVERNAME] = {
-		ForeignServerRelationId,
-		ForeignServerNameIndexId,
-		KEY(Anum_pg_foreign_server_srvname),
-		2
-	},
-	[FOREIGNSERVEROID] = {
-		ForeignServerRelationId,
-		ForeignServerOidIndexId,
-		KEY(Anum_pg_foreign_server_oid),
-		2
-	},
-	[FOREIGNTABLEREL] = {
-		ForeignTableRelationId,
-		ForeignTableRelidIndexId,
-		KEY(Anum_pg_foreign_table_ftrelid),
-		4
-	},
-	[INDEXRELID] = {
-		IndexRelationId,
-		IndexRelidIndexId,
-		KEY(Anum_pg_index_indexrelid),
-		64
-	},
-	[LANGNAME] = {
-		LanguageRelationId,
-		LanguageNameIndexId,
-		KEY(Anum_pg_language_lanname),
-		4
-	},
-	[LANGOID] = {
-		LanguageRelationId,
-		LanguageOidIndexId,
-		KEY(Anum_pg_language_oid),
-		4
-	},
-	[NAMESPACENAME] = {
-		NamespaceRelationId,
-		NamespaceNameIndexId,
-		KEY(Anum_pg_namespace_nspname),
-		4
-	},
-	[NAMESPACEOID] = {
-		NamespaceRelationId,
-		NamespaceOidIndexId,
-		KEY(Anum_pg_namespace_oid),
-		16
-	},
-	[OPERNAMENSP] = {
-		OperatorRelationId,
-		OperatorNameNspIndexId,
-		KEY(Anum_pg_operator_oprname,
-			Anum_pg_operator_oprleft,
-			Anum_pg_operator_oprright,
-			Anum_pg_operator_oprnamespace),
-		256
-	},
-	[OPEROID] = {
-		OperatorRelationId,
-		OperatorOidIndexId,
-		KEY(Anum_pg_operator_oid),
-		32
-	},
-	[OPFAMILYAMNAMENSP] = {
-		OperatorFamilyRelationId,
-		OpfamilyAmNameNspIndexId,
-		KEY(Anum_pg_opfamily_opfmethod,
-			Anum_pg_opfamily_opfname,
-			Anum_pg_opfamily_opfnamespace),
-		8
-	},
-	[OPFAMILYOID] = {
-		OperatorFamilyRelationId,
-		OpfamilyOidIndexId,
-		KEY(Anum_pg_opfamily_oid),
-		8
-	},
-	[PARAMETERACLNAME] = {
-		ParameterAclRelationId,
-		ParameterAclParnameIndexId,
-		KEY(Anum_pg_parameter_acl_parname),
-		4
-	},
-	[PARAMETERACLOID] = {
-		ParameterAclRelationId,
-		ParameterAclOidIndexId,
-		KEY(Anum_pg_parameter_acl_oid),
-		4
-	},
-	[PARTRELID] = {
-		PartitionedRelationId,
-		PartitionedRelidIndexId,
-		KEY(Anum_pg_partitioned_table_partrelid),
-		32
-	},
-	[PROCNAMEARGSNSP] = {
-		ProcedureRelationId,
-		ProcedureNameArgsNspIndexId,
-		KEY(Anum_pg_proc_proname,
-			Anum_pg_proc_proargtypes,
-			Anum_pg_proc_pronamespace),
-		128
-	},
-	[PROCOID] = {
-		ProcedureRelationId,
-		ProcedureOidIndexId,
-		KEY(Anum_pg_proc_oid),
-		128
-	},
-	[PUBLICATIONNAME] = {
-		PublicationRelationId,
-		PublicationNameIndexId,
-		KEY(Anum_pg_publication_pubname),
-		8
-	},
-	[PUBLICATIONNAMESPACE] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespaceObjectIndexId,
-		KEY(Anum_pg_publication_namespace_oid),
-		64
-	},
-	[PUBLICATIONNAMESPACEMAP] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespacePnnspidPnpubidIndexId,
-		KEY(Anum_pg_publication_namespace_pnnspid,
-			Anum_pg_publication_namespace_pnpubid),
-		64
-	},
-	[PUBLICATIONOID] = {
-		PublicationRelationId,
-		PublicationObjectIndexId,
-		KEY(Anum_pg_publication_oid),
-		8
-	},
-	[PUBLICATIONREL] = {
-		PublicationRelRelationId,
-		PublicationRelObjectIndexId,
-		KEY(Anum_pg_publication_rel_oid),
-		64
-	},
-	[PUBLICATIONRELMAP] = {
-		PublicationRelRelationId,
-		PublicationRelPrrelidPrpubidIndexId,
-		KEY(Anum_pg_publication_rel_prrelid,
-			Anum_pg_publication_rel_prpubid),
-		64
-	},
-	[RANGEMULTIRANGE] = {
-		RangeRelationId,
-		RangeMultirangeTypidIndexId,
-		KEY(Anum_pg_range_rngmultitypid),
-		4
-	},
-	[RANGETYPE] = {
-		RangeRelationId,
-		RangeTypidIndexId,
-		KEY(Anum_pg_range_rngtypid),
-		4
-	},
-	[RELNAMENSP] = {
-		RelationRelationId,
-		ClassNameNspIndexId,
-		KEY(Anum_pg_class_relname,
-			Anum_pg_class_relnamespace),
-		128
-	},
-	[RELOID] = {
-		RelationRelationId,
-		ClassOidIndexId,
-		KEY(Anum_pg_class_oid),
-		128
-	},
-	[REPLORIGIDENT] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginIdentIndex,
-		KEY(Anum_pg_replication_origin_roident),
-		16
-	},
-	[REPLORIGNAME] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginNameIndex,
-		KEY(Anum_pg_replication_origin_roname),
-		16
-	},
-	[RULERELNAME] = {
-		RewriteRelationId,
-		RewriteRelRulenameIndexId,
-		KEY(Anum_pg_rewrite_ev_class,
-			Anum_pg_rewrite_rulename),
-		8
-	},
-	[SEQRELID] = {
-		SequenceRelationId,
-		SequenceRelidIndexId,
-		KEY(Anum_pg_sequence_seqrelid),
-		32
-	},
-	[STATEXTDATASTXOID] = {
-		StatisticExtDataRelationId,
-		StatisticExtDataStxoidInhIndexId,
-		KEY(Anum_pg_statistic_ext_data_stxoid,
-			Anum_pg_statistic_ext_data_stxdinherit),
-		4
-	},
-	[STATEXTNAMENSP] = {
-		StatisticExtRelationId,
-		StatisticExtNameIndexId,
-		KEY(Anum_pg_statistic_ext_stxname,
-			Anum_pg_statistic_ext_stxnamespace),
-		4
-	},
-	[STATEXTOID] = {
-		StatisticExtRelationId,
-		StatisticExtOidIndexId,
-		KEY(Anum_pg_statistic_ext_oid),
-		4
-	},
-	[STATRELATTINH] = {
-		StatisticRelationId,
-		StatisticRelidAttnumInhIndexId,
-		KEY(Anum_pg_statistic_starelid,
-			Anum_pg_statistic_staattnum,
-			Anum_pg_statistic_stainherit),
-		128
-	},
-	[SUBSCRIPTIONNAME] = {
-		SubscriptionRelationId,
-		SubscriptionNameIndexId,
-		KEY(Anum_pg_subscription_subdbid,
-			Anum_pg_subscription_subname),
-		4
-	},
-	[SUBSCRIPTIONOID] = {
-		SubscriptionRelationId,
-		SubscriptionObjectIndexId,
-		KEY(Anum_pg_subscription_oid),
-		4
-	},
-	[SUBSCRIPTIONRELMAP] = {
-		SubscriptionRelRelationId,
-		SubscriptionRelSrrelidSrsubidIndexId,
-		KEY(Anum_pg_subscription_rel_srrelid,
-			Anum_pg_subscription_rel_srsubid),
-		64
-	},
-	[TABLESPACEOID] = {
-		TableSpaceRelationId,
-		TablespaceOidIndexId,
-		KEY(Anum_pg_tablespace_oid),
-		4
-	},
-	[TRFOID] = {
-		TransformRelationId,
-		TransformOidIndexId,
-		KEY(Anum_pg_transform_oid),
-		16
-	},
-	[TRFTYPELANG] = {
-		TransformRelationId,
-		TransformTypeLangIndexId,
-		KEY(Anum_pg_transform_trftype,
-			Anum_pg_transform_trflang),
-		16
-	},
-	[TSCONFIGMAP] = {
-		TSConfigMapRelationId,
-		TSConfigMapIndexId,
-		KEY(Anum_pg_ts_config_map_mapcfg,
-			Anum_pg_ts_config_map_maptokentype,
-			Anum_pg_ts_config_map_mapseqno),
-		2
-	},
-	[TSCONFIGNAMENSP] = {
-		TSConfigRelationId,
-		TSConfigNameNspIndexId,
-		KEY(Anum_pg_ts_config_cfgname,
-			Anum_pg_ts_config_cfgnamespace),
-		2
-	},
-	[TSCONFIGOID] = {
-		TSConfigRelationId,
-		TSConfigOidIndexId,
-		KEY(Anum_pg_ts_config_oid),
-		2
-	},
-	[TSDICTNAMENSP] = {
-		TSDictionaryRelationId,
-		TSDictionaryNameNspIndexId,
-		KEY(Anum_pg_ts_dict_dictname,
-			Anum_pg_ts_dict_dictnamespace),
-		2
-	},
-	[TSDICTOID] = {
-		TSDictionaryRelationId,
-		TSDictionaryOidIndexId,
-		KEY(Anum_pg_ts_dict_oid),
-		2
-	},
-	[TSPARSERNAMENSP] = {
-		TSParserRelationId,
-		TSParserNameNspIndexId,
-		KEY(Anum_pg_ts_parser_prsname,
-			Anum_pg_ts_parser_prsnamespace),
-		2
-	},
-	[TSPARSEROID] = {
-		TSParserRelationId,
-		TSParserOidIndexId,
-		KEY(Anum_pg_ts_parser_oid),
-		2
-	},
-	[TSTEMPLATENAMENSP] = {
-		TSTemplateRelationId,
-		TSTemplateNameNspIndexId,
-		KEY(Anum_pg_ts_template_tmplname,
-			Anum_pg_ts_template_tmplnamespace),
-		2
-	},
-	[TSTEMPLATEOID] = {
-		TSTemplateRelationId,
-		TSTemplateOidIndexId,
-		KEY(Anum_pg_ts_template_oid),
-		2
-	},
-	[TYPENAMENSP] = {
-		TypeRelationId,
-		TypeNameNspIndexId,
-		KEY(Anum_pg_type_typname,
-			Anum_pg_type_typnamespace),
-		64
-	},
-	[TYPEOID] = {
-		TypeRelationId,
-		TypeOidIndexId,
-		KEY(Anum_pg_type_oid),
-		64
-	},
-	[USERMAPPINGOID] = {
-		UserMappingRelationId,
-		UserMappingOidIndexId,
-		KEY(Anum_pg_user_mapping_oid),
-		2
-	},
-	[USERMAPPINGUSERSERVER] = {
-		UserMappingRelationId,
-		UserMappingUserServerIndexId,
-		KEY(Anum_pg_user_mapping_umuser,
-			Anum_pg_user_mapping_umserver),
-		2
-	}
-};
+#include "catalog/syscache_info.c.h"
 
 StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
 				 "SysCacheSize does not match syscache.c's array");
diff --git a/src/include/catalog/.gitignore b/src/include/catalog/.gitignore
index 6b83d4c7e6e..f7ddf2554b8 100644
--- a/src/include/catalog/.gitignore
+++ b/src/include/catalog/.gitignore
@@ -1,4 +1,6 @@
 /schemapg.h
+/syscache_info.c.h
+/syscache_info.h
 /system_fk_info.h
 /pg_*_d.h
 /header-stamp
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index e22a6902fb0..2d5bd38cde0 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -77,13 +77,14 @@
  * is the name of a #define to generate for its OID.  References to the index
  * in the C code should always use these #defines, not the actual index name
  * (much less the numeric OID).  The fourth argument is the table name.  The
- * rest is much like a standard 'create index' SQL command.
+ * decl argument is much like a standard 'create index' SQL command.
+ * Optionally, specify the syscache ID and bucket size.
  *
  * The macro definitions are just to keep the C compiler from spitting up.
  */
 #define DECLARE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
 
 /*
  * These lines inform genbki.pl about manually-assigned OIDs that do not
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index dcb3c5f7666..39d8e94ae27 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -102,8 +102,22 @@ bki_data_f = files(bki_data)
 
 
 input = []
-output_files = ['postgres.bki', 'system_constraints.sql', 'schemapg.h', 'system_fk_info.h']
-output_install = [dir_data, dir_data, dir_include_server / 'catalog', dir_include_server / 'catalog']
+output_files = [
+  'postgres.bki',
+  'system_constraints.sql',
+  'schemapg.h',
+  'syscache_info.c.h',
+  'syscache_info.h',
+  'system_fk_info.h',
+]
+output_install = [
+  dir_data,
+  dir_data,
+  dir_include_server / 'catalog',
+  false,
+  dir_include_server / 'catalog',
+  dir_include_server / 'catalog',
+]
 
 foreach h : catalog_headers
   fname = h.split('.h')[0] + '_d.h'
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 085149e2584..e6f6f4ccb52 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -110,7 +110,7 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
 
 DECLARE_TOAST(pg_aggregate, 4159, 4160);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops), AGGFNOID, 16);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index d5314bb38be..e3a1313e6c4 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -47,8 +47,8 @@ CATALOG(pg_am,2601,AccessMethodRelationId)
  */
 typedef FormData_pg_am *Form_pg_am;
 
-DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops), AMNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops), AMOID, 4);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index c9bb7b47872..3449166507b 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -87,8 +87,8 @@ CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
  */
 typedef FormData_pg_amop *Form_pg_amop;
 
-DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
-DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId, pg_amop, btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops), AMOPSTRATEGY, 64);
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops), AMOPOPID, 64);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, pg_amop, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 5acf4efab90..31e67be344b 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -67,7 +67,7 @@ CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
  */
 typedef FormData_pg_amproc *Form_pg_amproc;
 
-DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops), AMPROCNUM, 16);
 DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, pg_amproc, btree(oid oid_ops));
 
 #endif							/* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 672a5a16ff7..84759175de4 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -208,8 +208,8 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
  */
 typedef FormData_pg_attribute *Form_pg_attribute;
 
-DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops), ATTNAME, 32);
+DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops), ATTNUM, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index 4ab8a9f7b75..37104cf20f7 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -46,8 +46,8 @@ CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_
 typedef FormData_pg_auth_members *Form_pg_auth_members;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_auth_members_oid_index, 6303, AuthMemOidIndexId, pg_auth_members, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops));
-DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops));
+DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemIndexId, pg_auth_members, btree(roleid oid_ops, member oid_ops, grantor oid_ops), AUTHMEMROLEMEM, 8);
+DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops), AUTHMEMMEMROLE, 8);
 DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, pg_auth_members, btree(grantor oid_ops));
 
 #endif							/* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index 0e7ddc56ea3..748ab95fad8 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -57,7 +57,7 @@ typedef FormData_pg_authid *Form_pg_authid;
 
 DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops), AUTHNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops), AUTHOID, 8);
 
 #endif							/* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index a6bfa0dc68b..0ed965ab31d 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -57,7 +57,7 @@ CATALOG(pg_cast,2605,CastRelationId)
 typedef FormData_pg_cast *Form_pg_cast;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, pg_cast, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops), CASTSOURCETARGET, 256);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 55dcd541009..52edbf0229a 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -152,8 +152,8 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat
  */
 typedef FormData_pg_class *Form_pg_class;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, btree(oid oid_ops), RELOID, 128);
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops), RELNAMENSP, 128);
 DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, pg_class, btree(reltablespace oid_ops, relfilenode oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index 2d7dcde183c..6cf59f479a1 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -59,8 +59,8 @@ typedef FormData_pg_collation *Form_pg_collation;
 
 DECLARE_TOAST(pg_collation, 6175, 6176);
 
-DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops), COLLNAMEENCNSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops), COLLOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index a026b42515f..e47f257c4cd 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -169,7 +169,7 @@ DECLARE_TOAST(pg_constraint, 2832, 2833);
 DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, ConstraintNameNspIndexId, pg_constraint, btree(conname name_ops, connamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, ConstraintRelidTypidNameIndexId, pg_constraint, btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
 DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_constraint, btree(contypid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops), CONSTROID, 16);
 DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops));
 
 /* conkey can contain zero (InvalidAttrNumber) if a whole-row Var is used */
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index 42847fdf12d..acd944a4ae6 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -60,9 +60,9 @@ CATALOG(pg_conversion,2607,ConversionRelationId)
  */
 typedef FormData_pg_conversion *Form_pg_conversion;
 
-DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId, pg_conversion, btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops), CONDEFAULT, 8);
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops), CONNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops), CONVOID, 8);
 
 
 extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 3e50a570046..fbcecdf12bf 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -98,7 +98,7 @@ typedef FormData_pg_database *Form_pg_database;
 DECLARE_TOAST_WITH_MACRO(pg_database, 4177, 4178, PgDatabaseToastTable, PgDatabaseToastIndex);
 
 DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, pg_database, btree(datname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops), DATABASEOID, 4);
 
 /*
  * pg_database.dat contains an entry for template1, but not for the template0
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index 803ce3eab83..b526af26a61 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -51,7 +51,7 @@ typedef FormData_pg_default_acl *Form_pg_default_acl;
 
 DECLARE_TOAST(pg_default_acl, 4143, 4144);
 
-DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
+DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops), DEFACLROLENSPOBJ, 8);
 DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, pg_default_acl, btree(oid oid_ops));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index c483cb1042c..4ea20aeabe4 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -43,8 +43,8 @@ CATALOG(pg_enum,3501,EnumRelationId)
  */
 typedef FormData_pg_enum *Form_pg_enum;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btree(oid oid_ops), ENUMOID, 8);
+DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops), ENUMTYPOIDNAME, 8);
 DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, pg_enum, btree(enumtypid oid_ops, enumsortorder float4_ops));
 
 /*
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index 0ec42edff61..ca1c5bd728a 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -51,7 +51,7 @@ typedef FormData_pg_event_trigger *Form_pg_event_trigger;
 
 DECLARE_TOAST(pg_event_trigger, 4145, 4146);
 
-DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops), EVENTTRIGGERNAME, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops), EVENTTRIGGEROID, 8);
 
 #endif							/* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 37387f93553..8674eb261a0 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -52,7 +52,7 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
 
 DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops), FOREIGNDATAWRAPPEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops), FOREIGNDATAWRAPPERNAME, 2);
 
 #endif							/* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 5993967c6ec..fb77abe36f7 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -49,7 +49,7 @@ typedef FormData_pg_foreign_server *Form_pg_foreign_server;
 
 DECLARE_TOAST(pg_foreign_server, 4151, 4152);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops), FOREIGNSERVEROID, 2);
+DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops), FOREIGNSERVERNAME, 2);
 
 #endif							/* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 2420e23401e..8a10130cc02 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -44,6 +44,6 @@ typedef FormData_pg_foreign_table *Form_pg_foreign_table;
 
 DECLARE_TOAST(pg_foreign_table, 4153, 4154);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops), FOREIGNTABLEREL, 4);
 
 #endif							/* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 32930411b69..9352d8a9edc 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -70,7 +70,7 @@ CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
 typedef FormData_pg_index *Form_pg_index;
 
 DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops), INDEXRELID, 64);
 
 /* indkey can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((indrelid, indkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index d666ea20441..070094edb82 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -66,7 +66,7 @@ typedef FormData_pg_language *Form_pg_language;
 
 DECLARE_TOAST(pg_language, 4157, 4158);
 
-DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops), LANGNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops), LANGOID, 4);
 
 #endif							/* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index fc74a14c370..b70073d456e 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -53,8 +53,8 @@ typedef FormData_pg_namespace *Form_pg_namespace;
 
 DECLARE_TOAST(pg_namespace, 4163, 4164);
 
-DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops), NAMESPACENAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops), NAMESPACEOID, 16);
 
 /*
  * prototypes for functions in pg_namespace.c
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index a5d09faf1fa..18ecd56ada3 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -82,7 +82,7 @@ CATALOG(pg_opclass,2616,OperatorClassRelationId)
  */
 typedef FormData_pg_opclass *Form_pg_opclass;
 
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops), CLAAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops), CLAOID, 8);
 
 #endif							/* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index e890cee2df3..7ebc892bdbe 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -82,8 +82,8 @@ CATALOG(pg_operator,2617,OperatorRelationId)
  */
 typedef FormData_pg_operator *Form_pg_operator;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops), OPEROID, 32);
+DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops), OPERNAMENSP, 256);
 
 
 extern Oid	OperatorLookup(List *operatorName,
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 88940de9167..fe2b5c60c4f 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -50,8 +50,8 @@ CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
  */
 typedef FormData_pg_opfamily *Form_pg_opfamily;
 
-DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops), OPFAMILYAMNAMENSP, 8);
+DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops), OPFAMILYOID, 8);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h
index f46cdd15243..aef18ff4a75 100644
--- a/src/include/catalog/pg_parameter_acl.h
+++ b/src/include/catalog/pg_parameter_acl.h
@@ -50,8 +50,8 @@ typedef FormData_pg_parameter_acl * Form_pg_parameter_acl;
 
 DECLARE_TOAST_WITH_MACRO(pg_parameter_acl, 6244, 6245, PgParameterAclToastTable, PgParameterAclToastIndex);
 
-DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops), PARAMETERACLNAME, 4);
+DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops), PARAMETERACLOID, 4);
 
 
 extern Oid	ParameterAclLookup(const char *parameter, bool missing_ok);
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index 0cf512e1c82..a137f031f7e 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -66,7 +66,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
 
 DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops), PARTRELID, 32);
 
 /* partattrs can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((partrelid, partattrs), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index fdb39d40018..29ef344cc2d 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -137,8 +137,8 @@ typedef FormData_pg_proc *Form_pg_proc;
 
 DECLARE_TOAST(pg_proc, 2836, 2837);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops), PROCOID, 128);
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops), PROCNAMEARGSNSP, 128);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index d929c9a1880..c17be5ed88a 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -63,8 +63,8 @@ CATALOG(pg_publication,6104,PublicationRelationId)
  */
 typedef FormData_pg_publication *Form_pg_publication;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops), PUBLICATIONOID, 8);
+DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops), PUBLICATIONNAME, 8);
 
 typedef struct PublicationActions
 {
diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h
index b361c8ab5e0..b6326c7730e 100644
--- a/src/include/catalog/pg_publication_namespace.h
+++ b/src/include/catalog/pg_publication_namespace.h
@@ -41,7 +41,7 @@ CATALOG(pg_publication_namespace,6237,PublicationNamespaceRelationId)
  */
 typedef FormData_pg_publication_namespace *Form_pg_publication_namespace;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops), PUBLICATIONNAMESPACE, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops), PUBLICATIONNAMESPACEMAP, 64);
 
 #endif							/* PG_PUBLICATION_NAMESPACE_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index bef508764a4..19cad0a3443 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -47,8 +47,8 @@ typedef FormData_pg_publication_rel *Form_pg_publication_rel;
 
 DECLARE_TOAST(pg_publication_rel, 6228, 6229);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObjectIndexId, pg_publication_rel, btree(oid oid_ops), PUBLICATIONREL, 64);
+DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops), PUBLICATIONRELMAP, 64);
 DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, pg_publication_rel, btree(prpubid oid_ops));
 
 #endif							/* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index 1247fa7c773..ce662c6a03b 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -57,8 +57,8 @@ CATALOG(pg_range,3541,RangeRelationId)
  */
 typedef FormData_pg_range *Form_pg_range;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops), RANGETYPE, 4);
+DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops), RANGEMULTIRANGE, 4);
 
 /*
  * prototypes for functions in pg_range.c
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index 83ff36dcba6..49824dbc073 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -56,7 +56,7 @@ typedef FormData_pg_replication_origin *Form_pg_replication_origin;
 
 DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops));
-DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops), REPLORIGIDENT, 16);
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops), REPLORIGNAME, 16);
 
 #endif							/* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 60d642b595f..8148e3568b5 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -54,6 +54,6 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
 DECLARE_TOAST(pg_rewrite, 2838, 2839);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, pg_rewrite, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops));
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops), RULERELNAME, 8);
 
 #endif							/* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index fdfc27bbd95..efd441c339d 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -39,6 +39,6 @@ CATALOG(pg_sequence,2224,SequenceRelationId)
  */
 typedef FormData_pg_sequence *Form_pg_sequence;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops), SEQRELID, 32);
 
 #endif							/* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 0808c5fc893..d67f90d9f19 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -136,7 +136,7 @@ typedef FormData_pg_statistic *Form_pg_statistic;
 
 DECLARE_TOAST(pg_statistic, 2840, 2841);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops), STATRELATTINH, 128);
 
 DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index a136ceffc60..9576fe723e0 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -70,8 +70,8 @@ typedef FormData_pg_statistic_ext *Form_pg_statistic_ext;
 
 DECLARE_TOAST(pg_statistic_ext, 3439, 3440);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndexId, pg_statistic_ext, btree(oid oid_ops), STATEXTOID, 4);
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops), STATEXTNAMENSP, 4);
 DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, pg_statistic_ext, btree(stxrelid oid_ops));
 
 DECLARE_ARRAY_FOREIGN_KEY((stxrelid, stxkeys), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
index 19a00705e6a..0f09883e129 100644
--- a/src/include/catalog/pg_statistic_ext_data.h
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -54,7 +54,7 @@ typedef FormData_pg_statistic_ext_data *Form_pg_statistic_ext_data;
 
 DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops), STATEXTDATASTXOID, 4);
 
 
 #endif							/* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index e0b91eacd2a..9a6a3f2dd47 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -115,8 +115,8 @@ typedef FormData_pg_subscription *Form_pg_subscription;
 
 DECLARE_TOAST_WITH_MACRO(pg_subscription, 4183, 4184, PgSubscriptionToastTable, PgSubscriptionToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops), SUBSCRIPTIONOID, 4);
+DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops), SUBSCRIPTIONNAME, 4);
 
 typedef struct Subscription
 {
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index f5324b710d6..638f0d54471 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -49,7 +49,7 @@ CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
 
 typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops), SUBSCRIPTIONRELMAP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index ea8665e83a4..8910fe362c3 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -49,7 +49,7 @@ typedef FormData_pg_tablespace *Form_pg_tablespace;
 
 DECLARE_TOAST_WITH_MACRO(pg_tablespace, 4185, 4186, PgTablespaceToastTable, PgTablespaceToastIndex);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops), TABLESPACEOID, 4);
 DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, pg_tablespace, btree(spcname name_ops));
 
 #endif							/* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index 8eb189784da..2660d7a706b 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -42,7 +42,7 @@ CATALOG(pg_transform,3576,TransformRelationId)
  */
 typedef FormData_pg_transform *Form_pg_transform;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops), TRFOID, 16);
+DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops), TRFTYPELANG, 16);
 
 #endif							/* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index e52720387da..3699551f0fe 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -47,7 +47,7 @@ CATALOG(pg_ts_config,3602,TSConfigRelationId)
 
 typedef FormData_pg_ts_config *Form_pg_ts_config;
 
-DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops), TSCONFIGNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops), TSCONFIGOID, 2);
 
 #endif							/* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index 91f092ca483..437b34a20cc 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -44,6 +44,6 @@ CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
 
 typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops), TSCONFIGMAP, 2);
 
 #endif							/* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 10a64902130..34e22d9434f 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -53,7 +53,7 @@ typedef FormData_pg_ts_dict *Form_pg_ts_dict;
 
 DECLARE_TOAST(pg_ts_dict, 4169, 4170);
 
-DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops), TSDICTNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops), TSDICTOID, 2);
 
 #endif							/* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index 57d9e8428a1..7885c2555ec 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -54,7 +54,7 @@ CATALOG(pg_ts_parser,3601,TSParserRelationId)
 
 typedef FormData_pg_ts_parser *Form_pg_ts_parser;
 
-DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops), TSPARSERNAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops), TSPARSEROID, 2);
 
 #endif							/* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index f3bdc7b200f..cd569a700eb 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -45,7 +45,7 @@ CATALOG(pg_ts_template,3764,TSTemplateRelationId)
 
 typedef FormData_pg_ts_template *Form_pg_ts_template;
 
-DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops));
-DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops), TSTEMPLATENAMENSP, 2);
+DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops), TSTEMPLATEOID, 2);
 
 #endif							/* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 508ba7b0f71..9d00be8dbbf 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -262,8 +262,8 @@ typedef FormData_pg_type *Form_pg_type;
 
 DECLARE_TOAST(pg_type, 4171, 4172);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops), TYPEOID, 64);
+DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops), TYPENAMENSP, 64);
 
 #ifdef EXPOSE_TO_CLIENT_CODE
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index eca33f4cb40..94bc93a83fb 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -49,7 +49,7 @@ typedef FormData_pg_user_mapping *Form_pg_user_mapping;
 
 DECLARE_TOAST(pg_user_mapping, 4173, 4174);
 
-DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops), USERMAPPINGOID, 2);
+DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops), USERMAPPINGUSERSERVER, 2);
 
 #endif							/* PG_USER_MAPPING_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 5d47a652cc1..68827fba505 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -20,103 +20,7 @@
 #include "access/htup.h"
 /* we intentionally do not include utils/catcache.h here */
 
-/*
- *		SysCache identifiers.
- *
- *		The order of these identifiers must match the order
- *		of the entries in the array cacheinfo[] in syscache.c.
- *		Keep them in alphabetical order (renumbering only costs a
- *		backend rebuild).
- */
-
-enum SysCacheIdentifier
-{
-	AGGFNOID = 0,
-	AMNAME,
-	AMOID,
-	AMOPOPID,
-	AMOPSTRATEGY,
-	AMPROCNUM,
-	ATTNAME,
-	ATTNUM,
-	AUTHMEMMEMROLE,
-	AUTHMEMROLEMEM,
-	AUTHNAME,
-	AUTHOID,
-	CASTSOURCETARGET,
-	CLAAMNAMENSP,
-	CLAOID,
-	COLLNAMEENCNSP,
-	COLLOID,
-	CONDEFAULT,
-	CONNAMENSP,
-	CONSTROID,
-	CONVOID,
-	DATABASEOID,
-	DEFACLROLENSPOBJ,
-	ENUMOID,
-	ENUMTYPOIDNAME,
-	EVENTTRIGGERNAME,
-	EVENTTRIGGEROID,
-	FOREIGNDATAWRAPPERNAME,
-	FOREIGNDATAWRAPPEROID,
-	FOREIGNSERVERNAME,
-	FOREIGNSERVEROID,
-	FOREIGNTABLEREL,
-	INDEXRELID,
-	LANGNAME,
-	LANGOID,
-	NAMESPACENAME,
-	NAMESPACEOID,
-	OPERNAMENSP,
-	OPEROID,
-	OPFAMILYAMNAMENSP,
-	OPFAMILYOID,
-	PARAMETERACLNAME,
-	PARAMETERACLOID,
-	PARTRELID,
-	PROCNAMEARGSNSP,
-	PROCOID,
-	PUBLICATIONNAME,
-	PUBLICATIONNAMESPACE,
-	PUBLICATIONNAMESPACEMAP,
-	PUBLICATIONOID,
-	PUBLICATIONREL,
-	PUBLICATIONRELMAP,
-	RANGEMULTIRANGE,
-	RANGETYPE,
-	RELNAMENSP,
-	RELOID,
-	REPLORIGIDENT,
-	REPLORIGNAME,
-	RULERELNAME,
-	SEQRELID,
-	STATEXTDATASTXOID,
-	STATEXTNAMENSP,
-	STATEXTOID,
-	STATRELATTINH,
-	SUBSCRIPTIONNAME,
-	SUBSCRIPTIONOID,
-	SUBSCRIPTIONRELMAP,
-	TABLESPACEOID,
-	TRFOID,
-	TRFTYPELANG,
-	TSCONFIGMAP,
-	TSCONFIGNAMENSP,
-	TSCONFIGOID,
-	TSDICTNAMENSP,
-	TSDICTOID,
-	TSPARSERNAMENSP,
-	TSPARSEROID,
-	TSTEMPLATENAMENSP,
-	TSTEMPLATEOID,
-	TYPENAMENSP,
-	TYPEOID,
-	USERMAPPINGOID,
-	USERMAPPINGUSERSERVER,
-
-#define SysCacheSize (USERMAPPINGUSERSERVER + 1)
-};
+#include "catalog/syscache_info.h"
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 4e09c4686b3..56ed4235679 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 8dee1b56709..477e4dd7e6b 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_info.c.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_info.c.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
-- 
2.42.0

v4-0002-Generate-ObjectProperty-from-catalog-files.patchtext/plain; charset=UTF-8; name=v4-0002-Generate-ObjectProperty-from-catalog-files.patchDownload
From ff2ef28a0eb2adca9cc36d103aa3fb48695ce51a Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 1 Nov 2023 16:56:50 -0400
Subject: [PATCH v4 2/2] Generate ObjectProperty from catalog files

Most of the information can be extracted from catalog files and
generated automatically.

TODO: Currently missing: object type and class description.  There are
some workarounds in place.

We also now replace the linear search with a hash function generated
using PerfectHash.  This would allow this lookup table to be used in
more performance-sensitive situations.

Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
 src/backend/catalog/.gitignore      |   1 +
 src/backend/catalog/Makefile        |   2 +-
 src/backend/catalog/genbki.pl       | 167 ++++++++++++++++++++++++++++
 src/backend/catalog/objectaddress.c |  22 ++--
 src/include/catalog/meson.build     |   2 +
 src/tools/pginclude/cpluspluscheck  |   3 +
 src/tools/pginclude/headerscheck    |   3 +
 7 files changed, 188 insertions(+), 12 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index ff655603792..d817798dc0e 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,3 +1,4 @@
+/objectproperty_info.c.h
 /postgres.bki
 /schemapg.h
 /syscache_info.c.h
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 2c94126ec5c..e6c5878e99c 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -120,7 +120,7 @@ CATALOG_HEADERS := \
 	pg_subscription.h \
 	pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) objectproperty_info.c.h schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 78f2da690ec..199091305c3 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -19,8 +19,10 @@
 
 use FindBin;
 use lib $FindBin::RealBin;
+use lib "$FindBin::RealBin/../../tools";
 
 use Catalog;
+use PerfectHash;
 
 my $output_path = '';
 my $major_version;
@@ -59,6 +61,7 @@
 my %syscaches;
 my %oidcounts;
 my @system_constraints;
+my @object_properties;
 
 foreach my $header (@ARGV)
 {
@@ -133,6 +136,7 @@
 		$oidcounts{ $toast->{toast_oid} }++;
 		$oidcounts{ $toast->{toast_index_oid} }++;
 	}
+	my ($oid_index, $oid_syscache, $name_syscache, $is_nsp_name_unique);
 	foreach my $index (@{ $catalog->{indexing} })
 	{
 		push @index_decls,
@@ -166,7 +170,136 @@
 				nbuckets => $index->{syscache_nbuckets},
 			};
 		}
+
+		if ($index->{index_decl} eq 'btree(oid oid_ops)')
+		{
+			$oid_index = $index->{index_oid_macro};
+			$oid_syscache = $index->{syscache_name};
+		}
+		if ($index->{index_decl} =~ /\(\w+name name_ops(, \w+namespace oid_ops)?\)/)
+		{
+			$name_syscache = $index->{syscache_name};
+			$is_nsp_name_unique = 1 if $index->{is_unique};
+		}
+	}
+
+	my ($attnum_oid, $attnum_name, $attnum_namespace, $attnum_owner, $attnum_acl);
+	foreach my $att (@$schema)
+	{
+		if ($att->{name} eq 'oid' && $att->{type} eq 'oid')
+		{
+			$attnum_oid = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}name$/ && $att->{type} eq 'name')
+		{
+			$attnum_name = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}namespace$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_namespace')
+		{
+			$attnum_namespace = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}owner$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_authid')
+		{
+			$attnum_owner = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}acl$/ && $att->{type} eq '_aclitem')
+		{
+			$attnum_acl = "Anum_${catname}_" . $att->{name};
+		}
+	}
+
+	# XXX hardcoded exceptions
+	# extension doesn't belong to extnamespace
+	$attnum_namespace = undef if $catname eq 'pg_extension';
+	# pg_database owner is spelled datdba
+	$attnum_owner = "Anum_pg_database_datdba" if $catname eq 'pg_database';
+	# XXX?
+	$name_syscache = "SUBSCRIPTIONNAME" if $catname eq 'pg_subscription';
+	# XXX?
+	$is_nsp_name_unique = 1 if $catname eq 'pg_collation';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_opclass';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_opfamily';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_subscription';
+
+	# XXX These catalogs were not covered by the previous hand-maintained table.
+	my @skip = qw(
+		AttrDefaultRelationId EnumRelationId IndexRelationId
+		LargeObjectRelationId ParameterAclRelationId
+		PublicationNamespaceRelationId PublicationRelRelationId
+		InheritsRelationId AggregateRelationId StatisticRelationId
+		StatisticExtDataRelationId DescriptionRelationId
+		DependRelationId DbRoleSettingRelationId
+		SharedDependRelationId SharedDescriptionRelationId
+		TSConfigMapRelationId ForeignTableRelationId
+		ReplicationOriginRelationId InitPrivsRelationId
+		SecLabelRelationId SharedSecLabelRelationId
+		PartitionedRelationId RangeRelationId SequenceRelationId
+		SubscriptionRelRelationId);
+	# XXX This one neither, but if I add it to @skip, PerfectHash will fail. (???)
+	#FIXME: AttributeRelationId
+
+	# XXX hardcoded ObjectType mapping -- where to put this?
+	my %objtypes = (
+		'AccessMethodRelationId' => 'OBJECT_ACCESS_METHOD',
+		'AccessMethodOperatorRelationId' => 'OBJECT_AMOP',
+		'AccessMethodProcedureRelationId' => 'OBJECT_AMPROC',
+		'CastRelationId' => 'OBJECT_CAST',
+		'CollationRelationId' => 'OBJECT_COLLATION',
+		'ConversionRelationId' => 'OBJECT_CONVERSION',
+		'DatabaseRelationId' => 'OBJECT_DATABASE',
+		'DefaultAclRelationId' => 'OBJECT_DEFACL',
+		'ExtensionRelationId' => 'OBJECT_EXTENSION',
+		'ForeignDataWrapperRelationId' => 'OBJECT_FDW',
+		'ForeignServerRelationId' => 'OBJECT_FOREIGN_SERVER',
+		'ProcedureRelationId' => 'OBJECT_FUNCTION',
+		'LanguageRelationId' => 'OBJECT_LANGUAGE',
+		'LargeObjectMetadataRelationId' => 'OBJECT_LARGEOBJECT',
+		'OperatorClassRelationId' => 'OBJECT_OPCLASS',
+		'OperatorRelationId' => 'OBJECT_OPERATOR',
+		'OperatorFamilyRelationId' => 'OBJECT_OPFAMILY',
+		'AuthIdRelationId' => 'OBJECT_ROLE',
+		'RewriteRelationId' => 'OBJECT_RULE',
+		'NamespaceRelationId' => 'OBJECT_SCHEMA',
+		'RelationRelationId' => 'OBJECT_TABLE',
+		'TableSpaceRelationId' => 'OBJECT_TABLESPACE',
+		'TransformRelationId' => 'OBJECT_TRANSFORM',
+		'TriggerRelationId' => 'OBJECT_TRIGGER',
+		'PolicyRelationId' => 'OBJECT_POLICY',
+		'EventTriggerRelationId' => 'OBJECT_EVENT_TRIGGER',
+		'TSConfigRelationId' => 'OBJECT_TSCONFIGURATION',
+		'TSDictionaryRelationId' => 'OBJECT_TSDICTIONARY',
+		'TSParserRelationId' => 'OBJECT_TSPARSER',
+		'TSTemplateRelationId' => 'OBJECT_TSTEMPLATE',
+		'TypeRelationId' => 'OBJECT_TYPE',
+		'PublicationRelationId' => 'OBJECT_PUBLICATION',
+		'SubscriptionRelationId' => 'OBJECT_SUBSCRIPTION',
+		'StatisticExtRelationId' => 'OBJECT_STATISTIC_EXT',
+		'UserMappingRelationId' => 'OBJECT_USER_MAPPING',
+	);
+	my $objtype = $objtypes{$catalog->{relation_oid_macro}};
+
+	# XXX This just uses the catalog name as a string rather than the
+	# previous natural-language description.  This could be changed if
+	# we decide on a place to store this.  But maybe for what we are
+	# using it, this is actually better.
+	my $class_descr = qq{"${catname}"};
+
+	push @object_properties, {
+		class_descr => $class_descr,
+		class_oid => $catalog->{relation_oid_macro},
+		_class_oid => $catalog->{relation_oid},
+		oid_index_oid => $oid_index,
+		oid_catcache_id => $oid_syscache || '-1',
+		name_catcache_id => $name_syscache || '-1',
+		attnum_oid => $attnum_oid,
+		attnum_name => $attnum_name,
+		attnum_namespace => $attnum_namespace,
+		attnum_owner => $attnum_owner,
+		attnum_acl => $attnum_acl,
+		objtype => $objtype,
+		is_nsp_name_unique => $is_nsp_name_unique ? 'true' : 'false',
 	}
+	unless grep { $_ eq $catalog->{relation_oid_macro} } @skip;
 }
 
 # Complain and exit if we found any duplicate OIDs.
@@ -441,6 +574,9 @@
 my $syscache_info_c = $output_path . 'syscache_info.c.h';
 open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
   or die "can't open $syscache_info_c$tmpext: $!";
+my $objectproperty_info = $output_path . 'objectproperty_info.c.h';
+open my $objectproperty_info_fh, '>', $objectproperty_info . $tmpext
+  or die "can't open $objectproperty_info$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -810,6 +946,35 @@
 
 print $syscache_info_c_fh "};\n";
 
+# Now generate objectproperty_info
+
+print_boilerplate($objectproperty_info_fh, "objectproperty_info.h", "object property data");
+print $objectproperty_info_fh "\n";
+foreach my $catname (@catnames)
+{
+	print $objectproperty_info_fh qq{#include "catalog/${catname}_d.h"\n};
+}
+print $objectproperty_info_fh "\n";
+print $objectproperty_info_fh "static const ObjectPropertyType ObjectProperty[] =
+{
+";
+
+my @class_oids;
+foreach my $op (@object_properties)
+{
+	print $objectproperty_info_fh "\t{\n";
+	foreach my $p (sort keys %{$op})
+	{
+		printf $objectproperty_info_fh "\t\t.%s = %s,\n", $p, ${$op}{$p} if $p !~ /^_/ && ${$op}{$p};
+	}
+	push @class_oids, pack('N', ${$op}{_class_oid});
+	print $objectproperty_info_fh "\t},\n";
+}
+
+print $objectproperty_info_fh "};\n";
+
+print $objectproperty_info_fh "\nstatic " . PerfectHash::generate_hash_function(\@class_oids, 'objectproperty_hash_func', fixed_key_length => 4);
+
 # We're done emitting data
 close $bki;
 close $schemapg;
@@ -817,6 +982,7 @@
 close $constraints;
 close $syscache_info_h_fh;
 close $syscache_info_c_fh;
+close $objectproperty_info_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
@@ -825,6 +991,7 @@
 Catalog::RenameTempFile($constraints_file, $tmpext);
 Catalog::RenameTempFile($syscache_info_h, $tmpext);
 Catalog::RenameTempFile($syscache_info_c, $tmpext);
+Catalog::RenameTempFile($objectproperty_info, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index bb4efcad202..6ba84ee86c8 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -32,19 +32,10 @@
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_conversion.h"
-#include "catalog/pg_database.h"
 #include "catalog/pg_default_acl.h"
-#include "catalog/pg_enum.h"
-#include "catalog/pg_event_trigger.h"
-#include "catalog/pg_extension.h"
-#include "catalog/pg_foreign_data_wrapper.h"
-#include "catalog/pg_foreign_server.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_largeobject.h"
-#include "catalog/pg_largeobject_metadata.h"
-#include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_parameter_acl.h"
 #include "catalog/pg_policy.h"
@@ -54,8 +45,6 @@
 #include "catalog/pg_publication_rel.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_statistic_ext.h"
-#include "catalog/pg_subscription.h"
-#include "catalog/pg_tablespace.h"
 #include "catalog/pg_transform.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_ts_config.h"
@@ -119,6 +108,9 @@ typedef struct
 									 * object of this class? */
 } ObjectPropertyType;
 
+#if 1
+#include "catalog/objectproperty_info.c.h"
+#else
 static const ObjectPropertyType ObjectProperty[] =
 {
 	{
@@ -640,6 +632,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		false
 	},
 };
+#endif
 
 /*
  * This struct maps the string object types as returned by
@@ -2791,6 +2784,7 @@ get_object_property_data(Oid class_id)
 {
 	static const ObjectPropertyType *prop_last = NULL;
 	int			index;
+	uint32      hashkey;
 
 	/*
 	 * A shortcut to speed up multiple consecutive lookups of a particular
@@ -2799,7 +2793,13 @@ get_object_property_data(Oid class_id)
 	if (prop_last && prop_last->class_oid == class_id)
 		return prop_last;
 
+#if 1
+	hashkey = pg_hton32(class_id);
+	index = objectproperty_hash_func(&hashkey);
+	if (index >= 0 && index < lengthof(ObjectProperty))
+#else
 	for (index = 0; index < lengthof(ObjectProperty); index++)
+#endif
 	{
 		if (ObjectProperty[index].class_oid == class_id)
 		{
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index 39d8e94ae27..3362733b5ab 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -103,6 +103,7 @@ bki_data_f = files(bki_data)
 
 input = []
 output_files = [
+  'objectproperty_info.c.h',
   'postgres.bki',
   'system_constraints.sql',
   'schemapg.h',
@@ -111,6 +112,7 @@ output_files = [
   'system_fk_info.h',
 ]
 output_install = [
+  dir_data,
   dir_data,
   dir_data,
   dir_include_server / 'catalog',
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 56ed4235679..49e3ca7a7bd 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 477e4dd7e6b..a1ea2ef6925 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
 	test "$f" = src/backend/catalog/syscache_info.c.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_info.c.h && continue
-- 
2.42.0

#12John Naylor
johncnaylorls@gmail.com
In reply to: Peter Eisentraut (#11)
Re: generate syscache info automatically

On Thu, Nov 2, 2023 at 4:13 AM Peter Eisentraut <peter@eisentraut.org> wrote:

Here is a rebased patch set, along with a summary of the questions I
have about these patches:

This is an excellent summary of the issues, thanks.

v4-0001-Generate-syscache-info-from-catalog-files.patch

What's a good syntax to declare a syscache? Currently, I have, for example

-DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId,
pg_type, btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId,
pg_type, btree(oid oid_ops), TYPEOID, 64);

I suppose a sensible alternative could be to leave the
DECLARE_..._INDEX... alone and make a separate statement, like

MAKE_SYSCACHE(pg_type_oid_index, TYPEOID, 64);

That's at least visually easier, because some of those
DECLARE_... lines are getting pretty long.

Probably a good idea, and below I mention a third possible macro.

I would like to keep those MAKE_SYSCACHE lines in the catalog files.
That just makes it easier to reference everything together.

That seems fine. If we ever want to do something more invasive with
the syscaches, some of that can be copied/moved out into a separate
script, but what's there in 0001 is pretty small.

v4-0002-Generate-ObjectProperty-from-catalog-files.patch

Several questions here:

* What's a good way to declare the mapping between catalog and object
type?

Perhaps this idea:

I suppose a sensible alternative could be to leave the
DECLARE_..._INDEX... alone and make a separate statement, like

MAKE_SYSCACHE(pg_type_oid_index, TYPEOID, 64);

...could be used, so something like

DECLARE_OBJECT_INFO(OBJECT_ACCESS_METHOD);

* How to select which catalogs have ObjectProperty entries generated?

Would the above work for that as well?

* Where to declare class descriptions? Or just keep the current hack in
the patch.

I don't have an opinion on this.

* How to declare the purpose of a catalog column, like "this is the ACL
column for this catalog". This is currently done by name, but maybe
it should be more explicit.

Perhaps we can have additional column macros, like BKI_OBJ_ACL or
something, but that doesn't seem like it would result in less code.

* Question about how to pick the correct value for is_nsp_name_unique?

How is that known now -- I don't mean in the patch, but in general?

Also, I get most of the hard-wired exceptions, but

+ # XXX?
+ $name_syscache = "SUBSCRIPTIONNAME" if $catname eq 'pg_subscription';

What is not right otherwise?

+ if ($index->{index_decl} eq 'btree(oid oid_ops)')
+ {
+ $oid_index = $index->{index_oid_macro};
+ $oid_syscache = $index->{syscache_name};
+ }
+ if ($index->{index_decl} =~ /\(\w+name name_ops(, \w+namespace oid_ops)?\)/)
+ {
+ $name_syscache = $index->{syscache_name};
+ $is_nsp_name_unique = 1 if $index->{is_unique};
+ }

The variables name_syscache and syscache_name are unfortunately close
to eachother.

#13Peter Eisentraut
peter@eisentraut.org
In reply to: John Naylor (#12)
2 attachment(s)
Re: generate syscache info automatically

On 10.01.24 09:00, John Naylor wrote:

I suppose a sensible alternative could be to leave the
DECLARE_..._INDEX... alone and make a separate statement, like

MAKE_SYSCACHE(pg_type_oid_index, TYPEOID, 64);

That's at least visually easier, because some of those
DECLARE_... lines are getting pretty long.

Probably a good idea, and below I mention a third possible macro.

I updated the patch to use this style (but I swapped the first two
arguments from my example, so that the thing being created is named first).

I also changed the names of the output files a bit to make them less
confusing. (I initially had some files named .c.h, which was weird, but
apparently necessary to avoid confusing the build system. But it's all
clearer now.)

Other than bugs and perhaps style opinions, I think the first patch is
pretty good now.

I haven't changed much in the second patch, other than to update it for
the code changes made in the first patch. It's still very much
WIP/preview at the moment.

Attachments:

v5-0001-Generate-syscache-info-from-catalog-files.patchtext/plain; charset=UTF-8; name=v5-0001-Generate-syscache-info-from-catalog-files.patchDownload
From f77c381b9df30824e469f72f4e7754d03cb97d78 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 17 Jan 2024 12:33:42 +0100
Subject: [PATCH v5 1/2] Generate syscache info from catalog files

Add a new genbki macros MAKE_SYSCACHE that specifies the syscache ID
macro, the underlying index, and the number of buckets.  From that, we
can generate the existing tables in syscache.h and syscache.c via
genbki.pl.

Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
 src/backend/catalog/.gitignore                |   2 +
 src/backend/catalog/Catalog.pm                |  10 +
 src/backend/catalog/Makefile                  |   2 +-
 src/backend/catalog/genbki.pl                 |  72 ++
 src/backend/utils/cache/syscache.c            | 632 +-----------------
 src/include/catalog/.gitignore                |   2 +
 src/include/catalog/genbki.h                  |  10 +-
 src/include/catalog/meson.build               |  18 +-
 src/include/catalog/pg_aggregate.h            |   2 +
 src/include/catalog/pg_am.h                   |   3 +
 src/include/catalog/pg_amop.h                 |   3 +
 src/include/catalog/pg_amproc.h               |   2 +
 src/include/catalog/pg_attribute.h            |   3 +
 src/include/catalog/pg_auth_members.h         |   3 +
 src/include/catalog/pg_authid.h               |   3 +
 src/include/catalog/pg_cast.h                 |   2 +
 src/include/catalog/pg_class.h                |   3 +
 src/include/catalog/pg_collation.h            |   3 +
 src/include/catalog/pg_constraint.h           |   2 +
 src/include/catalog/pg_conversion.h           |   4 +
 src/include/catalog/pg_database.h             |   2 +
 src/include/catalog/pg_default_acl.h          |   2 +
 src/include/catalog/pg_enum.h                 |   3 +
 src/include/catalog/pg_event_trigger.h        |   3 +
 src/include/catalog/pg_foreign_data_wrapper.h |   3 +
 src/include/catalog/pg_foreign_server.h       |   3 +
 src/include/catalog/pg_foreign_table.h        |   2 +
 src/include/catalog/pg_index.h                |   2 +
 src/include/catalog/pg_language.h             |   3 +
 src/include/catalog/pg_namespace.h            |   3 +
 src/include/catalog/pg_opclass.h              |   3 +
 src/include/catalog/pg_operator.h             |   2 +
 src/include/catalog/pg_opfamily.h             |   3 +
 src/include/catalog/pg_parameter_acl.h        |   2 +
 src/include/catalog/pg_partitioned_table.h    |   2 +
 src/include/catalog/pg_proc.h                 |   3 +
 src/include/catalog/pg_publication.h          |   3 +
 .../catalog/pg_publication_namespace.h        |   3 +
 src/include/catalog/pg_publication_rel.h      |   3 +
 src/include/catalog/pg_range.h                |   3 +
 src/include/catalog/pg_replication_origin.h   |   3 +
 src/include/catalog/pg_rewrite.h              |   2 +
 src/include/catalog/pg_sequence.h             |   2 +
 src/include/catalog/pg_statistic.h            |   2 +
 src/include/catalog/pg_statistic_ext.h        |   3 +
 src/include/catalog/pg_statistic_ext_data.h   |   1 +
 src/include/catalog/pg_subscription.h         |   3 +
 src/include/catalog/pg_subscription_rel.h     |   2 +
 src/include/catalog/pg_tablespace.h           |   2 +
 src/include/catalog/pg_transform.h            |   3 +
 src/include/catalog/pg_ts_config.h            |   3 +
 src/include/catalog/pg_ts_config_map.h        |   2 +
 src/include/catalog/pg_ts_dict.h              |   3 +
 src/include/catalog/pg_ts_parser.h            |   3 +
 src/include/catalog/pg_ts_template.h          |   3 +
 src/include/catalog/pg_type.h                 |   3 +
 src/include/catalog/pg_user_mapping.h         |   3 +
 src/include/utils/syscache.h                  |  98 +--
 src/tools/pginclude/cpluspluscheck            |   5 +
 src/tools/pginclude/headerscheck              |   5 +
 60 files changed, 266 insertions(+), 719 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index 237ff541659..b580f734c71 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,5 +1,7 @@
 /postgres.bki
 /schemapg.h
+/syscache_ids.h
+/syscache_info.h
 /system_fk_info.h
 /system_constraints.sql
 /pg_*_d.h
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 643560cd473..55a8877aede 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -129,6 +129,16 @@ sub ParseHeader
 				%+,
 			  };
 		}
+		elsif (
+			/^MAKE_SYSCACHE\(\s*
+			(?<syscache_name>\w+),\s*
+			(?<index_name>\w+),\s*
+			(?<syscache_nbuckets>\w+)\s*
+			\)/x
+		  )
+		{
+			push @{ $catalog{syscaches} }, {%+};
+		}
 		elsif (
 			/^DECLARE_OID_DEFINING_MACRO\(\s*
 			 (?<other_name>\w+),\s*
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index d6b23b4bfd5..352ba6d3e2e 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -120,7 +120,7 @@ CATALOG_HEADERS := \
 	pg_subscription.h \
 	pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_ids.h syscache_info.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 93553e8c3c4..677a12acf3e 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -56,6 +56,8 @@
 my %catalog_data;
 my @toast_decls;
 my @index_decls;
+my %syscaches;
+my %syscache_catalogs;
 my %oidcounts;
 my @system_constraints;
 
@@ -121,6 +123,9 @@
 		}
 	}
 
+	# Lookup table to get index info by index name
+	my %indexes;
+
 	# If the header file contained toast or index info, build BKI
 	# commands for those, which we'll output later.
 	foreach my $toast (@{ $catalog->{toasting} })
@@ -134,6 +139,8 @@
 	}
 	foreach my $index (@{ $catalog->{indexing} })
 	{
+		$indexes{$index->{index_name}} = $index;
+
 		push @index_decls,
 		  sprintf "declare %sindex %s %s on %s using %s\n",
 		  $index->{is_unique} ? 'unique ' : '',
@@ -151,6 +158,26 @@
 			  $index->{index_name};
 		}
 	}
+
+	# Analyze syscache info
+	foreach my $syscache (@{ $catalog->{syscaches} })
+	{
+		my $index = $indexes{$syscache->{index_name}};
+		my $tblname = $index->{table_name};
+		my $key = $index->{index_decl};
+		$key =~ s/^\w+\(//;
+		$key =~ s/\)$//;
+		$key =~ s/(\w+)\s+\w+/Anum_${tblname}_$1/g;
+
+		$syscaches{$syscache->{syscache_name}} = {
+			table_oid_macro => $catalogs{$tblname}->{relation_oid_macro},
+			index_oid_macro => $index->{index_oid_macro},
+			key => $key,
+			nbuckets => $syscache->{syscache_nbuckets},
+		};
+
+		$syscache_catalogs{$catname} = 1;
+	}
 }
 
 # Complain and exit if we found any duplicate OIDs.
@@ -419,6 +446,12 @@
 my $constraints_file = $output_path . 'system_constraints.sql';
 open my $constraints, '>', $constraints_file . $tmpext
   or die "can't open $constraints_file$tmpext: $!";
+my $syscache_ids_file = $output_path . 'syscache_ids.h';
+open my $syscache_ids_fh, '>', $syscache_ids_file . $tmpext
+  or die "can't open $syscache_ids_file$tmpext: $!";
+my $syscache_info_file = $output_path . 'syscache_info.h';
+open my $syscache_info_fh, '>', $syscache_info_file . $tmpext
+  or die "can't open $syscache_info_file$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -753,17 +786,56 @@
 # Closing boilerplate for system_fk_info.h
 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_boilerplate($syscache_info_fh, "syscache_info.h", "SysCache definitions");
+print $syscache_info_fh "\n";
+foreach my $catname (sort keys %syscache_catalogs)
+{
+	print $syscache_info_fh qq{#include "catalog/${catname}_d.h"\n};
+}
+print $syscache_info_fh "\n";
+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";
+	$last_syscache = $syscache;
+
+	print $syscache_info_fh "\t[$syscache] = {\n";
+	print $syscache_info_fh "\t\t", $syscaches{$syscache}{table_oid_macro}, ",\n";
+	print $syscache_info_fh "\t\t", $syscaches{$syscache}{index_oid_macro}, ",\n";
+	print $syscache_info_fh "\t\tKEY(", $syscaches{$syscache}{key}, "),\n";
+	print $syscache_info_fh "\t\t", $syscaches{$syscache}{nbuckets}, "\n";
+	print $syscache_info_fh "\t},\n";
+}
+
+print $syscache_ids_fh "};\n";
+print $syscache_ids_fh "#define SysCacheSize ($last_syscache + 1)\n";
+
+print $syscache_info_fh "};\n";
+
 # We're done emitting data
 close $bki;
 close $schemapg;
 close $fk_info;
 close $constraints;
+close $syscache_ids_fh;
+close $syscache_info_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
 Catalog::RenameTempFile($schemafile, $tmpext);
 Catalog::RenameTempFile($fk_info_file, $tmpext);
 Catalog::RenameTempFile($constraints_file, $tmpext);
+Catalog::RenameTempFile($syscache_ids_file, $tmpext);
+Catalog::RenameTempFile($syscache_info_file, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index c10a7b3d0d2..162855b1587 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -22,59 +22,13 @@
 
 #include "access/htup_details.h"
 #include "access/sysattr.h"
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_am.h"
-#include "catalog/pg_amop.h"
-#include "catalog/pg_amproc.h"
-#include "catalog/pg_auth_members.h"
-#include "catalog/pg_authid.h"
-#include "catalog/pg_cast.h"
-#include "catalog/pg_collation.h"
-#include "catalog/pg_constraint.h"
-#include "catalog/pg_conversion.h"
-#include "catalog/pg_database.h"
-#include "catalog/pg_db_role_setting.h"
-#include "catalog/pg_default_acl.h"
-#include "catalog/pg_depend.h"
-#include "catalog/pg_description.h"
-#include "catalog/pg_enum.h"
-#include "catalog/pg_event_trigger.h"
-#include "catalog/pg_foreign_data_wrapper.h"
-#include "catalog/pg_foreign_server.h"
-#include "catalog/pg_foreign_table.h"
-#include "catalog/pg_language.h"
-#include "catalog/pg_namespace.h"
-#include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
-#include "catalog/pg_opfamily.h"
-#include "catalog/pg_parameter_acl.h"
-#include "catalog/pg_partitioned_table.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_publication.h"
-#include "catalog/pg_publication_namespace.h"
-#include "catalog/pg_publication_rel.h"
-#include "catalog/pg_range.h"
-#include "catalog/pg_replication_origin.h"
-#include "catalog/pg_rewrite.h"
-#include "catalog/pg_seclabel.h"
-#include "catalog/pg_sequence.h"
-#include "catalog/pg_shdepend.h"
-#include "catalog/pg_shdescription.h"
-#include "catalog/pg_shseclabel.h"
-#include "catalog/pg_statistic.h"
-#include "catalog/pg_statistic_ext.h"
-#include "catalog/pg_statistic_ext_data.h"
-#include "catalog/pg_subscription.h"
-#include "catalog/pg_subscription_rel.h"
-#include "catalog/pg_tablespace.h"
-#include "catalog/pg_transform.h"
-#include "catalog/pg_ts_config.h"
-#include "catalog/pg_ts_config_map.h"
-#include "catalog/pg_ts_dict.h"
-#include "catalog/pg_ts_parser.h"
-#include "catalog/pg_ts_template.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_user_mapping.h"
+#include "catalog/pg_db_role_setting_d.h"
+#include "catalog/pg_depend_d.h"
+#include "catalog/pg_description_d.h"
+#include "catalog/pg_seclabel_d.h"
+#include "catalog/pg_shdepend_d.h"
+#include "catalog/pg_shdescription_d.h"
+#include "catalog/pg_shseclabel_d.h"
 #include "lib/qunique.h"
 #include "utils/catcache.h"
 #include "utils/lsyscache.h"
@@ -85,18 +39,6 @@
 
 	Adding system caches:
 
-	Add your new cache to the list in include/utils/syscache.h.
-	Keep the list sorted alphabetically.
-
-	Add your entry to the cacheinfo[] array below. All cache lists are
-	alphabetical, so add it in the proper place.  Specify the relation OID,
-	index OID, number of keys, key attribute numbers, and initial number of
-	hash buckets.
-
-	The number of hash buckets must be a power of 2.  It's reasonable to
-	set this to the number of entries that might be in the particular cache
-	in a medium-size database.
-
 	There must be a unique index underlying each syscache (ie, an index
 	whose key is the same as that of the cache).  If there is not one
 	already, add the definition for it to include/catalog/pg_*.h using
@@ -104,6 +46,13 @@
 	(Adding an index requires a catversion.h update, while simply
 	adding/deleting caches only requires a recompile.)
 
+	Add a MAKE_SYSCACHE call to the same pg_*.h file specifying the name of
+	your cache, the underlying index, and the initial number of hash buckets.
+
+	The number of hash buckets must be a power of 2.  It's reasonable to
+	set this to the number of entries that might be in the particular cache
+	in a medium-size database.
+
 	Finally, any place your relation gets heap_insert() or
 	heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
 	instead, which also update indexes.  The heap_* calls do not do that.
@@ -126,558 +75,7 @@ struct cachedesc
 /* Macro to provide nkeys and key array with convenient syntax. */
 #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
 
-static const struct cachedesc cacheinfo[] = {
-	[AGGFNOID] = {
-		AggregateRelationId,
-		AggregateFnoidIndexId,
-		KEY(Anum_pg_aggregate_aggfnoid),
-		16
-	},
-	[AMNAME] = {
-		AccessMethodRelationId,
-		AmNameIndexId,
-		KEY(Anum_pg_am_amname),
-		4
-	},
-	[AMOID] = {
-		AccessMethodRelationId,
-		AmOidIndexId,
-		KEY(Anum_pg_am_oid),
-		4
-	},
-	[AMOPOPID] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodOperatorIndexId,
-		KEY(Anum_pg_amop_amopopr,
-			Anum_pg_amop_amoppurpose,
-			Anum_pg_amop_amopfamily),
-		64
-	},
-	[AMOPSTRATEGY] = {
-		AccessMethodOperatorRelationId,
-		AccessMethodStrategyIndexId,
-		KEY(Anum_pg_amop_amopfamily,
-			Anum_pg_amop_amoplefttype,
-			Anum_pg_amop_amoprighttype,
-			Anum_pg_amop_amopstrategy),
-		64
-	},
-	[AMPROCNUM] = {
-		AccessMethodProcedureRelationId,
-		AccessMethodProcedureIndexId,
-		KEY(Anum_pg_amproc_amprocfamily,
-			Anum_pg_amproc_amproclefttype,
-			Anum_pg_amproc_amprocrighttype,
-			Anum_pg_amproc_amprocnum),
-		16
-	},
-	[ATTNAME] = {
-		AttributeRelationId,
-		AttributeRelidNameIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attname),
-		32
-	},
-	[ATTNUM] = {
-		AttributeRelationId,
-		AttributeRelidNumIndexId,
-		KEY(Anum_pg_attribute_attrelid,
-			Anum_pg_attribute_attnum),
-		128
-	},
-	[AUTHMEMMEMROLE] = {
-		AuthMemRelationId,
-		AuthMemMemRoleIndexId,
-		KEY(Anum_pg_auth_members_member,
-			Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHMEMROLEMEM] = {
-		AuthMemRelationId,
-		AuthMemRoleMemIndexId,
-		KEY(Anum_pg_auth_members_roleid,
-			Anum_pg_auth_members_member,
-			Anum_pg_auth_members_grantor),
-		8
-	},
-	[AUTHNAME] = {
-		AuthIdRelationId,
-		AuthIdRolnameIndexId,
-		KEY(Anum_pg_authid_rolname),
-		8
-	},
-	[AUTHOID] = {
-		AuthIdRelationId,
-		AuthIdOidIndexId,
-		KEY(Anum_pg_authid_oid),
-		8
-	},
-	[CASTSOURCETARGET] = {
-		CastRelationId,
-		CastSourceTargetIndexId,
-		KEY(Anum_pg_cast_castsource,
-			Anum_pg_cast_casttarget),
-		256
-	},
-	[CLAAMNAMENSP] = {
-		OperatorClassRelationId,
-		OpclassAmNameNspIndexId,
-		KEY(Anum_pg_opclass_opcmethod,
-			Anum_pg_opclass_opcname,
-			Anum_pg_opclass_opcnamespace),
-		8
-	},
-	[CLAOID] = {
-		OperatorClassRelationId,
-		OpclassOidIndexId,
-		KEY(Anum_pg_opclass_oid),
-		8
-	},
-	[COLLNAMEENCNSP] = {
-		CollationRelationId,
-		CollationNameEncNspIndexId,
-		KEY(Anum_pg_collation_collname,
-			Anum_pg_collation_collencoding,
-			Anum_pg_collation_collnamespace),
-		8
-	},
-	[COLLOID] = {
-		CollationRelationId,
-		CollationOidIndexId,
-		KEY(Anum_pg_collation_oid),
-		8
-	},
-	[CONDEFAULT] = {
-		ConversionRelationId,
-		ConversionDefaultIndexId,
-		KEY(Anum_pg_conversion_connamespace,
-			Anum_pg_conversion_conforencoding,
-			Anum_pg_conversion_contoencoding,
-			Anum_pg_conversion_oid),
-		8
-	},
-	[CONNAMENSP] = {
-		ConversionRelationId,
-		ConversionNameNspIndexId,
-		KEY(Anum_pg_conversion_conname,
-			Anum_pg_conversion_connamespace),
-		8
-	},
-	[CONSTROID] = {
-		ConstraintRelationId,
-		ConstraintOidIndexId,
-		KEY(Anum_pg_constraint_oid),
-		16
-	},
-	[CONVOID] = {
-		ConversionRelationId,
-		ConversionOidIndexId,
-		KEY(Anum_pg_conversion_oid),
-		8
-	},
-	[DATABASEOID] = {
-		DatabaseRelationId,
-		DatabaseOidIndexId,
-		KEY(Anum_pg_database_oid),
-		4
-	},
-	[DEFACLROLENSPOBJ] = {
-		DefaultAclRelationId,
-		DefaultAclRoleNspObjIndexId,
-		KEY(Anum_pg_default_acl_defaclrole,
-			Anum_pg_default_acl_defaclnamespace,
-			Anum_pg_default_acl_defaclobjtype),
-		8
-	},
-	[ENUMOID] = {
-		EnumRelationId,
-		EnumOidIndexId,
-		KEY(Anum_pg_enum_oid),
-		8
-	},
-	[ENUMTYPOIDNAME] = {
-		EnumRelationId,
-		EnumTypIdLabelIndexId,
-		KEY(Anum_pg_enum_enumtypid,
-			Anum_pg_enum_enumlabel),
-		8
-	},
-	[EVENTTRIGGERNAME] = {
-		EventTriggerRelationId,
-		EventTriggerNameIndexId,
-		KEY(Anum_pg_event_trigger_evtname),
-		8
-	},
-	[EVENTTRIGGEROID] = {
-		EventTriggerRelationId,
-		EventTriggerOidIndexId,
-		KEY(Anum_pg_event_trigger_oid),
-		8
-	},
-	[FOREIGNDATAWRAPPERNAME] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperNameIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_fdwname),
-		2
-	},
-	[FOREIGNDATAWRAPPEROID] = {
-		ForeignDataWrapperRelationId,
-		ForeignDataWrapperOidIndexId,
-		KEY(Anum_pg_foreign_data_wrapper_oid),
-		2
-	},
-	[FOREIGNSERVERNAME] = {
-		ForeignServerRelationId,
-		ForeignServerNameIndexId,
-		KEY(Anum_pg_foreign_server_srvname),
-		2
-	},
-	[FOREIGNSERVEROID] = {
-		ForeignServerRelationId,
-		ForeignServerOidIndexId,
-		KEY(Anum_pg_foreign_server_oid),
-		2
-	},
-	[FOREIGNTABLEREL] = {
-		ForeignTableRelationId,
-		ForeignTableRelidIndexId,
-		KEY(Anum_pg_foreign_table_ftrelid),
-		4
-	},
-	[INDEXRELID] = {
-		IndexRelationId,
-		IndexRelidIndexId,
-		KEY(Anum_pg_index_indexrelid),
-		64
-	},
-	[LANGNAME] = {
-		LanguageRelationId,
-		LanguageNameIndexId,
-		KEY(Anum_pg_language_lanname),
-		4
-	},
-	[LANGOID] = {
-		LanguageRelationId,
-		LanguageOidIndexId,
-		KEY(Anum_pg_language_oid),
-		4
-	},
-	[NAMESPACENAME] = {
-		NamespaceRelationId,
-		NamespaceNameIndexId,
-		KEY(Anum_pg_namespace_nspname),
-		4
-	},
-	[NAMESPACEOID] = {
-		NamespaceRelationId,
-		NamespaceOidIndexId,
-		KEY(Anum_pg_namespace_oid),
-		16
-	},
-	[OPERNAMENSP] = {
-		OperatorRelationId,
-		OperatorNameNspIndexId,
-		KEY(Anum_pg_operator_oprname,
-			Anum_pg_operator_oprleft,
-			Anum_pg_operator_oprright,
-			Anum_pg_operator_oprnamespace),
-		256
-	},
-	[OPEROID] = {
-		OperatorRelationId,
-		OperatorOidIndexId,
-		KEY(Anum_pg_operator_oid),
-		32
-	},
-	[OPFAMILYAMNAMENSP] = {
-		OperatorFamilyRelationId,
-		OpfamilyAmNameNspIndexId,
-		KEY(Anum_pg_opfamily_opfmethod,
-			Anum_pg_opfamily_opfname,
-			Anum_pg_opfamily_opfnamespace),
-		8
-	},
-	[OPFAMILYOID] = {
-		OperatorFamilyRelationId,
-		OpfamilyOidIndexId,
-		KEY(Anum_pg_opfamily_oid),
-		8
-	},
-	[PARAMETERACLNAME] = {
-		ParameterAclRelationId,
-		ParameterAclParnameIndexId,
-		KEY(Anum_pg_parameter_acl_parname),
-		4
-	},
-	[PARAMETERACLOID] = {
-		ParameterAclRelationId,
-		ParameterAclOidIndexId,
-		KEY(Anum_pg_parameter_acl_oid),
-		4
-	},
-	[PARTRELID] = {
-		PartitionedRelationId,
-		PartitionedRelidIndexId,
-		KEY(Anum_pg_partitioned_table_partrelid),
-		32
-	},
-	[PROCNAMEARGSNSP] = {
-		ProcedureRelationId,
-		ProcedureNameArgsNspIndexId,
-		KEY(Anum_pg_proc_proname,
-			Anum_pg_proc_proargtypes,
-			Anum_pg_proc_pronamespace),
-		128
-	},
-	[PROCOID] = {
-		ProcedureRelationId,
-		ProcedureOidIndexId,
-		KEY(Anum_pg_proc_oid),
-		128
-	},
-	[PUBLICATIONNAME] = {
-		PublicationRelationId,
-		PublicationNameIndexId,
-		KEY(Anum_pg_publication_pubname),
-		8
-	},
-	[PUBLICATIONNAMESPACE] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespaceObjectIndexId,
-		KEY(Anum_pg_publication_namespace_oid),
-		64
-	},
-	[PUBLICATIONNAMESPACEMAP] = {
-		PublicationNamespaceRelationId,
-		PublicationNamespacePnnspidPnpubidIndexId,
-		KEY(Anum_pg_publication_namespace_pnnspid,
-			Anum_pg_publication_namespace_pnpubid),
-		64
-	},
-	[PUBLICATIONOID] = {
-		PublicationRelationId,
-		PublicationObjectIndexId,
-		KEY(Anum_pg_publication_oid),
-		8
-	},
-	[PUBLICATIONREL] = {
-		PublicationRelRelationId,
-		PublicationRelObjectIndexId,
-		KEY(Anum_pg_publication_rel_oid),
-		64
-	},
-	[PUBLICATIONRELMAP] = {
-		PublicationRelRelationId,
-		PublicationRelPrrelidPrpubidIndexId,
-		KEY(Anum_pg_publication_rel_prrelid,
-			Anum_pg_publication_rel_prpubid),
-		64
-	},
-	[RANGEMULTIRANGE] = {
-		RangeRelationId,
-		RangeMultirangeTypidIndexId,
-		KEY(Anum_pg_range_rngmultitypid),
-		4
-	},
-	[RANGETYPE] = {
-		RangeRelationId,
-		RangeTypidIndexId,
-		KEY(Anum_pg_range_rngtypid),
-		4
-	},
-	[RELNAMENSP] = {
-		RelationRelationId,
-		ClassNameNspIndexId,
-		KEY(Anum_pg_class_relname,
-			Anum_pg_class_relnamespace),
-		128
-	},
-	[RELOID] = {
-		RelationRelationId,
-		ClassOidIndexId,
-		KEY(Anum_pg_class_oid),
-		128
-	},
-	[REPLORIGIDENT] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginIdentIndex,
-		KEY(Anum_pg_replication_origin_roident),
-		16
-	},
-	[REPLORIGNAME] = {
-		ReplicationOriginRelationId,
-		ReplicationOriginNameIndex,
-		KEY(Anum_pg_replication_origin_roname),
-		16
-	},
-	[RULERELNAME] = {
-		RewriteRelationId,
-		RewriteRelRulenameIndexId,
-		KEY(Anum_pg_rewrite_ev_class,
-			Anum_pg_rewrite_rulename),
-		8
-	},
-	[SEQRELID] = {
-		SequenceRelationId,
-		SequenceRelidIndexId,
-		KEY(Anum_pg_sequence_seqrelid),
-		32
-	},
-	[STATEXTDATASTXOID] = {
-		StatisticExtDataRelationId,
-		StatisticExtDataStxoidInhIndexId,
-		KEY(Anum_pg_statistic_ext_data_stxoid,
-			Anum_pg_statistic_ext_data_stxdinherit),
-		4
-	},
-	[STATEXTNAMENSP] = {
-		StatisticExtRelationId,
-		StatisticExtNameIndexId,
-		KEY(Anum_pg_statistic_ext_stxname,
-			Anum_pg_statistic_ext_stxnamespace),
-		4
-	},
-	[STATEXTOID] = {
-		StatisticExtRelationId,
-		StatisticExtOidIndexId,
-		KEY(Anum_pg_statistic_ext_oid),
-		4
-	},
-	[STATRELATTINH] = {
-		StatisticRelationId,
-		StatisticRelidAttnumInhIndexId,
-		KEY(Anum_pg_statistic_starelid,
-			Anum_pg_statistic_staattnum,
-			Anum_pg_statistic_stainherit),
-		128
-	},
-	[SUBSCRIPTIONNAME] = {
-		SubscriptionRelationId,
-		SubscriptionNameIndexId,
-		KEY(Anum_pg_subscription_subdbid,
-			Anum_pg_subscription_subname),
-		4
-	},
-	[SUBSCRIPTIONOID] = {
-		SubscriptionRelationId,
-		SubscriptionObjectIndexId,
-		KEY(Anum_pg_subscription_oid),
-		4
-	},
-	[SUBSCRIPTIONRELMAP] = {
-		SubscriptionRelRelationId,
-		SubscriptionRelSrrelidSrsubidIndexId,
-		KEY(Anum_pg_subscription_rel_srrelid,
-			Anum_pg_subscription_rel_srsubid),
-		64
-	},
-	[TABLESPACEOID] = {
-		TableSpaceRelationId,
-		TablespaceOidIndexId,
-		KEY(Anum_pg_tablespace_oid),
-		4
-	},
-	[TRFOID] = {
-		TransformRelationId,
-		TransformOidIndexId,
-		KEY(Anum_pg_transform_oid),
-		16
-	},
-	[TRFTYPELANG] = {
-		TransformRelationId,
-		TransformTypeLangIndexId,
-		KEY(Anum_pg_transform_trftype,
-			Anum_pg_transform_trflang),
-		16
-	},
-	[TSCONFIGMAP] = {
-		TSConfigMapRelationId,
-		TSConfigMapIndexId,
-		KEY(Anum_pg_ts_config_map_mapcfg,
-			Anum_pg_ts_config_map_maptokentype,
-			Anum_pg_ts_config_map_mapseqno),
-		2
-	},
-	[TSCONFIGNAMENSP] = {
-		TSConfigRelationId,
-		TSConfigNameNspIndexId,
-		KEY(Anum_pg_ts_config_cfgname,
-			Anum_pg_ts_config_cfgnamespace),
-		2
-	},
-	[TSCONFIGOID] = {
-		TSConfigRelationId,
-		TSConfigOidIndexId,
-		KEY(Anum_pg_ts_config_oid),
-		2
-	},
-	[TSDICTNAMENSP] = {
-		TSDictionaryRelationId,
-		TSDictionaryNameNspIndexId,
-		KEY(Anum_pg_ts_dict_dictname,
-			Anum_pg_ts_dict_dictnamespace),
-		2
-	},
-	[TSDICTOID] = {
-		TSDictionaryRelationId,
-		TSDictionaryOidIndexId,
-		KEY(Anum_pg_ts_dict_oid),
-		2
-	},
-	[TSPARSERNAMENSP] = {
-		TSParserRelationId,
-		TSParserNameNspIndexId,
-		KEY(Anum_pg_ts_parser_prsname,
-			Anum_pg_ts_parser_prsnamespace),
-		2
-	},
-	[TSPARSEROID] = {
-		TSParserRelationId,
-		TSParserOidIndexId,
-		KEY(Anum_pg_ts_parser_oid),
-		2
-	},
-	[TSTEMPLATENAMENSP] = {
-		TSTemplateRelationId,
-		TSTemplateNameNspIndexId,
-		KEY(Anum_pg_ts_template_tmplname,
-			Anum_pg_ts_template_tmplnamespace),
-		2
-	},
-	[TSTEMPLATEOID] = {
-		TSTemplateRelationId,
-		TSTemplateOidIndexId,
-		KEY(Anum_pg_ts_template_oid),
-		2
-	},
-	[TYPENAMENSP] = {
-		TypeRelationId,
-		TypeNameNspIndexId,
-		KEY(Anum_pg_type_typname,
-			Anum_pg_type_typnamespace),
-		64
-	},
-	[TYPEOID] = {
-		TypeRelationId,
-		TypeOidIndexId,
-		KEY(Anum_pg_type_oid),
-		64
-	},
-	[USERMAPPINGOID] = {
-		UserMappingRelationId,
-		UserMappingOidIndexId,
-		KEY(Anum_pg_user_mapping_oid),
-		2
-	},
-	[USERMAPPINGUSERSERVER] = {
-		UserMappingRelationId,
-		UserMappingUserServerIndexId,
-		KEY(Anum_pg_user_mapping_umuser,
-			Anum_pg_user_mapping_umserver),
-		2
-	}
-};
+#include "catalog/syscache_info.h"
 
 StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
 				 "SysCacheSize does not match syscache.c's array");
diff --git a/src/include/catalog/.gitignore b/src/include/catalog/.gitignore
index 6b83d4c7e6e..983574f2c4d 100644
--- a/src/include/catalog/.gitignore
+++ b/src/include/catalog/.gitignore
@@ -1,4 +1,6 @@
 /schemapg.h
+/syscache_ids.h
+/syscache_info.h
 /system_fk_info.h
 /pg_*_d.h
 /header-stamp
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index 01cf31354ff..3c8f3875d53 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -82,8 +82,8 @@
  * The macro definitions are just to keep the C compiler from spitting up.
  */
 #define DECLARE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl) extern int no_such_variable
-#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX_PKEY(name,oid,oidmacro,tblname,decl,...) extern int no_such_variable
 
 /*
  * These lines inform genbki.pl about manually-assigned OIDs that do not
@@ -120,6 +120,12 @@
 #define DECLARE_ARRAY_FOREIGN_KEY(cols,reftbl,refcols) extern int no_such_variable
 #define DECLARE_ARRAY_FOREIGN_KEY_OPT(cols,reftbl,refcols) extern int no_such_variable
 
+/*
+ * Create a syscache with the given name, index, and bucket size.  See
+ * syscache.c.
+ */
+#define MAKE_SYSCACHE(name,idxname,nbuckets) extern int no_such_variable
+
 /* The following are never defined; they are here only for documentation. */
 
 /*
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index 2bcbe327cfe..6be76dca1dd 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -102,8 +102,22 @@ bki_data_f = files(bki_data)
 
 
 input = []
-output_files = ['postgres.bki', 'system_constraints.sql', 'schemapg.h', 'system_fk_info.h']
-output_install = [dir_data, dir_data, dir_include_server / 'catalog', dir_include_server / 'catalog']
+output_files = [
+  'postgres.bki',
+  'system_constraints.sql',
+  'schemapg.h',
+  'syscache_ids.h',
+  'syscache_info.h',
+  'system_fk_info.h',
+]
+output_install = [
+  dir_data,
+  dir_data,
+  dir_include_server / 'catalog',
+  false,
+  dir_include_server / 'catalog',
+  dir_include_server / 'catalog',
+]
 
 foreach h : catalog_headers
   fname = h.split('.h')[0] + '_d.h'
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index db72a1233b3..490f6454695 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -112,6 +112,8 @@ DECLARE_TOAST(pg_aggregate, 4159, 4160);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_aggregate_fnoid_index, 2650, AggregateFnoidIndexId, pg_aggregate, btree(aggfnoid oid_ops));
 
+MAKE_SYSCACHE(AGGFNOID, pg_aggregate_fnoid_index, 16);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /*
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index e4bb61fc721..475593fad4c 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -50,6 +50,9 @@ typedef FormData_pg_am *Form_pg_am;
 DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, AmNameIndexId, pg_am, btree(amname name_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_am_oid_index, 2652, AmOidIndexId, pg_am, btree(oid oid_ops));
 
+MAKE_SYSCACHE(AMNAME, pg_am_name_index, 4);
+MAKE_SYSCACHE(AMOID, pg_am_oid_index, 4);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /*
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index 8ea18a2fe1b..570100fad41 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -91,6 +91,9 @@ DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, AccessMethodStrategyIndexId,
 DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, AccessMethodOperatorIndexId, pg_amop, btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_amop_oid_index, 2756, AccessMethodOperatorOidIndexId, pg_amop, btree(oid oid_ops));
 
+MAKE_SYSCACHE(AMOPSTRATEGY, pg_amop_fam_strat_index, 64);
+MAKE_SYSCACHE(AMOPOPID, pg_amop_opr_fam_index, 64);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /* allowed values of amoppurpose: */
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 43e8f5ef0d2..1dbebeca175 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -70,4 +70,6 @@ typedef FormData_pg_amproc *Form_pg_amproc;
 DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, AccessMethodProcedureIndexId, pg_amproc, btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_amproc_oid_index, 2757, AccessMethodProcedureOidIndexId, pg_amproc, btree(oid oid_ops));
 
+MAKE_SYSCACHE(AMPROCNUM, pg_amproc_fam_proc_index, 16);
+
 #endif							/* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index e2aadb94141..9f2706c4e87 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -211,6 +211,9 @@ typedef FormData_pg_attribute *Form_pg_attribute;
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, AttributeRelidNameIndexId, pg_attribute, btree(attrelid oid_ops, attname name_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_attribute_relid_attnum_index, 2659, AttributeRelidNumIndexId, pg_attribute, btree(attrelid oid_ops, attnum int2_ops));
 
+MAKE_SYSCACHE(ATTNAME, pg_attribute_relid_attnam_index, 32);
+MAKE_SYSCACHE(ATTNUM, pg_attribute_relid_attnum_index, 128);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 #define		  ATTRIBUTE_IDENTITY_ALWAYS		'a'
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index c6f0782f468..5f4b30756ca 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -50,4 +50,7 @@ DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, AuthMemRoleMemInde
 DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, AuthMemMemRoleIndexId, pg_auth_members, btree(member oid_ops, roleid oid_ops, grantor oid_ops));
 DECLARE_INDEX(pg_auth_members_grantor_index, 6302, AuthMemGrantorIndexId, pg_auth_members, btree(grantor oid_ops));
 
+MAKE_SYSCACHE(AUTHMEMROLEMEM, pg_auth_members_role_member_index, 8);
+MAKE_SYSCACHE(AUTHMEMMEMROLE, pg_auth_members_member_role_index, 8);
+
 #endif							/* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index 6a177d1b7db..e08863f78ab 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -60,4 +60,7 @@ DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToas
 DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops));
 
+MAKE_SYSCACHE(AUTHNAME, pg_authid_rolname_index, 8);
+MAKE_SYSCACHE(AUTHOID, pg_authid_oid_index, 8);
+
 #endif							/* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index 67bcc11619a..6c995509bc3 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -59,6 +59,8 @@ typedef FormData_pg_cast *Form_pg_cast;
 DECLARE_UNIQUE_INDEX_PKEY(pg_cast_oid_index, 2660, CastOidIndexId, pg_cast, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, CastSourceTargetIndexId, pg_cast, btree(castsource oid_ops, casttarget oid_ops));
 
+MAKE_SYSCACHE(CASTSOURCETARGET, pg_cast_source_target_index, 256);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /*
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 4f24d9a92f5..3b7533e7bb3 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -156,6 +156,9 @@ DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, pg_class, b
 DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, pg_class, btree(relname name_ops, relnamespace oid_ops));
 DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, pg_class, btree(reltablespace oid_ops, relfilenode oid_ops));
 
+MAKE_SYSCACHE(RELOID, pg_class_oid_index, 128);
+MAKE_SYSCACHE(RELNAMENSP, pg_class_relname_nsp_index, 128);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 #define		  RELKIND_RELATION		  'r'	/* ordinary table */
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index 744e64c7770..5f08eb0a4af 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -62,6 +62,9 @@ DECLARE_TOAST(pg_collation, 6175, 6176);
 DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, CollationNameEncNspIndexId, pg_collation, btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_collation_oid_index, 3085, CollationOidIndexId, pg_collation, btree(oid oid_ops));
 
+MAKE_SYSCACHE(COLLNAMEENCNSP, pg_collation_name_enc_nsp_index, 8);
+MAKE_SYSCACHE(COLLOID, pg_collation_oid_index, 8);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 #define COLLPROVIDER_DEFAULT	'd'
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index d79432e142b..c693091d426 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -172,6 +172,8 @@ DECLARE_INDEX(pg_constraint_contypid_index, 2666, ConstraintTypidIndexId, pg_con
 DECLARE_UNIQUE_INDEX_PKEY(pg_constraint_oid_index, 2667, ConstraintOidIndexId, pg_constraint, btree(oid oid_ops));
 DECLARE_INDEX(pg_constraint_conparentid_index, 2579, ConstraintParentIndexId, pg_constraint, btree(conparentid oid_ops));
 
+MAKE_SYSCACHE(CONSTROID, pg_constraint_oid_index, 16);
+
 /* conkey can contain zero (InvalidAttrNumber) if a whole-row Var is used */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((conrelid, conkey), pg_attribute, (attrelid, attnum));
 DECLARE_ARRAY_FOREIGN_KEY((confrelid, confkey), pg_attribute, (attrelid, attnum));
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index cdbc03b915b..d94f0229672 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -64,6 +64,10 @@ DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, ConversionDefaultIndexId
 DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, ConversionNameNspIndexId, pg_conversion, btree(conname name_ops, connamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_conversion_oid_index, 2670, ConversionOidIndexId, pg_conversion, btree(oid oid_ops));
 
+MAKE_SYSCACHE(CONDEFAULT, pg_conversion_default_index, 8);
+MAKE_SYSCACHE(CONNAMENSP, pg_conversion_name_nsp_index, 8);
+MAKE_SYSCACHE(CONVOID, pg_conversion_oid_index, 8);
+
 
 extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
 									  Oid conowner,
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index f0ed776b603..014baa7baba 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -100,6 +100,8 @@ DECLARE_TOAST_WITH_MACRO(pg_database, 4177, 4178, PgDatabaseToastTable, PgDataba
 DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, DatabaseNameIndexId, pg_database, btree(datname name_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_database_oid_index, 2672, DatabaseOidIndexId, pg_database, btree(oid oid_ops));
 
+MAKE_SYSCACHE(DATABASEOID, pg_database_oid_index, 4);
+
 /*
  * pg_database.dat contains an entry for template1, but not for the template0
  * or postgres databases, because those are created later in initdb.
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index c52ad381edb..d272cdf08b4 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -54,6 +54,8 @@ DECLARE_TOAST(pg_default_acl, 4143, 4144);
 DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, DefaultAclRoleNspObjIndexId, pg_default_acl, btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_default_acl_oid_index, 828, DefaultAclOidIndexId, pg_default_acl, btree(oid oid_ops));
 
+MAKE_SYSCACHE(DEFACLROLENSPOBJ, pg_default_acl_role_nsp_obj_index, 8);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /*
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index 6a05fc8ca2b..4d9a241d348 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -47,6 +47,9 @@ DECLARE_UNIQUE_INDEX_PKEY(pg_enum_oid_index, 3502, EnumOidIndexId, pg_enum, btre
 DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, EnumTypIdLabelIndexId, pg_enum, btree(enumtypid oid_ops, enumlabel name_ops));
 DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, EnumTypIdSortOrderIndexId, pg_enum, btree(enumtypid oid_ops, enumsortorder float4_ops));
 
+MAKE_SYSCACHE(ENUMOID, pg_enum_oid_index, 8);
+MAKE_SYSCACHE(ENUMTYPOIDNAME, pg_enum_typid_label_index, 8);
+
 /*
  * prototypes for functions in pg_enum.c
  */
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index d8e99da37db..9170a4ddfe8 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -54,4 +54,7 @@ DECLARE_TOAST(pg_event_trigger, 4145, 4146);
 DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, EventTriggerNameIndexId, pg_event_trigger, btree(evtname name_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_event_trigger_oid_index, 3468, EventTriggerOidIndexId, pg_event_trigger, btree(oid oid_ops));
 
+MAKE_SYSCACHE(EVENTTRIGGERNAME, pg_event_trigger_evtname_index, 8);
+MAKE_SYSCACHE(EVENTTRIGGEROID, pg_event_trigger_oid_index, 8);
+
 #endif							/* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 5e39e4b42f8..0d8759d3fd3 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -55,4 +55,7 @@ DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
 DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_data_wrapper_oid_index, 112, ForeignDataWrapperOidIndexId, pg_foreign_data_wrapper, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, ForeignDataWrapperNameIndexId, pg_foreign_data_wrapper, btree(fdwname name_ops));
 
+MAKE_SYSCACHE(FOREIGNDATAWRAPPEROID, pg_foreign_data_wrapper_oid_index, 2);
+MAKE_SYSCACHE(FOREIGNDATAWRAPPERNAME, pg_foreign_data_wrapper_name_index, 2);
+
 #endif							/* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 995f140bf35..a4b81936b09 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -52,4 +52,7 @@ DECLARE_TOAST(pg_foreign_server, 4151, 4152);
 DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_server_oid_index, 113, ForeignServerOidIndexId, pg_foreign_server, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, ForeignServerNameIndexId, pg_foreign_server, btree(srvname name_ops));
 
+MAKE_SYSCACHE(FOREIGNSERVEROID, pg_foreign_server_oid_index, 2);
+MAKE_SYSCACHE(FOREIGNSERVERNAME, pg_foreign_server_name_index, 2);
+
 #endif							/* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 19e7373b027..d17ff0e76e1 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -46,4 +46,6 @@ DECLARE_TOAST(pg_foreign_table, 4153, 4154);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_foreign_table_relid_index, 3119, ForeignTableRelidIndexId, pg_foreign_table, btree(ftrelid oid_ops));
 
+MAKE_SYSCACHE(FOREIGNTABLEREL, pg_foreign_table_relid_index, 4);
+
 #endif							/* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index e4f3f708071..3462572eb55 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -72,6 +72,8 @@ typedef FormData_pg_index *Form_pg_index;
 DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops));
 
+MAKE_SYSCACHE(INDEXRELID, pg_index_indexrelid_index, 64);
+
 /* indkey can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((indrelid, indkey), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index 581372addd4..7256908a95c 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -69,4 +69,7 @@ DECLARE_TOAST(pg_language, 4157, 4158);
 DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, LanguageNameIndexId, pg_language, btree(lanname name_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_language_oid_index, 2682, LanguageOidIndexId, pg_language, btree(oid oid_ops));
 
+MAKE_SYSCACHE(LANGNAME, pg_language_name_index, 4);
+MAKE_SYSCACHE(LANGOID, pg_language_oid_index, 4);
+
 #endif							/* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index abae5e2824b..e101808ae1e 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -56,6 +56,9 @@ DECLARE_TOAST(pg_namespace, 4163, 4164);
 DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, NamespaceNameIndexId, pg_namespace, btree(nspname name_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, NamespaceOidIndexId, pg_namespace, btree(oid oid_ops));
 
+MAKE_SYSCACHE(NAMESPACENAME, pg_namespace_nspname_index, 4);
+MAKE_SYSCACHE(NAMESPACEOID, pg_namespace_oid_index, 16);
+
 /*
  * prototypes for functions in pg_namespace.c
  */
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index 9cbdab52b16..05867d08f93 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -85,4 +85,7 @@ typedef FormData_pg_opclass *Form_pg_opclass;
 DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, OpclassAmNameNspIndexId, pg_opclass, btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_opclass_oid_index, 2687, OpclassOidIndexId, pg_opclass, btree(oid oid_ops));
 
+MAKE_SYSCACHE(CLAAMNAMENSP, pg_opclass_am_name_nsp_index, 8);
+MAKE_SYSCACHE(CLAOID, pg_opclass_oid_index, 8);
+
 #endif							/* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 7d6bbbb90f0..3ff1acc37ef 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -85,6 +85,8 @@ typedef FormData_pg_operator *Form_pg_operator;
 DECLARE_UNIQUE_INDEX_PKEY(pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
 
+MAKE_SYSCACHE(OPEROID, pg_operator_oid_index, 32);
+MAKE_SYSCACHE(OPERNAMENSP, pg_operator_oprname_l_r_n_index, 256);
 
 extern Oid	OperatorLookup(List *operatorName,
 						   Oid leftObjectId,
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index c974f41d952..52f9c4acf97 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -53,6 +53,9 @@ typedef FormData_pg_opfamily *Form_pg_opfamily;
 DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, OpfamilyAmNameNspIndexId, pg_opfamily, btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, pg_opfamily, btree(oid oid_ops));
 
+MAKE_SYSCACHE(OPFAMILYAMNAMENSP, pg_opfamily_am_name_nsp_index, 8);
+MAKE_SYSCACHE(OPFAMILYOID, pg_opfamily_oid_index, 8);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /* This does not account for non-core opfamilies that might accept boolean */
diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h
index 09c51e5d34a..8f6b6f92b3e 100644
--- a/src/include/catalog/pg_parameter_acl.h
+++ b/src/include/catalog/pg_parameter_acl.h
@@ -53,6 +53,8 @@ DECLARE_TOAST_WITH_MACRO(pg_parameter_acl, 6244, 6245, PgParameterAclToastTable,
 DECLARE_UNIQUE_INDEX(pg_parameter_acl_parname_index, 6246, ParameterAclParnameIndexId, pg_parameter_acl, btree(parname text_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_parameter_acl_oid_index, 6247, ParameterAclOidIndexId, pg_parameter_acl, btree(oid oid_ops));
 
+MAKE_SYSCACHE(PARAMETERACLNAME, pg_parameter_acl_parname_index, 4);
+MAKE_SYSCACHE(PARAMETERACLOID, pg_parameter_acl_oid_index, 4);
 
 extern Oid	ParameterAclLookup(const char *parameter, bool missing_ok);
 extern Oid	ParameterAclCreate(const char *parameter);
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index bd6798e3ad4..daf57008b69 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -68,6 +68,8 @@ DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_partitioned_table_partrelid_index, 3351, PartitionedRelidIndexId, pg_partitioned_table, btree(partrelid oid_ops));
 
+MAKE_SYSCACHE(PARTRELID, pg_partitioned_table_partrelid_index, 32);
+
 /* partattrs can contain zero (InvalidAttrNumber) to represent expressions */
 DECLARE_ARRAY_FOREIGN_KEY_OPT((partrelid, partattrs), pg_attribute, (attrelid, attnum));
 
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 24f743329d9..51f43092415 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -140,6 +140,9 @@ DECLARE_TOAST(pg_proc, 2836, 2837);
 DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, pg_proc, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, pg_proc, btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
 
+MAKE_SYSCACHE(PROCOID, pg_proc_oid_index, 128);
+MAKE_SYSCACHE(PROCNAMEARGSNSP, pg_proc_proname_args_nsp_index, 128);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /*
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 6e9bbe80ffc..2f1b6abbfa7 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -66,6 +66,9 @@ typedef FormData_pg_publication *Form_pg_publication;
 DECLARE_UNIQUE_INDEX_PKEY(pg_publication_oid_index, 6110, PublicationObjectIndexId, pg_publication, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, PublicationNameIndexId, pg_publication, btree(pubname name_ops));
 
+MAKE_SYSCACHE(PUBLICATIONOID, pg_publication_oid_index, 8);
+MAKE_SYSCACHE(PUBLICATIONNAME, pg_publication_pubname_index, 8);
+
 typedef struct PublicationActions
 {
 	bool		pubinsert;
diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h
index 92aa58c1ed0..1cfb557684f 100644
--- a/src/include/catalog/pg_publication_namespace.h
+++ b/src/include/catalog/pg_publication_namespace.h
@@ -44,4 +44,7 @@ typedef FormData_pg_publication_namespace *Form_pg_publication_namespace;
 DECLARE_UNIQUE_INDEX_PKEY(pg_publication_namespace_oid_index, 6238, PublicationNamespaceObjectIndexId, pg_publication_namespace, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_publication_namespace_pnnspid_pnpubid_index, 6239, PublicationNamespacePnnspidPnpubidIndexId, pg_publication_namespace, btree(pnnspid oid_ops, pnpubid oid_ops));
 
+MAKE_SYSCACHE(PUBLICATIONNAMESPACE, pg_publication_namespace_oid_index, 64);
+MAKE_SYSCACHE(PUBLICATIONNAMESPACEMAP, pg_publication_namespace_pnnspid_pnpubid_index, 64);
+
 #endif							/* PG_PUBLICATION_NAMESPACE_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index 8219e854170..25fa630675a 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -51,4 +51,7 @@ DECLARE_UNIQUE_INDEX_PKEY(pg_publication_rel_oid_index, 6112, PublicationRelObje
 DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, PublicationRelPrrelidPrpubidIndexId, pg_publication_rel, btree(prrelid oid_ops, prpubid oid_ops));
 DECLARE_INDEX(pg_publication_rel_prpubid_index, 6116, PublicationRelPrpubidIndexId, pg_publication_rel, btree(prpubid oid_ops));
 
+MAKE_SYSCACHE(PUBLICATIONREL, pg_publication_rel_oid_index, 64);
+MAKE_SYSCACHE(PUBLICATIONRELMAP, pg_publication_rel_prrelid_prpubid_index, 64);
+
 #endif							/* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index a1f527130bf..0bd3ab688bd 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -60,6 +60,9 @@ typedef FormData_pg_range *Form_pg_range;
 DECLARE_UNIQUE_INDEX_PKEY(pg_range_rngtypid_index, 3542, RangeTypidIndexId, pg_range, btree(rngtypid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_range_rngmultitypid_index, 2228, RangeMultirangeTypidIndexId, pg_range, btree(rngmultitypid oid_ops));
 
+MAKE_SYSCACHE(RANGETYPE, pg_range_rngtypid_index, 4);
+MAKE_SYSCACHE(RANGEMULTIRANGE, pg_range_rngmultitypid_index, 4);
+
 /*
  * prototypes for functions in pg_range.c
  */
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index 0280aa2f768..e9bc0209c26 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -59,4 +59,7 @@ DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginT
 DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops));
 DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops));
 
+MAKE_SYSCACHE(REPLORIGIDENT, pg_replication_origin_roiident_index, 16);
+MAKE_SYSCACHE(REPLORIGNAME, pg_replication_origin_roname_index, 16);
+
 #endif							/* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index c346c5b384d..e42ff73d29c 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -56,4 +56,6 @@ DECLARE_TOAST(pg_rewrite, 2838, 2839);
 DECLARE_UNIQUE_INDEX_PKEY(pg_rewrite_oid_index, 2692, RewriteOidIndexId, pg_rewrite, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, RewriteRelRulenameIndexId, pg_rewrite, btree(ev_class oid_ops, rulename name_ops));
 
+MAKE_SYSCACHE(RULERELNAME, pg_rewrite_rel_rulename_index, 8);
+
 #endif							/* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index 3fba57a7397..8c3f0dd1ab8 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -41,4 +41,6 @@ typedef FormData_pg_sequence *Form_pg_sequence;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_sequence_seqrelid_index, 5002, SequenceRelidIndexId, pg_sequence, btree(seqrelid oid_ops));
 
+MAKE_SYSCACHE(SEQRELID, pg_sequence_seqrelid_index, 32);
+
 #endif							/* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 949a103f9ff..041e626390a 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -138,6 +138,8 @@ DECLARE_TOAST(pg_statistic, 2840, 2841);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_relid_att_inh_index, 2696, StatisticRelidAttnumInhIndexId, pg_statistic, btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
 
+MAKE_SYSCACHE(STATRELATTINH, pg_statistic_relid_att_inh_index, 128);
+
 DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index 104b7db1f95..85064086ec5 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -74,6 +74,9 @@ DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_oid_index, 3380, StatisticExtOidIndex
 DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, StatisticExtNameIndexId, pg_statistic_ext, btree(stxname name_ops, stxnamespace oid_ops));
 DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, StatisticExtRelidIndexId, pg_statistic_ext, btree(stxrelid oid_ops));
 
+MAKE_SYSCACHE(STATEXTOID, pg_statistic_ext_oid_index, 4);
+MAKE_SYSCACHE(STATEXTNAMENSP, pg_statistic_ext_name_index, 4);
+
 DECLARE_ARRAY_FOREIGN_KEY((stxrelid, stxkeys), pg_attribute, (attrelid, attnum));
 
 #ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
index 48c5c2d1225..18b00ce8b52 100644
--- a/src/include/catalog/pg_statistic_ext_data.h
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -56,5 +56,6 @@ DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_statistic_ext_data_stxoid_inh_index, 3433, StatisticExtDataStxoidInhIndexId, pg_statistic_ext_data, btree(stxoid oid_ops, stxdinherit bool_ops));
 
+MAKE_SYSCACHE(STATEXTDATASTXOID, pg_statistic_ext_data_stxoid_inh_index, 4);
 
 #endif							/* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index ca326255852..ab206bad7de 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -118,6 +118,9 @@ DECLARE_TOAST_WITH_MACRO(pg_subscription, 4183, 4184, PgSubscriptionToastTable,
 DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_oid_index, 6114, SubscriptionObjectIndexId, pg_subscription, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, SubscriptionNameIndexId, pg_subscription, btree(subdbid oid_ops, subname name_ops));
 
+MAKE_SYSCACHE(SUBSCRIPTIONOID, pg_subscription_oid_index, 4);
+MAKE_SYSCACHE(SUBSCRIPTIONNAME, pg_subscription_subname_index, 4);
+
 typedef struct Subscription
 {
 	Oid			oid;			/* Oid of the subscription */
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index fbedb0fedbf..f4e372e565e 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -51,6 +51,8 @@ typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_subscription_rel_srrelid_srsubid_index, 6117, SubscriptionRelSrrelidSrsubidIndexId, pg_subscription_rel, btree(srrelid oid_ops, srsubid oid_ops));
 
+MAKE_SYSCACHE(SUBSCRIPTIONRELMAP, pg_subscription_rel_srrelid_srsubid_index,  64);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /* ----------------
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index db3edd7eb20..6b9bdcf8b05 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -52,4 +52,6 @@ DECLARE_TOAST_WITH_MACRO(pg_tablespace, 4185, 4186, PgTablespaceToastTable, PgTa
 DECLARE_UNIQUE_INDEX_PKEY(pg_tablespace_oid_index, 2697, TablespaceOidIndexId, pg_tablespace, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, pg_tablespace, btree(spcname name_ops));
 
+MAKE_SYSCACHE(TABLESPACEOID, pg_tablespace_oid_index, 4);
+
 #endif							/* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index 33cc8c74c01..3b69960af60 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -45,4 +45,7 @@ typedef FormData_pg_transform *Form_pg_transform;
 DECLARE_UNIQUE_INDEX_PKEY(pg_transform_oid_index, 3574, TransformOidIndexId, pg_transform, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, TransformTypeLangIndexId, pg_transform, btree(trftype oid_ops, trflang oid_ops));
 
+MAKE_SYSCACHE(TRFOID, pg_transform_oid_index, 16);
+MAKE_SYSCACHE(TRFTYPELANG, pg_transform_type_lang_index, 16);
+
 #endif							/* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index 8fdf9ee27b1..fc0bf447b1d 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -50,4 +50,7 @@ typedef FormData_pg_ts_config *Form_pg_ts_config;
 DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, TSConfigNameNspIndexId, pg_ts_config, btree(cfgname name_ops, cfgnamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_oid_index, 3712, TSConfigOidIndexId, pg_ts_config, btree(oid oid_ops));
 
+MAKE_SYSCACHE(TSCONFIGNAMENSP, pg_ts_config_cfgname_index, 2);
+MAKE_SYSCACHE(TSCONFIGOID, pg_ts_config_oid_index, 2);
+
 #endif							/* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index fa5813a32d5..efced44941d 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -46,4 +46,6 @@ typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
 
 DECLARE_UNIQUE_INDEX_PKEY(pg_ts_config_map_index, 3609, TSConfigMapIndexId, pg_ts_config_map, btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
 
+MAKE_SYSCACHE(TSCONFIGMAP, pg_ts_config_map_index, 2);
+
 #endif							/* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 69b22021c56..1320468de0e 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -56,4 +56,7 @@ DECLARE_TOAST(pg_ts_dict, 4169, 4170);
 DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, TSDictionaryNameNspIndexId, pg_ts_dict, btree(dictname name_ops, dictnamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_ts_dict_oid_index, 3605, TSDictionaryOidIndexId, pg_ts_dict, btree(oid oid_ops));
 
+MAKE_SYSCACHE(TSDICTNAMENSP, pg_ts_dict_dictname_index, 2);
+MAKE_SYSCACHE(TSDICTOID, pg_ts_dict_oid_index, 2);
+
 #endif							/* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index f77fad4b329..909644c96f2 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -57,4 +57,7 @@ typedef FormData_pg_ts_parser *Form_pg_ts_parser;
 DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, TSParserNameNspIndexId, pg_ts_parser, btree(prsname name_ops, prsnamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_ts_parser_oid_index, 3607, TSParserOidIndexId, pg_ts_parser, btree(oid oid_ops));
 
+MAKE_SYSCACHE(TSPARSERNAMENSP, pg_ts_parser_prsname_index, 2);
+MAKE_SYSCACHE(TSPARSEROID, pg_ts_parser_oid_index, 2);
+
 #endif							/* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index edb9fac5d01..0562a4a7583 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -48,4 +48,7 @@ typedef FormData_pg_ts_template *Form_pg_ts_template;
 DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, TSTemplateNameNspIndexId, pg_ts_template, btree(tmplname name_ops, tmplnamespace oid_ops));
 DECLARE_UNIQUE_INDEX_PKEY(pg_ts_template_oid_index, 3767, TSTemplateOidIndexId, pg_ts_template, btree(oid oid_ops));
 
+MAKE_SYSCACHE(TSTEMPLATENAMENSP, pg_ts_template_tmplname_index, 2);
+MAKE_SYSCACHE(TSTEMPLATEOID, pg_ts_template_oid_index, 2);
+
 #endif							/* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index d28490e4806..e9259697321 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -265,6 +265,9 @@ DECLARE_TOAST(pg_type, 4171, 4172);
 DECLARE_UNIQUE_INDEX_PKEY(pg_type_oid_index, 2703, TypeOidIndexId, pg_type, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, TypeNameNspIndexId, pg_type, btree(typname name_ops, typnamespace oid_ops));
 
+MAKE_SYSCACHE(TYPEOID, pg_type_oid_index, 64);
+MAKE_SYSCACHE(TYPENAMENSP, pg_type_typname_nsp_index, 64);
+
 #ifdef EXPOSE_TO_CLIENT_CODE
 
 /*
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index 7ad846edd28..3632448cce0 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -52,4 +52,7 @@ DECLARE_TOAST(pg_user_mapping, 4173, 4174);
 DECLARE_UNIQUE_INDEX_PKEY(pg_user_mapping_oid_index, 174, UserMappingOidIndexId, pg_user_mapping, btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, UserMappingUserServerIndexId, pg_user_mapping, btree(umuser oid_ops, umserver oid_ops));
 
+MAKE_SYSCACHE(USERMAPPINGOID, pg_user_mapping_oid_index, 2);
+MAKE_SYSCACHE(USERMAPPINGUSERSERVER, pg_user_mapping_user_server_index, 2);
+
 #endif							/* PG_USER_MAPPING_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 3fb3314b6ca..03a27dd0a83 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -20,103 +20,7 @@
 #include "access/htup.h"
 /* we intentionally do not include utils/catcache.h here */
 
-/*
- *		SysCache identifiers.
- *
- *		The order of these identifiers must match the order
- *		of the entries in the array cacheinfo[] in syscache.c.
- *		Keep them in alphabetical order (renumbering only costs a
- *		backend rebuild).
- */
-
-enum SysCacheIdentifier
-{
-	AGGFNOID = 0,
-	AMNAME,
-	AMOID,
-	AMOPOPID,
-	AMOPSTRATEGY,
-	AMPROCNUM,
-	ATTNAME,
-	ATTNUM,
-	AUTHMEMMEMROLE,
-	AUTHMEMROLEMEM,
-	AUTHNAME,
-	AUTHOID,
-	CASTSOURCETARGET,
-	CLAAMNAMENSP,
-	CLAOID,
-	COLLNAMEENCNSP,
-	COLLOID,
-	CONDEFAULT,
-	CONNAMENSP,
-	CONSTROID,
-	CONVOID,
-	DATABASEOID,
-	DEFACLROLENSPOBJ,
-	ENUMOID,
-	ENUMTYPOIDNAME,
-	EVENTTRIGGERNAME,
-	EVENTTRIGGEROID,
-	FOREIGNDATAWRAPPERNAME,
-	FOREIGNDATAWRAPPEROID,
-	FOREIGNSERVERNAME,
-	FOREIGNSERVEROID,
-	FOREIGNTABLEREL,
-	INDEXRELID,
-	LANGNAME,
-	LANGOID,
-	NAMESPACENAME,
-	NAMESPACEOID,
-	OPERNAMENSP,
-	OPEROID,
-	OPFAMILYAMNAMENSP,
-	OPFAMILYOID,
-	PARAMETERACLNAME,
-	PARAMETERACLOID,
-	PARTRELID,
-	PROCNAMEARGSNSP,
-	PROCOID,
-	PUBLICATIONNAME,
-	PUBLICATIONNAMESPACE,
-	PUBLICATIONNAMESPACEMAP,
-	PUBLICATIONOID,
-	PUBLICATIONREL,
-	PUBLICATIONRELMAP,
-	RANGEMULTIRANGE,
-	RANGETYPE,
-	RELNAMENSP,
-	RELOID,
-	REPLORIGIDENT,
-	REPLORIGNAME,
-	RULERELNAME,
-	SEQRELID,
-	STATEXTDATASTXOID,
-	STATEXTNAMENSP,
-	STATEXTOID,
-	STATRELATTINH,
-	SUBSCRIPTIONNAME,
-	SUBSCRIPTIONOID,
-	SUBSCRIPTIONRELMAP,
-	TABLESPACEOID,
-	TRFOID,
-	TRFTYPELANG,
-	TSCONFIGMAP,
-	TSCONFIGNAMENSP,
-	TSCONFIGOID,
-	TSDICTNAMENSP,
-	TSDICTOID,
-	TSPARSERNAMENSP,
-	TSPARSEROID,
-	TSTEMPLATENAMENSP,
-	TSTEMPLATEOID,
-	TYPENAMENSP,
-	TYPEOID,
-	USERMAPPINGOID,
-	USERMAPPINGUSERSERVER,
-
-#define SysCacheSize (USERMAPPINGUSERSERVER + 1)
-};
+#include "catalog/syscache_ids.h"
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 215473d22c9..7edfc44b49a 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_ids.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_ids.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index a3eea5d3c87..84b892b5c51 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,11 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/syscache_ids.h && continue
+	test "$f" = src/backend/catalog/syscache_info.h && continue
+	test "$f" = src/include/catalog/syscache_ids.h && continue
+	test "$f" = src/include/catalog/syscache_info.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.

base-commit: 44ad5129ce19d22afe757a6b56e41eaa91304869
-- 
2.43.0

v5-0002-WIP-Generate-ObjectProperty-from-catalog-files.patchtext/plain; charset=UTF-8; name=v5-0002-WIP-Generate-ObjectProperty-from-catalog-files.patchDownload
From 3c698856dc4753d75d7ca552351881bf84582da6 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 17 Jan 2024 13:08:41 +0100
Subject: [PATCH v5 2/2] WIP: Generate ObjectProperty from catalog files

Most of the information can be extracted from catalog files and
generated automatically.

TODO: Currently missing: object type and class description.  There are
some workarounds in place.

We also now replace the linear search with a hash function generated
using PerfectHash.  This would allow this lookup table to be used in
more performance-sensitive situations.

Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
 src/backend/catalog/.gitignore      |   1 +
 src/backend/catalog/Makefile        |   2 +-
 src/backend/catalog/genbki.pl       | 169 ++++++++++++++++++++++++++++
 src/backend/catalog/objectaddress.c |  22 ++--
 src/include/catalog/meson.build     |   2 +
 src/tools/pginclude/cpluspluscheck  |   3 +
 src/tools/pginclude/headerscheck    |   3 +
 7 files changed, 190 insertions(+), 12 deletions(-)

diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index b580f734c71..74bfc848f62 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,3 +1,4 @@
+/objectproperty_info.h
 /postgres.bki
 /schemapg.h
 /syscache_ids.h
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 352ba6d3e2e..0f03552e020 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -120,7 +120,7 @@ CATALOG_HEADERS := \
 	pg_subscription.h \
 	pg_subscription_rel.h
 
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_ids.h syscache_info.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) objectproperty_info.h schemapg.h syscache_ids.h syscache_info.h system_fk_info.h
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
 
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 677a12acf3e..756aed3ad4d 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -19,8 +19,10 @@
 
 use FindBin;
 use lib $FindBin::RealBin;
+use lib "$FindBin::RealBin/../../tools";
 
 use Catalog;
+use PerfectHash;
 
 my $output_path = '';
 my $major_version;
@@ -60,6 +62,7 @@
 my %syscache_catalogs;
 my %oidcounts;
 my @system_constraints;
+my @object_properties;
 
 foreach my $header (@ARGV)
 {
@@ -137,6 +140,7 @@
 		$oidcounts{ $toast->{toast_oid} }++;
 		$oidcounts{ $toast->{toast_index_oid} }++;
 	}
+	my ($oid_index, $oid_syscache, $name_index, $name_syscache, $is_nsp_name_unique);
 	foreach my $index (@{ $catalog->{indexing} })
 	{
 		$indexes{$index->{index_name}} = $index;
@@ -157,6 +161,16 @@
 			  $index->{is_pkey} ? "PRIMARY KEY" : "UNIQUE",
 			  $index->{index_name};
 		}
+
+		if ($index->{index_decl} eq 'btree(oid oid_ops)')
+		{
+			$oid_index = $index;
+		}
+		if ($index->{index_decl} =~ /\(\w+name name_ops(, \w+namespace oid_ops)?\)/)
+		{
+			$name_index = $index;
+			$is_nsp_name_unique = 1 if $index->{is_unique};
+		}
 	}
 
 	# Analyze syscache info
@@ -177,7 +191,128 @@
 		};
 
 		$syscache_catalogs{$catname} = 1;
+
+		$oid_syscache = $syscache->{syscache_name} if $oid_index && $syscache->{index_name} eq $oid_index->{index_name};
+		$name_syscache = $syscache->{syscache_name} if $name_index && $syscache->{index_name} eq $name_index->{index_name};
 	}
+
+	my ($attnum_oid, $attnum_name, $attnum_namespace, $attnum_owner, $attnum_acl);
+	foreach my $att (@$schema)
+	{
+		if ($att->{name} eq 'oid' && $att->{type} eq 'oid')
+		{
+			$attnum_oid = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}name$/ && $att->{type} eq 'name')
+		{
+			$attnum_name = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}namespace$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_namespace')
+		{
+			$attnum_namespace = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}owner$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_authid')
+		{
+			$attnum_owner = "Anum_${catname}_" . $att->{name};
+		}
+		elsif ($att->{name} =~ /^\w{2,4}acl$/ && $att->{type} eq '_aclitem')
+		{
+			$attnum_acl = "Anum_${catname}_" . $att->{name};
+		}
+	}
+
+	# XXX hardcoded exceptions
+	# extension doesn't belong to extnamespace
+	$attnum_namespace = undef if $catname eq 'pg_extension';
+	# pg_database owner is spelled datdba
+	$attnum_owner = "Anum_pg_database_datdba" if $catname eq 'pg_database';
+	# XXX?
+	$name_syscache = "SUBSCRIPTIONNAME" if $catname eq 'pg_subscription';
+	# XXX?
+	$is_nsp_name_unique = 1 if $catname eq 'pg_collation';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_opclass';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_opfamily';
+	$is_nsp_name_unique = 1 if $catname eq 'pg_subscription';
+
+	# XXX These catalogs were not covered by the previous hand-maintained table.
+	my @skip = qw(
+		AttrDefaultRelationId EnumRelationId IndexRelationId
+		LargeObjectRelationId ParameterAclRelationId
+		PublicationNamespaceRelationId PublicationRelRelationId
+		InheritsRelationId AggregateRelationId StatisticRelationId
+		StatisticExtDataRelationId DescriptionRelationId
+		DependRelationId DbRoleSettingRelationId
+		SharedDependRelationId SharedDescriptionRelationId
+		TSConfigMapRelationId ForeignTableRelationId
+		ReplicationOriginRelationId InitPrivsRelationId
+		SecLabelRelationId SharedSecLabelRelationId
+		PartitionedRelationId RangeRelationId SequenceRelationId
+		SubscriptionRelRelationId);
+	# XXX This one neither, but if I add it to @skip, PerfectHash will fail. (???)
+	#FIXME: AttributeRelationId
+
+	# XXX hardcoded ObjectType mapping -- where to put this?
+	my %objtypes = (
+		'AccessMethodRelationId' => 'OBJECT_ACCESS_METHOD',
+		'AccessMethodOperatorRelationId' => 'OBJECT_AMOP',
+		'AccessMethodProcedureRelationId' => 'OBJECT_AMPROC',
+		'CastRelationId' => 'OBJECT_CAST',
+		'CollationRelationId' => 'OBJECT_COLLATION',
+		'ConversionRelationId' => 'OBJECT_CONVERSION',
+		'DatabaseRelationId' => 'OBJECT_DATABASE',
+		'DefaultAclRelationId' => 'OBJECT_DEFACL',
+		'ExtensionRelationId' => 'OBJECT_EXTENSION',
+		'ForeignDataWrapperRelationId' => 'OBJECT_FDW',
+		'ForeignServerRelationId' => 'OBJECT_FOREIGN_SERVER',
+		'ProcedureRelationId' => 'OBJECT_FUNCTION',
+		'LanguageRelationId' => 'OBJECT_LANGUAGE',
+		'LargeObjectMetadataRelationId' => 'OBJECT_LARGEOBJECT',
+		'OperatorClassRelationId' => 'OBJECT_OPCLASS',
+		'OperatorRelationId' => 'OBJECT_OPERATOR',
+		'OperatorFamilyRelationId' => 'OBJECT_OPFAMILY',
+		'AuthIdRelationId' => 'OBJECT_ROLE',
+		'RewriteRelationId' => 'OBJECT_RULE',
+		'NamespaceRelationId' => 'OBJECT_SCHEMA',
+		'RelationRelationId' => 'OBJECT_TABLE',
+		'TableSpaceRelationId' => 'OBJECT_TABLESPACE',
+		'TransformRelationId' => 'OBJECT_TRANSFORM',
+		'TriggerRelationId' => 'OBJECT_TRIGGER',
+		'PolicyRelationId' => 'OBJECT_POLICY',
+		'EventTriggerRelationId' => 'OBJECT_EVENT_TRIGGER',
+		'TSConfigRelationId' => 'OBJECT_TSCONFIGURATION',
+		'TSDictionaryRelationId' => 'OBJECT_TSDICTIONARY',
+		'TSParserRelationId' => 'OBJECT_TSPARSER',
+		'TSTemplateRelationId' => 'OBJECT_TSTEMPLATE',
+		'TypeRelationId' => 'OBJECT_TYPE',
+		'PublicationRelationId' => 'OBJECT_PUBLICATION',
+		'SubscriptionRelationId' => 'OBJECT_SUBSCRIPTION',
+		'StatisticExtRelationId' => 'OBJECT_STATISTIC_EXT',
+		'UserMappingRelationId' => 'OBJECT_USER_MAPPING',
+	);
+	my $objtype = $objtypes{$catalog->{relation_oid_macro}};
+
+	# XXX This just uses the catalog name as a string rather than the
+	# previous natural-language description.  This could be changed if
+	# we decide on a place to store this.  But maybe for what we are
+	# using it, this is actually better.
+	my $class_descr = qq{"${catname}"};
+
+	push @object_properties, {
+		class_descr => $class_descr,
+		class_oid => $catalog->{relation_oid_macro},
+		_class_oid => $catalog->{relation_oid},
+		oid_index_oid => $oid_index->{index_oid_macro},
+		oid_catcache_id => $oid_syscache || '-1',
+		name_catcache_id => $name_syscache || '-1',
+		attnum_oid => $attnum_oid,
+		attnum_name => $attnum_name,
+		attnum_namespace => $attnum_namespace,
+		attnum_owner => $attnum_owner,
+		attnum_acl => $attnum_acl,
+		objtype => $objtype,
+		is_nsp_name_unique => $is_nsp_name_unique ? 'true' : 'false',
+	}
+	unless grep { $_ eq $catalog->{relation_oid_macro} } @skip;
 }
 
 # Complain and exit if we found any duplicate OIDs.
@@ -452,6 +587,9 @@
 my $syscache_info_file = $output_path . 'syscache_info.h';
 open my $syscache_info_fh, '>', $syscache_info_file . $tmpext
   or die "can't open $syscache_info_file$tmpext: $!";
+my $objectproperty_info_file = $output_path . 'objectproperty_info.h';
+open my $objectproperty_info_fh, '>', $objectproperty_info_file . $tmpext
+  or die "can't open $objectproperty_info_file$tmpext: $!";
 
 # Generate postgres.bki and pg_*_d.h headers.
 
@@ -821,6 +959,35 @@
 
 print $syscache_info_fh "};\n";
 
+# Now generate objectproperty_info
+
+print_boilerplate($objectproperty_info_fh, "objectproperty_info.h", "object property data");
+print $objectproperty_info_fh "\n";
+foreach my $catname (@catnames)
+{
+	print $objectproperty_info_fh qq{#include "catalog/${catname}_d.h"\n};
+}
+print $objectproperty_info_fh "\n";
+print $objectproperty_info_fh "static const ObjectPropertyType ObjectProperty[] =
+{
+";
+
+my @class_oids;
+foreach my $op (@object_properties)
+{
+	print $objectproperty_info_fh "\t{\n";
+	foreach my $p (sort keys %{$op})
+	{
+		printf $objectproperty_info_fh "\t\t.%s = %s,\n", $p, ${$op}{$p} if $p !~ /^_/ && ${$op}{$p};
+	}
+	push @class_oids, pack('N', ${$op}{_class_oid});
+	print $objectproperty_info_fh "\t},\n";
+}
+
+print $objectproperty_info_fh "};\n";
+
+print $objectproperty_info_fh "\nstatic " . PerfectHash::generate_hash_function(\@class_oids, 'objectproperty_hash_func', fixed_key_length => 4);
+
 # We're done emitting data
 close $bki;
 close $schemapg;
@@ -828,6 +995,7 @@
 close $constraints;
 close $syscache_ids_fh;
 close $syscache_info_fh;
+close $objectproperty_info_fh;
 
 # Finally, rename the completed files into place.
 Catalog::RenameTempFile($bkifile, $tmpext);
@@ -836,6 +1004,7 @@
 Catalog::RenameTempFile($constraints_file, $tmpext);
 Catalog::RenameTempFile($syscache_ids_file, $tmpext);
 Catalog::RenameTempFile($syscache_info_file, $tmpext);
+Catalog::RenameTempFile($objectproperty_info_file, $tmpext);
 
 exit($num_errors != 0 ? 1 : 0);
 
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 8bb2924b9cd..1606cea7bbc 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -32,19 +32,10 @@
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_conversion.h"
-#include "catalog/pg_database.h"
 #include "catalog/pg_default_acl.h"
-#include "catalog/pg_enum.h"
-#include "catalog/pg_event_trigger.h"
-#include "catalog/pg_extension.h"
-#include "catalog/pg_foreign_data_wrapper.h"
-#include "catalog/pg_foreign_server.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_largeobject.h"
-#include "catalog/pg_largeobject_metadata.h"
-#include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_parameter_acl.h"
 #include "catalog/pg_policy.h"
@@ -54,8 +45,6 @@
 #include "catalog/pg_publication_rel.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_statistic_ext.h"
-#include "catalog/pg_subscription.h"
-#include "catalog/pg_tablespace.h"
 #include "catalog/pg_transform.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_ts_config.h"
@@ -119,6 +108,9 @@ typedef struct
 									 * object of this class? */
 } ObjectPropertyType;
 
+#if 1
+#include "catalog/objectproperty_info.h"
+#else
 static const ObjectPropertyType ObjectProperty[] =
 {
 	{
@@ -640,6 +632,7 @@ static const ObjectPropertyType ObjectProperty[] =
 		false
 	},
 };
+#endif
 
 /*
  * This struct maps the string object types as returned by
@@ -2791,6 +2784,7 @@ get_object_property_data(Oid class_id)
 {
 	static const ObjectPropertyType *prop_last = NULL;
 	int			index;
+	uint32      hashkey;
 
 	/*
 	 * A shortcut to speed up multiple consecutive lookups of a particular
@@ -2799,7 +2793,13 @@ get_object_property_data(Oid class_id)
 	if (prop_last && prop_last->class_oid == class_id)
 		return prop_last;
 
+#if 1
+	hashkey = pg_hton32(class_id);
+	index = objectproperty_hash_func(&hashkey);
+	if (index >= 0 && index < lengthof(ObjectProperty))
+#else
 	for (index = 0; index < lengthof(ObjectProperty); index++)
+#endif
 	{
 		if (ObjectProperty[index].class_oid == class_id)
 		{
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index 6be76dca1dd..4c8d2b7402e 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -103,6 +103,7 @@ bki_data_f = files(bki_data)
 
 input = []
 output_files = [
+  'objectproperty_info.h',
   'postgres.bki',
   'system_constraints.sql',
   'schemapg.h',
@@ -111,6 +112,7 @@ output_files = [
   'system_fk_info.h',
 ]
 output_install = [
+  dir_data,
   dir_data,
   dir_data,
   dir_include_server / 'catalog',
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 7edfc44b49a..6a90a79ab67 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.h && continue
+
 	test "$f" = src/backend/catalog/syscache_ids.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_ids.h && continue
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 84b892b5c51..2df66965f41 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,9 @@ do
 	test "$f" = src/include/common/unicode_nonspacing_table.h && continue
 	test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
 
+	test "$f" = src/backend/catalog/objectproperty_info.h && continue
+	test "$f" = src/include/catalog/objectproperty_info.h && continue
+
 	test "$f" = src/backend/catalog/syscache_ids.h && continue
 	test "$f" = src/backend/catalog/syscache_info.h && continue
 	test "$f" = src/include/catalog/syscache_ids.h && continue
-- 
2.43.0

#14John Naylor
johncnaylorls@gmail.com
In reply to: Peter Eisentraut (#13)
Re: generate syscache info automatically

On Wed, Jan 17, 2024 at 7:46 PM Peter Eisentraut <peter@eisentraut.org> wrote:

I updated the patch to use this style (but I swapped the first two
arguments from my example, so that the thing being created is named first).

I also changed the names of the output files a bit to make them less
confusing. (I initially had some files named .c.h, which was weird, but
apparently necessary to avoid confusing the build system. But it's all
clearer now.)

Other than bugs and perhaps style opinions, I think the first patch is
pretty good now.

LGTM. The only style consideration that occurred to me just now was
MAKE_SYSCACHE, since it doesn't match the DECLARE_... macros. It seems
like the same thing from a code generation perspective. The other
macros refer to relations, so there is a difference, but maybe it
doesn't matter. I don't have a strong opinion.

#15Peter Eisentraut
peter@eisentraut.org
In reply to: John Naylor (#14)
Re: generate syscache info automatically

On 19.01.24 06:28, John Naylor wrote:

On Wed, Jan 17, 2024 at 7:46 PM Peter Eisentraut <peter@eisentraut.org> wrote:

I updated the patch to use this style (but I swapped the first two
arguments from my example, so that the thing being created is named first).

I also changed the names of the output files a bit to make them less
confusing. (I initially had some files named .c.h, which was weird, but
apparently necessary to avoid confusing the build system. But it's all
clearer now.)

Other than bugs and perhaps style opinions, I think the first patch is
pretty good now.

LGTM. The only style consideration that occurred to me just now was
MAKE_SYSCACHE, since it doesn't match the DECLARE_... macros. It seems
like the same thing from a code generation perspective. The other
macros refer to relations, so there is a difference, but maybe it
doesn't matter. I don't have a strong opinion.

The DECLARE_* macros map to actual BKI commands ("declare toast",
"declare index"). So I wanted to use a different verb to distinguish
"generate code for this" from those BKI commands.

#16John Naylor
johncnaylorls@gmail.com
In reply to: Peter Eisentraut (#15)
Re: generate syscache info automatically

On Fri, Jan 19, 2024 at 9:03 PM Peter Eisentraut <peter@eisentraut.org> wrote:

The DECLARE_* macros map to actual BKI commands ("declare toast",
"declare index"). So I wanted to use a different verb to distinguish
"generate code for this" from those BKI commands.

That makes sense to me.

#17Peter Eisentraut
peter@eisentraut.org
In reply to: John Naylor (#16)
Re: generate syscache info automatically

On 22.01.24 01:33, John Naylor wrote:

On Fri, Jan 19, 2024 at 9:03 PM Peter Eisentraut <peter@eisentraut.org> wrote:

The DECLARE_* macros map to actual BKI commands ("declare toast",
"declare index"). So I wanted to use a different verb to distinguish
"generate code for this" from those BKI commands.

That makes sense to me.

I have committed the first patch, and the buildfarm hiccup seems to have
passed.

I'll close this commitfest entry now. I have enough feedback to work on
the ObjectProperty generation, but I'll make a new entry for that.