LCOV - code coverage report
Current view: top level - src/backend/utils/cache - syscache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 146 154 94.8 %
Date: 2019-06-19 14:06:47 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_rewrite.h"
      57             : #include "catalog/pg_seclabel.h"
      58             : #include "catalog/pg_sequence.h"
      59             : #include "catalog/pg_shdepend.h"
      60             : #include "catalog/pg_shdescription.h"
      61             : #include "catalog/pg_shseclabel.h"
      62             : #include "catalog/pg_replication_origin.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 "utils/rel.h"
      78             : #include "utils/catcache.h"
      79             : #include "utils/syscache.h"
      80             : 
      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        9798 : InitCatalogCache(void)
    1011             : {
    1012             :     int         cacheId;
    1013             :     int         i,
    1014             :                 j;
    1015             : 
    1016             :     StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo),
    1017             :                      "SysCacheSize does not match syscache.c's array");
    1018             : 
    1019             :     Assert(!CacheInitialized);
    1020             : 
    1021        9798 :     SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
    1022             : 
    1023      774042 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
    1024             :     {
    1025     1528488 :         SysCache[cacheId] = InitCatCache(cacheId,
    1026             :                                          cacheinfo[cacheId].reloid,
    1027             :                                          cacheinfo[cacheId].indoid,
    1028             :                                          cacheinfo[cacheId].nkeys,
    1029      764244 :                                          cacheinfo[cacheId].key,
    1030             :                                          cacheinfo[cacheId].nbuckets);
    1031      764244 :         if (!PointerIsValid(SysCache[cacheId]))
    1032           0 :             elog(ERROR, "could not initialize cache %u (%d)",
    1033             :                  cacheinfo[cacheId].reloid, cacheId);
    1034             :         /* Accumulate data for OID lists, too */
    1035     1528488 :         SysCacheRelationOid[SysCacheRelationOidSize++] =
    1036      764244 :             cacheinfo[cacheId].reloid;
    1037     1528488 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
    1038      764244 :             cacheinfo[cacheId].reloid;
    1039     1528488 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
    1040      764244 :             cacheinfo[cacheId].indoid;
    1041             :         /* see comments for RelationInvalidatesSnapshotsOnly */
    1042             :         Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
    1043             :     }
    1044             : 
    1045             :     Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
    1046             :     Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
    1047             : 
    1048             :     /* Sort and de-dup OID arrays, so we can use binary search. */
    1049        9798 :     pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
    1050             :              sizeof(Oid), oid_compare);
    1051      764244 :     for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
    1052             :     {
    1053      754446 :         if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
    1054      450708 :             SysCacheRelationOid[++j] = SysCacheRelationOid[i];
    1055             :     }
    1056        9798 :     SysCacheRelationOidSize = j + 1;
    1057             : 
    1058        9798 :     pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
    1059             :              sizeof(Oid), oid_compare);
    1060     1528488 :     for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
    1061             :     {
    1062     1518690 :         if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
    1063     1214952 :             SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
    1064             :     }
    1065        9798 :     SysCacheSupportingRelOidSize = j + 1;
    1066             : 
    1067        9798 :     CacheInitialized = true;
    1068        9798 : }
    1069             : 
    1070             : /*
    1071             :  * InitCatalogCachePhase2 - finish initializing the caches
    1072             :  *
    1073             :  * Finish initializing all the caches, including necessary database
    1074             :  * access.
    1075             :  *
    1076             :  * This is *not* essential; normally we allow syscaches to be initialized
    1077             :  * on first use.  However, it is useful as a mechanism to preload the
    1078             :  * relcache with entries for the most-commonly-used system catalogs.
    1079             :  * Therefore, we invoke this routine when we need to write a new relcache
    1080             :  * init file.
    1081             :  */
    1082             : void
    1083        1264 : InitCatalogCachePhase2(void)
    1084             : {
    1085             :     int         cacheId;
    1086             : 
    1087             :     Assert(CacheInitialized);
    1088             : 
    1089       99856 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
    1090       98592 :         InitCatCachePhase2(SysCache[cacheId], true);
    1091        1264 : }
    1092             : 
    1093             : 
    1094             : /*
    1095             :  * SearchSysCache
    1096             :  *
    1097             :  *  A layer on top of SearchCatCache that does the initialization and
    1098             :  *  key-setting for you.
    1099             :  *
    1100             :  *  Returns the cache copy of the tuple if one is found, NULL if not.
    1101             :  *  The tuple is the 'cache' copy and must NOT be modified!
    1102             :  *
    1103             :  *  When the caller is done using the tuple, call ReleaseSysCache()
    1104             :  *  to release the reference count grabbed by SearchSysCache().  If this
    1105             :  *  is not done, the tuple will remain locked in cache until end of
    1106             :  *  transaction, which is tolerable but not desirable.
    1107             :  *
    1108             :  *  CAUTION: The tuple that is returned must NOT be freed by the caller!
    1109             :  */
    1110             : HeapTuple
    1111     4457548 : SearchSysCache(int cacheId,
    1112             :                Datum key1,
    1113             :                Datum key2,
    1114             :                Datum key3,
    1115             :                Datum key4)
    1116             : {
    1117             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
    1118             :            PointerIsValid(SysCache[cacheId]));
    1119             : 
    1120     4457548 :     return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
    1121             : }
    1122             : 
    1123             : HeapTuple
    1124    44031418 : SearchSysCache1(int cacheId,
    1125             :                 Datum key1)
    1126             : {
    1127             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
    1128             :            PointerIsValid(SysCache[cacheId]));
    1129             :     Assert(SysCache[cacheId]->cc_nkeys == 1);
    1130             : 
    1131    44031418 :     return SearchCatCache1(SysCache[cacheId], key1);
    1132             : }
    1133             : 
    1134             : HeapTuple
    1135     4144336 : SearchSysCache2(int cacheId,
    1136             :                 Datum key1, Datum key2)
    1137             : {
    1138             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
    1139             :            PointerIsValid(SysCache[cacheId]));
    1140             :     Assert(SysCache[cacheId]->cc_nkeys == 2);
    1141             : 
    1142     4144336 :     return SearchCatCache2(SysCache[cacheId], key1, key2);
    1143             : }
    1144             : 
    1145             : HeapTuple
    1146     2898200 : SearchSysCache3(int cacheId,
    1147             :                 Datum key1, Datum key2, Datum key3)
    1148             : {
    1149             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
    1150             :            PointerIsValid(SysCache[cacheId]));
    1151             :     Assert(SysCache[cacheId]->cc_nkeys == 3);
    1152             : 
    1153     2898200 :     return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
    1154             : }
    1155             : 
    1156             : HeapTuple
    1157     3362222 : SearchSysCache4(int cacheId,
    1158             :                 Datum key1, Datum key2, Datum key3, Datum key4)
    1159             : {
    1160             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
    1161             :            PointerIsValid(SysCache[cacheId]));
    1162             :     Assert(SysCache[cacheId]->cc_nkeys == 4);
    1163             : 
    1164     3362222 :     return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
    1165             : }
    1166             : 
    1167             : /*
    1168             :  * ReleaseSysCache
    1169             :  *      Release previously grabbed reference count on a tuple
    1170             :  */
    1171             : void
    1172    54846626 : ReleaseSysCache(HeapTuple tuple)
    1173             : {
    1174    54846626 :     ReleaseCatCache(tuple);
    1175    54846626 : }
    1176             : 
    1177             : /*
    1178             :  * SearchSysCacheCopy
    1179             :  *
    1180             :  * A convenience routine that does SearchSysCache and (if successful)
    1181             :  * returns a modifiable copy of the syscache entry.  The original
    1182             :  * syscache entry is released before returning.  The caller should
    1183             :  * heap_freetuple() the result when done with it.
    1184             :  */
    1185             : HeapTuple
    1186      722638 : SearchSysCacheCopy(int cacheId,
    1187             :                    Datum key1,
    1188             :                    Datum key2,
    1189             :                    Datum key3,
    1190             :                    Datum key4)
    1191             : {
    1192             :     HeapTuple   tuple,
    1193             :                 newtuple;
    1194             : 
    1195      722638 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
    1196      722638 :     if (!HeapTupleIsValid(tuple))
    1197      129174 :         return tuple;
    1198      593464 :     newtuple = heap_copytuple(tuple);
    1199      593464 :     ReleaseSysCache(tuple);
    1200      593464 :     return newtuple;
    1201             : }
    1202             : 
    1203             : /*
    1204             :  * SearchSysCacheExists
    1205             :  *
    1206             :  * A convenience routine that just probes to see if a tuple can be found.
    1207             :  * No lock is retained on the syscache entry.
    1208             :  */
    1209             : bool
    1210      474874 : SearchSysCacheExists(int cacheId,
    1211             :                      Datum key1,
    1212             :                      Datum key2,
    1213             :                      Datum key3,
    1214             :                      Datum key4)
    1215             : {
    1216             :     HeapTuple   tuple;
    1217             : 
    1218      474874 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
    1219      474874 :     if (!HeapTupleIsValid(tuple))
    1220       78220 :         return false;
    1221      396654 :     ReleaseSysCache(tuple);
    1222      396654 :     return true;
    1223             : }
    1224             : 
    1225             : /*
    1226             :  * GetSysCacheOid
    1227             :  *
    1228             :  * A convenience routine that does SearchSysCache and returns the OID in the
    1229             :  * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
    1230             :  * No lock is retained on the syscache entry.
    1231             :  */
    1232             : Oid
    1233     3260036 : GetSysCacheOid(int cacheId,
    1234             :                AttrNumber oidcol,
    1235             :                Datum key1,
    1236             :                Datum key2,
    1237             :                Datum key3,
    1238             :                Datum key4)
    1239             : {
    1240             :     HeapTuple   tuple;
    1241             :     bool        isNull;
    1242             :     Oid         result;
    1243             : 
    1244     3260036 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
    1245     3260036 :     if (!HeapTupleIsValid(tuple))
    1246     1430500 :         return InvalidOid;
    1247     1829536 :     result = heap_getattr(tuple, oidcol,
    1248             :                           SysCache[cacheId]->cc_tupdesc,
    1249             :                           &isNull);
    1250             :     Assert(!isNull);            /* columns used as oids should never be NULL */
    1251     1829536 :     ReleaseSysCache(tuple);
    1252     1829536 :     return result;
    1253             : }
    1254             : 
    1255             : 
    1256             : /*
    1257             :  * SearchSysCacheAttName
    1258             :  *
    1259             :  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
    1260             :  * except that it will return NULL if the found attribute is marked
    1261             :  * attisdropped.  This is convenient for callers that want to act as
    1262             :  * though dropped attributes don't exist.
    1263             :  */
    1264             : HeapTuple
    1265       92802 : SearchSysCacheAttName(Oid relid, const char *attname)
    1266             : {
    1267             :     HeapTuple   tuple;
    1268             : 
    1269       92802 :     tuple = SearchSysCache2(ATTNAME,
    1270             :                             ObjectIdGetDatum(relid),
    1271             :                             CStringGetDatum(attname));
    1272       92802 :     if (!HeapTupleIsValid(tuple))
    1273         536 :         return NULL;
    1274       92266 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
    1275             :     {
    1276          52 :         ReleaseSysCache(tuple);
    1277          52 :         return NULL;
    1278             :     }
    1279       92214 :     return tuple;
    1280             : }
    1281             : 
    1282             : /*
    1283             :  * SearchSysCacheCopyAttName
    1284             :  *
    1285             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
    1286             :  */
    1287             : HeapTuple
    1288        5100 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
    1289             : {
    1290             :     HeapTuple   tuple,
    1291             :                 newtuple;
    1292             : 
    1293        5100 :     tuple = SearchSysCacheAttName(relid, attname);
    1294        5100 :     if (!HeapTupleIsValid(tuple))
    1295         440 :         return tuple;
    1296        4660 :     newtuple = heap_copytuple(tuple);
    1297        4660 :     ReleaseSysCache(tuple);
    1298        4660 :     return newtuple;
    1299             : }
    1300             : 
    1301             : /*
    1302             :  * SearchSysCacheExistsAttName
    1303             :  *
    1304             :  * As above, an attisdropped-aware version of SearchSysCacheExists.
    1305             :  */
    1306             : bool
    1307         262 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
    1308             : {
    1309             :     HeapTuple   tuple;
    1310             : 
    1311         262 :     tuple = SearchSysCacheAttName(relid, attname);
    1312         262 :     if (!HeapTupleIsValid(tuple))
    1313           8 :         return false;
    1314         254 :     ReleaseSysCache(tuple);
    1315         254 :     return true;
    1316             : }
    1317             : 
    1318             : 
    1319             : /*
    1320             :  * SearchSysCacheAttNum
    1321             :  *
    1322             :  * This routine is equivalent to SearchSysCache on the ATTNUM cache,
    1323             :  * except that it will return NULL if the found attribute is marked
    1324             :  * attisdropped.  This is convenient for callers that want to act as
    1325             :  * though dropped attributes don't exist.
    1326             :  */
    1327             : HeapTuple
    1328          40 : SearchSysCacheAttNum(Oid relid, int16 attnum)
    1329             : {
    1330             :     HeapTuple   tuple;
    1331             : 
    1332          40 :     tuple = SearchSysCache2(ATTNUM,
    1333             :                             ObjectIdGetDatum(relid),
    1334             :                             Int16GetDatum(attnum));
    1335          40 :     if (!HeapTupleIsValid(tuple))
    1336           8 :         return NULL;
    1337          32 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
    1338             :     {
    1339           0 :         ReleaseSysCache(tuple);
    1340           0 :         return NULL;
    1341             :     }
    1342          32 :     return tuple;
    1343             : }
    1344             : 
    1345             : /*
    1346             :  * SearchSysCacheCopyAttNum
    1347             :  *
    1348             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
    1349             :  */
    1350             : HeapTuple
    1351          40 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
    1352             : {
    1353             :     HeapTuple   tuple,
    1354             :                 newtuple;
    1355             : 
    1356          40 :     tuple = SearchSysCacheAttNum(relid, attnum);
    1357          40 :     if (!HeapTupleIsValid(tuple))
    1358           8 :         return NULL;
    1359          32 :     newtuple = heap_copytuple(tuple);
    1360          32 :     ReleaseSysCache(tuple);
    1361          32 :     return newtuple;
    1362             : }
    1363             : 
    1364             : 
    1365             : /*
    1366             :  * SysCacheGetAttr
    1367             :  *
    1368             :  *      Given a tuple previously fetched by SearchSysCache(),
    1369             :  *      extract a specific attribute.
    1370             :  *
    1371             :  * This is equivalent to using heap_getattr() on a tuple fetched
    1372             :  * from a non-cached relation.  Usually, this is only used for attributes
    1373             :  * that could be NULL or variable length; the fixed-size attributes in
    1374             :  * a system table are accessed just by mapping the tuple onto the C struct
    1375             :  * declarations from include/catalog/.
    1376             :  *
    1377             :  * As with heap_getattr(), if the attribute is of a pass-by-reference type
    1378             :  * then a pointer into the tuple data area is returned --- the caller must
    1379             :  * not modify or pfree the datum!
    1380             :  *
    1381             :  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
    1382             :  * a different cache for the same catalog the tuple was fetched from.
    1383             :  */
    1384             : Datum
    1385     2118454 : SysCacheGetAttr(int cacheId, HeapTuple tup,
    1386             :                 AttrNumber attributeNumber,
    1387             :                 bool *isNull)
    1388             : {
    1389             :     /*
    1390             :      * We just need to get the TupleDesc out of the cache entry, and then we
    1391             :      * can apply heap_getattr().  Normally the cache control data is already
    1392             :      * valid (because the caller recently fetched the tuple via this same
    1393             :      * cache), but there are cases where we have to initialize the cache here.
    1394             :      */
    1395     4236908 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1396     2118454 :         !PointerIsValid(SysCache[cacheId]))
    1397           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1398     2118454 :     if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
    1399             :     {
    1400          94 :         InitCatCachePhase2(SysCache[cacheId], false);
    1401             :         Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
    1402             :     }
    1403             : 
    1404     2118454 :     return heap_getattr(tup, attributeNumber,
    1405             :                         SysCache[cacheId]->cc_tupdesc,
    1406             :                         isNull);
    1407             : }
    1408             : 
    1409             : /*
    1410             :  * GetSysCacheHashValue
    1411             :  *
    1412             :  * Get the hash value that would be used for a tuple in the specified cache
    1413             :  * with the given search keys.
    1414             :  *
    1415             :  * The reason for exposing this as part of the API is that the hash value is
    1416             :  * exposed in cache invalidation operations, so there are places outside the
    1417             :  * catcache code that need to be able to compute the hash values.
    1418             :  */
    1419             : uint32
    1420       94314 : GetSysCacheHashValue(int cacheId,
    1421             :                      Datum key1,
    1422             :                      Datum key2,
    1423             :                      Datum key3,
    1424             :                      Datum key4)
    1425             : {
    1426      188628 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1427       94314 :         !PointerIsValid(SysCache[cacheId]))
    1428           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1429             : 
    1430       94314 :     return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
    1431             : }
    1432             : 
    1433             : /*
    1434             :  * List-search interface
    1435             :  */
    1436             : struct catclist *
    1437     3208372 : SearchSysCacheList(int cacheId, int nkeys,
    1438             :                    Datum key1, Datum key2, Datum key3)
    1439             : {
    1440     6416744 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
    1441     3208372 :         !PointerIsValid(SysCache[cacheId]))
    1442           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1443             : 
    1444     3208372 :     return SearchCatCacheList(SysCache[cacheId], nkeys,
    1445             :                               key1, key2, key3);
    1446             : }
    1447             : 
    1448             : /*
    1449             :  * SysCacheInvalidate
    1450             :  *
    1451             :  *  Invalidate entries in the specified cache, given a hash value.
    1452             :  *  See CatCacheInvalidate() for more info.
    1453             :  *
    1454             :  *  This routine is only quasi-public: it should only be used by inval.c.
    1455             :  */
    1456             : void
    1457     9851950 : SysCacheInvalidate(int cacheId, uint32 hashValue)
    1458             : {
    1459     9851950 :     if (cacheId < 0 || cacheId >= SysCacheSize)
    1460           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
    1461             : 
    1462             :     /* if this cache isn't initialized yet, no need to do anything */
    1463     9851950 :     if (!PointerIsValid(SysCache[cacheId]))
    1464           0 :         return;
    1465             : 
    1466     9851950 :     CatCacheInvalidate(SysCache[cacheId], hashValue);
    1467             : }
    1468             : 
    1469             : /*
    1470             :  * Certain relations that do not have system caches send snapshot invalidation
    1471             :  * messages in lieu of catcache messages.  This is for the benefit of
    1472             :  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
    1473             :  * for scanning one of those catalogs, rather than taking a new one, if no
    1474             :  * invalidation has been received.
    1475             :  *
    1476             :  * Relations that have syscaches need not (and must not) be listed here.  The
    1477             :  * catcache invalidation messages will also flush the snapshot.  If you add a
    1478             :  * syscache for one of these relations, remove it from this list.
    1479             :  */
    1480             : bool
    1481    14732212 : RelationInvalidatesSnapshotsOnly(Oid relid)
    1482             : {
    1483    14732212 :     switch (relid)
    1484             :     {
    1485             :         case DbRoleSettingRelationId:
    1486             :         case DependRelationId:
    1487             :         case SharedDependRelationId:
    1488             :         case DescriptionRelationId:
    1489             :         case SharedDescriptionRelationId:
    1490             :         case SecLabelRelationId:
    1491             :         case SharedSecLabelRelationId:
    1492     7413692 :             return true;
    1493             :         default:
    1494     7318520 :             break;
    1495             :     }
    1496             : 
    1497     7318520 :     return false;
    1498             : }
    1499             : 
    1500             : /*
    1501             :  * Test whether a relation has a system cache.
    1502             :  */
    1503             : bool
    1504     5305144 : RelationHasSysCache(Oid relid)
    1505             : {
    1506     5305144 :     int         low = 0,
    1507     5305144 :                 high = SysCacheRelationOidSize - 1;
    1508             : 
    1509    27385266 :     while (low <= high)
    1510             :     {
    1511    21868982 :         int         middle = low + (high - low) / 2;
    1512             : 
    1513    21868982 :         if (SysCacheRelationOid[middle] == relid)
    1514     5094004 :             return true;
    1515    16774978 :         if (SysCacheRelationOid[middle] < relid)
    1516     5173072 :             low = middle + 1;
    1517             :         else
    1518    11601906 :             high = middle - 1;
    1519             :     }
    1520             : 
    1521      211140 :     return false;
    1522             : }
    1523             : 
    1524             : /*
    1525             :  * Test whether a relation supports a system cache, ie it is either a
    1526             :  * cached table or the index used for a cache.
    1527             :  */
    1528             : bool
    1529     1590844 : RelationSupportsSysCache(Oid relid)
    1530             : {
    1531     1590844 :     int         low = 0,
    1532     1590844 :                 high = SysCacheSupportingRelOidSize - 1;
    1533             : 
    1534    13862022 :     while (low <= high)
    1535             :     {
    1536    10914324 :         int         middle = low + (high - low) / 2;
    1537             : 
    1538    10914324 :         if (SysCacheSupportingRelOid[middle] == relid)
    1539      233990 :             return true;
    1540    10680334 :         if (SysCacheSupportingRelOid[middle] < relid)
    1541     9869858 :             low = middle + 1;
    1542             :         else
    1543      810476 :             high = middle - 1;
    1544             :     }
    1545             : 
    1546     1356854 :     return false;
    1547             : }
    1548             : 
    1549             : 
    1550             : /*
    1551             :  * OID comparator for pg_qsort
    1552             :  */
    1553             : static int
    1554    14912556 : oid_compare(const void *a, const void *b)
    1555             : {
    1556    14912556 :     Oid         oa = *((const Oid *) a);
    1557    14912556 :     Oid         ob = *((const Oid *) b);
    1558             : 
    1559    14912556 :     if (oa == ob)
    1560      813234 :         return 0;
    1561    14099322 :     return (oa > ob) ? 1 : -1;
    1562             : }

Generated by: LCOV version 1.13