LCOV - differential code coverage report
Current view: top level - src/backend/utils/cache - attoptcache.c (source / functions) Coverage Total Hit UBC GNC CBC ECB DCB
Current: b45a8d7d8b306b43f31a002f1b3f1dddc8defeaf vs 8767b449a3a1e75626dfb08f24da54933171d4c5 Lines: 96.0 % 50 48 2 1 47 1 1
Current Date: 2025-10-28 08:26:42 +0900 Functions: 100.0 % 4 4 2 2
Baseline: lcov-20251028-005825-baseline Branches: 79.2 % 24 19 5 19
Baseline Date: 2025-10-27 06:37:35 +0000 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 1 1 1
(360..) days: 95.9 % 49 47 2 47 1
Function coverage date bins:
(360..) days: 100.0 % 4 4 2 2
Branch coverage date bins:
(360..) days: 79.2 % 24 19 5 19

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * attoptcache.c
                                  4                 :                :  *    Attribute options cache management.
                                  5                 :                :  *
                                  6                 :                :  * Attribute options are cached separately from the fixed-size portion of
                                  7                 :                :  * pg_attribute entries, which are handled by the relcache.
                                  8                 :                :  *
                                  9                 :                :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
                                 10                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 11                 :                :  *
                                 12                 :                :  * IDENTIFICATION
                                 13                 :                :  *    src/backend/utils/cache/attoptcache.c
                                 14                 :                :  *
                                 15                 :                :  *-------------------------------------------------------------------------
                                 16                 :                :  */
                                 17                 :                : #include "postgres.h"
                                 18                 :                : 
                                 19                 :                : #include "access/reloptions.h"
                                 20                 :                : #include "utils/attoptcache.h"
                                 21                 :                : #include "utils/catcache.h"
                                 22                 :                : #include "utils/hsearch.h"
                                 23                 :                : #include "utils/inval.h"
                                 24                 :                : #include "utils/syscache.h"
                                 25                 :                : #include "varatt.h"
                                 26                 :                : 
                                 27                 :                : 
                                 28                 :                : /* Hash table for information about each attribute's options */
                                 29                 :                : static HTAB *AttoptCacheHash = NULL;
                                 30                 :                : 
                                 31                 :                : /* attrelid and attnum form the lookup key, and must appear first */
                                 32                 :                : typedef struct
                                 33                 :                : {
                                 34                 :                :     Oid         attrelid;
                                 35                 :                :     int         attnum;
                                 36                 :                : } AttoptCacheKey;
                                 37                 :                : 
                                 38                 :                : typedef struct
                                 39                 :                : {
                                 40                 :                :     AttoptCacheKey key;         /* lookup key - must be first */
                                 41                 :                :     AttributeOpts *opts;        /* options, or NULL if none */
                                 42                 :                : } AttoptCacheEntry;
                                 43                 :                : 
                                 44                 :                : 
                                 45                 :                : /*
                                 46                 :                :  * InvalidateAttoptCacheCallback
                                 47                 :                :  *      Flush cache entry (or entries) when pg_attribute is updated.
                                 48                 :                :  *
                                 49                 :                :  * When pg_attribute is updated, we must flush the cache entry at least
                                 50                 :                :  * for that attribute.
                                 51                 :                :  */
                                 52                 :                : static void
 5187 tgl@sss.pgh.pa.us          53                 :CBC      489816 : InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
                                 54                 :                : {
                                 55                 :                :     HASH_SEQ_STATUS status;
                                 56                 :                :     AttoptCacheEntry *attopt;
                                 57                 :                : 
                                 58                 :                :     /*
                                 59                 :                :      * By convention, zero hash value is passed to the callback as a sign that
                                 60                 :                :      * it's time to invalidate the whole cache. See sinval.c, inval.c and
                                 61                 :                :      * InvalidateSystemCachesExtended().
                                 62                 :                :      */
  447 akorotkov@postgresql       63         [ +  + ]:         489816 :     if (hashvalue == 0)
                                 64                 :             27 :         hash_seq_init(&status, AttoptCacheHash);
                                 65                 :                :     else
                                 66                 :         489789 :         hash_seq_init_with_hash_value(&status, AttoptCacheHash, hashvalue);
                                 67                 :                : 
 5758 rhaas@postgresql.org       68         [ +  + ]:         492332 :     while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL)
                                 69                 :                :     {
                                 70         [ +  + ]:           2516 :         if (attopt->opts)
                                 71                 :              3 :             pfree(attopt->opts);
                                 72         [ -  + ]:           2516 :         if (hash_search(AttoptCacheHash,
  995 peter@eisentraut.org       73                 :           2516 :                         &attopt->key,
                                 74                 :                :                         HASH_REMOVE,
                                 75                 :                :                         NULL) == NULL)
 5758 rhaas@postgresql.org       76         [ #  # ]:UBC           0 :             elog(ERROR, "hash table corrupted");
                                 77                 :                :     }
 5758 rhaas@postgresql.org       78                 :CBC      489816 : }
                                 79                 :                : 
                                 80                 :                : /*
                                 81                 :                :  * Hash function compatible with two-arg system cache hash function.
                                 82                 :                :  */
                                 83                 :                : static uint32
  447 akorotkov@postgresql       84                 :          87595 : relatt_cache_syshash(const void *key, Size keysize)
                                 85                 :                : {
                                 86                 :          87595 :     const AttoptCacheKey *ckey = key;
                                 87                 :                : 
                                 88         [ -  + ]:          87595 :     Assert(keysize == sizeof(*ckey));
   81 peter@eisentraut.org       89                 :GNC       87595 :     return GetSysCacheHashValue2(ATTNUM, ObjectIdGetDatum(ckey->attrelid), Int32GetDatum(ckey->attnum));
                                 90                 :                : }
                                 91                 :                : 
                                 92                 :                : /*
                                 93                 :                :  * InitializeAttoptCache
                                 94                 :                :  *      Initialize the attribute options cache.
                                 95                 :                :  */
                                 96                 :                : static void
 5758 rhaas@postgresql.org       97                 :CBC         298 : InitializeAttoptCache(void)
                                 98                 :                : {
                                 99                 :                :     HASHCTL     ctl;
                                100                 :                : 
                                101                 :                :     /* Initialize the hash table. */
                                102                 :            298 :     ctl.keysize = sizeof(AttoptCacheKey);
                                103                 :            298 :     ctl.entrysize = sizeof(AttoptCacheEntry);
                                104                 :                : 
                                105                 :                :     /*
                                106                 :                :      * AttoptCacheEntry takes hash value from the system cache. For
                                107                 :                :      * AttoptCacheHash we use the same hash in order to speedup search by hash
                                108                 :                :      * value. This is used by hash_seq_init_with_hash_value().
                                109                 :                :      */
  447 akorotkov@postgresql      110                 :            298 :     ctl.hash = relatt_cache_syshash;
                                111                 :                : 
 5758 rhaas@postgresql.org      112                 :            298 :     AttoptCacheHash =
                                113                 :            298 :         hash_create("Attopt cache", 256, &ctl,
                                114                 :                :                     HASH_ELEM | HASH_FUNCTION);
                                115                 :                : 
                                116                 :                :     /* Make sure we've initialized CacheMemoryContext. */
                                117         [ -  + ]:            298 :     if (!CacheMemoryContext)
 5758 rhaas@postgresql.org      118                 :UBC           0 :         CreateCacheMemoryContext();
                                119                 :                : 
                                120                 :                :     /* Watch for invalidation events. */
 5758 rhaas@postgresql.org      121                 :CBC         298 :     CacheRegisterSyscacheCallback(ATTNUM,
                                122                 :                :                                   InvalidateAttoptCacheCallback,
                                123                 :                :                                   (Datum) 0);
                                124                 :            298 : }
                                125                 :                : 
                                126                 :                : /*
                                127                 :                :  * get_attribute_options
                                128                 :                :  *      Fetch attribute options for a specified table OID.
                                129                 :                :  */
                                130                 :                : AttributeOpts *
                                131                 :          43697 : get_attribute_options(Oid attrelid, int attnum)
                                132                 :                : {
                                133                 :                :     AttoptCacheKey key;
                                134                 :                :     AttoptCacheEntry *attopt;
                                135                 :                :     AttributeOpts *result;
                                136                 :                :     HeapTuple   tp;
                                137                 :                : 
                                138                 :                :     /* Find existing cache entry, if any. */
                                139         [ +  + ]:          43697 :     if (!AttoptCacheHash)
                                140                 :            298 :         InitializeAttoptCache();
 3051 tgl@sss.pgh.pa.us         141                 :          43697 :     memset(&key, 0, sizeof(key));   /* make sure any padding bits are unset */
 5758 rhaas@postgresql.org      142                 :          43697 :     key.attrelid = attrelid;
                                143                 :          43697 :     key.attnum = attnum;
                                144                 :                :     attopt =
                                145                 :          43697 :         (AttoptCacheEntry *) hash_search(AttoptCacheHash,
                                146                 :                :                                          &key,
                                147                 :                :                                          HASH_FIND,
                                148                 :                :                                          NULL);
                                149                 :                : 
                                150                 :                :     /* Not found in Attopt cache.  Construct new cache entry. */
                                151         [ +  + ]:          43697 :     if (!attopt)
                                152                 :                :     {
                                153                 :                :         AttributeOpts *opts;
                                154                 :                : 
 5735                           155                 :          41382 :         tp = SearchSysCache2(ATTNUM,
                                156                 :                :                              ObjectIdGetDatum(attrelid),
                                157                 :                :                              Int16GetDatum(attnum));
                                158                 :                : 
                                159                 :                :         /*
                                160                 :                :          * If we don't find a valid HeapTuple, it must mean someone has
                                161                 :                :          * managed to request attribute details for a non-existent attribute.
                                162                 :                :          * We treat that case as if no options were specified.
                                163                 :                :          */
 5758                           164         [ +  + ]:          41382 :         if (!HeapTupleIsValid(tp))
                                165                 :             30 :             opts = NULL;
                                166                 :                :         else
                                167                 :                :         {
                                168                 :                :             Datum       datum;
                                169                 :                :             bool        isNull;
                                170                 :                : 
                                171                 :          41352 :             datum = SysCacheGetAttr(ATTNUM,
                                172                 :                :                                     tp,
                                173                 :                :                                     Anum_pg_attribute_attoptions,
                                174                 :                :                                     &isNull);
                                175         [ +  + ]:          41352 :             if (isNull)
                                176                 :          41349 :                 opts = NULL;
                                177                 :                :             else
                                178                 :                :             {
 5723 bruce@momjian.us          179                 :              3 :                 bytea      *bytea_opts = attribute_reloptions(datum, false);
                                180                 :                : 
 5758 rhaas@postgresql.org      181                 :              3 :                 opts = MemoryContextAlloc(CacheMemoryContext,
 5758 rhaas@postgresql.org      182                 :ECB         (3) :                                           VARSIZE(bytea_opts));
 5758 rhaas@postgresql.org      183                 :CBC           3 :                 memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
                                184                 :                :             }
                                185                 :          41352 :             ReleaseSysCache(tp);
                                186                 :                :         }
                                187                 :                : 
                                188                 :                :         /*
                                189                 :                :          * It's important to create the actual cache entry only after reading
                                190                 :                :          * pg_attribute, since the read could cause a cache flush.
                                191                 :                :          */
                                192                 :          41382 :         attopt = (AttoptCacheEntry *) hash_search(AttoptCacheHash,
                                193                 :                :                                                   &key,
                                194                 :                :                                                   HASH_ENTER,
                                195                 :                :                                                   NULL);
                                196                 :          41382 :         attopt->opts = opts;
                                197                 :                :     }
                                198                 :                : 
                                199                 :                :     /* Return results in caller's memory context. */
                                200         [ +  + ]:          43697 :     if (attopt->opts == NULL)
                                201                 :          43694 :         return NULL;
                                202                 :              3 :     result = palloc(VARSIZE(attopt->opts));
                                203                 :              3 :     memcpy(result, attopt->opts, VARSIZE(attopt->opts));
                                204                 :              3 :     return result;
                                205                 :                : }
        

Generated by: LCOV version 2.4-beta