1
/*-------------------------------------------------------------------------
4
* Attribute options cache management.
6
* Attribute options are cached separately from the fixed-size portion of
7
* pg_attribute entries, which are handled by the relcache.
9
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
10
* Portions Copyright (c) 1994, Regents of the University of California
13
* src/backend/utils/cache/attoptcache.c
15
*-------------------------------------------------------------------------
19
#include "access/reloptions.h"
20
#include "catalog/pg_attribute.h"
21
#include "utils/attoptcache.h"
22
#include "utils/catcache.h"
23
#include "utils/hsearch.h"
24
#include "utils/inval.h"
25
#include "utils/rel.h"
26
#include "utils/syscache.h"
29
/* Hash table for informations about each attribute's options */
30
static HTAB *AttoptCacheHash = NULL;
32
/* attrelid and attnum form the lookup key, and must appear first */
41
AttoptCacheKey key; /* lookup key - must be first */
42
AttributeOpts *opts; /* options, or NULL if none */
47
* InvalidateAttoptCacheCallback
48
* Flush all cache entries when pg_attribute is updated.
50
* When pg_attribute is updated, we must flush the cache entry at least
51
* for that attribute. Currently, we just flush them all. Since attribute
52
* options are not currently used in performance-critical paths (such as
53
* query execution), this seems OK.
56
InvalidateAttoptCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
58
HASH_SEQ_STATUS status;
59
AttoptCacheEntry *attopt;
61
hash_seq_init(&status, AttoptCacheHash);
62
while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL)
66
if (hash_search(AttoptCacheHash,
67
(void *) &attopt->key,
70
elog(ERROR, "hash table corrupted");
75
* InitializeAttoptCache
76
* Initialize the tablespace cache.
79
InitializeAttoptCache(void)
83
/* Initialize the hash table. */
84
MemSet(&ctl, 0, sizeof(ctl));
85
ctl.keysize = sizeof(AttoptCacheKey);
86
ctl.entrysize = sizeof(AttoptCacheEntry);
89
hash_create("Attopt cache", 256, &ctl,
90
HASH_ELEM | HASH_FUNCTION);
92
/* Make sure we've initialized CacheMemoryContext. */
93
if (!CacheMemoryContext)
94
CreateCacheMemoryContext();
96
/* Watch for invalidation events. */
97
CacheRegisterSyscacheCallback(ATTNUM,
98
InvalidateAttoptCacheCallback,
103
* get_attribute_options
104
* Fetch attribute options for a specified table OID.
107
get_attribute_options(Oid attrelid, int attnum)
110
AttoptCacheEntry *attopt;
111
AttributeOpts *result;
114
/* Find existing cache entry, if any. */
115
if (!AttoptCacheHash)
116
InitializeAttoptCache();
117
memset(&key, 0, sizeof(key)); /* make sure any padding bits are
119
key.attrelid = attrelid;
122
(AttoptCacheEntry *) hash_search(AttoptCacheHash,
127
/* Not found in Attopt cache. Construct new cache entry. */
132
tp = SearchSysCache2(ATTNUM,
133
ObjectIdGetDatum(attrelid),
134
Int16GetDatum(attnum));
137
* If we don't find a valid HeapTuple, it must mean someone has
138
* managed to request attribute details for a non-existent attribute.
139
* We treat that case as if no options were specified.
141
if (!HeapTupleIsValid(tp))
148
datum = SysCacheGetAttr(ATTNUM,
150
Anum_pg_attribute_attoptions,
156
bytea *bytea_opts = attribute_reloptions(datum, false);
158
opts = MemoryContextAlloc(CacheMemoryContext,
159
VARSIZE(bytea_opts));
160
memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
166
* It's important to create the actual cache entry only after reading
167
* pg_attribute, since the read could cause a cache flush.
169
attopt = (AttoptCacheEntry *) hash_search(AttoptCacheHash,
176
/* Return results in caller's memory context. */
177
if (attopt->opts == NULL)
179
result = palloc(VARSIZE(attopt->opts));
180
memcpy(result, attopt->opts, VARSIZE(attopt->opts));