LCOV - differential code coverage report
Current view: top level - src/backend/utils/cache - syscache.c (source / functions) Coverage Total Hit UNC UIC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 95.0 % 180 171 1 8 3 150 5 13 4 70 2 88
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 25 25 24 1 12 13
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a