LCOV - code coverage report
Current view: top level - src/backend/utils/cache - syscache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 147 157 93.6 %
Date: 2024-07-18 16:11:39 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       26022 : InitCatalogCache(void)
     108             : {
     109             :     int         cacheId;
     110             : 
     111             :     Assert(!CacheInitialized);
     112             : 
     113       26022 :     SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
     114             : 
     115     2185848 :     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     4319652 :         SysCache[cacheId] = InitCatCache(cacheId,
     126             :                                          cacheinfo[cacheId].reloid,
     127             :                                          cacheinfo[cacheId].indoid,
     128             :                                          cacheinfo[cacheId].nkeys,
     129     2159826 :                                          cacheinfo[cacheId].key,
     130             :                                          cacheinfo[cacheId].nbuckets);
     131     2159826 :         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     2159826 :         SysCacheRelationOid[SysCacheRelationOidSize++] =
     136     2159826 :             cacheinfo[cacheId].reloid;
     137     2159826 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     138     2159826 :             cacheinfo[cacheId].reloid;
     139     2159826 :         SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
     140     2159826 :             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       26022 :     qsort(SysCacheRelationOid, SysCacheRelationOidSize,
     150             :           sizeof(Oid), oid_compare);
     151       26022 :     SysCacheRelationOidSize =
     152       26022 :         qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
     153             :                 oid_compare);
     154             : 
     155       26022 :     qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     156             :           sizeof(Oid), oid_compare);
     157       26022 :     SysCacheSupportingRelOidSize =
     158       26022 :         qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
     159             :                 sizeof(Oid), oid_compare);
     160             : 
     161       26022 :     CacheInitialized = true;
     162       26022 : }
     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        2170 : InitCatalogCachePhase2(void)
     178             : {
     179             :     int         cacheId;
     180             : 
     181             :     Assert(CacheInitialized);
     182             : 
     183      182102 :     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
     184      179936 :         InitCatCachePhase2(SysCache[cacheId], true);
     185        2166 : }
     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     4710198 : 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     4710198 :     return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
     215             : }
     216             : 
     217             : HeapTuple
     218    56589940 : 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    56589940 :     return SearchCatCache1(SysCache[cacheId], key1);
     226             : }
     227             : 
     228             : HeapTuple
     229     4511914 : 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     4511914 :     return SearchCatCache2(SysCache[cacheId], key1, key2);
     237             : }
     238             : 
     239             : HeapTuple
     240     4396078 : 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     4396078 :     return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
     248             : }
     249             : 
     250             : HeapTuple
     251     3417876 : 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     3417876 :     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    68723314 : ReleaseSysCache(HeapTuple tuple)
     267             : {
     268    68723314 :     ReleaseCatCache(tuple);
     269    68723314 : }
     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      476440 : SearchSysCacheCopy(int cacheId,
     281             :                    Datum key1,
     282             :                    Datum key2,
     283             :                    Datum key3,
     284             :                    Datum key4)
     285             : {
     286             :     HeapTuple   tuple,
     287             :                 newtuple;
     288             : 
     289      476440 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     290      476440 :     if (!HeapTupleIsValid(tuple))
     291      119642 :         return tuple;
     292      356798 :     newtuple = heap_copytuple(tuple);
     293      356798 :     ReleaseSysCache(tuple);
     294      356798 :     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     1082996 : SearchSysCacheExists(int cacheId,
     305             :                      Datum key1,
     306             :                      Datum key2,
     307             :                      Datum key3,
     308             :                      Datum key4)
     309             : {
     310             :     HeapTuple   tuple;
     311             : 
     312     1082996 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     313     1082996 :     if (!HeapTupleIsValid(tuple))
     314      217690 :         return false;
     315      865306 :     ReleaseSysCache(tuple);
     316      865306 :     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     3150762 : 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     3150762 :     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
     339     3150762 :     if (!HeapTupleIsValid(tuple))
     340     1251170 :         return InvalidOid;
     341     3799184 :     result = heap_getattr(tuple, oidcol,
     342     1899592 :                           SysCache[cacheId]->cc_tupdesc,
     343             :                           &isNull);
     344             :     Assert(!isNull);            /* columns used as oids should never be NULL */
     345     1899592 :     ReleaseSysCache(tuple);
     346     1899592 :     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       84110 : SearchSysCacheAttName(Oid relid, const char *attname)
     360             : {
     361             :     HeapTuple   tuple;
     362             : 
     363       84110 :     tuple = SearchSysCache2(ATTNAME,
     364             :                             ObjectIdGetDatum(relid),
     365             :                             CStringGetDatum(attname));
     366       84110 :     if (!HeapTupleIsValid(tuple))
     367         852 :         return NULL;
     368       83258 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
     369             :     {
     370          78 :         ReleaseSysCache(tuple);
     371          78 :         return NULL;
     372             :     }
     373       83180 :     return tuple;
     374             : }
     375             : 
     376             : /*
     377             :  * SearchSysCacheCopyAttName
     378             :  *
     379             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
     380             :  */
     381             : HeapTuple
     382       17586 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
     383             : {
     384             :     HeapTuple   tuple,
     385             :                 newtuple;
     386             : 
     387       17586 :     tuple = SearchSysCacheAttName(relid, attname);
     388       17586 :     if (!HeapTupleIsValid(tuple))
     389         684 :         return tuple;
     390       16902 :     newtuple = heap_copytuple(tuple);
     391       16902 :     ReleaseSysCache(tuple);
     392       16902 :     return newtuple;
     393             : }
     394             : 
     395             : /*
     396             :  * SearchSysCacheExistsAttName
     397             :  *
     398             :  * As above, an attisdropped-aware version of SearchSysCacheExists.
     399             :  */
     400             : bool
     401        1992 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
     402             : {
     403             :     HeapTuple   tuple;
     404             : 
     405        1992 :     tuple = SearchSysCacheAttName(relid, attname);
     406        1992 :     if (!HeapTupleIsValid(tuple))
     407          12 :         return false;
     408        1980 :     ReleaseSysCache(tuple);
     409        1980 :     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         142 : SearchSysCacheAttNum(Oid relid, int16 attnum)
     423             : {
     424             :     HeapTuple   tuple;
     425             : 
     426         142 :     tuple = SearchSysCache2(ATTNUM,
     427             :                             ObjectIdGetDatum(relid),
     428             :                             Int16GetDatum(attnum));
     429         142 :     if (!HeapTupleIsValid(tuple))
     430          12 :         return NULL;
     431         130 :     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
     432             :     {
     433           0 :         ReleaseSysCache(tuple);
     434           0 :         return NULL;
     435             :     }
     436         130 :     return tuple;
     437             : }
     438             : 
     439             : /*
     440             :  * SearchSysCacheCopyAttNum
     441             :  *
     442             :  * As above, an attisdropped-aware version of SearchSysCacheCopy.
     443             :  */
     444             : HeapTuple
     445          78 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
     446             : {
     447             :     HeapTuple   tuple,
     448             :                 newtuple;
     449             : 
     450          78 :     tuple = SearchSysCacheAttNum(relid, attnum);
     451          78 :     if (!HeapTupleIsValid(tuple))
     452           0 :         return NULL;
     453          78 :     newtuple = heap_copytuple(tuple);
     454          78 :     ReleaseSysCache(tuple);
     455          78 :     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     4539940 : 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     4539940 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
     490     4539940 :         !PointerIsValid(SysCache[cacheId]))
     491           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
     492     4539940 :     if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
     493             :     {
     494       24634 :         InitCatCachePhase2(SysCache[cacheId], false);
     495             :         Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
     496             :     }
     497             : 
     498     9079880 :     return heap_getattr(tup, attributeNumber,
     499     4539940 :                         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     2616362 : SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
     511             :                        AttrNumber attributeNumber)
     512             : {
     513             :     bool        isnull;
     514             :     Datum       attr;
     515             : 
     516     2616362 :     attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
     517             : 
     518     2616362 :     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     2616362 :     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      140646 : GetSysCacheHashValue(int cacheId,
     541             :                      Datum key1,
     542             :                      Datum key2,
     543             :                      Datum key3,
     544             :                      Datum key4)
     545             : {
     546      140646 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
     547      140646 :         !PointerIsValid(SysCache[cacheId]))
     548           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
     549             : 
     550      140646 :     return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
     551             : }
     552             : 
     553             : /*
     554             :  * List-search interface
     555             :  */
     556             : struct catclist *
     557     3023470 : SearchSysCacheList(int cacheId, int nkeys,
     558             :                    Datum key1, Datum key2, Datum key3)
     559             : {
     560     3023470 :     if (cacheId < 0 || cacheId >= SysCacheSize ||
     561     3023470 :         !PointerIsValid(SysCache[cacheId]))
     562           0 :         elog(ERROR, "invalid cache ID: %d", cacheId);
     563             : 
     564     3023470 :     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    18501864 : SysCacheInvalidate(int cacheId, uint32 hashValue)
     578             : {
     579    18501864 :     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    18501864 :     if (!PointerIsValid(SysCache[cacheId]))
     584           0 :         return;
     585             : 
     586    18501864 :     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    12274266 : RelationInvalidatesSnapshotsOnly(Oid relid)
     602             : {
     603    12274266 :     switch (relid)
     604             :     {
     605     2162726 :         case DbRoleSettingRelationId:
     606             :         case DependRelationId:
     607             :         case SharedDependRelationId:
     608             :         case DescriptionRelationId:
     609             :         case SharedDescriptionRelationId:
     610             :         case SecLabelRelationId:
     611             :         case SharedSecLabelRelationId:
     612     2162726 :             return true;
     613    10111540 :         default:
     614    10111540 :             break;
     615             :     }
     616             : 
     617    10111540 :     return false;
     618             : }
     619             : 
     620             : /*
     621             :  * Test whether a relation has a system cache.
     622             :  */
     623             : bool
     624     7572214 : RelationHasSysCache(Oid relid)
     625             : {
     626     7572214 :     int         low = 0,
     627     7572214 :                 high = SysCacheRelationOidSize - 1;
     628             : 
     629    33458454 :     while (low <= high)
     630             :     {
     631    33049008 :         int         middle = low + (high - low) / 2;
     632             : 
     633    33049008 :         if (SysCacheRelationOid[middle] == relid)
     634     7162768 :             return true;
     635    25886240 :         if (SysCacheRelationOid[middle] < relid)
     636     8980706 :             low = middle + 1;
     637             :         else
     638    16905534 :             high = middle - 1;
     639             :     }
     640             : 
     641      409446 :     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     1869996 : RelationSupportsSysCache(Oid relid)
     650             : {
     651     1869996 :     int         low = 0,
     652     1869996 :                 high = SysCacheSupportingRelOidSize - 1;
     653             : 
     654    15996952 :     while (low <= high)
     655             :     {
     656    14410626 :         int         middle = low + (high - low) / 2;
     657             : 
     658    14410626 :         if (SysCacheSupportingRelOid[middle] == relid)
     659      283670 :             return true;
     660    14126956 :         if (SysCacheSupportingRelOid[middle] < relid)
     661    13313598 :             low = middle + 1;
     662             :         else
     663      813358 :             high = middle - 1;
     664             :     }
     665             : 
     666     1586326 :     return false;
     667             : }
     668             : 
     669             : 
     670             : /*
     671             :  * OID comparator for qsort
     672             :  */
     673             : static int
     674    49389756 : oid_compare(const void *a, const void *b)
     675             : {
     676    49389756 :     Oid         oa = *((const Oid *) a);
     677    49389756 :     Oid         ob = *((const Oid *) b);
     678             : 
     679    49389756 :     return pg_cmp_u32(oa, ob);
     680             : }

Generated by: LCOV version 1.14