LCOV - code coverage report
Current view: top level - src/backend/utils/cache - syscache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 150 159 94.3 %
Date: 2023-05-30 23:12:14 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       24036 : InitCatalogCache(void)
     710             : {
     711             :     int         cacheId;
     712             : 
     713             :     Assert(!CacheInitialized);
     714             : 
     715       24036 :     SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
     716             : 
     717     2019024 :     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(cacheinfo[cacheId].reloid != 0);
     724             : 
     725     3989976 :         SysCache[cacheId] = InitCatCache(cacheId,
     726             :                                          cacheinfo[cacheId].reloid,
     727             :                                          cacheinfo[cacheId].indoid,
     728             :                                          cacheinfo[cacheId].nkeys,
     729     1994988 :                                          cacheinfo[cacheId].key,
     730             :                                          cacheinfo[cacheId].nbuckets);
     731     1994988 :         if (!PointerIsValid(SysCache[cacheId]))
     732           0 :             elog(ERROR, "could not initialize cache %u (%d)",
     733             :                  cacheinfo[cacheId].reloid, cacheId);
     734             :         /* Accumulate data for OID lists, too */
     735     1994988 :         SysCacheRelationOid[SysCacheRelationOidSize++] =
     736     1994988 :             cacheinfo[cacheId].reloid;
     737     1994988 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     738     1994988 :             cacheinfo[cacheId].reloid;
     739     1994988 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     740     1994988 :             cacheinfo[cacheId].indoid;
     741             :         /* see comments for RelationInvalidatesSnapshotsOnly */
     742             :         Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
     743             :     }
     744             : 
     745             :     Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
     746             :     Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
     747             : 
     748             :     /* Sort and de-dup OID arrays, so we can use binary search. */
     749       24036 :     pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
     750             :              sizeof(Oid), oid_compare);
     751       24036 :     SysCacheRelationOidSize =
     752       24036 :         qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
     753             :                 oid_compare);
     754             : 
     755       24036 :     pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     756             :              sizeof(Oid), oid_compare);
     757       24036 :     SysCacheSupportingRelOidSize =
     758       24036 :         qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     759             :                 sizeof(Oid), oid_compare);
     760             : 
     761       24036 :     CacheInitialized = true;
     762       24036 : }
     763             : 
     764             : /*
     765             :  * InitCatalogCachePhase2 - finish initializing the caches
     766             :  *
     767             :  * Finish initializing all the caches, including necessary database
     768             :  * access.
     769             :  *
     770             :  * This is *not* essential; normally we allow syscaches to be initialized
     771             :  * on first use.  However, it is useful as a mechanism to preload the
     772             :  * relcache with entries for the most-commonly-used system catalogs.
     773             :  * Therefore, we invoke this routine when we need to write a new relcache
     774             :  * init file.
     775             :  */
     776             : void
     777        2296 : InitCatalogCachePhase2(void)
     778             : {
     779             :     int         cacheId;
     780             : 
     781             :     Assert(CacheInitialized);
     782             : 
     783      192826 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
     784      190532 :         InitCatCachePhase2(SysCache[cacheId], true);
     785        2294 : }
     786             : 
     787             : 
     788             : /*
     789             :  * SearchSysCache
     790             :  *
     791             :  *  A layer on top of SearchCatCache that does the initialization and
     792             :  *  key-setting for you.
     793             :  *
     794             :  *  Returns the cache copy of the tuple if one is found, NULL if not.
     795             :  *  The tuple is the 'cache' copy and must NOT be modified!
     796             :  *
     797             :  *  When the caller is done using the tuple, call ReleaseSysCache()
     798             :  *  to release the reference count grabbed by SearchSysCache().  If this
     799             :  *  is not done, the tuple will remain locked in cache until end of
     800             :  *  transaction, which is tolerable but not desirable.
     801             :  *
     802             :  *  CAUTION: The tuple that is returned must NOT be freed by the caller!
     803             :  */
     804             : HeapTuple
     805     8792244 : SearchSysCache(int cacheId,
     806             :                Datum key1,
     807             :                Datum key2,
     808             :                Datum key3,
     809             :                Datum key4)
     810             : {
     811             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     812             :            PointerIsValid(SysCache[cacheId]));
     813             : 
     814     8792244 :     return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
     815             : }
     816             : 
     817             : HeapTuple
     818    80298590 : SearchSysCache1(int cacheId,
     819             :                 Datum key1)
     820             : {
     821             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     822             :            PointerIsValid(SysCache[cacheId]));
     823             :     Assert(SysCache[cacheId]->cc_nkeys == 1);
     824             : 
     825    80298590 :     return SearchCatCache1(SysCache[cacheId], key1);
     826             : }
     827             : 
     828             : HeapTuple
     829     8462100 : SearchSysCache2(int cacheId,
     830             :                 Datum key1, Datum key2)
     831             : {
     832             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     833             :            PointerIsValid(SysCache[cacheId]));
     834             :     Assert(SysCache[cacheId]->cc_nkeys == 2);
     835             : 
     836     8462100 :     return SearchCatCache2(SysCache[cacheId], key1, key2);
     837             : }
     838             : 
     839             : HeapTuple
     840     4191554 : SearchSysCache3(int cacheId,
     841             :                 Datum key1, Datum key2, Datum key3)
     842             : {
     843             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     844             :            PointerIsValid(SysCache[cacheId]));
     845             :     Assert(SysCache[cacheId]->cc_nkeys == 3);
     846             : 
     847     4191554 :     return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
     848             : }
     849             : 
     850             : HeapTuple
     851     3676606 : SearchSysCache4(int cacheId,
     852             :                 Datum key1, Datum key2, Datum key3, Datum key4)
     853             : {
     854             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     855             :            PointerIsValid(SysCache[cacheId]));
     856             :     Assert(SysCache[cacheId]->cc_nkeys == 4);
     857             : 
     858     3676606 :     return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
     859             : }
     860             : 
     861             : /*
     862             :  * ReleaseSysCache
     863             :  *      Release previously grabbed reference count on a tuple
     864             :  */
     865             : void
     866    95158806 : ReleaseSysCache(HeapTuple tuple)
     867             : {
     868    95158806 :     ReleaseCatCache(tuple);
     869    95158806 : }
     870             : 
     871             : /*
     872             :  * SearchSysCacheCopy
     873             :  *
     874             :  * A convenience routine that does SearchSysCache and (if successful)
     875             :  * returns a modifiable copy of the syscache entry.  The original
     876             :  * syscache entry is released before returning.  The caller should
     877             :  * heap_freetuple() the result when done with it.
     878             :  */
     879             : HeapTuple
     880     1257866 : SearchSysCacheCopy(int cacheId,
     881             :                    Datum key1,
     882             :                    Datum key2,
     883             :                    Datum key3,
     884             :                    Datum key4)
     885             : {
     886             :     HeapTuple   tuple,
     887             :                 newtuple;
     888             : 
     889     1257866 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     890     1257866 :     if (!HeapTupleIsValid(tuple))
     891      332190 :         return tuple;
     892      925676 :     newtuple = heap_copytuple(tuple);
     893      925676 :     ReleaseSysCache(tuple);
     894      925676 :     return newtuple;
     895             : }
     896             : 
     897             : /*
     898             :  * SearchSysCacheExists
     899             :  *
     900             :  * A convenience routine that just probes to see if a tuple can be found.
     901             :  * No lock is retained on the syscache entry.
     902             :  */
     903             : bool
     904     1227102 : SearchSysCacheExists(int cacheId,
     905             :                      Datum key1,
     906             :                      Datum key2,
     907             :                      Datum key3,
     908             :                      Datum key4)
     909             : {
     910             :     HeapTuple   tuple;
     911             : 
     912     1227102 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     913     1227102 :     if (!HeapTupleIsValid(tuple))
     914      301806 :         return false;
     915      925296 :     ReleaseSysCache(tuple);
     916      925296 :     return true;
     917             : }
     918             : 
     919             : /*
     920             :  * GetSysCacheOid
     921             :  *
     922             :  * A convenience routine that does SearchSysCache and returns the OID in the
     923             :  * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
     924             :  * No lock is retained on the syscache entry.
     925             :  */
     926             : Oid
     927     6307276 : GetSysCacheOid(int cacheId,
     928             :                AttrNumber oidcol,
     929             :                Datum key1,
     930             :                Datum key2,
     931             :                Datum key3,
     932             :                Datum key4)
     933             : {
     934             :     HeapTuple   tuple;
     935             :     bool        isNull;
     936             :     Oid         result;
     937             : 
     938     6307276 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     939     6307276 :     if (!HeapTupleIsValid(tuple))
     940     3058154 :         return InvalidOid;
     941     6498244 :     result = heap_getattr(tuple, oidcol,
     942     3249122 :                           SysCache[cacheId]->cc_tupdesc,
     943             :                           &isNull);
     944             :     Assert(!isNull);            /* columns used as oids should never be NULL */
     945     3249122 :     ReleaseSysCache(tuple);
     946     3249122 :     return result;
     947             : }
     948             : 
     949             : 
     950             : /*
     951             :  * SearchSysCacheAttName
     952             :  *
     953             :  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
     954             :  * except that it will return NULL if the found attribute is marked
     955             :  * attisdropped.  This is convenient for callers that want to act as
     956             :  * though dropped attributes don't exist.
     957             :  */
     958             : HeapTuple
     959      236784 : SearchSysCacheAttName(Oid relid, const char *attname)
     960             : {
     961             :     HeapTuple   tuple;
     962             : 
     963      236784 :     tuple = SearchSysCache2(ATTNAME,
     964             :                             ObjectIdGetDatum(relid),
     965             :                             CStringGetDatum(attname));
     966      236784 :     if (!HeapTupleIsValid(tuple))
     967         820 :         return NULL;
     968      235964 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
     969             :     {
     970          78 :         ReleaseSysCache(tuple);
     971          78 :         return NULL;
     972             :     }
     973      235886 :     return tuple;
     974             : }
     975             : 
     976             : /*
     977             :  * SearchSysCacheCopyAttName
     978             :  *
     979             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
     980             :  */
     981             : HeapTuple
     982       58692 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
     983             : {
     984             :     HeapTuple   tuple,
     985             :                 newtuple;
     986             : 
     987       58692 :     tuple = SearchSysCacheAttName(relid, attname);
     988       58692 :     if (!HeapTupleIsValid(tuple))
     989         666 :         return tuple;
     990       58026 :     newtuple = heap_copytuple(tuple);
     991       58026 :     ReleaseSysCache(tuple);
     992       58026 :     return newtuple;
     993             : }
     994             : 
     995             : /*
     996             :  * SearchSysCacheExistsAttName
     997             :  *
     998             :  * As above, an attisdropped-aware version of SearchSysCacheExists.
     999             :  */
    1000             : bool
    1001         792 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
    1002             : {
    1003             :     HeapTuple   tuple;
    1004             : 
    1005         792 :     tuple = SearchSysCacheAttName(relid, attname);
    1006         792 :     if (!HeapTupleIsValid(tuple))
    1007          12 :         return false;
    1008         780 :     ReleaseSysCache(tuple);
    1009         780 :     return true;
    1010             : }
    1011             : 
    1012             : 
    1013             : /*
    1014             :  * SearchSysCacheAttNum
    1015             :  *
    1016             :  * This routine is equivalent to SearchSysCache on the ATTNUM cache,
    1017             :  * except that it will return NULL if the found attribute is marked
    1018             :  * attisdropped.  This is convenient for callers that want to act as
    1019             :  * though dropped attributes don't exist.
    1020             :  */
    1021             : HeapTuple
    1022          92 : SearchSysCacheAttNum(Oid relid, int16 attnum)
    1023             : {
    1024             :     HeapTuple   tuple;
    1025             : 
    1026          92 :     tuple = SearchSysCache2(ATTNUM,
    1027             :                             ObjectIdGetDatum(relid),
    1028             :                             Int16GetDatum(attnum));
    1029          92 :     if (!HeapTupleIsValid(tuple))
    1030          12 :         return NULL;
    1031          80 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
    1032             :     {
    1033           0 :         ReleaseSysCache(tuple);
    1034           0 :         return NULL;
    1035             :     }
    1036          80 :     return tuple;
    1037             : }
    1038             : 
    1039             : /*
    1040             :  * SearchSysCacheCopyAttNum
    1041             :  *
    1042             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
    1043             :  */
    1044             : HeapTuple
    1045          92 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
    1046             : {
    1047             :     HeapTuple   tuple,
    1048             :                 newtuple;
    1049             : 
    1050          92 :     tuple = SearchSysCacheAttNum(relid, attnum);
    1051          92 :     if (!HeapTupleIsValid(tuple))
    1052          12 :         return NULL;
    1053          80 :     newtuple = heap_copytuple(tuple);
    1054          80 :     ReleaseSysCache(tuple);
    1055          80 :     return newtuple;
    1056             : }
    1057             : 
    1058             : 
    1059             : /*
    1060             :  * SysCacheGetAttr
    1061             :  *
    1062             :  *      Given a tuple previously fetched by SearchSysCache(),
    1063             :  *      extract a specific attribute.
    1064             :  *
    1065             :  * This is equivalent to using heap_getattr() on a tuple fetched
    1066             :  * from a non-cached relation.  Usually, this is only used for attributes
    1067             :  * that could be NULL or variable length; the fixed-size attributes in
    1068             :  * a system table are accessed just by mapping the tuple onto the C struct
    1069             :  * declarations from include/catalog/.
    1070             :  *
    1071             :  * As with heap_getattr(), if the attribute is of a pass-by-reference type
    1072             :  * then a pointer into the tuple data area is returned --- the caller must
    1073             :  * not modify or pfree the datum!
    1074             :  *
    1075             :  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
    1076             :  * a different cache for the same catalog the tuple was fetched from.
    1077             :  */
    1078             : Datum
    1079     5516380 : SysCacheGetAttr(int cacheId, HeapTuple tup,
    1080             :                 AttrNumber attributeNumber,
    1081             :                 bool *isNull)
    1082             : {
    1083             :     /*
    1084             :      * We just need to get the TupleDesc out of the cache entry, and then we
    1085             :      * can apply heap_getattr().  Normally the cache control data is already
    1086             :      * valid (because the caller recently fetched the tuple via this same
    1087             :      * cache), but there are cases where we have to initialize the cache here.
    1088             :      */
    1089     5516380 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1090     5516380 :         !PointerIsValid(SysCache[cacheId]))
    1091           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1092     5516380 :     if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
    1093             :     {
    1094       22330 :         InitCatCachePhase2(SysCache[cacheId], false);
    1095             :         Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
    1096             :     }
    1097             : 
    1098    11032760 :     return heap_getattr(tup, attributeNumber,
    1099     5516380 :                         SysCache[cacheId]->cc_tupdesc,
    1100             :                         isNull);
    1101             : }
    1102             : 
    1103             : /*
    1104             :  * SysCacheGetAttrNotNull
    1105             :  *
    1106             :  * As above, a version of SysCacheGetAttr which knows that the attr cannot
    1107             :  * be NULL.
    1108             :  */
    1109             : Datum
    1110     2916604 : SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
    1111             :                        AttrNumber attributeNumber)
    1112             : {
    1113             :     bool        isnull;
    1114             :     Datum       attr;
    1115             : 
    1116     2916604 :     attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
    1117             : 
    1118     2916604 :     if (isnull)
    1119             :     {
    1120           0 :         elog(ERROR,
    1121             :              "unexpected null value in cached tuple for catalog %s column %s",
    1122             :              get_rel_name(cacheinfo[cacheId].reloid),
    1123             :              NameStr(TupleDescAttr(SysCache[cacheId]->cc_tupdesc, attributeNumber - 1)->attname));
    1124             :     }
    1125             : 
    1126     2916604 :     return attr;
    1127             : }
    1128             : 
    1129             : /*
    1130             :  * GetSysCacheHashValue
    1131             :  *
    1132             :  * Get the hash value that would be used for a tuple in the specified cache
    1133             :  * with the given search keys.
    1134             :  *
    1135             :  * The reason for exposing this as part of the API is that the hash value is
    1136             :  * exposed in cache invalidation operations, so there are places outside the
    1137             :  * catcache code that need to be able to compute the hash values.
    1138             :  */
    1139             : uint32
    1140      214786 : GetSysCacheHashValue(int cacheId,
    1141             :                      Datum key1,
    1142             :                      Datum key2,
    1143             :                      Datum key3,
    1144             :                      Datum key4)
    1145             : {
    1146      214786 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1147      214786 :         !PointerIsValid(SysCache[cacheId]))
    1148           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1149             : 
    1150      214786 :     return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
    1151             : }
    1152             : 
    1153             : /*
    1154             :  * List-search interface
    1155             :  */
    1156             : struct catclist *
    1157     3117474 : SearchSysCacheList(int cacheId, int nkeys,
    1158             :                    Datum key1, Datum key2, Datum key3)
    1159             : {
    1160     3117474 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1161     3117474 :         !PointerIsValid(SysCache[cacheId]))
    1162           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1163             : 
    1164     3117474 :     return SearchCatCacheList(SysCache[cacheId], nkeys,
    1165             :                               key1, key2, key3);
    1166             : }
    1167             : 
    1168             : /*
    1169             :  * SysCacheInvalidate
    1170             :  *
    1171             :  *  Invalidate entries in the specified cache, given a hash value.
    1172             :  *  See CatCacheInvalidate() for more info.
    1173             :  *
    1174             :  *  This routine is only quasi-public: it should only be used by inval.c.
    1175             :  */
    1176             : void
    1177    25035450 : SysCacheInvalidate(int cacheId, uint32 hashValue)
    1178             : {
    1179    25035450 :     if (cacheId < 0 || cacheId >= SysCacheSize)
    1180           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1181             : 
    1182             :     /* if this cache isn't initialized yet, no need to do anything */
    1183    25035450 :     if (!PointerIsValid(SysCache[cacheId]))
    1184           0 :         return;
    1185             : 
    1186    25035450 :     CatCacheInvalidate(SysCache[cacheId], hashValue);
    1187             : }
    1188             : 
    1189             : /*
    1190             :  * Certain relations that do not have system caches send snapshot invalidation
    1191             :  * messages in lieu of catcache messages.  This is for the benefit of
    1192             :  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
    1193             :  * for scanning one of those catalogs, rather than taking a new one, if no
    1194             :  * invalidation has been received.
    1195             :  *
    1196             :  * Relations that have syscaches need not (and must not) be listed here.  The
    1197             :  * catcache invalidation messages will also flush the snapshot.  If you add a
    1198             :  * syscache for one of these relations, remove it from this list.
    1199             :  */
    1200             : bool
    1201    21084520 : RelationInvalidatesSnapshotsOnly(Oid relid)
    1202             : {
    1203    21084520 :     switch (relid)
    1204             :     {
    1205     4018762 :         case DbRoleSettingRelationId:
    1206             :         case DependRelationId:
    1207             :         case SharedDependRelationId:
    1208             :         case DescriptionRelationId:
    1209             :         case SharedDescriptionRelationId:
    1210             :         case SecLabelRelationId:
    1211             :         case SharedSecLabelRelationId:
    1212     4018762 :             return true;
    1213    17065758 :         default:
    1214    17065758 :             break;
    1215             :     }
    1216             : 
    1217    17065758 :     return false;
    1218             : }
    1219             : 
    1220             : /*
    1221             :  * Test whether a relation has a system cache.
    1222             :  */
    1223             : bool
    1224    12036080 : RelationHasSysCache(Oid relid)
    1225             : {
    1226    12036080 :     int         low = 0,
    1227    12036080 :                 high = SysCacheRelationOidSize - 1;
    1228             : 
    1229    53583876 :     while (low <= high)
    1230             :     {
    1231    53210278 :         int         middle = low + (high - low) / 2;
    1232             : 
    1233    53210278 :         if (SysCacheRelationOid[middle] == relid)
    1234    11662482 :             return true;
    1235    41547796 :         if (SysCacheRelationOid[middle] < relid)
    1236    14894208 :             low = middle + 1;
    1237             :         else
    1238    26653588 :             high = middle - 1;
    1239             :     }
    1240             : 
    1241      373598 :     return false;
    1242             : }
    1243             : 
    1244             : /*
    1245             :  * Test whether a relation supports a system cache, ie it is either a
    1246             :  * cached table or the index used for a cache.
    1247             :  */
    1248             : bool
    1249     3099104 : RelationSupportsSysCache(Oid relid)
    1250             : {
    1251     3099104 :     int         low = 0,
    1252     3099104 :                 high = SysCacheSupportingRelOidSize - 1;
    1253             : 
    1254    26279474 :     while (low <= high)
    1255             :     {
    1256    23693272 :         int         middle = low + (high - low) / 2;
    1257             : 
    1258    23693272 :         if (SysCacheSupportingRelOid[middle] == relid)
    1259      512902 :             return true;
    1260    23180370 :         if (SysCacheSupportingRelOid[middle] < relid)
    1261    21442650 :             low = middle + 1;
    1262             :         else
    1263     1737720 :             high = middle - 1;
    1264             :     }
    1265             : 
    1266     2586202 :     return false;
    1267             : }
    1268             : 
    1269             : 
    1270             : /*
    1271             :  * OID comparator for pg_qsort
    1272             :  */
    1273             : static int
    1274    45620328 : oid_compare(const void *a, const void *b)
    1275             : {
    1276    45620328 :     Oid         oa = *((const Oid *) a);
    1277    45620328 :     Oid         ob = *((const Oid *) b);
    1278             : 
    1279    45620328 :     if (oa == ob)
    1280     3869796 :         return 0;
    1281    41750532 :     return (oa > ob) ? 1 : -1;
    1282             : }

Generated by: LCOV version 1.14