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

Generated by: LCOV version 1.13