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: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 96.0 % 50 48 2 1 47 1 1
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 4 4 2 2
Baseline: lcov-20250906-005545-baseline Branches: 79.2 % 24 19 5 19
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] 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
 5135 tgl@sss.pgh.pa.us          53                 :CBC      464273 : 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                 :                :      */
  395 akorotkov@postgresql       63         [ +  + ]:         464273 :     if (hashvalue == 0)
                                 64                 :             24 :         hash_seq_init(&status, AttoptCacheHash);
                                 65                 :                :     else
                                 66                 :         464249 :         hash_seq_init_with_hash_value(&status, AttoptCacheHash, hashvalue);
                                 67                 :                : 
 5706 rhaas@postgresql.org       68         [ +  + ]:         466552 :     while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL)
                                 69                 :                :     {
                                 70         [ +  + ]:           2279 :         if (attopt->opts)
                                 71                 :              3 :             pfree(attopt->opts);
                                 72         [ -  + ]:           2279 :         if (hash_search(AttoptCacheHash,
  943 peter@eisentraut.org       73                 :           2279 :                         &attopt->key,
                                 74                 :                :                         HASH_REMOVE,
                                 75                 :                :                         NULL) == NULL)
 5706 rhaas@postgresql.org       76         [ #  # ]:UBC           0 :             elog(ERROR, "hash table corrupted");
                                 77                 :                :     }
 5706 rhaas@postgresql.org       78                 :CBC      464273 : }
                                 79                 :                : 
                                 80                 :                : /*
                                 81                 :                :  * Hash function compatible with two-arg system cache hash function.
                                 82                 :                :  */
                                 83                 :                : static uint32
  395 akorotkov@postgresql       84                 :          85309 : relatt_cache_syshash(const void *key, Size keysize)
                                 85                 :                : {
                                 86                 :          85309 :     const AttoptCacheKey *ckey = key;
                                 87                 :                : 
                                 88         [ -  + ]:          85309 :     Assert(keysize == sizeof(*ckey));
   29 peter@eisentraut.org       89                 :GNC       85309 :     return GetSysCacheHashValue2(ATTNUM, ObjectIdGetDatum(ckey->attrelid), Int32GetDatum(ckey->attnum));
                                 90                 :                : }
                                 91                 :                : 
                                 92                 :                : /*
                                 93                 :                :  * InitializeAttoptCache
                                 94                 :                :  *      Initialize the attribute options cache.
                                 95                 :                :  */
                                 96                 :                : static void
 5706 rhaas@postgresql.org       97                 :CBC         292 : InitializeAttoptCache(void)
                                 98                 :                : {
                                 99                 :                :     HASHCTL     ctl;
                                100                 :                : 
                                101                 :                :     /* Initialize the hash table. */
                                102                 :            292 :     ctl.keysize = sizeof(AttoptCacheKey);
                                103                 :            292 :     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                 :                :      */
  395 akorotkov@postgresql      110                 :            292 :     ctl.hash = relatt_cache_syshash;
                                111                 :                : 
 5706 rhaas@postgresql.org      112                 :            292 :     AttoptCacheHash =
                                113                 :            292 :         hash_create("Attopt cache", 256, &ctl,
                                114                 :                :                     HASH_ELEM | HASH_FUNCTION);
                                115                 :                : 
                                116                 :                :     /* Make sure we've initialized CacheMemoryContext. */
                                117         [ -  + ]:            292 :     if (!CacheMemoryContext)
 5706 rhaas@postgresql.org      118                 :UBC           0 :         CreateCacheMemoryContext();
                                119                 :                : 
                                120                 :                :     /* Watch for invalidation events. */
 5706 rhaas@postgresql.org      121                 :CBC         292 :     CacheRegisterSyscacheCallback(ATTNUM,
                                122                 :                :                                   InvalidateAttoptCacheCallback,
                                123                 :                :                                   (Datum) 0);
                                124                 :            292 : }
                                125                 :                : 
                                126                 :                : /*
                                127                 :                :  * get_attribute_options
                                128                 :                :  *      Fetch attribute options for a specified table OID.
                                129                 :                :  */
                                130                 :                : AttributeOpts *
                                131                 :          42661 : 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         [ +  + ]:          42661 :     if (!AttoptCacheHash)
                                140                 :            292 :         InitializeAttoptCache();
 2999 tgl@sss.pgh.pa.us         141                 :          42661 :     memset(&key, 0, sizeof(key));   /* make sure any padding bits are unset */
 5706 rhaas@postgresql.org      142                 :          42661 :     key.attrelid = attrelid;
                                143                 :          42661 :     key.attnum = attnum;
                                144                 :                :     attopt =
                                145                 :          42661 :         (AttoptCacheEntry *) hash_search(AttoptCacheHash,
                                146                 :                :                                          &key,
                                147                 :                :                                          HASH_FIND,
                                148                 :                :                                          NULL);
                                149                 :                : 
                                150                 :                :     /* Not found in Attopt cache.  Construct new cache entry. */
                                151         [ +  + ]:          42661 :     if (!attopt)
                                152                 :                :     {
                                153                 :                :         AttributeOpts *opts;
                                154                 :                : 
 5683                           155                 :          40369 :         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                 :                :          */
 5706                           164         [ +  + ]:          40369 :         if (!HeapTupleIsValid(tp))
                                165                 :             27 :             opts = NULL;
                                166                 :                :         else
                                167                 :                :         {
                                168                 :                :             Datum       datum;
                                169                 :                :             bool        isNull;
                                170                 :                : 
                                171                 :          40342 :             datum = SysCacheGetAttr(ATTNUM,
                                172                 :                :                                     tp,
                                173                 :                :                                     Anum_pg_attribute_attoptions,
                                174                 :                :                                     &isNull);
                                175         [ +  + ]:          40342 :             if (isNull)
                                176                 :          40339 :                 opts = NULL;
                                177                 :                :             else
                                178                 :                :             {
 5671 bruce@momjian.us          179                 :              3 :                 bytea      *bytea_opts = attribute_reloptions(datum, false);
                                180                 :                : 
 5706 rhaas@postgresql.org      181                 :              3 :                 opts = MemoryContextAlloc(CacheMemoryContext,
 5706 rhaas@postgresql.org      182                 :ECB         (3) :                                           VARSIZE(bytea_opts));
 5706 rhaas@postgresql.org      183                 :CBC           3 :                 memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
                                184                 :                :             }
                                185                 :          40342 :             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                 :          40369 :         attopt = (AttoptCacheEntry *) hash_search(AttoptCacheHash,
                                193                 :                :                                                   &key,
                                194                 :                :                                                   HASH_ENTER,
                                195                 :                :                                                   NULL);
                                196                 :          40369 :         attopt->opts = opts;
                                197                 :                :     }
                                198                 :                : 
                                199                 :                :     /* Return results in caller's memory context. */
                                200         [ +  + ]:          42661 :     if (attopt->opts == NULL)
                                201                 :          42658 :         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