PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
attoptcache.c
Go to the documentation of this file.
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-2017, 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 
26 
27 /* Hash table for informations about each attribute's options */
29 
30 /* attrelid and attnum form the lookup key, and must appear first */
31 typedef struct
32 {
34  int attnum;
36 
37 typedef struct
38 {
39  AttoptCacheKey key; /* lookup key - must be first */
40  AttributeOpts *opts; /* options, or NULL if none */
42 
43 
44 /*
45  * InvalidateAttoptCacheCallback
46  * Flush all cache entries when pg_attribute is updated.
47  *
48  * When pg_attribute is updated, we must flush the cache entry at least
49  * for that attribute. Currently, we just flush them all. Since attribute
50  * options are not currently used in performance-critical paths (such as
51  * query execution), this seems OK.
52  */
53 static void
55 {
57  AttoptCacheEntry *attopt;
58 
59  hash_seq_init(&status, AttoptCacheHash);
60  while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL)
61  {
62  if (attopt->opts)
63  pfree(attopt->opts);
64  if (hash_search(AttoptCacheHash,
65  (void *) &attopt->key,
67  NULL) == NULL)
68  elog(ERROR, "hash table corrupted");
69  }
70 }
71 
72 /*
73  * InitializeAttoptCache
74  * Initialize the tablespace cache.
75  */
76 static void
78 {
79  HASHCTL ctl;
80 
81  /* Initialize the hash table. */
82  MemSet(&ctl, 0, sizeof(ctl));
83  ctl.keysize = sizeof(AttoptCacheKey);
84  ctl.entrysize = sizeof(AttoptCacheEntry);
85  AttoptCacheHash =
86  hash_create("Attopt cache", 256, &ctl,
88 
89  /* Make sure we've initialized CacheMemoryContext. */
90  if (!CacheMemoryContext)
92 
93  /* Watch for invalidation events. */
96  (Datum) 0);
97 }
98 
99 /*
100  * get_attribute_options
101  * Fetch attribute options for a specified table OID.
102  */
104 get_attribute_options(Oid attrelid, int attnum)
105 {
106  AttoptCacheKey key;
107  AttoptCacheEntry *attopt;
109  HeapTuple tp;
110 
111  /* Find existing cache entry, if any. */
112  if (!AttoptCacheHash)
114  memset(&key, 0, sizeof(key)); /* make sure any padding bits are
115  * unset */
116  key.attrelid = attrelid;
117  key.attnum = attnum;
118  attopt =
119  (AttoptCacheEntry *) hash_search(AttoptCacheHash,
120  (void *) &key,
121  HASH_FIND,
122  NULL);
123 
124  /* Not found in Attopt cache. Construct new cache entry. */
125  if (!attopt)
126  {
127  AttributeOpts *opts;
128 
129  tp = SearchSysCache2(ATTNUM,
130  ObjectIdGetDatum(attrelid),
131  Int16GetDatum(attnum));
132 
133  /*
134  * If we don't find a valid HeapTuple, it must mean someone has
135  * managed to request attribute details for a non-existent attribute.
136  * We treat that case as if no options were specified.
137  */
138  if (!HeapTupleIsValid(tp))
139  opts = NULL;
140  else
141  {
142  Datum datum;
143  bool isNull;
144 
145  datum = SysCacheGetAttr(ATTNUM,
146  tp,
148  &isNull);
149  if (isNull)
150  opts = NULL;
151  else
152  {
153  bytea *bytea_opts = attribute_reloptions(datum, false);
154 
156  VARSIZE(bytea_opts));
157  memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
158  }
159  ReleaseSysCache(tp);
160  }
161 
162  /*
163  * It's important to create the actual cache entry only after reading
164  * pg_attribute, since the read could cause a cache flush.
165  */
166  attopt = (AttoptCacheEntry *) hash_search(AttoptCacheHash,
167  (void *) &key,
168  HASH_ENTER,
169  NULL);
170  attopt->opts = opts;
171  }
172 
173  /* Return results in caller's memory context. */
174  if (attopt->opts == NULL)
175  return NULL;
176  result = palloc(VARSIZE(attopt->opts));
177  memcpy(result, attopt->opts, VARSIZE(attopt->opts));
178  return result;
179 }
AttributeOpts * get_attribute_options(Oid attrelid, int attnum)
Definition: attoptcache.c:104
#define HASH_ELEM
Definition: hsearch.h:87
#define VARSIZE(PTR)
Definition: postgres.h:304
#define Int16GetDatum(X)
Definition: postgres.h:457
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:857
return result
Definition: formatting.c:1632
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
unsigned int Oid
Definition: postgres_ext.h:31
bytea * attribute_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1462
AttoptCacheKey key
Definition: attoptcache.c:39
Definition: dynahash.c:193
void pfree(void *pointer)
Definition: mcxt.c:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static HTAB * AttoptCacheHash
Definition: attoptcache.c:28
unsigned int uint32
Definition: c.h:268
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
Size keysize
Definition: hsearch.h:72
static void InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: attoptcache.c:54
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
AttributeOpts * opts
Definition: attoptcache.c:40
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1351
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1341
#define Anum_pg_attribute_attoptions
Definition: pg_attribute.h:215
void * palloc(Size size)
Definition: mcxt.c:849
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
void * arg
static void InitializeAttoptCache(void)
Definition: attoptcache.c:77
Definition: c.h:439
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:158