Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d779199

Browse files
committed
Fix several oversights in previous commit - attribute options patch.
I failed to 'cvs add' the new files and also neglected to bump catversion.
1 parent 76a47c0 commit d779199

File tree

3 files changed

+211
-2
lines changed

3 files changed

+211
-2
lines changed

src/backend/utils/cache/attoptcache.c

+181
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
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-2010, PostgreSQL Global Development Group
10+
* Portions Copyright (c) 1994, Regents of the University of California
11+
*
12+
* IDENTIFICATION
13+
* $PostgreSQL: pgsql/src/backend/utils/cache/attoptcache.c,v 1.1 2010/01/22 16:42:31 rhaas Exp $
14+
*
15+
*-------------------------------------------------------------------------
16+
*/
17+
#include "postgres.h"
18+
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"
27+
28+
29+
/* Hash table for informations about each attribute's options */
30+
static HTAB *AttoptCacheHash = NULL;
31+
32+
/* attrelid and attnum form the lookup key, and must appear first */
33+
typedef struct
34+
{
35+
Oid attrelid;
36+
int attnum;
37+
} AttoptCacheKey;
38+
39+
typedef struct
40+
{
41+
AttoptCacheKey key; /* lookup key - must be first */
42+
AttributeOpts *opts; /* options, or NULL if none */
43+
} AttoptCacheEntry;
44+
45+
46+
/*
47+
* InvalidateAttoptCacheCallback
48+
* Flush all cache entries when pg_attribute is updated.
49+
*
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.
54+
*/
55+
static void
56+
InvalidateAttoptCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
57+
{
58+
HASH_SEQ_STATUS status;
59+
AttoptCacheEntry *attopt;
60+
61+
hash_seq_init(&status, AttoptCacheHash);
62+
while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL)
63+
{
64+
if (attopt->opts)
65+
pfree(attopt->opts);
66+
if (hash_search(AttoptCacheHash,
67+
(void *) &attopt->key,
68+
HASH_REMOVE,
69+
NULL) == NULL)
70+
elog(ERROR, "hash table corrupted");
71+
}
72+
}
73+
74+
/*
75+
* InitializeAttoptCache
76+
* Initialize the tablespace cache.
77+
*/
78+
static void
79+
InitializeAttoptCache(void)
80+
{
81+
HASHCTL ctl;
82+
83+
/* Initialize the hash table. */
84+
MemSet(&ctl, 0, sizeof(ctl));
85+
ctl.keysize = sizeof(AttoptCacheKey);
86+
ctl.entrysize = sizeof(AttoptCacheEntry);
87+
ctl.hash = tag_hash;
88+
AttoptCacheHash =
89+
hash_create("Attopt cache", 256, &ctl,
90+
HASH_ELEM | HASH_FUNCTION);
91+
92+
/* Make sure we've initialized CacheMemoryContext. */
93+
if (!CacheMemoryContext)
94+
CreateCacheMemoryContext();
95+
96+
/* Watch for invalidation events. */
97+
CacheRegisterSyscacheCallback(ATTNUM,
98+
InvalidateAttoptCacheCallback,
99+
(Datum) 0);
100+
}
101+
102+
/*
103+
* get_attribute_options
104+
* Fetch attribute options for a specified table OID.
105+
*/
106+
AttributeOpts *
107+
get_attribute_options(Oid attrelid, int attnum)
108+
{
109+
AttoptCacheKey key;
110+
AttoptCacheEntry *attopt;
111+
AttributeOpts *result;
112+
HeapTuple tp;
113+
114+
/* Find existing cache entry, if any. */
115+
if (!AttoptCacheHash)
116+
InitializeAttoptCache();
117+
memset(&key, 0, sizeof(key)); /* make sure any padding bits are unset */
118+
key.attrelid = attrelid;
119+
key.attnum = attnum;
120+
attopt =
121+
(AttoptCacheEntry *) hash_search(AttoptCacheHash,
122+
(void *) &key,
123+
HASH_FIND,
124+
NULL);
125+
126+
/* Not found in Attopt cache. Construct new cache entry. */
127+
if (!attopt)
128+
{
129+
AttributeOpts *opts;
130+
131+
tp = SearchSysCache(ATTNUM,
132+
ObjectIdGetDatum(attrelid),
133+
Int16GetDatum(attnum),
134+
0, 0);
135+
136+
/*
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.
140+
*/
141+
if (!HeapTupleIsValid(tp))
142+
opts = NULL;
143+
else
144+
{
145+
Datum datum;
146+
bool isNull;
147+
148+
datum = SysCacheGetAttr(ATTNUM,
149+
tp,
150+
Anum_pg_attribute_attoptions,
151+
&isNull);
152+
if (isNull)
153+
opts = NULL;
154+
else
155+
{
156+
bytea *bytea_opts = attribute_reloptions(datum, false);
157+
opts = MemoryContextAlloc(CacheMemoryContext,
158+
VARSIZE(bytea_opts));
159+
memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
160+
}
161+
ReleaseSysCache(tp);
162+
}
163+
164+
/*
165+
* It's important to create the actual cache entry only after
166+
* reading pg_attribute, since the read could cause a cache flush.
167+
*/
168+
attopt = (AttoptCacheEntry *) hash_search(AttoptCacheHash,
169+
(void *) &key,
170+
HASH_ENTER,
171+
NULL);
172+
attopt->opts = opts;
173+
}
174+
175+
/* Return results in caller's memory context. */
176+
if (attopt->opts == NULL)
177+
return NULL;
178+
result = palloc(VARSIZE(attopt->opts));
179+
memcpy(result, attopt->opts, VARSIZE(attopt->opts));
180+
return result;
181+
}

src/include/catalog/catversion.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.577 2010/01/22 15:45:15 petere Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.578 2010/01/22 16:42:31 rhaas Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 201001221
56+
#define CATALOG_VERSION_NO 201001222
5757

5858
#endif

src/include/utils/attoptcache.h

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* attoptcache.h
4+
* Attribute options cache.
5+
*
6+
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* $PostgreSQL: pgsql/src/include/utils/attoptcache.h,v 1.1 2010/01/22 16:42:31 rhaas Exp $
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
#ifndef SPCCACHE_H
14+
#define SPCCACHE_H
15+
16+
/*
17+
* Attribute options.
18+
*/
19+
typedef struct AttributeOpts
20+
{
21+
int32 vl_len_; /* varlena header (do not touch directly!) */
22+
float8 n_distinct;
23+
float8 n_distinct_inherited;
24+
} AttributeOpts;
25+
26+
AttributeOpts *get_attribute_options(Oid spcid, int attnum);
27+
28+
#endif /* SPCCACHE_H */

0 commit comments

Comments
 (0)