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

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

Attached is an updated patch set.

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

[0]: https://www.postgresql.org/message-id/flat/12f1b1d2-f8cf-c4a2-72ec-441bd7954...@enterprisedb.com

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

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

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


On 24.08.23 16:03, Peter Eisentraut wrote:
On 03.07.23 07:45, Peter Eisentraut wrote:
Here is an updated patch set that adjusts for the recently introduced named captures.  I will address the other issues later.  I think the first few patches in the series can be considered nonetheless.

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

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

The remaining patches are still WIP.


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

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

#define DECLARE_SYSCACHE(cacheid,indexname,numbuckets) cacheid

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

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

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

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

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

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

[1] https://www.postgresql.org/message-id/12460.1570734...@sss.pgh.pa.us <https://www.postgresql.org/message-id/12460.1570734...@sss.pgh.pa.us> [2] https://www.postgresql.org/message-id/20210831205906.4wk3s4lvgzkdaqpi%40alap3.anarazel.de <https://www.postgresql.org/message-id/20210831205906.4wk3s4lvgzkdaqpi%40alap3.anarazel.de>

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



From 399b6add1e775083317b60f51dfd7e6c41209421 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v3 1/3] Fill in more of ObjectProperty

Fill in .objtype field where an appropriate value exists.

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

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

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

From dd888bd6f70ee0a25fa8c3f8e905f98a5b73cf2d Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 3 Jul 2023 07:39:25 +0200
Subject: [PATCH v3 2/3] Generate syscache info from catalog files

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

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

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

From a17faafd7c55f446bd3eb99e3451e23f74a06873 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Thu, 31 Aug 2023 09:51:28 +0200
Subject: [PATCH v3 3/3] Generate ObjectProperty from catalog files

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

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

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

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

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

Reply via email to