LCOV - code coverage report
Current view: top level - src/backend/utils/cache - syscache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 150 159 94.3 %
Date: 2023-12-02 14:10:25 Functions: 25 25 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * syscache.c
       4             :  *    System cache management routines
       5             :  *
       6             :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/cache/syscache.c
      12             :  *
      13             :  * NOTES
      14             :  *    These routines allow the parser/planner/executor to perform
      15             :  *    rapid lookups on the contents of the system catalogs.
      16             :  *
      17             :  *    see utils/syscache.h for a list of the cache IDs
      18             :  *
      19             :  *-------------------------------------------------------------------------
      20             :  */
      21             : #include "postgres.h"
      22             : 
      23             : #include "access/htup_details.h"
      24             : #include "access/sysattr.h"
      25             : #include "catalog/pg_aggregate.h"
      26             : #include "catalog/pg_am.h"
      27             : #include "catalog/pg_amop.h"
      28             : #include "catalog/pg_amproc.h"
      29             : #include "catalog/pg_auth_members.h"
      30             : #include "catalog/pg_authid.h"
      31             : #include "catalog/pg_cast.h"
      32             : #include "catalog/pg_collation.h"
      33             : #include "catalog/pg_constraint.h"
      34             : #include "catalog/pg_conversion.h"
      35             : #include "catalog/pg_database.h"
      36             : #include "catalog/pg_db_role_setting.h"
      37             : #include "catalog/pg_default_acl.h"
      38             : #include "catalog/pg_depend.h"
      39             : #include "catalog/pg_description.h"
      40             : #include "catalog/pg_enum.h"
      41             : #include "catalog/pg_event_trigger.h"
      42             : #include "catalog/pg_foreign_data_wrapper.h"
      43             : #include "catalog/pg_foreign_server.h"
      44             : #include "catalog/pg_foreign_table.h"
      45             : #include "catalog/pg_language.h"
      46             : #include "catalog/pg_namespace.h"
      47             : #include "catalog/pg_opclass.h"
      48             : #include "catalog/pg_operator.h"
      49             : #include "catalog/pg_opfamily.h"
      50             : #include "catalog/pg_parameter_acl.h"
      51             : #include "catalog/pg_partitioned_table.h"
      52             : #include "catalog/pg_proc.h"
      53             : #include "catalog/pg_publication.h"
      54             : #include "catalog/pg_publication_namespace.h"
      55             : #include "catalog/pg_publication_rel.h"
      56             : #include "catalog/pg_range.h"
      57             : #include "catalog/pg_replication_origin.h"
      58             : #include "catalog/pg_rewrite.h"
      59             : #include "catalog/pg_seclabel.h"
      60             : #include "catalog/pg_sequence.h"
      61             : #include "catalog/pg_shdepend.h"
      62             : #include "catalog/pg_shdescription.h"
      63             : #include "catalog/pg_shseclabel.h"
      64             : #include "catalog/pg_statistic.h"
      65             : #include "catalog/pg_statistic_ext.h"
      66             : #include "catalog/pg_statistic_ext_data.h"
      67             : #include "catalog/pg_subscription.h"
      68             : #include "catalog/pg_subscription_rel.h"
      69             : #include "catalog/pg_tablespace.h"
      70             : #include "catalog/pg_transform.h"
      71             : #include "catalog/pg_ts_config.h"
      72             : #include "catalog/pg_ts_config_map.h"
      73             : #include "catalog/pg_ts_dict.h"
      74             : #include "catalog/pg_ts_parser.h"
      75             : #include "catalog/pg_ts_template.h"
      76             : #include "catalog/pg_type.h"
      77             : #include "catalog/pg_user_mapping.h"
      78             : #include "lib/qunique.h"
      79             : #include "utils/catcache.h"
      80             : #include "utils/lsyscache.h"
      81             : #include "utils/rel.h"
      82             : #include "utils/syscache.h"
      83             : 
      84             : /*---------------------------------------------------------------------------
      85             : 
      86             :     Adding system caches:
      87             : 
      88             :     Add your new cache to the list in include/utils/syscache.h.
      89             :     Keep the list sorted alphabetically.
      90             : 
      91             :     Add your entry to the cacheinfo[] array below. All cache lists are
      92             :     alphabetical, so add it in the proper place.  Specify the relation OID,
      93             :     index OID, number of keys, key attribute numbers, and initial number of
      94             :     hash buckets.
      95             : 
      96             :     The number of hash buckets must be a power of 2.  It's reasonable to
      97             :     set this to the number of entries that might be in the particular cache
      98             :     in a medium-size database.
      99             : 
     100             :     There must be a unique index underlying each syscache (ie, an index
     101             :     whose key is the same as that of the cache).  If there is not one
     102             :     already, add the definition for it to include/catalog/pg_*.h using
     103             :     DECLARE_UNIQUE_INDEX.
     104             :     (Adding an index requires a catversion.h update, while simply
     105             :     adding/deleting caches only requires a recompile.)
     106             : 
     107             :     Finally, any place your relation gets heap_insert() or
     108             :     heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
     109             :     instead, which also update indexes.  The heap_* calls do not do that.
     110             : 
     111             : *---------------------------------------------------------------------------
     112             : */
     113             : 
     114             : /*
     115             :  *      struct cachedesc: information defining a single syscache
     116             :  */
     117             : struct cachedesc
     118             : {
     119             :     Oid         reloid;         /* OID of the relation being cached */
     120             :     Oid         indoid;         /* OID of index relation for this cache */
     121             :     int         nkeys;          /* # of keys needed for cache lookup */
     122             :     int         key[4];         /* attribute numbers of key attrs */
     123             :     int         nbuckets;       /* number of hash buckets for this cache */
     124             : };
     125             : 
     126             : /* Macro to provide nkeys and key array with convenient syntax. */
     127             : #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
     128             : 
     129             : static const struct cachedesc cacheinfo[] = {
     130             :     [AGGFNOID] = {
     131             :         AggregateRelationId,
     132             :         AggregateFnoidIndexId,
     133             :         KEY(Anum_pg_aggregate_aggfnoid),
     134             :         16
     135             :     },
     136             :     [AMNAME] = {
     137             :         AccessMethodRelationId,
     138             :         AmNameIndexId,
     139             :         KEY(Anum_pg_am_amname),
     140             :         4
     141             :     },
     142             :     [AMOID] = {
     143             :         AccessMethodRelationId,
     144             :         AmOidIndexId,
     145             :         KEY(Anum_pg_am_oid),
     146             :         4
     147             :     },
     148             :     [AMOPOPID] = {
     149             :         AccessMethodOperatorRelationId,
     150             :         AccessMethodOperatorIndexId,
     151             :         KEY(Anum_pg_amop_amopopr,
     152             :             Anum_pg_amop_amoppurpose,
     153             :             Anum_pg_amop_amopfamily),
     154             :         64
     155             :     },
     156             :     [AMOPSTRATEGY] = {
     157             :         AccessMethodOperatorRelationId,
     158             :         AccessMethodStrategyIndexId,
     159             :         KEY(Anum_pg_amop_amopfamily,
     160             :             Anum_pg_amop_amoplefttype,
     161             :             Anum_pg_amop_amoprighttype,
     162             :             Anum_pg_amop_amopstrategy),
     163             :         64
     164             :     },
     165             :     [AMPROCNUM] = {
     166             :         AccessMethodProcedureRelationId,
     167             :         AccessMethodProcedureIndexId,
     168             :         KEY(Anum_pg_amproc_amprocfamily,
     169             :             Anum_pg_amproc_amproclefttype,
     170             :             Anum_pg_amproc_amprocrighttype,
     171             :             Anum_pg_amproc_amprocnum),
     172             :         16
     173             :     },
     174             :     [ATTNAME] = {
     175             :         AttributeRelationId,
     176             :         AttributeRelidNameIndexId,
     177             :         KEY(Anum_pg_attribute_attrelid,
     178             :             Anum_pg_attribute_attname),
     179             :         32
     180             :     },
     181             :     [ATTNUM] = {
     182             :         AttributeRelationId,
     183             :         AttributeRelidNumIndexId,
     184             :         KEY(Anum_pg_attribute_attrelid,
     185             :             Anum_pg_attribute_attnum),
     186             :         128
     187             :     },
     188             :     [AUTHMEMMEMROLE] = {
     189             :         AuthMemRelationId,
     190             :         AuthMemMemRoleIndexId,
     191             :         KEY(Anum_pg_auth_members_member,
     192             :             Anum_pg_auth_members_roleid,
     193             :             Anum_pg_auth_members_grantor),
     194             :         8
     195             :     },
     196             :     [AUTHMEMROLEMEM] = {
     197             :         AuthMemRelationId,
     198             :         AuthMemRoleMemIndexId,
     199             :         KEY(Anum_pg_auth_members_roleid,
     200             :             Anum_pg_auth_members_member,
     201             :             Anum_pg_auth_members_grantor),
     202             :         8
     203             :     },
     204             :     [AUTHNAME] = {
     205             :         AuthIdRelationId,
     206             :         AuthIdRolnameIndexId,
     207             :         KEY(Anum_pg_authid_rolname),
     208             :         8
     209             :     },
     210             :     [AUTHOID] = {
     211             :         AuthIdRelationId,
     212             :         AuthIdOidIndexId,
     213             :         KEY(Anum_pg_authid_oid),
     214             :         8
     215             :     },
     216             :     [CASTSOURCETARGET] = {
     217             :         CastRelationId,
     218             :         CastSourceTargetIndexId,
     219             :         KEY(Anum_pg_cast_castsource,
     220             :             Anum_pg_cast_casttarget),
     221             :         256
     222             :     },
     223             :     [CLAAMNAMENSP] = {
     224             :         OperatorClassRelationId,
     225             :         OpclassAmNameNspIndexId,
     226             :         KEY(Anum_pg_opclass_opcmethod,
     227             :             Anum_pg_opclass_opcname,
     228             :             Anum_pg_opclass_opcnamespace),
     229             :         8
     230             :     },
     231             :     [CLAOID] = {
     232             :         OperatorClassRelationId,
     233             :         OpclassOidIndexId,
     234             :         KEY(Anum_pg_opclass_oid),
     235             :         8
     236             :     },
     237             :     [COLLNAMEENCNSP] = {
     238             :         CollationRelationId,
     239             :         CollationNameEncNspIndexId,
     240             :         KEY(Anum_pg_collation_collname,
     241             :             Anum_pg_collation_collencoding,
     242             :             Anum_pg_collation_collnamespace),
     243             :         8
     244             :     },
     245             :     [COLLOID] = {
     246             :         CollationRelationId,
     247             :         CollationOidIndexId,
     248             :         KEY(Anum_pg_collation_oid),
     249             :         8
     250             :     },
     251             :     [CONDEFAULT] = {
     252             :         ConversionRelationId,
     253             :         ConversionDefaultIndexId,
     254             :         KEY(Anum_pg_conversion_connamespace,
     255             :             Anum_pg_conversion_conforencoding,
     256             :             Anum_pg_conversion_contoencoding,
     257             :             Anum_pg_conversion_oid),
     258             :         8
     259             :     },
     260             :     [CONNAMENSP] = {
     261             :         ConversionRelationId,
     262             :         ConversionNameNspIndexId,
     263             :         KEY(Anum_pg_conversion_conname,
     264             :             Anum_pg_conversion_connamespace),
     265             :         8
     266             :     },
     267             :     [CONSTROID] = {
     268             :         ConstraintRelationId,
     269             :         ConstraintOidIndexId,
     270             :         KEY(Anum_pg_constraint_oid),
     271             :         16
     272             :     },
     273             :     [CONVOID] = {
     274             :         ConversionRelationId,
     275             :         ConversionOidIndexId,
     276             :         KEY(Anum_pg_conversion_oid),
     277             :         8
     278             :     },
     279             :     [DATABASEOID] = {
     280             :         DatabaseRelationId,
     281             :         DatabaseOidIndexId,
     282             :         KEY(Anum_pg_database_oid),
     283             :         4
     284             :     },
     285             :     [DEFACLROLENSPOBJ] = {
     286             :         DefaultAclRelationId,
     287             :         DefaultAclRoleNspObjIndexId,
     288             :         KEY(Anum_pg_default_acl_defaclrole,
     289             :             Anum_pg_default_acl_defaclnamespace,
     290             :             Anum_pg_default_acl_defaclobjtype),
     291             :         8
     292             :     },
     293             :     [ENUMOID] = {
     294             :         EnumRelationId,
     295             :         EnumOidIndexId,
     296             :         KEY(Anum_pg_enum_oid),
     297             :         8
     298             :     },
     299             :     [ENUMTYPOIDNAME] = {
     300             :         EnumRelationId,
     301             :         EnumTypIdLabelIndexId,
     302             :         KEY(Anum_pg_enum_enumtypid,
     303             :             Anum_pg_enum_enumlabel),
     304             :         8
     305             :     },
     306             :     [EVENTTRIGGERNAME] = {
     307             :         EventTriggerRelationId,
     308             :         EventTriggerNameIndexId,
     309             :         KEY(Anum_pg_event_trigger_evtname),
     310             :         8
     311             :     },
     312             :     [EVENTTRIGGEROID] = {
     313             :         EventTriggerRelationId,
     314             :         EventTriggerOidIndexId,
     315             :         KEY(Anum_pg_event_trigger_oid),
     316             :         8
     317             :     },
     318             :     [FOREIGNDATAWRAPPERNAME] = {
     319             :         ForeignDataWrapperRelationId,
     320             :         ForeignDataWrapperNameIndexId,
     321             :         KEY(Anum_pg_foreign_data_wrapper_fdwname),
     322             :         2
     323             :     },
     324             :     [FOREIGNDATAWRAPPEROID] = {
     325             :         ForeignDataWrapperRelationId,
     326             :         ForeignDataWrapperOidIndexId,
     327             :         KEY(Anum_pg_foreign_data_wrapper_oid),
     328             :         2
     329             :     },
     330             :     [FOREIGNSERVERNAME] = {
     331             :         ForeignServerRelationId,
     332             :         ForeignServerNameIndexId,
     333             :         KEY(Anum_pg_foreign_server_srvname),
     334             :         2
     335             :     },
     336             :     [FOREIGNSERVEROID] = {
     337             :         ForeignServerRelationId,
     338             :         ForeignServerOidIndexId,
     339             :         KEY(Anum_pg_foreign_server_oid),
     340             :         2
     341             :     },
     342             :     [FOREIGNTABLEREL] = {
     343             :         ForeignTableRelationId,
     344             :         ForeignTableRelidIndexId,
     345             :         KEY(Anum_pg_foreign_table_ftrelid),
     346             :         4
     347             :     },
     348             :     [INDEXRELID] = {
     349             :         IndexRelationId,
     350             :         IndexRelidIndexId,
     351             :         KEY(Anum_pg_index_indexrelid),
     352             :         64
     353             :     },
     354             :     [LANGNAME] = {
     355             :         LanguageRelationId,
     356             :         LanguageNameIndexId,
     357             :         KEY(Anum_pg_language_lanname),
     358             :         4
     359             :     },
     360             :     [LANGOID] = {
     361             :         LanguageRelationId,
     362             :         LanguageOidIndexId,
     363             :         KEY(Anum_pg_language_oid),
     364             :         4
     365             :     },
     366             :     [NAMESPACENAME] = {
     367             :         NamespaceRelationId,
     368             :         NamespaceNameIndexId,
     369             :         KEY(Anum_pg_namespace_nspname),
     370             :         4
     371             :     },
     372             :     [NAMESPACEOID] = {
     373             :         NamespaceRelationId,
     374             :         NamespaceOidIndexId,
     375             :         KEY(Anum_pg_namespace_oid),
     376             :         16
     377             :     },
     378             :     [OPERNAMENSP] = {
     379             :         OperatorRelationId,
     380             :         OperatorNameNspIndexId,
     381             :         KEY(Anum_pg_operator_oprname,
     382             :             Anum_pg_operator_oprleft,
     383             :             Anum_pg_operator_oprright,
     384             :             Anum_pg_operator_oprnamespace),
     385             :         256
     386             :     },
     387             :     [OPEROID] = {
     388             :         OperatorRelationId,
     389             :         OperatorOidIndexId,
     390             :         KEY(Anum_pg_operator_oid),
     391             :         32
     392             :     },
     393             :     [OPFAMILYAMNAMENSP] = {
     394             :         OperatorFamilyRelationId,
     395             :         OpfamilyAmNameNspIndexId,
     396             :         KEY(Anum_pg_opfamily_opfmethod,
     397             :             Anum_pg_opfamily_opfname,
     398             :             Anum_pg_opfamily_opfnamespace),
     399             :         8
     400             :     },
     401             :     [OPFAMILYOID] = {
     402             :         OperatorFamilyRelationId,
     403             :         OpfamilyOidIndexId,
     404             :         KEY(Anum_pg_opfamily_oid),
     405             :         8
     406             :     },
     407             :     [PARAMETERACLNAME] = {
     408             :         ParameterAclRelationId,
     409             :         ParameterAclParnameIndexId,
     410             :         KEY(Anum_pg_parameter_acl_parname),
     411             :         4
     412             :     },
     413             :     [PARAMETERACLOID] = {
     414             :         ParameterAclRelationId,
     415             :         ParameterAclOidIndexId,
     416             :         KEY(Anum_pg_parameter_acl_oid),
     417             :         4
     418             :     },
     419             :     [PARTRELID] = {
     420             :         PartitionedRelationId,
     421             :         PartitionedRelidIndexId,
     422             :         KEY(Anum_pg_partitioned_table_partrelid),
     423             :         32
     424             :     },
     425             :     [PROCNAMEARGSNSP] = {
     426             :         ProcedureRelationId,
     427             :         ProcedureNameArgsNspIndexId,
     428             :         KEY(Anum_pg_proc_proname,
     429             :             Anum_pg_proc_proargtypes,
     430             :             Anum_pg_proc_pronamespace),
     431             :         128
     432             :     },
     433             :     [PROCOID] = {
     434             :         ProcedureRelationId,
     435             :         ProcedureOidIndexId,
     436             :         KEY(Anum_pg_proc_oid),
     437             :         128
     438             :     },
     439             :     [PUBLICATIONNAME] = {
     440             :         PublicationRelationId,
     441             :         PublicationNameIndexId,
     442             :         KEY(Anum_pg_publication_pubname),
     443             :         8
     444             :     },
     445             :     [PUBLICATIONNAMESPACE] = {
     446             :         PublicationNamespaceRelationId,
     447             :         PublicationNamespaceObjectIndexId,
     448             :         KEY(Anum_pg_publication_namespace_oid),
     449             :         64
     450             :     },
     451             :     [PUBLICATIONNAMESPACEMAP] = {
     452             :         PublicationNamespaceRelationId,
     453             :         PublicationNamespacePnnspidPnpubidIndexId,
     454             :         KEY(Anum_pg_publication_namespace_pnnspid,
     455             :             Anum_pg_publication_namespace_pnpubid),
     456             :         64
     457             :     },
     458             :     [PUBLICATIONOID] = {
     459             :         PublicationRelationId,
     460             :         PublicationObjectIndexId,
     461             :         KEY(Anum_pg_publication_oid),
     462             :         8
     463             :     },
     464             :     [PUBLICATIONREL] = {
     465             :         PublicationRelRelationId,
     466             :         PublicationRelObjectIndexId,
     467             :         KEY(Anum_pg_publication_rel_oid),
     468             :         64
     469             :     },
     470             :     [PUBLICATIONRELMAP] = {
     471             :         PublicationRelRelationId,
     472             :         PublicationRelPrrelidPrpubidIndexId,
     473             :         KEY(Anum_pg_publication_rel_prrelid,
     474             :             Anum_pg_publication_rel_prpubid),
     475             :         64
     476             :     },
     477             :     [RANGEMULTIRANGE] = {
     478             :         RangeRelationId,
     479             :         RangeMultirangeTypidIndexId,
     480             :         KEY(Anum_pg_range_rngmultitypid),
     481             :         4
     482             :     },
     483             :     [RANGETYPE] = {
     484             :         RangeRelationId,
     485             :         RangeTypidIndexId,
     486             :         KEY(Anum_pg_range_rngtypid),
     487             :         4
     488             :     },
     489             :     [RELNAMENSP] = {
     490             :         RelationRelationId,
     491             :         ClassNameNspIndexId,
     492             :         KEY(Anum_pg_class_relname,
     493             :             Anum_pg_class_relnamespace),
     494             :         128
     495             :     },
     496             :     [RELOID] = {
     497             :         RelationRelationId,
     498             :         ClassOidIndexId,
     499             :         KEY(Anum_pg_class_oid),
     500             :         128
     501             :     },
     502             :     [REPLORIGIDENT] = {
     503             :         ReplicationOriginRelationId,
     504             :         ReplicationOriginIdentIndex,
     505             :         KEY(Anum_pg_replication_origin_roident),
     506             :         16
     507             :     },
     508             :     [REPLORIGNAME] = {
     509             :         ReplicationOriginRelationId,
     510             :         ReplicationOriginNameIndex,
     511             :         KEY(Anum_pg_replication_origin_roname),
     512             :         16
     513             :     },
     514             :     [RULERELNAME] = {
     515             :         RewriteRelationId,
     516             :         RewriteRelRulenameIndexId,
     517             :         KEY(Anum_pg_rewrite_ev_class,
     518             :             Anum_pg_rewrite_rulename),
     519             :         8
     520             :     },
     521             :     [SEQRELID] = {
     522             :         SequenceRelationId,
     523             :         SequenceRelidIndexId,
     524             :         KEY(Anum_pg_sequence_seqrelid),
     525             :         32
     526             :     },
     527             :     [STATEXTDATASTXOID] = {
     528             :         StatisticExtDataRelationId,
     529             :         StatisticExtDataStxoidInhIndexId,
     530             :         KEY(Anum_pg_statistic_ext_data_stxoid,
     531             :             Anum_pg_statistic_ext_data_stxdinherit),
     532             :         4
     533             :     },
     534             :     [STATEXTNAMENSP] = {
     535             :         StatisticExtRelationId,
     536             :         StatisticExtNameIndexId,
     537             :         KEY(Anum_pg_statistic_ext_stxname,
     538             :             Anum_pg_statistic_ext_stxnamespace),
     539             :         4
     540             :     },
     541             :     [STATEXTOID] = {
     542             :         StatisticExtRelationId,
     543             :         StatisticExtOidIndexId,
     544             :         KEY(Anum_pg_statistic_ext_oid),
     545             :         4
     546             :     },
     547             :     [STATRELATTINH] = {
     548             :         StatisticRelationId,
     549             :         StatisticRelidAttnumInhIndexId,
     550             :         KEY(Anum_pg_statistic_starelid,
     551             :             Anum_pg_statistic_staattnum,
     552             :             Anum_pg_statistic_stainherit),
     553             :         128
     554             :     },
     555             :     [SUBSCRIPTIONNAME] = {
     556             :         SubscriptionRelationId,
     557             :         SubscriptionNameIndexId,
     558             :         KEY(Anum_pg_subscription_subdbid,
     559             :             Anum_pg_subscription_subname),
     560             :         4
     561             :     },
     562             :     [SUBSCRIPTIONOID] = {
     563             :         SubscriptionRelationId,
     564             :         SubscriptionObjectIndexId,
     565             :         KEY(Anum_pg_subscription_oid),
     566             :         4
     567             :     },
     568             :     [SUBSCRIPTIONRELMAP] = {
     569             :         SubscriptionRelRelationId,
     570             :         SubscriptionRelSrrelidSrsubidIndexId,
     571             :         KEY(Anum_pg_subscription_rel_srrelid,
     572             :             Anum_pg_subscription_rel_srsubid),
     573             :         64
     574             :     },
     575             :     [TABLESPACEOID] = {
     576             :         TableSpaceRelationId,
     577             :         TablespaceOidIndexId,
     578             :         KEY(Anum_pg_tablespace_oid),
     579             :         4
     580             :     },
     581             :     [TRFOID] = {
     582             :         TransformRelationId,
     583             :         TransformOidIndexId,
     584             :         KEY(Anum_pg_transform_oid),
     585             :         16
     586             :     },
     587             :     [TRFTYPELANG] = {
     588             :         TransformRelationId,
     589             :         TransformTypeLangIndexId,
     590             :         KEY(Anum_pg_transform_trftype,
     591             :             Anum_pg_transform_trflang),
     592             :         16
     593             :     },
     594             :     [TSCONFIGMAP] = {
     595             :         TSConfigMapRelationId,
     596             :         TSConfigMapIndexId,
     597             :         KEY(Anum_pg_ts_config_map_mapcfg,
     598             :             Anum_pg_ts_config_map_maptokentype,
     599             :             Anum_pg_ts_config_map_mapseqno),
     600             :         2
     601             :     },
     602             :     [TSCONFIGNAMENSP] = {
     603             :         TSConfigRelationId,
     604             :         TSConfigNameNspIndexId,
     605             :         KEY(Anum_pg_ts_config_cfgname,
     606             :             Anum_pg_ts_config_cfgnamespace),
     607             :         2
     608             :     },
     609             :     [TSCONFIGOID] = {
     610             :         TSConfigRelationId,
     611             :         TSConfigOidIndexId,
     612             :         KEY(Anum_pg_ts_config_oid),
     613             :         2
     614             :     },
     615             :     [TSDICTNAMENSP] = {
     616             :         TSDictionaryRelationId,
     617             :         TSDictionaryNameNspIndexId,
     618             :         KEY(Anum_pg_ts_dict_dictname,
     619             :             Anum_pg_ts_dict_dictnamespace),
     620             :         2
     621             :     },
     622             :     [TSDICTOID] = {
     623             :         TSDictionaryRelationId,
     624             :         TSDictionaryOidIndexId,
     625             :         KEY(Anum_pg_ts_dict_oid),
     626             :         2
     627             :     },
     628             :     [TSPARSERNAMENSP] = {
     629             :         TSParserRelationId,
     630             :         TSParserNameNspIndexId,
     631             :         KEY(Anum_pg_ts_parser_prsname,
     632             :             Anum_pg_ts_parser_prsnamespace),
     633             :         2
     634             :     },
     635             :     [TSPARSEROID] = {
     636             :         TSParserRelationId,
     637             :         TSParserOidIndexId,
     638             :         KEY(Anum_pg_ts_parser_oid),
     639             :         2
     640             :     },
     641             :     [TSTEMPLATENAMENSP] = {
     642             :         TSTemplateRelationId,
     643             :         TSTemplateNameNspIndexId,
     644             :         KEY(Anum_pg_ts_template_tmplname,
     645             :             Anum_pg_ts_template_tmplnamespace),
     646             :         2
     647             :     },
     648             :     [TSTEMPLATEOID] = {
     649             :         TSTemplateRelationId,
     650             :         TSTemplateOidIndexId,
     651             :         KEY(Anum_pg_ts_template_oid),
     652             :         2
     653             :     },
     654             :     [TYPENAMENSP] = {
     655             :         TypeRelationId,
     656             :         TypeNameNspIndexId,
     657             :         KEY(Anum_pg_type_typname,
     658             :             Anum_pg_type_typnamespace),
     659             :         64
     660             :     },
     661             :     [TYPEOID] = {
     662             :         TypeRelationId,
     663             :         TypeOidIndexId,
     664             :         KEY(Anum_pg_type_oid),
     665             :         64
     666             :     },
     667             :     [USERMAPPINGOID] = {
     668             :         UserMappingRelationId,
     669             :         UserMappingOidIndexId,
     670             :         KEY(Anum_pg_user_mapping_oid),
     671             :         2
     672             :     },
     673             :     [USERMAPPINGUSERSERVER] = {
     674             :         UserMappingRelationId,
     675             :         UserMappingUserServerIndexId,
     676             :         KEY(Anum_pg_user_mapping_umuser,
     677             :             Anum_pg_user_mapping_umserver),
     678             :         2
     679             :     }
     680             : };
     681             : 
     682             : StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
     683             :                  "SysCacheSize does not match syscache.c's array");
     684             : 
     685             : static CatCache *SysCache[SysCacheSize];
     686             : 
     687             : static bool CacheInitialized = false;
     688             : 
     689             : /* Sorted array of OIDs of tables that have caches on them */
     690             : static Oid  SysCacheRelationOid[SysCacheSize];
     691             : static int  SysCacheRelationOidSize;
     692             : 
     693             : /* Sorted array of OIDs of tables and indexes used by caches */
     694             : static Oid  SysCacheSupportingRelOid[SysCacheSize * 2];
     695             : static int  SysCacheSupportingRelOidSize;
     696             : 
     697             : static int  oid_compare(const void *a, const void *b);
     698             : 
     699             : 
     700             : /*
     701             :  * InitCatalogCache - initialize the caches
     702             :  *
     703             :  * Note that no database access is done here; we only allocate memory
     704             :  * and initialize the cache structure.  Interrogation of the database
     705             :  * to complete initialization of a cache happens upon first use
     706             :  * of that cache.
     707             :  */
     708             : void
     709       24214 : InitCatalogCache(void)
     710             : {
     711             :     int         cacheId;
     712             : 
     713             :     Assert(!CacheInitialized);
     714             : 
     715       24214 :     SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
     716             : 
     717     2033976 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
     718             :     {
     719             :         /*
     720             :          * Assert that every enumeration value defined in syscache.h has been
     721             :          * populated in the cacheinfo array.
     722             :          */
     723             :         Assert(OidIsValid(cacheinfo[cacheId].reloid));
     724             :         Assert(OidIsValid(cacheinfo[cacheId].indoid));
     725             :         /* .nbuckets and .key[] are checked by InitCatCache() */
     726             : 
     727     4019524 :         SysCache[cacheId] = InitCatCache(cacheId,
     728             :                                          cacheinfo[cacheId].reloid,
     729             :                                          cacheinfo[cacheId].indoid,
     730             :                                          cacheinfo[cacheId].nkeys,
     731     2009762 :                                          cacheinfo[cacheId].key,
     732             :                                          cacheinfo[cacheId].nbuckets);
     733     2009762 :         if (!PointerIsValid(SysCache[cacheId]))
     734           0 :             elog(ERROR, "could not initialize cache %u (%d)",
     735             :                  cacheinfo[cacheId].reloid, cacheId);
     736             :         /* Accumulate data for OID lists, too */
     737     2009762 :         SysCacheRelationOid[SysCacheRelationOidSize++] =
     738     2009762 :             cacheinfo[cacheId].reloid;
     739     2009762 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     740     2009762 :             cacheinfo[cacheId].reloid;
     741     2009762 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     742     2009762 :             cacheinfo[cacheId].indoid;
     743             :         /* see comments for RelationInvalidatesSnapshotsOnly */
     744             :         Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
     745             :     }
     746             : 
     747             :     Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
     748             :     Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
     749             : 
     750             :     /* Sort and de-dup OID arrays, so we can use binary search. */
     751       24214 :     pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
     752             :              sizeof(Oid), oid_compare);
     753       24214 :     SysCacheRelationOidSize =
     754       24214 :         qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
     755             :                 oid_compare);
     756             : 
     757       24214 :     pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     758             :              sizeof(Oid), oid_compare);
     759       24214 :     SysCacheSupportingRelOidSize =
     760       24214 :         qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     761             :                 sizeof(Oid), oid_compare);
     762             : 
     763       24214 :     CacheInitialized = true;
     764       24214 : }
     765             : 
     766             : /*
     767             :  * InitCatalogCachePhase2 - finish initializing the caches
     768             :  *
     769             :  * Finish initializing all the caches, including necessary database
     770             :  * access.
     771             :  *
     772             :  * This is *not* essential; normally we allow syscaches to be initialized
     773             :  * on first use.  However, it is useful as a mechanism to preload the
     774             :  * relcache with entries for the most-commonly-used system catalogs.
     775             :  * Therefore, we invoke this routine when we need to write a new relcache
     776             :  * init file.
     777             :  */
     778             : void
     779        1918 : InitCatalogCachePhase2(void)
     780             : {
     781             :     int         cacheId;
     782             : 
     783             :     Assert(CacheInitialized);
     784             : 
     785      160972 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
     786      159056 :         InitCatCachePhase2(SysCache[cacheId], true);
     787        1916 : }
     788             : 
     789             : 
     790             : /*
     791             :  * SearchSysCache
     792             :  *
     793             :  *  A layer on top of SearchCatCache that does the initialization and
     794             :  *  key-setting for you.
     795             :  *
     796             :  *  Returns the cache copy of the tuple if one is found, NULL if not.
     797             :  *  The tuple is the 'cache' copy and must NOT be modified!
     798             :  *
     799             :  *  When the caller is done using the tuple, call ReleaseSysCache()
     800             :  *  to release the reference count grabbed by SearchSysCache().  If this
     801             :  *  is not done, the tuple will remain locked in cache until end of
     802             :  *  transaction, which is tolerable but not desirable.
     803             :  *
     804             :  *  CAUTION: The tuple that is returned must NOT be freed by the caller!
     805             :  */
     806             : HeapTuple
     807     4308924 : SearchSysCache(int cacheId,
     808             :                Datum key1,
     809             :                Datum key2,
     810             :                Datum key3,
     811             :                Datum key4)
     812             : {
     813             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     814             :            PointerIsValid(SysCache[cacheId]));
     815             : 
     816     4308924 :     return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
     817             : }
     818             : 
     819             : HeapTuple
     820    53256460 : SearchSysCache1(int cacheId,
     821             :                 Datum key1)
     822             : {
     823             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     824             :            PointerIsValid(SysCache[cacheId]));
     825             :     Assert(SysCache[cacheId]->cc_nkeys == 1);
     826             : 
     827    53256460 :     return SearchCatCache1(SysCache[cacheId], key1);
     828             : }
     829             : 
     830             : HeapTuple
     831     4023942 : SearchSysCache2(int cacheId,
     832             :                 Datum key1, Datum key2)
     833             : {
     834             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     835             :            PointerIsValid(SysCache[cacheId]));
     836             :     Assert(SysCache[cacheId]->cc_nkeys == 2);
     837             : 
     838     4023942 :     return SearchCatCache2(SysCache[cacheId], key1, key2);
     839             : }
     840             : 
     841             : HeapTuple
     842     4121072 : SearchSysCache3(int cacheId,
     843             :                 Datum key1, Datum key2, Datum key3)
     844             : {
     845             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     846             :            PointerIsValid(SysCache[cacheId]));
     847             :     Assert(SysCache[cacheId]->cc_nkeys == 3);
     848             : 
     849     4121072 :     return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
     850             : }
     851             : 
     852             : HeapTuple
     853     3192638 : SearchSysCache4(int cacheId,
     854             :                 Datum key1, Datum key2, Datum key3, Datum key4)
     855             : {
     856             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     857             :            PointerIsValid(SysCache[cacheId]));
     858             :     Assert(SysCache[cacheId]->cc_nkeys == 4);
     859             : 
     860     3192638 :     return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
     861             : }
     862             : 
     863             : /*
     864             :  * ReleaseSysCache
     865             :  *      Release previously grabbed reference count on a tuple
     866             :  */
     867             : void
     868    64424452 : ReleaseSysCache(HeapTuple tuple)
     869             : {
     870    64424452 :     ReleaseCatCache(tuple);
     871    64424452 : }
     872             : 
     873             : /*
     874             :  * SearchSysCacheCopy
     875             :  *
     876             :  * A convenience routine that does SearchSysCache and (if successful)
     877             :  * returns a modifiable copy of the syscache entry.  The original
     878             :  * syscache entry is released before returning.  The caller should
     879             :  * heap_freetuple() the result when done with it.
     880             :  */
     881             : HeapTuple
     882      419800 : SearchSysCacheCopy(int cacheId,
     883             :                    Datum key1,
     884             :                    Datum key2,
     885             :                    Datum key3,
     886             :                    Datum key4)
     887             : {
     888             :     HeapTuple   tuple,
     889             :                 newtuple;
     890             : 
     891      419800 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     892      419800 :     if (!HeapTupleIsValid(tuple))
     893      106534 :         return tuple;
     894      313266 :     newtuple = heap_copytuple(tuple);
     895      313266 :     ReleaseSysCache(tuple);
     896      313266 :     return newtuple;
     897             : }
     898             : 
     899             : /*
     900             :  * SearchSysCacheExists
     901             :  *
     902             :  * A convenience routine that just probes to see if a tuple can be found.
     903             :  * No lock is retained on the syscache entry.
     904             :  */
     905             : bool
     906     1024596 : SearchSysCacheExists(int cacheId,
     907             :                      Datum key1,
     908             :                      Datum key2,
     909             :                      Datum key3,
     910             :                      Datum key4)
     911             : {
     912             :     HeapTuple   tuple;
     913             : 
     914     1024596 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     915     1024596 :     if (!HeapTupleIsValid(tuple))
     916      201088 :         return false;
     917      823508 :     ReleaseSysCache(tuple);
     918      823508 :     return true;
     919             : }
     920             : 
     921             : /*
     922             :  * GetSysCacheOid
     923             :  *
     924             :  * A convenience routine that does SearchSysCache and returns the OID in the
     925             :  * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
     926             :  * No lock is retained on the syscache entry.
     927             :  */
     928             : Oid
     929     2864528 : GetSysCacheOid(int cacheId,
     930             :                AttrNumber oidcol,
     931             :                Datum key1,
     932             :                Datum key2,
     933             :                Datum key3,
     934             :                Datum key4)
     935             : {
     936             :     HeapTuple   tuple;
     937             :     bool        isNull;
     938             :     Oid         result;
     939             : 
     940     2864528 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     941     2864528 :     if (!HeapTupleIsValid(tuple))
     942     1145688 :         return InvalidOid;
     943     3437680 :     result = heap_getattr(tuple, oidcol,
     944     1718840 :                           SysCache[cacheId]->cc_tupdesc,
     945             :                           &isNull);
     946             :     Assert(!isNull);            /* columns used as oids should never be NULL */
     947     1718840 :     ReleaseSysCache(tuple);
     948     1718840 :     return result;
     949             : }
     950             : 
     951             : 
     952             : /*
     953             :  * SearchSysCacheAttName
     954             :  *
     955             :  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
     956             :  * except that it will return NULL if the found attribute is marked
     957             :  * attisdropped.  This is convenient for callers that want to act as
     958             :  * though dropped attributes don't exist.
     959             :  */
     960             : HeapTuple
     961       87916 : SearchSysCacheAttName(Oid relid, const char *attname)
     962             : {
     963             :     HeapTuple   tuple;
     964             : 
     965       87916 :     tuple = SearchSysCache2(ATTNAME,
     966             :                             ObjectIdGetDatum(relid),
     967             :                             CStringGetDatum(attname));
     968       87916 :     if (!HeapTupleIsValid(tuple))
     969         826 :         return NULL;
     970       87090 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
     971             :     {
     972          78 :         ReleaseSysCache(tuple);
     973          78 :         return NULL;
     974             :     }
     975       87012 :     return tuple;
     976             : }
     977             : 
     978             : /*
     979             :  * SearchSysCacheCopyAttName
     980             :  *
     981             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
     982             :  */
     983             : HeapTuple
     984        8184 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
     985             : {
     986             :     HeapTuple   tuple,
     987             :                 newtuple;
     988             : 
     989        8184 :     tuple = SearchSysCacheAttName(relid, attname);
     990        8184 :     if (!HeapTupleIsValid(tuple))
     991         636 :         return tuple;
     992        7548 :     newtuple = heap_copytuple(tuple);
     993        7548 :     ReleaseSysCache(tuple);
     994        7548 :     return newtuple;
     995             : }
     996             : 
     997             : /*
     998             :  * SearchSysCacheExistsAttName
     999             :  *
    1000             :  * As above, an attisdropped-aware version of SearchSysCacheExists.
    1001             :  */
    1002             : bool
    1003         798 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
    1004             : {
    1005             :     HeapTuple   tuple;
    1006             : 
    1007         798 :     tuple = SearchSysCacheAttName(relid, attname);
    1008         798 :     if (!HeapTupleIsValid(tuple))
    1009          12 :         return false;
    1010         786 :     ReleaseSysCache(tuple);
    1011         786 :     return true;
    1012             : }
    1013             : 
    1014             : 
    1015             : /*
    1016             :  * SearchSysCacheAttNum
    1017             :  *
    1018             :  * This routine is equivalent to SearchSysCache on the ATTNUM cache,
    1019             :  * except that it will return NULL if the found attribute is marked
    1020             :  * attisdropped.  This is convenient for callers that want to act as
    1021             :  * though dropped attributes don't exist.
    1022             :  */
    1023             : HeapTuple
    1024       21224 : SearchSysCacheAttNum(Oid relid, int16 attnum)
    1025             : {
    1026             :     HeapTuple   tuple;
    1027             : 
    1028       21224 :     tuple = SearchSysCache2(ATTNUM,
    1029             :                             ObjectIdGetDatum(relid),
    1030             :                             Int16GetDatum(attnum));
    1031       21224 :     if (!HeapTupleIsValid(tuple))
    1032          12 :         return NULL;
    1033       21212 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
    1034             :     {
    1035           0 :         ReleaseSysCache(tuple);
    1036           0 :         return NULL;
    1037             :     }
    1038       21212 :     return tuple;
    1039             : }
    1040             : 
    1041             : /*
    1042             :  * SearchSysCacheCopyAttNum
    1043             :  *
    1044             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
    1045             :  */
    1046             : HeapTuple
    1047       21224 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
    1048             : {
    1049             :     HeapTuple   tuple,
    1050             :                 newtuple;
    1051             : 
    1052       21224 :     tuple = SearchSysCacheAttNum(relid, attnum);
    1053       21224 :     if (!HeapTupleIsValid(tuple))
    1054          12 :         return NULL;
    1055       21212 :     newtuple = heap_copytuple(tuple);
    1056       21212 :     ReleaseSysCache(tuple);
    1057       21212 :     return newtuple;
    1058             : }
    1059             : 
    1060             : 
    1061             : /*
    1062             :  * SysCacheGetAttr
    1063             :  *
    1064             :  *      Given a tuple previously fetched by SearchSysCache(),
    1065             :  *      extract a specific attribute.
    1066             :  *
    1067             :  * This is equivalent to using heap_getattr() on a tuple fetched
    1068             :  * from a non-cached relation.  Usually, this is only used for attributes
    1069             :  * that could be NULL or variable length; the fixed-size attributes in
    1070             :  * a system table are accessed just by mapping the tuple onto the C struct
    1071             :  * declarations from include/catalog/.
    1072             :  *
    1073             :  * As with heap_getattr(), if the attribute is of a pass-by-reference type
    1074             :  * then a pointer into the tuple data area is returned --- the caller must
    1075             :  * not modify or pfree the datum!
    1076             :  *
    1077             :  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
    1078             :  * a different cache for the same catalog the tuple was fetched from.
    1079             :  */
    1080             : Datum
    1081     4161828 : SysCacheGetAttr(int cacheId, HeapTuple tup,
    1082             :                 AttrNumber attributeNumber,
    1083             :                 bool *isNull)
    1084             : {
    1085             :     /*
    1086             :      * We just need to get the TupleDesc out of the cache entry, and then we
    1087             :      * can apply heap_getattr().  Normally the cache control data is already
    1088             :      * valid (because the caller recently fetched the tuple via this same
    1089             :      * cache), but there are cases where we have to initialize the cache here.
    1090             :      */
    1091     4161828 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1092     4161828 :         !PointerIsValid(SysCache[cacheId]))
    1093           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1094     4161828 :     if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
    1095             :     {
    1096       23024 :         InitCatCachePhase2(SysCache[cacheId], false);
    1097             :         Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
    1098             :     }
    1099             : 
    1100     8323656 :     return heap_getattr(tup, attributeNumber,
    1101     4161828 :                         SysCache[cacheId]->cc_tupdesc,
    1102             :                         isNull);
    1103             : }
    1104             : 
    1105             : /*
    1106             :  * SysCacheGetAttrNotNull
    1107             :  *
    1108             :  * As above, a version of SysCacheGetAttr which knows that the attr cannot
    1109             :  * be NULL.
    1110             :  */
    1111             : Datum
    1112     2503956 : SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
    1113             :                        AttrNumber attributeNumber)
    1114             : {
    1115             :     bool        isnull;
    1116             :     Datum       attr;
    1117             : 
    1118     2503956 :     attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
    1119             : 
    1120     2503956 :     if (isnull)
    1121             :     {
    1122           0 :         elog(ERROR,
    1123             :              "unexpected null value in cached tuple for catalog %s column %s",
    1124             :              get_rel_name(cacheinfo[cacheId].reloid),
    1125             :              NameStr(TupleDescAttr(SysCache[cacheId]->cc_tupdesc, attributeNumber - 1)->attname));
    1126             :     }
    1127             : 
    1128     2503956 :     return attr;
    1129             : }
    1130             : 
    1131             : /*
    1132             :  * GetSysCacheHashValue
    1133             :  *
    1134             :  * Get the hash value that would be used for a tuple in the specified cache
    1135             :  * with the given search keys.
    1136             :  *
    1137             :  * The reason for exposing this as part of the API is that the hash value is
    1138             :  * exposed in cache invalidation operations, so there are places outside the
    1139             :  * catcache code that need to be able to compute the hash values.
    1140             :  */
    1141             : uint32
    1142      133450 : GetSysCacheHashValue(int cacheId,
    1143             :                      Datum key1,
    1144             :                      Datum key2,
    1145             :                      Datum key3,
    1146             :                      Datum key4)
    1147             : {
    1148      133450 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1149      133450 :         !PointerIsValid(SysCache[cacheId]))
    1150           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1151             : 
    1152      133450 :     return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
    1153             : }
    1154             : 
    1155             : /*
    1156             :  * List-search interface
    1157             :  */
    1158             : struct catclist *
    1159     2747382 : SearchSysCacheList(int cacheId, int nkeys,
    1160             :                    Datum key1, Datum key2, Datum key3)
    1161             : {
    1162     2747382 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1163     2747382 :         !PointerIsValid(SysCache[cacheId]))
    1164           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1165             : 
    1166     2747382 :     return SearchCatCacheList(SysCache[cacheId], nkeys,
    1167             :                               key1, key2, key3);
    1168             : }
    1169             : 
    1170             : /*
    1171             :  * SysCacheInvalidate
    1172             :  *
    1173             :  *  Invalidate entries in the specified cache, given a hash value.
    1174             :  *  See CatCacheInvalidate() for more info.
    1175             :  *
    1176             :  *  This routine is only quasi-public: it should only be used by inval.c.
    1177             :  */
    1178             : void
    1179    16033556 : SysCacheInvalidate(int cacheId, uint32 hashValue)
    1180             : {
    1181    16033556 :     if (cacheId < 0 || cacheId >= SysCacheSize)
    1182           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1183             : 
    1184             :     /* if this cache isn't initialized yet, no need to do anything */
    1185    16033556 :     if (!PointerIsValid(SysCache[cacheId]))
    1186           0 :         return;
    1187             : 
    1188    16033556 :     CatCacheInvalidate(SysCache[cacheId], hashValue);
    1189             : }
    1190             : 
    1191             : /*
    1192             :  * Certain relations that do not have system caches send snapshot invalidation
    1193             :  * messages in lieu of catcache messages.  This is for the benefit of
    1194             :  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
    1195             :  * for scanning one of those catalogs, rather than taking a new one, if no
    1196             :  * invalidation has been received.
    1197             :  *
    1198             :  * Relations that have syscaches need not (and must not) be listed here.  The
    1199             :  * catcache invalidation messages will also flush the snapshot.  If you add a
    1200             :  * syscache for one of these relations, remove it from this list.
    1201             :  */
    1202             : bool
    1203    11252592 : RelationInvalidatesSnapshotsOnly(Oid relid)
    1204             : {
    1205    11252592 :     switch (relid)
    1206             :     {
    1207     2018366 :         case DbRoleSettingRelationId:
    1208             :         case DependRelationId:
    1209             :         case SharedDependRelationId:
    1210             :         case DescriptionRelationId:
    1211             :         case SharedDescriptionRelationId:
    1212             :         case SecLabelRelationId:
    1213             :         case SharedSecLabelRelationId:
    1214     2018366 :             return true;
    1215     9234226 :         default:
    1216     9234226 :             break;
    1217             :     }
    1218             : 
    1219     9234226 :     return false;
    1220             : }
    1221             : 
    1222             : /*
    1223             :  * Test whether a relation has a system cache.
    1224             :  */
    1225             : bool
    1226     6900520 : RelationHasSysCache(Oid relid)
    1227             : {
    1228     6900520 :     int         low = 0,
    1229     6900520 :                 high = SysCacheRelationOidSize - 1;
    1230             : 
    1231    30470134 :     while (low <= high)
    1232             :     {
    1233    30084582 :         int         middle = low + (high - low) / 2;
    1234             : 
    1235    30084582 :         if (SysCacheRelationOid[middle] == relid)
    1236     6514968 :             return true;
    1237    23569614 :         if (SysCacheRelationOid[middle] < relid)
    1238     8209368 :             low = middle + 1;
    1239             :         else
    1240    15360246 :             high = middle - 1;
    1241             :     }
    1242             : 
    1243      385552 :     return false;
    1244             : }
    1245             : 
    1246             : /*
    1247             :  * Test whether a relation supports a system cache, ie it is either a
    1248             :  * cached table or the index used for a cache.
    1249             :  */
    1250             : bool
    1251     1671510 : RelationSupportsSysCache(Oid relid)
    1252             : {
    1253     1671510 :     int         low = 0,
    1254     1671510 :                 high = SysCacheSupportingRelOidSize - 1;
    1255             : 
    1256    14329708 :     while (low <= high)
    1257             :     {
    1258    12902714 :         int         middle = low + (high - low) / 2;
    1259             : 
    1260    12902714 :         if (SysCacheSupportingRelOid[middle] == relid)
    1261      244516 :             return true;
    1262    12658198 :         if (SysCacheSupportingRelOid[middle] < relid)
    1263    11968992 :             low = middle + 1;
    1264             :         else
    1265      689206 :             high = middle - 1;
    1266             :     }
    1267             : 
    1268     1426994 :     return false;
    1269             : }
    1270             : 
    1271             : 
    1272             : /*
    1273             :  * OID comparator for pg_qsort
    1274             :  */
    1275             : static int
    1276    45958172 : oid_compare(const void *a, const void *b)
    1277             : {
    1278    45958172 :     Oid         oa = *((const Oid *) a);
    1279    45958172 :     Oid         ob = *((const Oid *) b);
    1280             : 
    1281    45958172 :     if (oa == ob)
    1282     3898454 :         return 0;
    1283    42059718 :     return (oa > ob) ? 1 : -1;
    1284             : }

Generated by: LCOV version 1.14