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

Lines changed: 181 additions & 0 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 28 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy