LCOV - code coverage report
Current view: top level - src/backend/utils/cache - syscache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 147 157 93.6 %
Date: 2024-04-19 02:11:33 Functions: 25 25 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * syscache.c
       4             :  *    System cache management routines
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, 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 "catalog/pg_db_role_setting_d.h"
      25             : #include "catalog/pg_depend_d.h"
      26             : #include "catalog/pg_description_d.h"
      27             : #include "catalog/pg_seclabel_d.h"
      28             : #include "catalog/pg_shdepend_d.h"
      29             : #include "catalog/pg_shdescription_d.h"
      30             : #include "catalog/pg_shseclabel_d.h"
      31             : #include "common/int.h"
      32             : #include "lib/qunique.h"
      33             : #include "utils/catcache.h"
      34             : #include "utils/lsyscache.h"
      35             : #include "utils/rel.h"
      36             : #include "utils/syscache.h"
      37             : 
      38             : /*---------------------------------------------------------------------------
      39             : 
      40             :     Adding system caches:
      41             : 
      42             :     There must be a unique index underlying each syscache (ie, an index
      43             :     whose key is the same as that of the cache).  If there is not one
      44             :     already, add the definition for it to include/catalog/pg_*.h using
      45             :     DECLARE_UNIQUE_INDEX.
      46             :     (Adding an index requires a catversion.h update, while simply
      47             :     adding/deleting caches only requires a recompile.)
      48             : 
      49             :     Add a MAKE_SYSCACHE call to the same pg_*.h file specifying the name of
      50             :     your cache, the underlying index, and the initial number of hash buckets.
      51             : 
      52             :     The number of hash buckets must be a power of 2.  It's reasonable to
      53             :     set this to the number of entries that might be in the particular cache
      54             :     in a medium-size database.
      55             : 
      56             :     Finally, any place your relation gets heap_insert() or
      57             :     heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
      58             :     instead, which also update indexes.  The heap_* calls do not do that.
      59             : 
      60             : *---------------------------------------------------------------------------
      61             : */
      62             : 
      63             : /*
      64             :  *      struct cachedesc: information defining a single syscache
      65             :  */
      66             : struct cachedesc
      67             : {
      68             :     Oid         reloid;         /* OID of the relation being cached */
      69             :     Oid         indoid;         /* OID of index relation for this cache */
      70             :     int         nkeys;          /* # of keys needed for cache lookup */
      71             :     int         key[4];         /* attribute numbers of key attrs */
      72             :     int         nbuckets;       /* number of hash buckets for this cache */
      73             : };
      74             : 
      75             : /* Macro to provide nkeys and key array with convenient syntax. */
      76             : #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
      77             : 
      78             : #include "catalog/syscache_info.h"
      79             : 
      80             : StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
      81             :                  "SysCacheSize does not match syscache.c's array");
      82             : 
      83             : static CatCache *SysCache[SysCacheSize];
      84             : 
      85             : static bool CacheInitialized = false;
      86             : 
      87             : /* Sorted array of OIDs of tables that have caches on them */
      88             : static Oid  SysCacheRelationOid[SysCacheSize];
      89             : static int  SysCacheRelationOidSize;
      90             : 
      91             : /* Sorted array of OIDs of tables and indexes used by caches */
      92             : static Oid  SysCacheSupportingRelOid[SysCacheSize * 2];
      93             : static int  SysCacheSupportingRelOidSize;
      94             : 
      95             : static int  oid_compare(const void *a, const void *b);
      96             : 
      97             : 
      98             : /*
      99             :  * InitCatalogCache - initialize the caches
     100             :  *
     101             :  * Note that no database access is done here; we only allocate memory
     102             :  * and initialize the cache structure.  Interrogation of the database
     103             :  * to complete initialization of a cache happens upon first use
     104             :  * of that cache.
     105             :  */
     106             : void
     107       25896 : InitCatalogCache(void)
     108             : {
     109             :     int         cacheId;
     110             : 
     111             :     Assert(!CacheInitialized);
     112             : 
     113       25896 :     SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
     114             : 
     115     2175264 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
     116             :     {
     117             :         /*
     118             :          * Assert that every enumeration value defined in syscache.h has been
     119             :          * populated in the cacheinfo array.
     120             :          */
     121             :         Assert(OidIsValid(cacheinfo[cacheId].reloid));
     122             :         Assert(OidIsValid(cacheinfo[cacheId].indoid));
     123             :         /* .nbuckets and .key[] are checked by InitCatCache() */
     124             : 
     125     4298736 :         SysCache[cacheId] = InitCatCache(cacheId,
     126             :                                          cacheinfo[cacheId].reloid,
     127             :                                          cacheinfo[cacheId].indoid,
     128             :                                          cacheinfo[cacheId].nkeys,
     129     2149368 :                                          cacheinfo[cacheId].key,
     130             :                                          cacheinfo[cacheId].nbuckets);
     131     2149368 :         if (!PointerIsValid(SysCache[cacheId]))
     132           0 :             elog(ERROR, "could not initialize cache %u (%d)",
     133             :                  cacheinfo[cacheId].reloid, cacheId);
     134             :         /* Accumulate data for OID lists, too */
     135     2149368 :         SysCacheRelationOid[SysCacheRelationOidSize++] =
     136     2149368 :             cacheinfo[cacheId].reloid;
     137     2149368 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     138     2149368 :             cacheinfo[cacheId].reloid;
     139     2149368 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     140     2149368 :             cacheinfo[cacheId].indoid;
     141             :         /* see comments for RelationInvalidatesSnapshotsOnly */
     142             :         Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
     143             :     }
     144             : 
     145             :     Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
     146             :     Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
     147             : 
     148             :     /* Sort and de-dup OID arrays, so we can use binary search. */
     149       25896 :     qsort(SysCacheRelationOid, SysCacheRelationOidSize,
     150             :           sizeof(Oid), oid_compare);
     151       25896 :     SysCacheRelationOidSize =
     152       25896 :         qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
     153             :                 oid_compare);
     154             : 
     155       25896 :     qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     156             :           sizeof(Oid), oid_compare);
     157       25896 :     SysCacheSupportingRelOidSize =
     158       25896 :         qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     159             :                 sizeof(Oid), oid_compare);
     160             : 
     161       25896 :     CacheInitialized = true;
     162       25896 : }
     163             : 
     164             : /*
     165             :  * InitCatalogCachePhase2 - finish initializing the caches
     166             :  *
     167             :  * Finish initializing all the caches, including necessary database
     168             :  * access.
     169             :  *
     170             :  * This is *not* essential; normally we allow syscaches to be initialized
     171             :  * on first use.  However, it is useful as a mechanism to preload the
     172             :  * relcache with entries for the most-commonly-used system catalogs.
     173             :  * Therefore, we invoke this routine when we need to write a new relcache
     174             :  * init file.
     175             :  */
     176             : void
     177        2164 : InitCatalogCachePhase2(void)
     178             : {
     179             :     int         cacheId;
     180             : 
     181             :     Assert(CacheInitialized);
     182             : 
     183      181738 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
     184      179576 :         InitCatCachePhase2(SysCache[cacheId], true);
     185        2162 : }
     186             : 
     187             : 
     188             : /*
     189             :  * SearchSysCache
     190             :  *
     191             :  *  A layer on top of SearchCatCache that does the initialization and
     192             :  *  key-setting for you.
     193             :  *
     194             :  *  Returns the cache copy of the tuple if one is found, NULL if not.
     195             :  *  The tuple is the 'cache' copy and must NOT be modified!
     196             :  *
     197             :  *  When the caller is done using the tuple, call ReleaseSysCache()
     198             :  *  to release the reference count grabbed by SearchSysCache().  If this
     199             :  *  is not done, the tuple will remain locked in cache until end of
     200             :  *  transaction, which is tolerable but not desirable.
     201             :  *
     202             :  *  CAUTION: The tuple that is returned must NOT be freed by the caller!
     203             :  */
     204             : HeapTuple
     205     4728696 : SearchSysCache(int cacheId,
     206             :                Datum key1,
     207             :                Datum key2,
     208             :                Datum key3,
     209             :                Datum key4)
     210             : {
     211             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     212             :            PointerIsValid(SysCache[cacheId]));
     213             : 
     214     4728696 :     return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
     215             : }
     216             : 
     217             : HeapTuple
     218    57099338 : SearchSysCache1(int cacheId,
     219             :                 Datum key1)
     220             : {
     221             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     222             :            PointerIsValid(SysCache[cacheId]));
     223             :     Assert(SysCache[cacheId]->cc_nkeys == 1);
     224             : 
     225    57099338 :     return SearchCatCache1(SysCache[cacheId], key1);
     226             : }
     227             : 
     228             : HeapTuple
     229     4540694 : SearchSysCache2(int cacheId,
     230             :                 Datum key1, Datum key2)
     231             : {
     232             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     233             :            PointerIsValid(SysCache[cacheId]));
     234             :     Assert(SysCache[cacheId]->cc_nkeys == 2);
     235             : 
     236     4540694 :     return SearchCatCache2(SysCache[cacheId], key1, key2);
     237             : }
     238             : 
     239             : HeapTuple
     240     4485800 : SearchSysCache3(int cacheId,
     241             :                 Datum key1, Datum key2, Datum key3)
     242             : {
     243             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     244             :            PointerIsValid(SysCache[cacheId]));
     245             :     Assert(SysCache[cacheId]->cc_nkeys == 3);
     246             : 
     247     4485800 :     return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
     248             : }
     249             : 
     250             : HeapTuple
     251     3507590 : SearchSysCache4(int cacheId,
     252             :                 Datum key1, Datum key2, Datum key3, Datum key4)
     253             : {
     254             :     Assert(cacheId >= 0 && cacheId < SysCacheSize &&
     255             :            PointerIsValid(SysCache[cacheId]));
     256             :     Assert(SysCache[cacheId]->cc_nkeys == 4);
     257             : 
     258     3507590 :     return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
     259             : }
     260             : 
     261             : /*
     262             :  * ReleaseSysCache
     263             :  *      Release previously grabbed reference count on a tuple
     264             :  */
     265             : void
     266    69319398 : ReleaseSysCache(HeapTuple tuple)
     267             : {
     268    69319398 :     ReleaseCatCache(tuple);
     269    69319398 : }
     270             : 
     271             : /*
     272             :  * SearchSysCacheCopy
     273             :  *
     274             :  * A convenience routine that does SearchSysCache and (if successful)
     275             :  * returns a modifiable copy of the syscache entry.  The original
     276             :  * syscache entry is released before returning.  The caller should
     277             :  * heap_freetuple() the result when done with it.
     278             :  */
     279             : HeapTuple
     280      480692 : SearchSysCacheCopy(int cacheId,
     281             :                    Datum key1,
     282             :                    Datum key2,
     283             :                    Datum key3,
     284             :                    Datum key4)
     285             : {
     286             :     HeapTuple   tuple,
     287             :                 newtuple;
     288             : 
     289      480692 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     290      480692 :     if (!HeapTupleIsValid(tuple))
     291      119796 :         return tuple;
     292      360896 :     newtuple = heap_copytuple(tuple);
     293      360896 :     ReleaseSysCache(tuple);
     294      360896 :     return newtuple;
     295             : }
     296             : 
     297             : /*
     298             :  * SearchSysCacheExists
     299             :  *
     300             :  * A convenience routine that just probes to see if a tuple can be found.
     301             :  * No lock is retained on the syscache entry.
     302             :  */
     303             : bool
     304     1082326 : SearchSysCacheExists(int cacheId,
     305             :                      Datum key1,
     306             :                      Datum key2,
     307             :                      Datum key3,
     308             :                      Datum key4)
     309             : {
     310             :     HeapTuple   tuple;
     311             : 
     312     1082326 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     313     1082326 :     if (!HeapTupleIsValid(tuple))
     314      206636 :         return false;
     315      875690 :     ReleaseSysCache(tuple);
     316      875690 :     return true;
     317             : }
     318             : 
     319             : /*
     320             :  * GetSysCacheOid
     321             :  *
     322             :  * A convenience routine that does SearchSysCache and returns the OID in the
     323             :  * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
     324             :  * No lock is retained on the syscache entry.
     325             :  */
     326             : Oid
     327     3165678 : GetSysCacheOid(int cacheId,
     328             :                AttrNumber oidcol,
     329             :                Datum key1,
     330             :                Datum key2,
     331             :                Datum key3,
     332             :                Datum key4)
     333             : {
     334             :     HeapTuple   tuple;
     335             :     bool        isNull;
     336             :     Oid         result;
     337             : 
     338     3165678 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     339     3165678 :     if (!HeapTupleIsValid(tuple))
     340     1271530 :         return InvalidOid;
     341     3788296 :     result = heap_getattr(tuple, oidcol,
     342     1894148 :                           SysCache[cacheId]->cc_tupdesc,
     343             :                           &isNull);
     344             :     Assert(!isNull);            /* columns used as oids should never be NULL */
     345     1894148 :     ReleaseSysCache(tuple);
     346     1894148 :     return result;
     347             : }
     348             : 
     349             : 
     350             : /*
     351             :  * SearchSysCacheAttName
     352             :  *
     353             :  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
     354             :  * except that it will return NULL if the found attribute is marked
     355             :  * attisdropped.  This is convenient for callers that want to act as
     356             :  * though dropped attributes don't exist.
     357             :  */
     358             : HeapTuple
     359      101640 : SearchSysCacheAttName(Oid relid, const char *attname)
     360             : {
     361             :     HeapTuple   tuple;
     362             : 
     363      101640 :     tuple = SearchSysCache2(ATTNAME,
     364             :                             ObjectIdGetDatum(relid),
     365             :                             CStringGetDatum(attname));
     366      101640 :     if (!HeapTupleIsValid(tuple))
     367         858 :         return NULL;
     368      100782 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
     369             :     {
     370          78 :         ReleaseSysCache(tuple);
     371          78 :         return NULL;
     372             :     }
     373      100704 :     return tuple;
     374             : }
     375             : 
     376             : /*
     377             :  * SearchSysCacheCopyAttName
     378             :  *
     379             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
     380             :  */
     381             : HeapTuple
     382        9952 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
     383             : {
     384             :     HeapTuple   tuple,
     385             :                 newtuple;
     386             : 
     387        9952 :     tuple = SearchSysCacheAttName(relid, attname);
     388        9952 :     if (!HeapTupleIsValid(tuple))
     389         654 :         return tuple;
     390        9298 :     newtuple = heap_copytuple(tuple);
     391        9298 :     ReleaseSysCache(tuple);
     392        9298 :     return newtuple;
     393             : }
     394             : 
     395             : /*
     396             :  * SearchSysCacheExistsAttName
     397             :  *
     398             :  * As above, an attisdropped-aware version of SearchSysCacheExists.
     399             :  */
     400             : bool
     401        1818 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
     402             : {
     403             :     HeapTuple   tuple;
     404             : 
     405        1818 :     tuple = SearchSysCacheAttName(relid, attname);
     406        1818 :     if (!HeapTupleIsValid(tuple))
     407          12 :         return false;
     408        1806 :     ReleaseSysCache(tuple);
     409        1806 :     return true;
     410             : }
     411             : 
     412             : 
     413             : /*
     414             :  * SearchSysCacheAttNum
     415             :  *
     416             :  * This routine is equivalent to SearchSysCache on the ATTNUM cache,
     417             :  * except that it will return NULL if the found attribute is marked
     418             :  * attisdropped.  This is convenient for callers that want to act as
     419             :  * though dropped attributes don't exist.
     420             :  */
     421             : HeapTuple
     422       24196 : SearchSysCacheAttNum(Oid relid, int16 attnum)
     423             : {
     424             :     HeapTuple   tuple;
     425             : 
     426       24196 :     tuple = SearchSysCache2(ATTNUM,
     427             :                             ObjectIdGetDatum(relid),
     428             :                             Int16GetDatum(attnum));
     429       24196 :     if (!HeapTupleIsValid(tuple))
     430          12 :         return NULL;
     431       24184 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
     432             :     {
     433           0 :         ReleaseSysCache(tuple);
     434           0 :         return NULL;
     435             :     }
     436       24184 :     return tuple;
     437             : }
     438             : 
     439             : /*
     440             :  * SearchSysCacheCopyAttNum
     441             :  *
     442             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
     443             :  */
     444             : HeapTuple
     445       24132 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
     446             : {
     447             :     HeapTuple   tuple,
     448             :                 newtuple;
     449             : 
     450       24132 :     tuple = SearchSysCacheAttNum(relid, attnum);
     451       24132 :     if (!HeapTupleIsValid(tuple))
     452           0 :         return NULL;
     453       24132 :     newtuple = heap_copytuple(tuple);
     454       24132 :     ReleaseSysCache(tuple);
     455       24132 :     return newtuple;
     456             : }
     457             : 
     458             : 
     459             : /*
     460             :  * SysCacheGetAttr
     461             :  *
     462             :  *      Given a tuple previously fetched by SearchSysCache(),
     463             :  *      extract a specific attribute.
     464             :  *
     465             :  * This is equivalent to using heap_getattr() on a tuple fetched
     466             :  * from a non-cached relation.  Usually, this is only used for attributes
     467             :  * that could be NULL or variable length; the fixed-size attributes in
     468             :  * a system table are accessed just by mapping the tuple onto the C struct
     469             :  * declarations from include/catalog/.
     470             :  *
     471             :  * As with heap_getattr(), if the attribute is of a pass-by-reference type
     472             :  * then a pointer into the tuple data area is returned --- the caller must
     473             :  * not modify or pfree the datum!
     474             :  *
     475             :  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
     476             :  * a different cache for the same catalog the tuple was fetched from.
     477             :  */
     478             : Datum
     479     4543654 : SysCacheGetAttr(int cacheId, HeapTuple tup,
     480             :                 AttrNumber attributeNumber,
     481             :                 bool *isNull)
     482             : {
     483             :     /*
     484             :      * We just need to get the TupleDesc out of the cache entry, and then we
     485             :      * can apply heap_getattr().  Normally the cache control data is already
     486             :      * valid (because the caller recently fetched the tuple via this same
     487             :      * cache), but there are cases where we have to initialize the cache here.
     488             :      */
     489     4543654 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
     490     4543654 :         !PointerIsValid(SysCache[cacheId]))
     491           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
     492     4543654 :     if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
     493             :     {
     494       24518 :         InitCatCachePhase2(SysCache[cacheId], false);
     495             :         Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
     496             :     }
     497             : 
     498     9087308 :     return heap_getattr(tup, attributeNumber,
     499     4543654 :                         SysCache[cacheId]->cc_tupdesc,
     500             :                         isNull);
     501             : }
     502             : 
     503             : /*
     504             :  * SysCacheGetAttrNotNull
     505             :  *
     506             :  * As above, a version of SysCacheGetAttr which knows that the attr cannot
     507             :  * be NULL.
     508             :  */
     509             : Datum
     510     2656574 : SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
     511             :                        AttrNumber attributeNumber)
     512             : {
     513             :     bool        isnull;
     514             :     Datum       attr;
     515             : 
     516     2656574 :     attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
     517             : 
     518     2656574 :     if (isnull)
     519             :     {
     520           0 :         elog(ERROR,
     521             :              "unexpected null value in cached tuple for catalog %s column %s",
     522             :              get_rel_name(cacheinfo[cacheId].reloid),
     523             :              NameStr(TupleDescAttr(SysCache[cacheId]->cc_tupdesc, attributeNumber - 1)->attname));
     524             :     }
     525             : 
     526     2656574 :     return attr;
     527             : }
     528             : 
     529             : /*
     530             :  * GetSysCacheHashValue
     531             :  *
     532             :  * Get the hash value that would be used for a tuple in the specified cache
     533             :  * with the given search keys.
     534             :  *
     535             :  * The reason for exposing this as part of the API is that the hash value is
     536             :  * exposed in cache invalidation operations, so there are places outside the
     537             :  * catcache code that need to be able to compute the hash values.
     538             :  */
     539             : uint32
     540      141006 : GetSysCacheHashValue(int cacheId,
     541             :                      Datum key1,
     542             :                      Datum key2,
     543             :                      Datum key3,
     544             :                      Datum key4)
     545             : {
     546      141006 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
     547      141006 :         !PointerIsValid(SysCache[cacheId]))
     548           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
     549             : 
     550      141006 :     return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
     551             : }
     552             : 
     553             : /*
     554             :  * List-search interface
     555             :  */
     556             : struct catclist *
     557     3048946 : SearchSysCacheList(int cacheId, int nkeys,
     558             :                    Datum key1, Datum key2, Datum key3)
     559             : {
     560     3048946 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
     561     3048946 :         !PointerIsValid(SysCache[cacheId]))
     562           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
     563             : 
     564     3048946 :     return SearchCatCacheList(SysCache[cacheId], nkeys,
     565             :                               key1, key2, key3);
     566             : }
     567             : 
     568             : /*
     569             :  * SysCacheInvalidate
     570             :  *
     571             :  *  Invalidate entries in the specified cache, given a hash value.
     572             :  *  See CatCacheInvalidate() for more info.
     573             :  *
     574             :  *  This routine is only quasi-public: it should only be used by inval.c.
     575             :  */
     576             : void
     577    18303686 : SysCacheInvalidate(int cacheId, uint32 hashValue)
     578             : {
     579    18303686 :     if (cacheId < 0 || cacheId >= SysCacheSize)
     580           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
     581             : 
     582             :     /* if this cache isn't initialized yet, no need to do anything */
     583    18303686 :     if (!PointerIsValid(SysCache[cacheId]))
     584           0 :         return;
     585             : 
     586    18303686 :     CatCacheInvalidate(SysCache[cacheId], hashValue);
     587             : }
     588             : 
     589             : /*
     590             :  * Certain relations that do not have system caches send snapshot invalidation
     591             :  * messages in lieu of catcache messages.  This is for the benefit of
     592             :  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
     593             :  * for scanning one of those catalogs, rather than taking a new one, if no
     594             :  * invalidation has been received.
     595             :  *
     596             :  * Relations that have syscaches need not (and must not) be listed here.  The
     597             :  * catcache invalidation messages will also flush the snapshot.  If you add a
     598             :  * syscache for one of these relations, remove it from this list.
     599             :  */
     600             : bool
     601    12443020 : RelationInvalidatesSnapshotsOnly(Oid relid)
     602             : {
     603    12443020 :     switch (relid)
     604             :     {
     605     2236080 :         case DbRoleSettingRelationId:
     606             :         case DependRelationId:
     607             :         case SharedDependRelationId:
     608             :         case DescriptionRelationId:
     609             :         case SharedDescriptionRelationId:
     610             :         case SecLabelRelationId:
     611             :         case SharedSecLabelRelationId:
     612     2236080 :             return true;
     613    10206940 :         default:
     614    10206940 :             break;
     615             :     }
     616             : 
     617    10206940 :     return false;
     618             : }
     619             : 
     620             : /*
     621             :  * Test whether a relation has a system cache.
     622             :  */
     623             : bool
     624     7650972 : RelationHasSysCache(Oid relid)
     625             : {
     626     7650972 :     int         low = 0,
     627     7650972 :                 high = SysCacheRelationOidSize - 1;
     628             : 
     629    33807182 :     while (low <= high)
     630             :     {
     631    33383908 :         int         middle = low + (high - low) / 2;
     632             : 
     633    33383908 :         if (SysCacheRelationOid[middle] == relid)
     634     7227698 :             return true;
     635    26156210 :         if (SysCacheRelationOid[middle] < relid)
     636     9097596 :             low = middle + 1;
     637             :         else
     638    17058614 :             high = middle - 1;
     639             :     }
     640             : 
     641      423274 :     return false;
     642             : }
     643             : 
     644             : /*
     645             :  * Test whether a relation supports a system cache, ie it is either a
     646             :  * cached table or the index used for a cache.
     647             :  */
     648             : bool
     649     1872440 : RelationSupportsSysCache(Oid relid)
     650             : {
     651     1872440 :     int         low = 0,
     652     1872440 :                 high = SysCacheSupportingRelOidSize - 1;
     653             : 
     654    16022568 :     while (low <= high)
     655             :     {
     656    14432562 :         int         middle = low + (high - low) / 2;
     657             : 
     658    14432562 :         if (SysCacheSupportingRelOid[middle] == relid)
     659      282434 :             return true;
     660    14150128 :         if (SysCacheSupportingRelOid[middle] < relid)
     661    13340430 :             low = middle + 1;
     662             :         else
     663      809698 :             high = middle - 1;
     664             :     }
     665             : 
     666     1590006 :     return false;
     667             : }
     668             : 
     669             : 
     670             : /*
     671             :  * OID comparator for qsort
     672             :  */
     673             : static int
     674    49150608 : oid_compare(const void *a, const void *b)
     675             : {
     676    49150608 :     Oid         oa = *((const Oid *) a);
     677    49150608 :     Oid         ob = *((const Oid *) b);
     678             : 
     679    49150608 :     return pg_cmp_u32(oa, ob);
     680             : }

Generated by: LCOV version 1.14