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.
From f77c381b9df30824e469f72f4e7754d03cb97d78 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@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-73247ed41...@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

From 3c698856dc4753d75d7ca552351881bf84582da6 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@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-73247ed41...@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

Reply via email to