]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/cache/syscache.c
Post-PG 10 beta1 pgindent run
[postgresql] / src / backend / utils / cache / syscache.c
index 75f290dda614f7a2e6e889de491734c8bf50fd77..922718c9d17378d4fb230c775a5c7bf1c86e27c4 100644 (file)
@@ -3,43 +3,78 @@
  * syscache.c
  *       System cache management routines
  *
- * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.111 2007/02/14 01:58:57 tgl Exp $
+ *       src/backend/utils/cache/syscache.c
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
  *       rapid lookups on the contents of the system catalogs.
  *
- *       see catalog/syscache.h for a list of the cache id's
+ *       see utils/syscache.h for a list of the cache IDs
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
-#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
 #include "catalog/indexing.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_partitioned_table.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_publication.h"
+#include "catalog/pg_publication_rel.h"
+#include "catalog/pg_range.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_replication_origin.h"
 #include "catalog/pg_statistic.h"
+#include "catalog/pg_statistic_ext.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 "utils/rel.h"
+#include "utils/catcache.h"
 #include "utils/syscache.h"
 
 
 
        Adding system caches:
 
-       Add your new cache to the list in include/utils/syscache.h.  Keep
-       the list sorted alphabetically and adjust the cache numbers
-       accordingly.
+       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 number of hash
-       buckets.  If the relation contains tuples that are associated with a
-       particular relation (for example, its attributes, rules, triggers, etc)
-       then specify the attribute number that contains the OID of the associated
-       relation.  This is used by CatalogCacheFlushRelation() to remove the
-       correct tuples during a table drop or relcache invalidation event.
+       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
        adding/deleting caches only requires a recompile.)
 
        Finally, any place your relation gets heap_insert() or
-       heap_update() calls, make sure there is a CatalogUpdateIndexes() or
-       similar call.  The heap_* calls do not update indexes.
-
-       bjm 1999/11/22
+       heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
+       instead, which also update indexes.  The heap_* calls do not do that.
 
 *---------------------------------------------------------------------------
 */
@@ -87,7 +115,6 @@ struct cachedesc
 {
        Oid                     reloid;                 /* OID of the relation being cached */
        Oid                     indoid;                 /* OID of index relation for this cache */
-       int                     reloidattr;             /* attr number of rel OID reference, or 0 */
        int                     nkeys;                  /* # of keys needed for cache lookup */
        int                     key[4];                 /* attribute numbers of key attrs */
        int                     nbuckets;               /* number of hash buckets for this cache */
@@ -96,7 +123,6 @@ struct cachedesc
 static const struct cachedesc cacheinfo[] = {
        {AggregateRelationId,           /* AGGFNOID */
                AggregateFnoidIndexId,
-               0,
                1,
                {
                        Anum_pg_aggregate_aggfnoid,
@@ -104,11 +130,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               32
+               16
        },
        {AccessMethodRelationId,        /* AMNAME */
                AmNameIndexId,
-               0,
                1,
                {
                        Anum_pg_am_amname,
@@ -120,7 +145,6 @@ static const struct cachedesc cacheinfo[] = {
        },
        {AccessMethodRelationId,        /* AMOID */
                AmOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -132,19 +156,17 @@ static const struct cachedesc cacheinfo[] = {
        },
        {AccessMethodOperatorRelationId,        /* AMOPOPID */
                AccessMethodOperatorIndexId,
-               0,
-               2,
+               3,
                {
                        Anum_pg_amop_amopopr,
+                       Anum_pg_amop_amoppurpose,
                        Anum_pg_amop_amopfamily,
-                       0,
                        0
                },
                64
        },
        {AccessMethodOperatorRelationId,        /* AMOPSTRATEGY */
                AccessMethodStrategyIndexId,
-               0,
                4,
                {
                        Anum_pg_amop_amopfamily,
@@ -156,7 +178,6 @@ static const struct cachedesc cacheinfo[] = {
        },
        {AccessMethodProcedureRelationId,       /* AMPROCNUM */
                AccessMethodProcedureIndexId,
-               0,
                4,
                {
                        Anum_pg_amproc_amprocfamily,
@@ -164,11 +185,10 @@ static const struct cachedesc cacheinfo[] = {
                        Anum_pg_amproc_amprocrighttype,
                        Anum_pg_amproc_amprocnum
                },
-               64
+               16
        },
        {AttributeRelationId,           /* ATTNAME */
                AttributeRelidNameIndexId,
-               Anum_pg_attribute_attrelid,
                2,
                {
                        Anum_pg_attribute_attrelid,
@@ -176,11 +196,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               2048
+               32
        },
        {AttributeRelationId,           /* ATTNUM */
                AttributeRelidNumIndexId,
-               Anum_pg_attribute_attrelid,
                2,
                {
                        Anum_pg_attribute_attrelid,
@@ -188,11 +207,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               2048
+               128
        },
        {AuthMemRelationId,                     /* AUTHMEMMEMROLE */
                AuthMemMemRoleIndexId,
-               0,
                2,
                {
                        Anum_pg_auth_members_member,
@@ -200,11 +218,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               128
+               8
        },
        {AuthMemRelationId,                     /* AUTHMEMROLEMEM */
                AuthMemRoleMemIndexId,
-               0,
                2,
                {
                        Anum_pg_auth_members_roleid,
@@ -212,11 +229,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               128
+               8
        },
        {AuthIdRelationId,                      /* AUTHNAME */
                AuthIdRolnameIndexId,
-               0,
                1,
                {
                        Anum_pg_authid_rolname,
@@ -224,11 +240,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               128
+               8
        },
        {AuthIdRelationId,                      /* AUTHOID */
                AuthIdOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -236,12 +251,11 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               128
+               8
        },
        {
                CastRelationId,                 /* CASTSOURCETARGET */
                CastSourceTargetIndexId,
-               0,
                2,
                {
                        Anum_pg_cast_castsource,
@@ -253,7 +267,6 @@ static const struct cachedesc cacheinfo[] = {
        },
        {OperatorClassRelationId,       /* CLAAMNAMENSP */
                OpclassAmNameNspIndexId,
-               0,
                3,
                {
                        Anum_pg_opclass_opcmethod,
@@ -261,11 +274,10 @@ static const struct cachedesc cacheinfo[] = {
                        Anum_pg_opclass_opcnamespace,
                        0
                },
-               64
+               8
        },
        {OperatorClassRelationId,       /* CLAOID */
                OpclassOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -273,11 +285,32 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               64
+               8
+       },
+       {CollationRelationId,           /* COLLNAMEENCNSP */
+               CollationNameEncNspIndexId,
+               3,
+               {
+                       Anum_pg_collation_collname,
+                       Anum_pg_collation_collencoding,
+                       Anum_pg_collation_collnamespace,
+                       0
+               },
+               8
+       },
+       {CollationRelationId,           /* COLLOID */
+               CollationOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               8
        },
        {ConversionRelationId,          /* CONDEFAULT */
                ConversionDefaultIndexId,
-               0,
                4,
                {
                        Anum_pg_conversion_connamespace,
@@ -285,11 +318,10 @@ static const struct cachedesc cacheinfo[] = {
                        Anum_pg_conversion_contoencoding,
                        ObjectIdAttributeNumber,
                },
-               128
+               8
        },
        {ConversionRelationId,          /* CONNAMENSP */
                ConversionNameNspIndexId,
-               0,
                2,
                {
                        Anum_pg_conversion_conname,
@@ -297,11 +329,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               128
+               8
        },
        {ConstraintRelationId,          /* CONSTROID */
                ConstraintOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -309,11 +340,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               16
        },
        {ConversionRelationId,          /* CONVOID */
                ConversionOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -321,11 +351,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               128
+               8
        },
        {DatabaseRelationId,            /* DATABASEOID */
                DatabaseOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -335,9 +364,118 @@ static const struct cachedesc cacheinfo[] = {
                },
                4
        },
+       {DefaultAclRelationId,          /* DEFACLROLENSPOBJ */
+               DefaultAclRoleNspObjIndexId,
+               3,
+               {
+                       Anum_pg_default_acl_defaclrole,
+                       Anum_pg_default_acl_defaclnamespace,
+                       Anum_pg_default_acl_defaclobjtype,
+                       0
+               },
+               8
+       },
+       {EnumRelationId,                        /* ENUMOID */
+               EnumOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               8
+       },
+       {EnumRelationId,                        /* ENUMTYPOIDNAME */
+               EnumTypIdLabelIndexId,
+               2,
+               {
+                       Anum_pg_enum_enumtypid,
+                       Anum_pg_enum_enumlabel,
+                       0,
+                       0
+               },
+               8
+       },
+       {EventTriggerRelationId,        /* EVENTTRIGGERNAME */
+               EventTriggerNameIndexId,
+               1,
+               {
+                       Anum_pg_event_trigger_evtname,
+                       0,
+                       0,
+                       0
+               },
+               8
+       },
+       {EventTriggerRelationId,        /* EVENTTRIGGEROID */
+               EventTriggerOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               8
+       },
+       {ForeignDataWrapperRelationId,          /* FOREIGNDATAWRAPPERNAME */
+               ForeignDataWrapperNameIndexId,
+               1,
+               {
+                       Anum_pg_foreign_data_wrapper_fdwname,
+                       0,
+                       0,
+                       0
+               },
+               2
+       },
+       {ForeignDataWrapperRelationId,          /* FOREIGNDATAWRAPPEROID */
+               ForeignDataWrapperOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               2
+       },
+       {ForeignServerRelationId,       /* FOREIGNSERVERNAME */
+               ForeignServerNameIndexId,
+               1,
+               {
+                       Anum_pg_foreign_server_srvname,
+                       0,
+                       0,
+                       0
+               },
+               2
+       },
+       {ForeignServerRelationId,       /* FOREIGNSERVEROID */
+               ForeignServerOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               2
+       },
+       {ForeignTableRelationId,        /* FOREIGNTABLEREL */
+               ForeignTableRelidIndexId,
+               1,
+               {
+                       Anum_pg_foreign_table_ftrelid,
+                       0,
+                       0,
+                       0
+               },
+               4
+       },
        {IndexRelationId,                       /* INDEXRELID */
                IndexRelidIndexId,
-               Anum_pg_index_indrelid,
                1,
                {
                        Anum_pg_index_indexrelid,
@@ -345,11 +483,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               64
        },
        {LanguageRelationId,            /* LANGNAME */
                LanguageNameIndexId,
-               0,
                1,
                {
                        Anum_pg_language_lanname,
@@ -361,7 +498,6 @@ static const struct cachedesc cacheinfo[] = {
        },
        {LanguageRelationId,            /* LANGOID */
                LanguageOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -373,7 +509,6 @@ static const struct cachedesc cacheinfo[] = {
        },
        {NamespaceRelationId,           /* NAMESPACENAME */
                NamespaceNameIndexId,
-               0,
                1,
                {
                        Anum_pg_namespace_nspname,
@@ -381,11 +516,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               256
+               4
        },
        {NamespaceRelationId,           /* NAMESPACEOID */
                NamespaceOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -393,11 +527,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               256
+               16
        },
        {OperatorRelationId,            /* OPERNAMENSP */
                OperatorNameNspIndexId,
-               0,
                4,
                {
                        Anum_pg_operator_oprname,
@@ -405,11 +538,10 @@ static const struct cachedesc cacheinfo[] = {
                        Anum_pg_operator_oprright,
                        Anum_pg_operator_oprnamespace
                },
-               1024
+               256
        },
        {OperatorRelationId,            /* OPEROID */
                OperatorOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -417,11 +549,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               32
        },
        {OperatorFamilyRelationId,      /* OPFAMILYAMNAMENSP */
                OpfamilyAmNameNspIndexId,
-               0,
                3,
                {
                        Anum_pg_opfamily_opfmethod,
@@ -429,11 +560,10 @@ static const struct cachedesc cacheinfo[] = {
                        Anum_pg_opfamily_opfnamespace,
                        0
                },
-               64
+               8
        },
        {OperatorFamilyRelationId,      /* OPFAMILYOID */
                OpfamilyOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -441,11 +571,21 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               64
+               8
+       },
+       {PartitionedRelationId,         /* PARTRELID */
+               PartitionedRelidIndexId,
+               1,
+               {
+                       Anum_pg_partitioned_table_partrelid,
+                       0,
+                       0,
+                       0
+               },
+               32
        },
        {ProcedureRelationId,           /* PROCNAMEARGSNSP */
                ProcedureNameArgsNspIndexId,
-               0,
                3,
                {
                        Anum_pg_proc_proname,
@@ -453,11 +593,10 @@ static const struct cachedesc cacheinfo[] = {
                        Anum_pg_proc_pronamespace,
                        0
                },
-               2048
+               128
        },
        {ProcedureRelationId,           /* PROCOID */
                ProcedureOidIndexId,
-               0,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -465,11 +604,21 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               2048
+               128
+       },
+       {RangeRelationId,                       /* RANGETYPE */
+               RangeTypidIndexId,
+               1,
+               {
+                       Anum_pg_range_rngtypid,
+                       0,
+                       0,
+                       0
+               },
+               4
        },
        {RelationRelationId,            /* RELNAMENSP */
                ClassNameNspIndexId,
-               ObjectIdAttributeNumber,
                2,
                {
                        Anum_pg_class_relname,
@@ -477,11 +626,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               128
        },
        {RelationRelationId,            /* RELOID */
                ClassOidIndexId,
-               ObjectIdAttributeNumber,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -489,11 +637,76 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               128
+       },
+       {ReplicationOriginRelationId,           /* REPLORIGIDENT */
+               ReplicationOriginIdentIndex,
+               1,
+               {
+                       Anum_pg_replication_origin_roident,
+                       0,
+                       0,
+                       0
+               },
+               16
+       },
+       {ReplicationOriginRelationId,           /* REPLORIGNAME */
+               ReplicationOriginNameIndex,
+               1,
+               {
+                       Anum_pg_replication_origin_roname,
+                       0,
+                       0,
+                       0
+               },
+               16
+       },
+       {PublicationRelationId,         /* PUBLICATIONOID */
+               PublicationObjectIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               8
+       },
+       {PublicationRelationId,         /* PUBLICATIONNAME */
+               PublicationNameIndexId,
+               1,
+               {
+                       Anum_pg_publication_pubname,
+                       0,
+                       0,
+                       0
+               },
+               8
+       },
+       {PublicationRelRelationId,      /* PUBLICATIONREL */
+               PublicationRelObjectIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               64
+       },
+       {PublicationRelRelationId,      /* PUBLICATIONRELMAP */
+               PublicationRelPrrelidPrpubidIndexId,
+               2,
+               {
+                       Anum_pg_publication_rel_prrelid,
+                       Anum_pg_publication_rel_prpubid,
+                       0,
+                       0
+               },
+               64
        },
        {RewriteRelationId,                     /* RULERELNAME */
                RewriteRelRulenameIndexId,
-               Anum_pg_rewrite_ev_class,
                2,
                {
                        Anum_pg_rewrite_ev_class,
@@ -501,23 +714,219 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               8
        },
-       {StatisticRelationId,           /* STATRELATT */
-               StatisticRelidAttnumIndexId,
-               Anum_pg_statistic_starelid,
+       {SequenceRelationId,            /* SEQRELID */
+               SequenceRelidIndexId,
+               1,
+               {
+                       Anum_pg_sequence_seqrelid,
+                       0,
+                       0,
+                       0
+               },
+               32
+       },
+       {StatisticExtRelationId,        /* STATEXTNAMENSP */
+               StatisticExtNameIndexId,
                2,
+               {
+                       Anum_pg_statistic_ext_stxname,
+                       Anum_pg_statistic_ext_stxnamespace,
+                       0,
+                       0
+               },
+               4
+       },
+       {StatisticExtRelationId,        /* STATEXTOID */
+               StatisticExtOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               4
+       },
+       {StatisticRelationId,           /* STATRELATTINH */
+               StatisticRelidAttnumInhIndexId,
+               3,
                {
                        Anum_pg_statistic_starelid,
                        Anum_pg_statistic_staattnum,
+                       Anum_pg_statistic_stainherit,
+                       0
+               },
+               128
+       },
+       {SubscriptionRelationId,        /* SUBSCRIPTIONOID */
+               SubscriptionObjectIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               4
+       },
+       {SubscriptionRelationId,        /* SUBSCRIPTIONNAME */
+               SubscriptionNameIndexId,
+               2,
+               {
+                       Anum_pg_subscription_subdbid,
+                       Anum_pg_subscription_subname,
+                       0,
+                       0
+               },
+               4
+       },
+       {SubscriptionRelRelationId, /* SUBSCRIPTIONRELMAP */
+               SubscriptionRelSrrelidSrsubidIndexId,
+               2,
+               {
+                       Anum_pg_subscription_rel_srrelid,
+                       Anum_pg_subscription_rel_srsubid,
+                       0,
+                       0
+               },
+               64
+       },
+       {TableSpaceRelationId,          /* TABLESPACEOID */
+               TablespaceOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0,
+               },
+               4
+       },
+       {TransformRelationId,           /* TRFOID */
+               TransformOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0,
+               },
+               16
+       },
+       {TransformRelationId,           /* TRFTYPELANG */
+               TransformTypeLangIndexId,
+               2,
+               {
+                       Anum_pg_transform_trftype,
+                       Anum_pg_transform_trflang,
+                       0,
+                       0,
+               },
+               16
+       },
+       {TSConfigMapRelationId,         /* TSCONFIGMAP */
+               TSConfigMapIndexId,
+               3,
+               {
+                       Anum_pg_ts_config_map_mapcfg,
+                       Anum_pg_ts_config_map_maptokentype,
+                       Anum_pg_ts_config_map_mapseqno,
+                       0
+               },
+               2
+       },
+       {TSConfigRelationId,            /* TSCONFIGNAMENSP */
+               TSConfigNameNspIndexId,
+               2,
+               {
+                       Anum_pg_ts_config_cfgname,
+                       Anum_pg_ts_config_cfgnamespace,
+                       0,
+                       0
+               },
+               2
+       },
+       {TSConfigRelationId,            /* TSCONFIGOID */
+               TSConfigOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               2
+       },
+       {TSDictionaryRelationId,        /* TSDICTNAMENSP */
+               TSDictionaryNameNspIndexId,
+               2,
+               {
+                       Anum_pg_ts_dict_dictname,
+                       Anum_pg_ts_dict_dictnamespace,
+                       0,
+                       0
+               },
+               2
+       },
+       {TSDictionaryRelationId,        /* TSDICTOID */
+               TSDictionaryOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
                        0,
                        0
                },
-               1024
+               2
+       },
+       {TSParserRelationId,            /* TSPARSERNAMENSP */
+               TSParserNameNspIndexId,
+               2,
+               {
+                       Anum_pg_ts_parser_prsname,
+                       Anum_pg_ts_parser_prsnamespace,
+                       0,
+                       0
+               },
+               2
+       },
+       {TSParserRelationId,            /* TSPARSEROID */
+               TSParserOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               2
+       },
+       {TSTemplateRelationId,          /* TSTEMPLATENAMENSP */
+               TSTemplateNameNspIndexId,
+               2,
+               {
+                       Anum_pg_ts_template_tmplname,
+                       Anum_pg_ts_template_tmplnamespace,
+                       0,
+                       0
+               },
+               2
+       },
+       {TSTemplateRelationId,          /* TSTEMPLATEOID */
+               TSTemplateOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               2
        },
        {TypeRelationId,                        /* TYPENAMENSP */
                TypeNameNspIndexId,
-               Anum_pg_type_typrelid,
                2,
                {
                        Anum_pg_type_typname,
@@ -525,11 +934,10 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               64
        },
        {TypeRelationId,                        /* TYPEOID */
                TypeOidIndexId,
-               Anum_pg_type_typrelid,
                1,
                {
                        ObjectIdAttributeNumber,
@@ -537,21 +945,52 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
                },
-               1024
+               64
+       },
+       {UserMappingRelationId,         /* USERMAPPINGOID */
+               UserMappingOidIndexId,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               2
+       },
+       {UserMappingRelationId,         /* USERMAPPINGUSERSERVER */
+               UserMappingUserServerIndexId,
+               2,
+               {
+                       Anum_pg_user_mapping_umuser,
+                       Anum_pg_user_mapping_umserver,
+                       0,
+                       0
+               },
+               2
        }
 };
 
-static CatCache *SysCache[
-                                                 lengthof(cacheinfo)];
-static int     SysCacheSize = lengthof(cacheinfo);
+static CatCache *SysCache[SysCacheSize];
+
 static bool CacheInitialized = false;
 
+/* Sorted array of OIDs of tables that have caches on them */
+static Oid     SysCacheRelationOid[SysCacheSize];
+static int     SysCacheRelationOidSize;
+
+/* Sorted array of OIDs of tables and indexes used by caches */
+static Oid     SysCacheSupportingRelOid[SysCacheSize * 2];
+static int     SysCacheSupportingRelOidSize;
+
+static int     oid_compare(const void *a, const void *b);
+
 
 /*
  * InitCatalogCache - initialize the caches
  *
  * Note that no database access is done here; we only allocate memory
- * and initialize the cache structure. Interrogation of the database
+ * and initialize the cache structure.  Interrogation of the database
  * to complete initialization of a cache happens upon first use
  * of that cache.
  */
@@ -559,28 +998,63 @@ void
 InitCatalogCache(void)
 {
        int                     cacheId;
+       int                     i,
+                               j;
+
+       StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo),
+                                        "SysCacheSize does not match syscache.c's array");
 
        Assert(!CacheInitialized);
 
-       MemSet(SysCache, 0, sizeof(SysCache));
+       SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
 
        for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
        {
                SysCache[cacheId] = InitCatCache(cacheId,
                                                                                 cacheinfo[cacheId].reloid,
                                                                                 cacheinfo[cacheId].indoid,
-                                                                                cacheinfo[cacheId].reloidattr,
                                                                                 cacheinfo[cacheId].nkeys,
                                                                                 cacheinfo[cacheId].key,
                                                                                 cacheinfo[cacheId].nbuckets);
                if (!PointerIsValid(SysCache[cacheId]))
                        elog(ERROR, "could not initialize cache %u (%d)",
                                 cacheinfo[cacheId].reloid, cacheId);
+               /* Accumulate data for OID lists, too */
+               SysCacheRelationOid[SysCacheRelationOidSize++] =
+                       cacheinfo[cacheId].reloid;
+               SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
+                       cacheinfo[cacheId].reloid;
+               SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
+                       cacheinfo[cacheId].indoid;
+               /* see comments for RelationInvalidatesSnapshotsOnly */
+               Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
        }
+
+       Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
+       Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
+
+       /* Sort and de-dup OID arrays, so we can use binary search. */
+       pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
+                        sizeof(Oid), oid_compare);
+       for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
+       {
+               if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
+                       SysCacheRelationOid[++j] = SysCacheRelationOid[i];
+       }
+       SysCacheRelationOidSize = j + 1;
+
+       pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
+                        sizeof(Oid), oid_compare);
+       for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
+       {
+               if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
+                       SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
+       }
+       SysCacheSupportingRelOidSize = j + 1;
+
        CacheInitialized = true;
 }
 
-
 /*
  * InitCatalogCachePhase2 - finish initializing the caches
  *
@@ -630,7 +1104,7 @@ SearchSysCache(int cacheId,
 {
        if (cacheId < 0 || cacheId >= SysCacheSize ||
                !PointerIsValid(SysCache[cacheId]))
-               elog(ERROR, "invalid cache id: %d", cacheId);
+               elog(ERROR, "invalid cache ID: %d", cacheId);
 
        return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
 }
@@ -732,10 +1206,9 @@ SearchSysCacheAttName(Oid relid, const char *attname)
 {
        HeapTuple       tuple;
 
-       tuple = SearchSysCache(ATTNAME,
-                                                  ObjectIdGetDatum(relid),
-                                                  CStringGetDatum(attname),
-                                                  0, 0);
+       tuple = SearchSysCache2(ATTNAME,
+                                                       ObjectIdGetDatum(relid),
+                                                       CStringGetDatum(attname));
        if (!HeapTupleIsValid(tuple))
                return NULL;
        if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
@@ -790,7 +1263,7 @@ SearchSysCacheExistsAttName(Oid relid, const char *attname)
  *             extract a specific attribute.
  *
  * This is equivalent to using heap_getattr() on a tuple fetched
- * from a non-cached relation. Usually, this is only used for attributes
+ * from a non-cached relation.  Usually, this is only used for attributes
  * that could be NULL or variable length; the fixed-size attributes in
  * a system table are accessed just by mapping the tuple onto the C struct
  * declarations from include/catalog/.
@@ -815,7 +1288,7 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
         */
        if (cacheId < 0 || cacheId >= SysCacheSize ||
                !PointerIsValid(SysCache[cacheId]))
-               elog(ERROR, "invalid cache id: %d", cacheId);
+               elog(ERROR, "invalid cache ID: %d", cacheId);
        if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
        {
                InitCatCachePhase2(SysCache[cacheId], false);
@@ -827,6 +1300,30 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
                                                isNull);
 }
 
+/*
+ * GetSysCacheHashValue
+ *
+ * Get the hash value that would be used for a tuple in the specified cache
+ * with the given search keys.
+ *
+ * The reason for exposing this as part of the API is that the hash value is
+ * exposed in cache invalidation operations, so there are places outside the
+ * catcache code that need to be able to compute the hash values.
+ */
+uint32
+GetSysCacheHashValue(int cacheId,
+                                        Datum key1,
+                                        Datum key2,
+                                        Datum key3,
+                                        Datum key4)
+{
+       if (cacheId < 0 || cacheId >= SysCacheSize ||
+               !PointerIsValid(SysCache[cacheId]))
+               elog(ERROR, "invalid cache ID: %d", cacheId);
+
+       return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
+}
+
 /*
  * List-search interface
  */
@@ -836,8 +1333,124 @@ SearchSysCacheList(int cacheId, int nkeys,
 {
        if (cacheId < 0 || cacheId >= SysCacheSize ||
                !PointerIsValid(SysCache[cacheId]))
-               elog(ERROR, "invalid cache id: %d", cacheId);
+               elog(ERROR, "invalid cache ID: %d", cacheId);
 
        return SearchCatCacheList(SysCache[cacheId], nkeys,
                                                          key1, key2, key3, key4);
 }
+
+/*
+ * SysCacheInvalidate
+ *
+ *     Invalidate entries in the specified cache, given a hash value.
+ *     See CatCacheInvalidate() for more info.
+ *
+ *     This routine is only quasi-public: it should only be used by inval.c.
+ */
+void
+SysCacheInvalidate(int cacheId, uint32 hashValue)
+{
+       if (cacheId < 0 || cacheId >= SysCacheSize)
+               elog(ERROR, "invalid cache ID: %d", cacheId);
+
+       /* if this cache isn't initialized yet, no need to do anything */
+       if (!PointerIsValid(SysCache[cacheId]))
+               return;
+
+       CatCacheInvalidate(SysCache[cacheId], hashValue);
+}
+
+/*
+ * Certain relations that do not have system caches send snapshot invalidation
+ * messages in lieu of catcache messages.  This is for the benefit of
+ * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
+ * for scanning one of those catalogs, rather than taking a new one, if no
+ * invalidation has been received.
+ *
+ * Relations that have syscaches need not (and must not) be listed here.  The
+ * catcache invalidation messages will also flush the snapshot.  If you add a
+ * syscache for one of these relations, remove it from this list.
+ */
+bool
+RelationInvalidatesSnapshotsOnly(Oid relid)
+{
+       switch (relid)
+       {
+               case DbRoleSettingRelationId:
+               case DependRelationId:
+               case SharedDependRelationId:
+               case DescriptionRelationId:
+               case SharedDescriptionRelationId:
+               case SecLabelRelationId:
+               case SharedSecLabelRelationId:
+                       return true;
+               default:
+                       break;
+       }
+
+       return false;
+}
+
+/*
+ * Test whether a relation has a system cache.
+ */
+bool
+RelationHasSysCache(Oid relid)
+{
+       int                     low = 0,
+                               high = SysCacheRelationOidSize - 1;
+
+       while (low <= high)
+       {
+               int                     middle = low + (high - low) / 2;
+
+               if (SysCacheRelationOid[middle] == relid)
+                       return true;
+               if (SysCacheRelationOid[middle] < relid)
+                       low = middle + 1;
+               else
+                       high = middle - 1;
+       }
+
+       return false;
+}
+
+/*
+ * Test whether a relation supports a system cache, ie it is either a
+ * cached table or the index used for a cache.
+ */
+bool
+RelationSupportsSysCache(Oid relid)
+{
+       int                     low = 0,
+                               high = SysCacheSupportingRelOidSize - 1;
+
+       while (low <= high)
+       {
+               int                     middle = low + (high - low) / 2;
+
+               if (SysCacheSupportingRelOid[middle] == relid)
+                       return true;
+               if (SysCacheSupportingRelOid[middle] < relid)
+                       low = middle + 1;
+               else
+                       high = middle - 1;
+       }
+
+       return false;
+}
+
+
+/*
+ * OID comparator for pg_qsort
+ */
+static int
+oid_compare(const void *a, const void *b)
+{
+       Oid                     oa = *((const Oid *) a);
+       Oid                     ob = *((const Oid *) b);
+
+       if (oa == ob)
+               return 0;
+       return (oa > ob) ? 1 : -1;
+}