LCOV - differential code coverage report
Current view: top level - src/backend/utils/cache - attoptcache.c (source / functions) Coverage Total Hit LBC UIC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 95.5 % 44 42 1 1 23 1 18 2 20 3
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 3 3 3 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 95.3 % 43 41 1 1 23 18 2 20
Function coverage date bins:
(240..) days: 50.0 % 6 3 3 3

 Age         Owner                  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-2023, 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 all cache 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.  Currently, we just flush them all.  Since attribute
                                 51                 :  * options are not currently used in performance-critical paths (such as
                                 52                 :  * query execution), this seems OK.
                                 53                 :  */
                                 54                 : static void
 4254 tgl                        55 GIC      358802 : InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
 4825 rhaas                      56 ECB             : {
                                 57                 :     HASH_SEQ_STATUS status;
                                 58                 :     AttoptCacheEntry *attopt;
                                 59                 : 
 4825 rhaas                      60 GIC      358802 :     hash_seq_init(&status, AttoptCacheHash);
 4825 rhaas                      61 CBC      363678 :     while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL)
 4825 rhaas                      62 ECB             :     {
 4825 rhaas                      63 GIC        4876 :         if (attopt->opts)
 4825 rhaas                      64 CBC           3 :             pfree(attopt->opts);
                                 65            4876 :         if (hash_search(AttoptCacheHash,
   62 peter                      66 GNC        4876 :                         &attopt->key,
 4825 rhaas                      67 ECB             :                         HASH_REMOVE,
                                 68                 :                         NULL) == NULL)
 4825 rhaas                      69 UIC           0 :             elog(ERROR, "hash table corrupted");
 4825 rhaas                      70 EUB             :     }
 4825 rhaas                      71 GIC      358802 : }
 4825 rhaas                      72 ECB             : 
                                 73                 : /*
                                 74                 :  * InitializeAttoptCache
                                 75                 :  *      Initialize the attribute options cache.
                                 76                 :  */
                                 77                 : static void
 4825 rhaas                      78 GIC         492 : InitializeAttoptCache(void)
 4825 rhaas                      79 ECB             : {
                                 80                 :     HASHCTL     ctl;
                                 81                 : 
                                 82                 :     /* Initialize the hash table. */
 4825 rhaas                      83 GIC         492 :     ctl.keysize = sizeof(AttoptCacheKey);
 4825 rhaas                      84 CBC         492 :     ctl.entrysize = sizeof(AttoptCacheEntry);
                                 85             492 :     AttoptCacheHash =
                                 86             492 :         hash_create("Attopt cache", 256, &ctl,
 3034 tgl                        87 ECB             :                     HASH_ELEM | HASH_BLOBS);
                                 88                 : 
                                 89                 :     /* Make sure we've initialized CacheMemoryContext. */
 4825 rhaas                      90 GIC         492 :     if (!CacheMemoryContext)
 4825 rhaas                      91 LBC           0 :         CreateCacheMemoryContext();
 4825 rhaas                      92 EUB             : 
                                 93                 :     /* Watch for invalidation events. */
 4825 rhaas                      94 GIC         492 :     CacheRegisterSyscacheCallback(ATTNUM,
 4825 rhaas                      95 ECB             :                                   InvalidateAttoptCacheCallback,
                                 96                 :                                   (Datum) 0);
 4825 rhaas                      97 GIC         492 : }
 4825 rhaas                      98 ECB             : 
                                 99                 : /*
                                100                 :  * get_attribute_options
                                101                 :  *      Fetch attribute options for a specified table OID.
                                102                 :  */
                                103                 : AttributeOpts *
 4825 rhaas                     104 GIC      139108 : get_attribute_options(Oid attrelid, int attnum)
 4825 rhaas                     105 ECB             : {
                                106                 :     AttoptCacheKey key;
                                107                 :     AttoptCacheEntry *attopt;
                                108                 :     AttributeOpts *result;
                                109                 :     HeapTuple   tp;
                                110                 : 
                                111                 :     /* Find existing cache entry, if any. */
 4825 rhaas                     112 GIC      139108 :     if (!AttoptCacheHash)
 4825 rhaas                     113 CBC         492 :         InitializeAttoptCache();
 2118 tgl                       114          139108 :     memset(&key, 0, sizeof(key));   /* make sure any padding bits are unset */
 4825 rhaas                     115          139108 :     key.attrelid = attrelid;
                                116          139108 :     key.attnum = attnum;
 4825 rhaas                     117 ECB             :     attopt =
 4825 rhaas                     118 GIC      139108 :         (AttoptCacheEntry *) hash_search(AttoptCacheHash,
                                119                 :                                          &key,
                                120                 :                                          HASH_FIND,
                                121                 :                                          NULL);
                                122                 : 
                                123                 :     /* Not found in Attopt cache.  Construct new cache entry. */
                                124          139108 :     if (!attopt)
 4825 rhaas                     125 ECB             :     {
                                126                 :         AttributeOpts *opts;
                                127                 : 
 4802 rhaas                     128 GIC      138441 :         tp = SearchSysCache2(ATTNUM,
 4802 rhaas                     129 ECB             :                              ObjectIdGetDatum(attrelid),
                                130                 :                              Int16GetDatum(attnum));
                                131                 : 
                                132                 :         /*
                                133                 :          * If we don't find a valid HeapTuple, it must mean someone has
                                134                 :          * managed to request attribute details for a non-existent attribute.
                                135                 :          * We treat that case as if no options were specified.
                                136                 :          */
 4825 rhaas                     137 GIC      138441 :         if (!HeapTupleIsValid(tp))
 4825 rhaas                     138 CBC          48 :             opts = NULL;
 4825 rhaas                     139 ECB             :         else
                                140                 :         {
                                141                 :             Datum       datum;
                                142                 :             bool        isNull;
                                143                 : 
 4825 rhaas                     144 GIC      138393 :             datum = SysCacheGetAttr(ATTNUM,
 4825 rhaas                     145 ECB             :                                     tp,
                                146                 :                                     Anum_pg_attribute_attoptions,
                                147                 :                                     &isNull);
 4825 rhaas                     148 GIC      138393 :             if (isNull)
 4825 rhaas                     149 CBC      138390 :                 opts = NULL;
 4825 rhaas                     150 ECB             :             else
                                151                 :             {
 4790 bruce                     152 GIC           3 :                 bytea      *bytea_opts = attribute_reloptions(datum, false);
 4790 bruce                     153 ECB             : 
 4825 rhaas                     154 GIC           3 :                 opts = MemoryContextAlloc(CacheMemoryContext,
 4825 rhaas                     155 CBC           3 :                                           VARSIZE(bytea_opts));
                                156               3 :                 memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
 4825 rhaas                     157 ECB             :             }
 4825 rhaas                     158 GIC      138393 :             ReleaseSysCache(tp);
 4825 rhaas                     159 ECB             :         }
                                160                 : 
                                161                 :         /*
                                162                 :          * It's important to create the actual cache entry only after reading
                                163                 :          * pg_attribute, since the read could cause a cache flush.
                                164                 :          */
 4825 rhaas                     165 GIC      138441 :         attopt = (AttoptCacheEntry *) hash_search(AttoptCacheHash,
                                166                 :                                                   &key,
                                167                 :                                                   HASH_ENTER,
                                168                 :                                                   NULL);
                                169          138441 :         attopt->opts = opts;
 4825 rhaas                     170 ECB             :     }
                                171                 : 
                                172                 :     /* Return results in caller's memory context. */
 4825 rhaas                     173 GIC      139108 :     if (attopt->opts == NULL)
 4825 rhaas                     174 CBC      139105 :         return NULL;
                                175               3 :     result = palloc(VARSIZE(attopt->opts));
                                176               3 :     memcpy(result, attopt->opts, VARSIZE(attopt->opts));
                                177               3 :     return result;
 4825 rhaas                     178 ECB             : }
        

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