diff options
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r-- | src/backend/utils/cache/catcache.c | 1786 | ||||
-rw-r--r-- | src/backend/utils/cache/fcache.c | 481 | ||||
-rw-r--r-- | src/backend/utils/cache/inval.c | 840 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 618 | ||||
-rw-r--r-- | src/backend/utils/cache/rel.c | 57 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 3493 | ||||
-rw-r--r-- | src/backend/utils/cache/syscache.c | 1057 |
7 files changed, 4279 insertions, 4053 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index aee835943e3..3edddd3c1aa 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * catcache.c-- - * System catalog cache for tuples matching a key. + * System catalog cache for tuples matching a key. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.10 1997/08/26 19:24:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.11 1997/09/07 04:52:56 momjian Exp $ * * Notes: - * XXX This needs to use exception.h to handle recovery when - * an abort occurs during DisableCache. - * + * XXX This needs to use exception.h to handle recovery when + * an abort occurs during DisableCache. + * *------------------------------------------------------------------------- */ #include <string.h> @@ -26,7 +26,7 @@ #include "miscadmin.h" #include "utils/portal.h" #include "utils/catcache.h" -#include "fmgr.h" /* for F_BOOLEQ, etc. DANGER */ +#include "fmgr.h" /* for F_BOOLEQ, etc. DANGER */ #include "utils/elog.h" #include "utils/palloc.h" #include "utils/mcxt.h" @@ -34,29 +34,31 @@ #include "catalog/pg_type.h" /* for OID of int28 type */ #include "lib/dllist.h" -static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e); -static Index CatalogCacheComputeHashIndex(struct catcache *cacheInP); -static Index CatalogCacheComputeTupleHashIndex(struct catcache *cacheInOutP, - Relation relation, HeapTuple tuple); -static void CatalogCacheInitializeCache(struct catcache *cache, - Relation relation); -static long comphash(long l, char *v); +static void CatCacheRemoveCTup(CatCache * cache, Dlelem * e); +static Index CatalogCacheComputeHashIndex(struct catcache * cacheInP); +static Index +CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP, + Relation relation, HeapTuple tuple); +static void +CatalogCacheInitializeCache(struct catcache * cache, + Relation relation); +static long comphash(long l, char *v); /* ---------------- - * variables, macros and other stuff + * variables, macros and other stuff * - * note CCSIZE allocates 51 buckets .. one was already allocated in - * the catcache structure. + * note CCSIZE allocates 51 buckets .. one was already allocated in + * the catcache structure. * ---------------- */ #ifdef CACHEDEBUG -#define CACHE1_elog(a,b) elog(a,b) -#define CACHE2_elog(a,b,c) elog(a,b,c) -#define CACHE3_elog(a,b,c,d) elog(a,b,c,d) -#define CACHE4_elog(a,b,c,d,e) elog(a,b,c,d,e) -#define CACHE5_elog(a,b,c,d,e,f) elog(a,b,c,d,e,f) -#define CACHE6_elog(a,b,c,d,e,f,g) elog(a,b,c,d,e,f,g) +#define CACHE1_elog(a,b) elog(a,b) +#define CACHE2_elog(a,b,c) elog(a,b,c) +#define CACHE3_elog(a,b,c,d) elog(a,b,c,d) +#define CACHE4_elog(a,b,c,d,e) elog(a,b,c,d,e) +#define CACHE5_elog(a,b,c,d,e,f) elog(a,b,c,d,e,f) +#define CACHE6_elog(a,b,c,d,e,f,g) elog(a,b,c,d,e,f,g) #else #define CACHE1_elog(a,b) #define CACHE2_elog(a,b,c) @@ -66,209 +68,217 @@ static long comphash(long l, char *v); #define CACHE6_elog(a,b,c,d,e,f,g) #endif -CatCache *Caches = NULL; +CatCache *Caches = NULL; GlobalMemory CacheCxt; -static int DisableCache; +static int DisableCache; /* ---------------- - * EQPROC is used in CatalogCacheInitializeCache - * XXX this should be replaced by catalog lookups soon + * EQPROC is used in CatalogCacheInitializeCache + * XXX this should be replaced by catalog lookups soon * ---------------- */ -static long eqproc[] = { - F_BOOLEQ, 0l, F_CHAREQ, F_CHAR16EQ, 0l, - F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, 0l, F_TEXTEQ, - F_OIDEQ, 0l, 0l, 0l, F_OID8EQ +static long eqproc[] = { + F_BOOLEQ, 0l, F_CHAREQ, F_CHAR16EQ, 0l, + F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, 0l, F_TEXTEQ, + F_OIDEQ, 0l, 0l, 0l, F_OID8EQ }; -#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-16] +#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-16] /* ---------------------------------------------------------------- - * internal support functions + * internal support functions * ---------------------------------------------------------------- */ /* -------------------------------- - * CatalogCacheInitializeCache + * CatalogCacheInitializeCache * -------------------------------- */ #ifdef CACHEDEBUG #define CatalogCacheInitializeCache_DEBUG1 \ - elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \ - if (relation) \ - elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \ - else \ - elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \ - cache->cc_relname) + elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \ + if (relation) \ + elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \ + else \ + elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \ + cache->cc_relname) #define CatalogCacheInitializeCache_DEBUG2 \ - if (cache->cc_key[i] > 0) { \ - elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %d", \ - i+1, cache->cc_nkeys, cache->cc_key[i], \ - relation->rd_att->attrs[cache->cc_key[i] - 1]->attlen); \ - } else { \ - elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \ - i+1, cache->cc_nkeys, cache->cc_key[i]); \ - } + if (cache->cc_key[i] > 0) { \ + elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %d", \ + i+1, cache->cc_nkeys, cache->cc_key[i], \ + relation->rd_att->attrs[cache->cc_key[i] - 1]->attlen); \ + } else { \ + elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \ + i+1, cache->cc_nkeys, cache->cc_key[i]); \ + } #else #define CatalogCacheInitializeCache_DEBUG1 #define CatalogCacheInitializeCache_DEBUG2 #endif static void -CatalogCacheInitializeCache(struct catcache *cache, - Relation relation) +CatalogCacheInitializeCache(struct catcache * cache, + Relation relation) { - MemoryContext oldcxt; - short didopen = 0; - short i; - TupleDesc tupdesc; - - CatalogCacheInitializeCache_DEBUG1; - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * If no relation was passed we must open it to get access to - * its fields. If one of the other caches has already opened - * it we use heap_open() instead of heap_openr() - * ---------------- - */ - if (! RelationIsValid(relation)) { - struct catcache *cp; + MemoryContext oldcxt; + short didopen = 0; + short i; + TupleDesc tupdesc; + + CatalogCacheInitializeCache_DEBUG1; + /* ---------------- - * scan the caches to see if any other cache has opened the relation + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction * ---------------- */ - for (cp = Caches; cp; cp = cp->cc_next) { - if (strncmp(cp->cc_relname, cache->cc_relname, NAMEDATALEN) == 0) { - if (cp->relationId != InvalidOid) - break; - } + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * If no relation was passed we must open it to get access to + * its fields. If one of the other caches has already opened + * it we use heap_open() instead of heap_openr() + * ---------------- + */ + if (!RelationIsValid(relation)) + { + struct catcache *cp; + + /* ---------------- + * scan the caches to see if any other cache has opened the relation + * ---------------- + */ + for (cp = Caches; cp; cp = cp->cc_next) + { + if (strncmp(cp->cc_relname, cache->cc_relname, NAMEDATALEN) == 0) + { + if (cp->relationId != InvalidOid) + break; + } + } + + /* ---------------- + * open the relation by name or by id + * ---------------- + */ + if (cp) + relation = heap_open(cp->relationId); + else + { + relation = heap_openr(cache->cc_relname); + } + + didopen = 1; } - + /* ---------------- - * open the relation by name or by id + * initialize the cache's relation id * ---------------- */ - if (cp) - relation = heap_open(cp->relationId); - else - { - relation = heap_openr(cache->cc_relname); - } - - didopen = 1; - } - - /* ---------------- - * initialize the cache's relation id - * ---------------- - */ - Assert(RelationIsValid(relation)); - cache->relationId = RelationGetRelationId(relation); - tupdesc = cache->cc_tupdesc = RelationGetTupleDescriptor(relation); - - CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: relid %d, %d keys", - cache->relationId, cache->cc_nkeys); - - /* ---------------- - * initialize cache's key information - * ---------------- - */ - for (i = 0; i < cache->cc_nkeys; ++i) { - CatalogCacheInitializeCache_DEBUG2; - - if (cache->cc_key[i] > 0) { - - /* - * Yoiks. The implementation of the hashing code and the - * implementation of int28's are at loggerheads. The right - * thing to do is to throw out the implementation of int28's - * altogether; until that happens, we do the right thing here - * to guarantee that the hash key generator doesn't try to - * dereference an int2 by mistake. - */ - - if (tupdesc->attrs[cache->cc_key[i]-1]->atttypid == INT28OID) - cache->cc_klen[i] = sizeof (short); - else - cache->cc_klen[i] = tupdesc->attrs[cache->cc_key[i]-1]->attlen; - - cache->cc_skey[i].sk_procedure = - EQPROC(tupdesc->attrs[cache->cc_key[i]-1]->atttypid); - - fmgr_info(cache->cc_skey[i].sk_procedure, - (func_ptr *) &cache->cc_skey[i].sk_func, - (int *) &cache->cc_skey[i].sk_nargs); - - CACHE5_elog(DEBUG, "CatalogCacheInit %16s %d %d %x", - &relation->rd_rel->relname, - i, - tupdesc->attrs[ cache->cc_key[i]-1 ]->attlen, - cache); + Assert(RelationIsValid(relation)); + cache->relationId = RelationGetRelationId(relation); + tupdesc = cache->cc_tupdesc = RelationGetTupleDescriptor(relation); + + CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: relid %d, %d keys", + cache->relationId, cache->cc_nkeys); + + /* ---------------- + * initialize cache's key information + * ---------------- + */ + for (i = 0; i < cache->cc_nkeys; ++i) + { + CatalogCacheInitializeCache_DEBUG2; + + if (cache->cc_key[i] > 0) + { + + /* + * Yoiks. The implementation of the hashing code and the + * implementation of int28's are at loggerheads. The right + * thing to do is to throw out the implementation of int28's + * altogether; until that happens, we do the right thing here + * to guarantee that the hash key generator doesn't try to + * dereference an int2 by mistake. + */ + + if (tupdesc->attrs[cache->cc_key[i] - 1]->atttypid == INT28OID) + cache->cc_klen[i] = sizeof(short); + else + cache->cc_klen[i] = tupdesc->attrs[cache->cc_key[i] - 1]->attlen; + + cache->cc_skey[i].sk_procedure = + EQPROC(tupdesc->attrs[cache->cc_key[i] - 1]->atttypid); + + fmgr_info(cache->cc_skey[i].sk_procedure, + (func_ptr *) & cache->cc_skey[i].sk_func, + (int *) &cache->cc_skey[i].sk_nargs); + + CACHE5_elog(DEBUG, "CatalogCacheInit %16s %d %d %x", + &relation->rd_rel->relname, + i, + tupdesc->attrs[cache->cc_key[i] - 1]->attlen, + cache); + } } - } - - /* ---------------- - * close the relation if we opened it - * ---------------- - */ - if (didopen) - heap_close(relation); - - /* ---------------- - * initialize index information for the cache. this - * should only be done once per cache. - * ---------------- - */ - if (cache->cc_indname != NULL && cache->indexId == InvalidOid) + + /* ---------------- + * close the relation if we opened it + * ---------------- + */ + if (didopen) + heap_close(relation); + + /* ---------------- + * initialize index information for the cache. this + * should only be done once per cache. + * ---------------- + */ + if (cache->cc_indname != NULL && cache->indexId == InvalidOid) { - if (RelationGetRelationTupleForm(relation)->relhasindex) + if (RelationGetRelationTupleForm(relation)->relhasindex) { - /* - * If the index doesn't exist we are in trouble. - */ - relation = index_openr( cache->cc_indname); - Assert(relation); - cache->indexId = RelationGetRelationId(relation); - index_close(relation); + + /* + * If the index doesn't exist we are in trouble. + */ + relation = index_openr(cache->cc_indname); + Assert(relation); + cache->indexId = RelationGetRelationId(relation); + index_close(relation); } - else - cache->cc_indname = NULL; + else + cache->cc_indname = NULL; } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); + + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * CatalogCacheSetId + * CatalogCacheSetId * - * XXX temporary function + * XXX temporary function * -------------------------------- */ #ifdef NOT_USED void -CatalogCacheSetId(CatCache *cacheInOutP, int id) +CatalogCacheSetId(CatCache * cacheInOutP, int id) { - Assert(id == InvalidCatalogCacheId || id >= 0); - cacheInOutP->id = id; + Assert(id == InvalidCatalogCacheId || id >= 0); + cacheInOutP->id = id; } + #endif /* ---------------- * comphash -- - * Compute a hash value, somehow. + * Compute a hash value, somehow. * * XXX explain algorithm here. * @@ -279,798 +289,846 @@ CatalogCacheSetId(CatCache *cacheInOutP, int id) static long comphash(long l, register char *v) { - long i; - NameData n; - - CACHE3_elog(DEBUG, "comphash (%d,%x)", l, v); - - switch (l) { - case 1: - case 2: - case 4: - return((long) v); - } - - if (l == NAMEDATALEN) { - /* if it's a name, make sure that the values - are null-padded. - - Note that this other fixed-length types can also have - the same typelen so this may break them - XXX - */ - namestrcpy(&n,v); - v = n.data; - } else - if (l < 0) - l = VARSIZE(v); - - i = 0; - while (l--) { - i += *v++; - } - return(i); + long i; + NameData n; + + CACHE3_elog(DEBUG, "comphash (%d,%x)", l, v); + + switch (l) + { + case 1: + case 2: + case 4: + return ((long) v); + } + + if (l == NAMEDATALEN) + { + + /* + * if it's a name, make sure that the values are null-padded. + * + * Note that this other fixed-length types can also have the same + * typelen so this may break them - XXX + */ + namestrcpy(&n, v); + v = n.data; + } + else if (l < 0) + l = VARSIZE(v); + + i = 0; + while (l--) + { + i += *v++; + } + return (i); } /* -------------------------------- - * CatalogCacheComputeHashIndex + * CatalogCacheComputeHashIndex * -------------------------------- */ -static Index -CatalogCacheComputeHashIndex(struct catcache *cacheInP) +static Index +CatalogCacheComputeHashIndex(struct catcache * cacheInP) { - Index hashIndex; - hashIndex = 0x0; - CACHE6_elog(DEBUG,"CatalogCacheComputeHashIndex %s %d %d %d %x", - cacheInP->cc_relname, - cacheInP->cc_nkeys, - cacheInP->cc_klen[0], - cacheInP->cc_klen[1], - cacheInP); - - switch (cacheInP->cc_nkeys) { - case 4: - hashIndex ^= comphash(cacheInP->cc_klen[3], - (char*)cacheInP->cc_skey[3].sk_argument) << 9; - /* FALLTHROUGH */ - case 3: - hashIndex ^= comphash(cacheInP->cc_klen[2], - (char*)cacheInP->cc_skey[2].sk_argument) << 6; - /* FALLTHROUGH */ - case 2: - hashIndex ^= comphash(cacheInP->cc_klen[1], - (char*)cacheInP->cc_skey[1].sk_argument) << 3; - /* FALLTHROUGH */ - case 1: - hashIndex ^= comphash(cacheInP->cc_klen[0], - (char*)cacheInP->cc_skey[0].sk_argument); - break; - default: - elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); - break; - } - hashIndex %= cacheInP->cc_size; - return (hashIndex); + Index hashIndex; + + hashIndex = 0x0; + CACHE6_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %d %d %x", + cacheInP->cc_relname, + cacheInP->cc_nkeys, + cacheInP->cc_klen[0], + cacheInP->cc_klen[1], + cacheInP); + + switch (cacheInP->cc_nkeys) + { + case 4: + hashIndex ^= comphash(cacheInP->cc_klen[3], + (char *) cacheInP->cc_skey[3].sk_argument) << 9; + /* FALLTHROUGH */ + case 3: + hashIndex ^= comphash(cacheInP->cc_klen[2], + (char *) cacheInP->cc_skey[2].sk_argument) << 6; + /* FALLTHROUGH */ + case 2: + hashIndex ^= comphash(cacheInP->cc_klen[1], + (char *) cacheInP->cc_skey[1].sk_argument) << 3; + /* FALLTHROUGH */ + case 1: + hashIndex ^= comphash(cacheInP->cc_klen[0], + (char *) cacheInP->cc_skey[0].sk_argument); + break; + default: + elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); + break; + } + hashIndex %= cacheInP->cc_size; + return (hashIndex); } /* -------------------------------- - * CatalogCacheComputeTupleHashIndex + * CatalogCacheComputeTupleHashIndex * -------------------------------- */ -static Index -CatalogCacheComputeTupleHashIndex(struct catcache *cacheInOutP, - Relation relation, - HeapTuple tuple) +static Index +CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP, + Relation relation, + HeapTuple tuple) { - bool isNull = '\0'; - if (cacheInOutP->relationId == InvalidOid) - CatalogCacheInitializeCache(cacheInOutP, relation); - switch (cacheInOutP->cc_nkeys) { - case 4: - cacheInOutP->cc_skey[3].sk_argument = - (cacheInOutP->cc_key[3] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[3], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 3: - cacheInOutP->cc_skey[2].sk_argument = - (cacheInOutP->cc_key[2] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[2], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 2: - cacheInOutP->cc_skey[1].sk_argument = - (cacheInOutP->cc_key[1] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[1], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 1: - cacheInOutP->cc_skey[0].sk_argument = - (cacheInOutP->cc_key[0] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[0], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - break; - default: - elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys", - cacheInOutP->cc_nkeys - ); - break; - } - - return - CatalogCacheComputeHashIndex(cacheInOutP); + bool isNull = '\0'; + + if (cacheInOutP->relationId == InvalidOid) + CatalogCacheInitializeCache(cacheInOutP, relation); + switch (cacheInOutP->cc_nkeys) + { + case 4: + cacheInOutP->cc_skey[3].sk_argument = + (cacheInOutP->cc_key[3] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[3], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 3: + cacheInOutP->cc_skey[2].sk_argument = + (cacheInOutP->cc_key[2] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[2], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 2: + cacheInOutP->cc_skey[1].sk_argument = + (cacheInOutP->cc_key[1] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[1], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 1: + cacheInOutP->cc_skey[0].sk_argument = + (cacheInOutP->cc_key[0] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[0], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + break; + default: + elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys", + cacheInOutP->cc_nkeys + ); + break; + } + + return + CatalogCacheComputeHashIndex(cacheInOutP); } /* -------------------------------- - * CatCacheRemoveCTup + * CatCacheRemoveCTup * -------------------------------- */ static void -CatCacheRemoveCTup(CatCache *cache, Dlelem *elt) +CatCacheRemoveCTup(CatCache * cache, Dlelem * elt) { - CatCTup *ct; - CatCTup *other_ct; - Dlelem *other_elt; - - if (elt) - ct = (CatCTup*) DLE_VAL(elt); - else - return; - - other_elt = ct->ct_node; - other_ct = (CatCTup*)DLE_VAL(other_elt); - DLRemove(other_elt); - DLFreeElem(other_elt); - free(other_ct); - DLRemove(elt); - DLFreeElem(elt); - free(ct); - --cache->cc_ntup; + CatCTup *ct; + CatCTup *other_ct; + Dlelem *other_elt; + + if (elt) + ct = (CatCTup *) DLE_VAL(elt); + else + return; + + other_elt = ct->ct_node; + other_ct = (CatCTup *) DLE_VAL(other_elt); + DLRemove(other_elt); + DLFreeElem(other_elt); + free(other_ct); + DLRemove(elt); + DLFreeElem(elt); + free(ct); + --cache->cc_ntup; } /* -------------------------------- - * CatalogCacheIdInvalidate() + * CatalogCacheIdInvalidate() * - * Invalidate a tuple given a cache id. In this case the id should always - * be found (whether the cache has opened its relation or not). Of course, - * if the cache has yet to open its relation, there will be no tuples so - * no problem. + * Invalidate a tuple given a cache id. In this case the id should always + * be found (whether the cache has opened its relation or not). Of course, + * if the cache has yet to open its relation, there will be no tuples so + * no problem. * -------------------------------- */ void -CatalogCacheIdInvalidate(int cacheId, /* XXX */ - Index hashIndex, - ItemPointer pointer) +CatalogCacheIdInvalidate(int cacheId, /* XXX */ + Index hashIndex, + ItemPointer pointer) { - CatCache *ccp; - CatCTup *ct; - Dlelem *elt; - MemoryContext oldcxt; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(hashIndex < NCCBUCK); - Assert(ItemPointerIsValid(pointer)); - CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called"); - - /* ---------------- - * switch to the cache context for our memory allocations - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * inspect every cache that could contain the tuple - * ---------------- - */ - for (ccp = Caches; ccp; ccp = ccp->cc_next) { - if (cacheId != ccp->id) - continue; + CatCache *ccp; + CatCTup *ct; + Dlelem *elt; + MemoryContext oldcxt; + /* ---------------- - * inspect the hash bucket until we find a match or exhaust + * sanity checks * ---------------- */ - for (elt = DLGetHead(ccp->cc_cache[hashIndex]); - elt; - elt = DLGetSucc(elt)) - { - ct = (CatCTup*) DLE_VAL(elt); - if (ItemPointerEquals(pointer, &ct->ct_tup->t_ctid)) - break; - } - + Assert(hashIndex < NCCBUCK); + Assert(ItemPointerIsValid(pointer)); + CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called"); + /* ---------------- - * if we found a matching tuple, invalidate it. + * switch to the cache context for our memory allocations * ---------------- */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * inspect every cache that could contain the tuple + * ---------------- + */ + for (ccp = Caches; ccp; ccp = ccp->cc_next) + { + if (cacheId != ccp->id) + continue; + /* ---------------- + * inspect the hash bucket until we find a match or exhaust + * ---------------- + */ + for (elt = DLGetHead(ccp->cc_cache[hashIndex]); + elt; + elt = DLGetSucc(elt)) + { + ct = (CatCTup *) DLE_VAL(elt); + if (ItemPointerEquals(pointer, &ct->ct_tup->t_ctid)) + break; + } - if (elt) { - CatCacheRemoveCTup(ccp, elt); + /* ---------------- + * if we found a matching tuple, invalidate it. + * ---------------- + */ - CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + if (elt) + { + CatCacheRemoveCTup(ccp, elt); + + CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + } + + if (cacheId != InvalidCatalogCacheId) + break; } - - if (cacheId != InvalidCatalogCacheId) - break; - } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - /* sendpm('I', "Invalidated tuple"); */ + + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + /* sendpm('I', "Invalidated tuple"); */ } /* ---------------------------------------------------------------- - * public functions + * public functions * - * ResetSystemCache - * InitIndexedSysCache - * InitSysCache - * SearchSysCache - * RelationInvalidateCatalogCacheTuple + * ResetSystemCache + * InitIndexedSysCache + * InitSysCache + * SearchSysCache + * RelationInvalidateCatalogCacheTuple * ---------------------------------------------------------------- */ /* -------------------------------- - * ResetSystemCache + * ResetSystemCache * -------------------------------- */ void ResetSystemCache() { - MemoryContext oldcxt; - struct catcache *cache; - - /* ---------------- - * sanity checks - * ---------------- - */ - CACHE1_elog(DEBUG, "ResetSystemCache called"); - if (DisableCache) { - elog(WARN, "ResetSystemCache: Called while cache disabled"); - return; - } - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * here we purge the contents of all the caches - * - * for each system cache - * for each hash bucket - * for each tuple in hash bucket - * remove the tuple - * ---------------- - */ - for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next) { - int hash; - for (hash = 0; hash < NCCBUCK; hash += 1) { - Dlelem *elt, *nextelt; - for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt) { - nextelt = DLGetSucc(elt); - CatCacheRemoveCTup(cache, elt); - if (cache->cc_ntup == -1) - elog(WARN, "ResetSystemCache: cc_ntup<0 (software error)"); - } + MemoryContext oldcxt; + struct catcache *cache; + + /* ---------------- + * sanity checks + * ---------------- + */ + CACHE1_elog(DEBUG, "ResetSystemCache called"); + if (DisableCache) + { + elog(WARN, "ResetSystemCache: Called while cache disabled"); + return; + } + + /* ---------------- + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * here we purge the contents of all the caches + * + * for each system cache + * for each hash bucket + * for each tuple in hash bucket + * remove the tuple + * ---------------- + */ + for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next) + { + int hash; + + for (hash = 0; hash < NCCBUCK; hash += 1) + { + Dlelem *elt, + *nextelt; + + for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt) + { + nextelt = DLGetSucc(elt); + CatCacheRemoveCTup(cache, elt); + if (cache->cc_ntup == -1) + elog(WARN, "ResetSystemCache: cc_ntup<0 (software error)"); + } + } + cache->cc_ntup = 0; /* in case of WARN error above */ } - cache->cc_ntup = 0; /* in case of WARN error above */ - } - - CACHE1_elog(DEBUG, "end of ResetSystemCache call"); - - /* ---------------- - * back to the old context before we return... - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); + + CACHE1_elog(DEBUG, "end of ResetSystemCache call"); + + /* ---------------- + * back to the old context before we return... + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * InitIndexedSysCache + * InitIndexedSysCache * - * This allocates and initializes a cache for a system catalog relation. - * Actually, the cache is only partially initialized to avoid opening the - * relation. The relation will be opened and the rest of the cache - * structure initialized on the first access. + * This allocates and initializes a cache for a system catalog relation. + * Actually, the cache is only partially initialized to avoid opening the + * relation. The relation will be opened and the rest of the cache + * structure initialized on the first access. * -------------------------------- */ #ifdef CACHEDEBUG #define InitSysCache_DEBUG1 \ elog(DEBUG, "InitSysCache: rid=%d id=%d nkeys=%d size=%d\n", \ - cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \ - for (i = 0; i < nkeys; i += 1) { \ - elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \ - cp->cc_key[i], cp->cc_klen[i], \ - cp->cc_skey[i].sk_flags, \ - cp->cc_skey[i].sk_attno, \ - cp->cc_skey[i].sk_procedure, \ - cp->cc_skey[i].sk_argument); \ - } + cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \ + for (i = 0; i < nkeys; i += 1) { \ + elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \ + cp->cc_key[i], cp->cc_klen[i], \ + cp->cc_skey[i].sk_flags, \ + cp->cc_skey[i].sk_attno, \ + cp->cc_skey[i].sk_procedure, \ + cp->cc_skey[i].sk_argument); \ + } #else #define InitSysCache_DEBUG1 #endif -CatCache* +CatCache * InitSysCache(char *relname, - char *iname, - int id, - int nkeys, - int key[], - HeapTuple (*iScanfuncP)()) + char *iname, + int id, + int nkeys, + int key[], + HeapTuple(*iScanfuncP) ()) { - CatCache *cp; - register int i; - MemoryContext oldcxt; - - char *indname; - - indname = (iname) ? iname : NULL; - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * allocate a new cache structure - * ---------------- - */ - cp = (CatCache *)palloc(sizeof(CatCache)); - memset((char*)cp, 0, sizeof(CatCache)); - - /* ---------------- - * initialize the cache buckets (each bucket is a list header) - * and the LRU tuple list - * ---------------- - */ - { - /* - * We can only do this optimization because the number of hash - * buckets never changes. Without it, we call malloc() too much. - * We could move this to dllist.c, but the way we do this is not - * dynamic/portabl, so why allow other routines to use it. - */ - Dllist *cache_begin = malloc((NCCBUCK+1)*sizeof(Dllist)); - for (i = 0; i <= NCCBUCK; ++i) { - cp->cc_cache[i] = &cache_begin[i]; - cp->cc_cache[i]->dll_head = 0; - cp->cc_cache[i]->dll_tail = 0; - } - } - - cp->cc_lrulist = DLNewList(); - - /* ---------------- - * Caches is the pointer to the head of the list of all the - * system caches. here we add the new cache to the top of the list. - * ---------------- - */ - cp->cc_next = Caches; /* list of caches (single link) */ - Caches = cp; - - /* ---------------- - * initialize the cache's relation information for the relation - * corresponding to this cache and initialize some of the the new - * cache's other internal fields. - * ---------------- - */ - cp->relationId = InvalidOid; - cp->indexId = InvalidOid; - cp->cc_relname = relname; - cp->cc_indname = indname; - cp->cc_tupdesc = (TupleDesc) NULL; - cp->id = id; - cp->cc_maxtup = MAXTUP; - cp->cc_size = NCCBUCK; - cp->cc_nkeys = nkeys; - cp->cc_iscanfunc = iScanfuncP; - - /* ---------------- - * initialize the cache's key information - * ---------------- - */ - for (i = 0; i < nkeys; ++i) { - cp->cc_key[i] = key[i]; - if (!key[i]) { - elog(FATAL, "InitSysCache: called with 0 key[%d]", i); - } - if (key[i] < 0) { - if (key[i] != ObjectIdAttributeNumber) { - elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i); - } else { - cp->cc_klen[i] = sizeof(Oid); + CatCache *cp; + register int i; + MemoryContext oldcxt; + + char *indname; + + indname = (iname) ? iname : NULL; + + /* ---------------- + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * allocate a new cache structure + * ---------------- + */ + cp = (CatCache *) palloc(sizeof(CatCache)); + memset((char *) cp, 0, sizeof(CatCache)); + + /* ---------------- + * initialize the cache buckets (each bucket is a list header) + * and the LRU tuple list + * ---------------- + */ + { + /* - * ScanKeyEntryData and struct skey are equivalent. It looks - * like a move was made to obsolete struct skey, but it - * didn't reach this file. Someday we should clean up this - * code and consolidate to ScanKeyEntry - mer 10 Nov 1991 + * We can only do this optimization because the number of hash + * buckets never changes. Without it, we call malloc() too much. + * We could move this to dllist.c, but the way we do this is not + * dynamic/portabl, so why allow other routines to use it. */ - ScanKeyEntryInitialize(&cp->cc_skey[i], - (bits16)0, - (AttrNumber)key[i], - (RegProcedure)F_OIDEQ, - (Datum)0); - continue; - } + Dllist *cache_begin = malloc((NCCBUCK + 1) * sizeof(Dllist)); + + for (i = 0; i <= NCCBUCK; ++i) + { + cp->cc_cache[i] = &cache_begin[i]; + cp->cc_cache[i]->dll_head = 0; + cp->cc_cache[i]->dll_tail = 0; + } + } + + cp->cc_lrulist = DLNewList(); + + /* ---------------- + * Caches is the pointer to the head of the list of all the + * system caches. here we add the new cache to the top of the list. + * ---------------- + */ + cp->cc_next = Caches; /* list of caches (single link) */ + Caches = cp; + + /* ---------------- + * initialize the cache's relation information for the relation + * corresponding to this cache and initialize some of the the new + * cache's other internal fields. + * ---------------- + */ + cp->relationId = InvalidOid; + cp->indexId = InvalidOid; + cp->cc_relname = relname; + cp->cc_indname = indname; + cp->cc_tupdesc = (TupleDesc) NULL; + cp->id = id; + cp->cc_maxtup = MAXTUP; + cp->cc_size = NCCBUCK; + cp->cc_nkeys = nkeys; + cp->cc_iscanfunc = iScanfuncP; + + /* ---------------- + * initialize the cache's key information + * ---------------- + */ + for (i = 0; i < nkeys; ++i) + { + cp->cc_key[i] = key[i]; + if (!key[i]) + { + elog(FATAL, "InitSysCache: called with 0 key[%d]", i); + } + if (key[i] < 0) + { + if (key[i] != ObjectIdAttributeNumber) + { + elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i); + } + else + { + cp->cc_klen[i] = sizeof(Oid); + + /* + * ScanKeyEntryData and struct skey are equivalent. It + * looks like a move was made to obsolete struct skey, but + * it didn't reach this file. Someday we should clean up + * this code and consolidate to ScanKeyEntry - mer 10 Nov + * 1991 + */ + ScanKeyEntryInitialize(&cp->cc_skey[i], + (bits16) 0, + (AttrNumber) key[i], + (RegProcedure) F_OIDEQ, + (Datum) 0); + continue; + } + } + + cp->cc_skey[i].sk_attno = key[i]; } - - cp->cc_skey[i].sk_attno = key[i]; - } - - /* ---------------- - * all done. new cache is initialized. print some debugging - * information, if appropriate. - * ---------------- - */ - InitSysCache_DEBUG1; - - /* ---------------- - * back to the old context before we return... - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - return(cp); + + /* ---------------- + * all done. new cache is initialized. print some debugging + * information, if appropriate. + * ---------------- + */ + InitSysCache_DEBUG1; + + /* ---------------- + * back to the old context before we return... + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + return (cp); } /* -------------------------------- - * SearchSysCache + * SearchSysCache * - * This call searches a system cache for a tuple, opening the relation - * if necessary (the first access to a particular cache). + * This call searches a system cache for a tuple, opening the relation + * if necessary (the first access to a particular cache). * -------------------------------- */ HeapTuple -SearchSysCache(struct catcache *cache, - Datum v1, - Datum v2, - Datum v3, - Datum v4) +SearchSysCache(struct catcache * cache, + Datum v1, + Datum v2, + Datum v3, + Datum v4) { - unsigned hash; - CatCTup *ct = NULL; - CatCTup *nct; - CatCTup *nct2; - Dlelem *elt; - HeapTuple ntp = 0; - Buffer buffer; - - Relation relation; - MemoryContext oldcxt; - - /* ---------------- - * sanity checks - * ---------------- - */ - if (cache->relationId == InvalidOid) - CatalogCacheInitializeCache(cache, NULL); - - /* ---------------- - * initialize the search key information - * ---------------- - */ - cache->cc_skey[0].sk_argument = v1; - cache->cc_skey[1].sk_argument = v2; - cache->cc_skey[2].sk_argument = v3; - cache->cc_skey[3].sk_argument = v4; - - /* ---------------- - * find the hash bucket in which to look for the tuple - * ---------------- - */ - hash = CatalogCacheComputeHashIndex(cache); - - /* ---------------- - * scan the hash bucket until we find a match or exhaust our tuples - * ---------------- - */ - for (elt = DLGetHead(cache->cc_cache[hash]); - elt; - elt = DLGetSucc(elt)) + unsigned hash; + CatCTup *ct = NULL; + CatCTup *nct; + CatCTup *nct2; + Dlelem *elt; + HeapTuple ntp = 0; + Buffer buffer; + + Relation relation; + MemoryContext oldcxt; + + /* ---------------- + * sanity checks + * ---------------- + */ + if (cache->relationId == InvalidOid) + CatalogCacheInitializeCache(cache, NULL); + + /* ---------------- + * initialize the search key information + * ---------------- + */ + cache->cc_skey[0].sk_argument = v1; + cache->cc_skey[1].sk_argument = v2; + cache->cc_skey[2].sk_argument = v3; + cache->cc_skey[3].sk_argument = v4; + + /* ---------------- + * find the hash bucket in which to look for the tuple + * ---------------- + */ + hash = CatalogCacheComputeHashIndex(cache); + + /* ---------------- + * scan the hash bucket until we find a match or exhaust our tuples + * ---------------- + */ + for (elt = DLGetHead(cache->cc_cache[hash]); + elt; + elt = DLGetSucc(elt)) { - ct = (CatCTup*)DLE_VAL(elt); - /* ---------------- - * see if the cached tuple matches our key. - * (should we be worried about time ranges? -cim 10/2/90) - * ---------------- - */ - if (heap_keytest(ct->ct_tup, - cache->cc_tupdesc, - cache->cc_nkeys, - cache->cc_skey)) - break; + ct = (CatCTup *) DLE_VAL(elt); + /* ---------------- + * see if the cached tuple matches our key. + * (should we be worried about time ranges? -cim 10/2/90) + * ---------------- + */ + if (heap_keytest(ct->ct_tup, + cache->cc_tupdesc, + cache->cc_nkeys, + cache->cc_skey)) + break; } - - /* ---------------- - * if we found a tuple in the cache, move it to the top of the - * lru list, and return it. - * ---------------- - */ - if (elt) { - Dlelem* old_lru_elt; - old_lru_elt = ((CatCTup*)DLE_VAL(elt))->ct_node; - DLRemove(old_lru_elt); - DLAddHead(cache->cc_lrulist, old_lru_elt); + + /* ---------------- + * if we found a tuple in the cache, move it to the top of the + * lru list, and return it. + * ---------------- + */ + if (elt) + { + Dlelem *old_lru_elt; + + old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node; + DLRemove(old_lru_elt); + DLAddHead(cache->cc_lrulist, old_lru_elt); #ifdef CACHEDEBUG + relation = heap_open(cache->relationId); + CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", + RelationGetRelationName(relation), hash); + heap_close(relation); +#endif /* CACHEDEBUG */ + + return (ct->ct_tup); + } + + /* ---------------- + * Tuple was not found in cache, so we have to try and + * retrieve it directly from the relation. If it's found, + * we add it to the cache. We must avoid recursion here, + * so we disable cache operations. If operations are + * currently disabled and we couldn't find the requested item + * in the cache, then this may be a recursive request, and we + * abort with an error. + * ---------------- + */ + + if (DisableCache) + { + elog(WARN, "SearchSysCache: Called while cache disabled"); + return ((HeapTuple) NULL); + } + + /* ---------------- + * open the relation associated with the cache + * ---------------- + */ relation = heap_open(cache->relationId); - CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", - RelationGetRelationName(relation), hash); - heap_close(relation); -#endif /* CACHEDEBUG */ - - return (ct->ct_tup); - } - - /* ---------------- - * Tuple was not found in cache, so we have to try and - * retrieve it directly from the relation. If it's found, - * we add it to the cache. We must avoid recursion here, - * so we disable cache operations. If operations are - * currently disabled and we couldn't find the requested item - * in the cache, then this may be a recursive request, and we - * abort with an error. - * ---------------- - */ - - if (DisableCache) { - elog(WARN, "SearchSysCache: Called while cache disabled"); - return((HeapTuple) NULL); - } - - /* ---------------- - * open the relation associated with the cache - * ---------------- - */ - relation = heap_open(cache->relationId); - CACHE2_elog(DEBUG, "SearchSysCache(%s)", - RelationGetRelationName(relation)); - - /* ---------------- - * DisableCache and then switch to the cache memory context. - * ---------------- - */ - DisableCache = 1; - - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * Scan the relation to find the tuple. If there's an index, and - * if this isn't bootstrap (initdb) time, use the index. - * ---------------- - */ - CACHE2_elog(DEBUG, "SearchSysCache: performing scan (override==%d)", - heapisoverride()); - - if ((RelationGetRelationTupleForm(relation))->relhasindex - && !IsBootstrapProcessingMode()) + CACHE2_elog(DEBUG, "SearchSysCache(%s)", + RelationGetRelationName(relation)); + + /* ---------------- + * DisableCache and then switch to the cache memory context. + * ---------------- + */ + DisableCache = 1; + + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * Scan the relation to find the tuple. If there's an index, and + * if this isn't bootstrap (initdb) time, use the index. + * ---------------- + */ + CACHE2_elog(DEBUG, "SearchSysCache: performing scan (override==%d)", + heapisoverride()); + + if ((RelationGetRelationTupleForm(relation))->relhasindex + && !IsBootstrapProcessingMode()) { - /* ---------- - * Switch back to old memory context so memory not freed - * in the scan function will go away at transaction end. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo(oldcxt); - Assert(cache->cc_iscanfunc); - switch(cache->cc_nkeys) + /* ---------- + * Switch back to old memory context so memory not freed + * in the scan function will go away at transaction end. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo(oldcxt); + Assert(cache->cc_iscanfunc); + switch (cache->cc_nkeys) + { + case 4: + ntp = cache->cc_iscanfunc(relation, v1, v2, v3, v4); + break; + case 3: + ntp = cache->cc_iscanfunc(relation, v1, v2, v3); + break; + case 2: + ntp = cache->cc_iscanfunc(relation, v1, v2); + break; + case 1: + ntp = cache->cc_iscanfunc(relation, v1); + break; + } + /* ---------- + * Back to Cache context. If we got a tuple copy it + * into our context. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo((MemoryContext) CacheCxt); + if (HeapTupleIsValid(ntp)) { - case 4: ntp = cache->cc_iscanfunc(relation,v1,v2,v3,v4); break; - case 3: ntp = cache->cc_iscanfunc(relation,v1,v2,v3); break; - case 2: ntp = cache->cc_iscanfunc(relation,v1,v2); break; - case 1: ntp = cache->cc_iscanfunc(relation,v1); break; + ntp = heap_copytuple(ntp); } - /* ---------- - * Back to Cache context. If we got a tuple copy it - * into our context. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo((MemoryContext)CacheCxt); - if(HeapTupleIsValid(ntp)) { - ntp = heap_copytuple(ntp); - } } - else + else { - HeapScanDesc sd; - - /* ---------- - * As above do the lookup in the callers memory - * context. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo(oldcxt); - - sd = heap_beginscan(relation, 0, NowTimeQual, - cache->cc_nkeys, cache->cc_skey); - - /* should this buffer be ReleaseBuffer'd? --djm 8/20/96 */ - ntp = heap_getnext(sd, 0, &buffer); - - MemoryContextSwitchTo((MemoryContext)CacheCxt); - - if (HeapTupleIsValid(ntp)) { - CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); - ntp = heap_copytuple(ntp); - } - - MemoryContextSwitchTo(oldcxt); - - heap_endscan(sd); - - MemoryContextSwitchTo((MemoryContext)CacheCxt); + HeapScanDesc sd; + + /* ---------- + * As above do the lookup in the callers memory + * context. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo(oldcxt); + + sd = heap_beginscan(relation, 0, NowTimeQual, + cache->cc_nkeys, cache->cc_skey); + + /* should this buffer be ReleaseBuffer'd? --djm 8/20/96 */ + ntp = heap_getnext(sd, 0, &buffer); + + MemoryContextSwitchTo((MemoryContext) CacheCxt); + + if (HeapTupleIsValid(ntp)) + { + CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); + ntp = heap_copytuple(ntp); + } + + MemoryContextSwitchTo(oldcxt); + + heap_endscan(sd); + + MemoryContextSwitchTo((MemoryContext) CacheCxt); } - - DisableCache = 0; - - /* ---------------- - * scan is complete. if tup is valid, we copy it and add the copy to - * the cache. - * ---------------- - */ - if (HeapTupleIsValid(ntp)) { + + DisableCache = 0; + /* ---------------- - * allocate a new cache tuple holder, store the pointer - * to the heap tuple there and initialize the list pointers. + * scan is complete. if tup is valid, we copy it and add the copy to + * the cache. * ---------------- */ - Dlelem *lru_elt; - - /* this is a little cumbersome here because we want the Dlelem's - in both doubly linked lists to point to one another. - That makes it easier to remove something from both the cache bucket - and the lru list at the same time */ - nct = (CatCTup*) malloc(sizeof(CatCTup)); - nct->ct_tup = ntp; - elt = DLNewElem(nct); - nct2 = (CatCTup*) malloc(sizeof(CatCTup)); - nct2->ct_tup = ntp; - lru_elt = DLNewElem(nct2); - nct2->ct_node = elt; - nct->ct_node = lru_elt; - - DLAddHead(cache->cc_lrulist, lru_elt); - DLAddHead(cache->cc_cache[hash], elt); + if (HeapTupleIsValid(ntp)) + { + /* ---------------- + * allocate a new cache tuple holder, store the pointer + * to the heap tuple there and initialize the list pointers. + * ---------------- + */ + Dlelem *lru_elt; + + /* + * this is a little cumbersome here because we want the Dlelem's + * in both doubly linked lists to point to one another. That makes + * it easier to remove something from both the cache bucket and + * the lru list at the same time + */ + nct = (CatCTup *) malloc(sizeof(CatCTup)); + nct->ct_tup = ntp; + elt = DLNewElem(nct); + nct2 = (CatCTup *) malloc(sizeof(CatCTup)); + nct2->ct_tup = ntp; + lru_elt = DLNewElem(nct2); + nct2->ct_node = elt; + nct->ct_node = lru_elt; + + DLAddHead(cache->cc_lrulist, lru_elt); + DLAddHead(cache->cc_cache[hash], elt); + + /* ---------------- + * deal with hash bucket overflow + * ---------------- + */ + if (++cache->cc_ntup > cache->cc_maxtup) + { + CatCTup *ct; + + elt = DLGetTail(cache->cc_lrulist); + ct = (CatCTup *) DLE_VAL(elt); + + if (ct != nct) + { + CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", + RelationGetRelationName(relation)); + + CatCacheRemoveCTup(cache, elt); + + } + } + + CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", + RelationGetRelationName(relation), + cache->cc_ntup, cache->cc_maxtup); + CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", + RelationGetRelationName(relation), hash); + } /* ---------------- - * deal with hash bucket overflow + * close the relation, switch back to the original memory context + * and return the tuple we found (or NULL) * ---------------- */ - if (++cache->cc_ntup > cache->cc_maxtup) { - CatCTup *ct; - elt = DLGetTail(cache->cc_lrulist); - ct = (CatCTup *) DLE_VAL(elt); - - if (ct != nct) { - CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", - RelationGetRelationName(relation)); - - CatCacheRemoveCTup(cache, elt); - - } - } - - CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", - RelationGetRelationName(relation), - cache->cc_ntup, cache->cc_maxtup); - CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", - RelationGetRelationName(relation), hash); - } - - /* ---------------- - * close the relation, switch back to the original memory context - * and return the tuple we found (or NULL) - * ---------------- - */ - heap_close(relation); - - MemoryContextSwitchTo(oldcxt); - return ntp; + heap_close(relation); + + MemoryContextSwitchTo(oldcxt); + return ntp; } /* -------------------------------- - * RelationInvalidateCatalogCacheTuple() + * RelationInvalidateCatalogCacheTuple() * - * Invalidate a tuple from a specific relation. This call determines the - * cache in question and calls CatalogCacheIdInvalidate(). It is -ok- - * if the relation cannot be found, it simply means this backend has yet - * to open it. + * Invalidate a tuple from a specific relation. This call determines the + * cache in question and calls CatalogCacheIdInvalidate(). It is -ok- + * if the relation cannot be found, it simply means this backend has yet + * to open it. * -------------------------------- */ void RelationInvalidateCatalogCacheTuple(Relation relation, - HeapTuple tuple, - void (*function)(int, Index, ItemPointer)) + HeapTuple tuple, + void (*function) (int, Index, ItemPointer)) { - struct catcache *ccp; - MemoryContext oldcxt; - Oid relationId; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - Assert(HeapTupleIsValid(tuple)); - CACHE1_elog(DEBUG, "RelationInvalidateCatalogCacheTuple: called"); - - /* ---------------- - * switch to the cache memory context - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * for each cache - * if the cache contains tuples from the specified relation - * call the invalidation function on the tuples - * in the proper hash bucket - * ---------------- - */ - relationId = RelationGetRelationId(relation); - - for (ccp = Caches; ccp; ccp = ccp->cc_next) { - if (relationId != ccp->relationId) - continue; - - /* OPT inline simplification of CatalogCacheIdInvalidate */ - if (!PointerIsValid(function)) { - function = CatalogCacheIdInvalidate; + struct catcache *ccp; + MemoryContext oldcxt; + Oid relationId; + + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(RelationIsValid(relation)); + Assert(HeapTupleIsValid(tuple)); + CACHE1_elog(DEBUG, "RelationInvalidateCatalogCacheTuple: called"); + + /* ---------------- + * switch to the cache memory context + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * for each cache + * if the cache contains tuples from the specified relation + * call the invalidation function on the tuples + * in the proper hash bucket + * ---------------- + */ + relationId = RelationGetRelationId(relation); + + for (ccp = Caches; ccp; ccp = ccp->cc_next) + { + if (relationId != ccp->relationId) + continue; + + /* OPT inline simplification of CatalogCacheIdInvalidate */ + if (!PointerIsValid(function)) + { + function = CatalogCacheIdInvalidate; + } + + (*function) (ccp->id, + CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), + &tuple->t_ctid); + + heap_close(relation); } - - (*function)(ccp->id, - CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), - &tuple->t_ctid); - - heap_close(relation); - } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - - /* sendpm('I', "Invalidated tuple"); */ -} + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + + /* sendpm('I', "Invalidated tuple"); */ +} diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c index 1d86364abda..ad174c6fdf5 100644 --- a/src/backend/utils/cache/fcache.c +++ b/src/backend/utils/cache/fcache.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * fcache.c-- - * Code for the 'function cache' used in Oper and Func nodes.... + * Code for the 'function cache' used in Oper and Func nodes.... * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.4 1996/11/10 03:03:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.5 1997/09/07 04:52:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,23 +23,24 @@ #include "catalog/pg_proc.h" #include "catalog/pg_language.h" #include "catalog/pg_class.h" -#include "parser/parsetree.h" /* for getrelname() */ +#include "parser/parsetree.h" /* for getrelname() */ #include "utils/builtins.h" #include "utils/fcache.h" #include "utils/fcache2.h" #include "nodes/primnodes.h" #include "nodes/execnodes.h" #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif -static Oid GetDynamicFuncArgType(Var *arg, ExprContext *econtext); -static FunctionCachePtr init_fcache(Oid foid, - bool use_syscache, - List *argList, - ExprContext *econtext); +static Oid GetDynamicFuncArgType(Var * arg, ExprContext * econtext); +static FunctionCachePtr +init_fcache(Oid foid, + bool use_syscache, + List * argList, + ExprContext * econtext); /*----------------------------------------------------------------- * @@ -47,259 +48,269 @@ static FunctionCachePtr init_fcache(Oid foid, * * * NOTE: This function can be called when the system cache is being - * initialized. Therefore, use_syscache should ONLY be true - * when the function return type is interesting (ie: set_fcache). + * initialized. Therefore, use_syscache should ONLY be true + * when the function return type is interesting (ie: set_fcache). *----------------------------------------------------------------- */ #define FuncArgTypeIsDynamic(arg) \ - (IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber) + (IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber) -static Oid -GetDynamicFuncArgType(Var *arg, ExprContext *econtext) +static Oid +GetDynamicFuncArgType(Var * arg, ExprContext * econtext) { - char *relname; - int rtid; - HeapTuple tup; - - Assert(IsA(arg,Var)); - - rtid = ((Var*)arg)->varno; - relname = (char*)getrelname(rtid, econtext->ecxt_range_table); - - - tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(relname), - 0,0,0); - if (!tup) - elog(WARN, "Lookup failed on type tuple for class %s", - relname); - - return tup->t_oid; + char *relname; + int rtid; + HeapTuple tup; + + Assert(IsA(arg, Var)); + + rtid = ((Var *) arg)->varno; + relname = (char *) getrelname(rtid, econtext->ecxt_range_table); + + + tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(relname), + 0, 0, 0); + if (!tup) + elog(WARN, "Lookup failed on type tuple for class %s", + relname); + + return tup->t_oid; } -static FunctionCachePtr +static FunctionCachePtr init_fcache(Oid foid, - bool use_syscache, - List *argList, - ExprContext *econtext) + bool use_syscache, + List * argList, + ExprContext * econtext) { - HeapTuple procedureTuple; - HeapTuple typeTuple; - Form_pg_proc procedureStruct; - TypeTupleForm typeStruct; - FunctionCachePtr retval; - text *tmp; - int nargs; - - /* ---------------- - * get the procedure tuple corresponding to the given - * functionOid. If this fails, returnValue has been - * pre-initialized to "null" so we just return it. - * ---------------- - */ - retval = (FunctionCachePtr) palloc(sizeof(FunctionCache)); - - if (!use_syscache) - elog(WARN, "what the ????, init the fcache without the catalogs?"); - - procedureTuple = SearchSysCacheTuple(PROOID, - ObjectIdGetDatum(foid), - 0,0,0); - - if (!HeapTupleIsValid(procedureTuple)) - elog(WARN, - "init_fcache: %s %d", - "Cache lookup failed for procedure", foid); - - /* ---------------- - * get the return type from the procedure tuple - * ---------------- - */ - procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); - - /* ---------------- - * get the type tuple corresponding to the return type - * If this fails, returnValue has been pre-initialized - * to "null" so we just return it. - * ---------------- - */ - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(procedureStruct->prorettype), - 0,0,0); - - if (!HeapTupleIsValid(typeTuple)) - elog(WARN, - "init_fcache: %s %d", - "Cache lookup failed for type", - (procedureStruct)->prorettype); - - /* ---------------- - * get the type length and by-value from the type tuple and - * save the information in our one element cache. - * ---------------- - */ - typeStruct = (TypeTupleForm) GETSTRUCT(typeTuple); - - retval->typlen = (typeStruct)->typlen; - if ((typeStruct)->typrelid == InvalidOid) { - /* The return type is not a relation, so just use byval */ - retval->typbyval = (typeStruct)->typbyval ? true : false ; - } else { - /* This is a hack. We assume here that any function returning - * a relation returns it by reference. This needs to be - * fixed. + HeapTuple procedureTuple; + HeapTuple typeTuple; + Form_pg_proc procedureStruct; + TypeTupleForm typeStruct; + FunctionCachePtr retval; + text *tmp; + int nargs; + + /* ---------------- + * get the procedure tuple corresponding to the given + * functionOid. If this fails, returnValue has been + * pre-initialized to "null" so we just return it. + * ---------------- + */ + retval = (FunctionCachePtr) palloc(sizeof(FunctionCache)); + + if (!use_syscache) + elog(WARN, "what the ????, init the fcache without the catalogs?"); + + procedureTuple = SearchSysCacheTuple(PROOID, + ObjectIdGetDatum(foid), + 0, 0, 0); + + if (!HeapTupleIsValid(procedureTuple)) + elog(WARN, + "init_fcache: %s %d", + "Cache lookup failed for procedure", foid); + + /* ---------------- + * get the return type from the procedure tuple + * ---------------- + */ + procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); + + /* ---------------- + * get the type tuple corresponding to the return type + * If this fails, returnValue has been pre-initialized + * to "null" so we just return it. + * ---------------- + */ + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(procedureStruct->prorettype), + 0, 0, 0); + + if (!HeapTupleIsValid(typeTuple)) + elog(WARN, + "init_fcache: %s %d", + "Cache lookup failed for type", + (procedureStruct)->prorettype); + + /* ---------------- + * get the type length and by-value from the type tuple and + * save the information in our one element cache. + * ---------------- */ - retval->typbyval = false; - } - retval->foid = foid; - retval->language = procedureStruct->prolang; - retval->func_state = (char *)NULL; - retval->setArg = NULL; - retval->hasSetArg = false; - retval->oneResult = ! procedureStruct->proretset; - retval->istrusted = procedureStruct->proistrusted; - - /* - * If we are returning exactly one result then we have to copy - * tuples and by reference results because we have to end the execution - * before we return the results. When you do this everything allocated - * by the executor (i.e. slots and tuples) is freed. - */ - if ((retval->language == SQLlanguageId) && - (retval->oneResult) && - !(retval->typbyval)) + typeStruct = (TypeTupleForm) GETSTRUCT(typeTuple); + + retval->typlen = (typeStruct)->typlen; + if ((typeStruct)->typrelid == InvalidOid) + { + /* The return type is not a relation, so just use byval */ + retval->typbyval = (typeStruct)->typbyval ? true : false; + } + else { - Form_pg_class relationStruct; - HeapTuple relationTuple; - TupleDesc td; - TupleTableSlot *slot; - - slot = makeNode(TupleTableSlot); - slot->ttc_shouldFree = true; - slot->ttc_descIsNew = true; - slot->ttc_tupleDescriptor = (TupleDesc) NULL; - slot->ttc_buffer = InvalidBuffer; - slot->ttc_whichplan = -1; - retval->funcSlot = (Pointer)slot; - - relationTuple = (HeapTuple) - SearchSysCacheTuple(RELNAME, - PointerGetDatum(&typeStruct->typname), - 0,0,0); - - if (relationTuple) + + /* + * This is a hack. We assume here that any function returning a + * relation returns it by reference. This needs to be fixed. + */ + retval->typbyval = false; + } + retval->foid = foid; + retval->language = procedureStruct->prolang; + retval->func_state = (char *) NULL; + retval->setArg = NULL; + retval->hasSetArg = false; + retval->oneResult = !procedureStruct->proretset; + retval->istrusted = procedureStruct->proistrusted; + + /* + * If we are returning exactly one result then we have to copy tuples + * and by reference results because we have to end the execution + * before we return the results. When you do this everything + * allocated by the executor (i.e. slots and tuples) is freed. + */ + if ((retval->language == SQLlanguageId) && + (retval->oneResult) && + !(retval->typbyval)) + { + Form_pg_class relationStruct; + HeapTuple relationTuple; + TupleDesc td; + TupleTableSlot *slot; + + slot = makeNode(TupleTableSlot); + slot->ttc_shouldFree = true; + slot->ttc_descIsNew = true; + slot->ttc_tupleDescriptor = (TupleDesc) NULL; + slot->ttc_buffer = InvalidBuffer; + slot->ttc_whichplan = -1; + retval->funcSlot = (Pointer) slot; + + relationTuple = (HeapTuple) + SearchSysCacheTuple(RELNAME, + PointerGetDatum(&typeStruct->typname), + 0, 0, 0); + + if (relationTuple) { - relationStruct = (Form_pg_class)GETSTRUCT(relationTuple); - td = CreateTemplateTupleDesc(relationStruct->relnatts); + relationStruct = (Form_pg_class) GETSTRUCT(relationTuple); + td = CreateTemplateTupleDesc(relationStruct->relnatts); } - else - td = CreateTemplateTupleDesc(1); - - ((TupleTableSlot*)retval->funcSlot)->ttc_tupleDescriptor = td; + else + td = CreateTemplateTupleDesc(1); + + ((TupleTableSlot *) retval->funcSlot)->ttc_tupleDescriptor = td; } - else - retval->funcSlot = (char *)NULL; - - nargs = procedureStruct->pronargs; - retval->nargs = nargs; - - if (nargs > 0) + else + retval->funcSlot = (char *) NULL; + + nargs = procedureStruct->pronargs; + retval->nargs = nargs; + + if (nargs > 0) { - Oid *argTypes; - - retval->nullVect = (bool *)palloc((retval->nargs)*sizeof(bool)); - - if (retval->language == SQLlanguageId) + Oid *argTypes; + + retval->nullVect = (bool *) palloc((retval->nargs) * sizeof(bool)); + + if (retval->language == SQLlanguageId) { - int i; - List *oneArg; - - retval->argOidVect = - (Oid *)palloc(retval->nargs*sizeof(Oid)); - argTypes = procedureStruct->proargtypes; - memmove(retval->argOidVect, - argTypes, - (retval->nargs)*sizeof(Oid)); - - for (i=0; - argList; - i++, argList = lnext(argList)) + int i; + List *oneArg; + + retval->argOidVect = + (Oid *) palloc(retval->nargs * sizeof(Oid)); + argTypes = procedureStruct->proargtypes; + memmove(retval->argOidVect, + argTypes, + (retval->nargs) * sizeof(Oid)); + + for (i = 0; + argList; + i++, argList = lnext(argList)) { - oneArg = lfirst(argList); - if (FuncArgTypeIsDynamic(oneArg)) - retval->argOidVect[i] = GetDynamicFuncArgType((Var*)oneArg, - econtext); + oneArg = lfirst(argList); + if (FuncArgTypeIsDynamic(oneArg)) + retval->argOidVect[i] = GetDynamicFuncArgType((Var *) oneArg, + econtext); } } - else - retval->argOidVect = (Oid *)NULL; + else + retval->argOidVect = (Oid *) NULL; } - else + else { - retval->argOidVect = (Oid *)NULL; - retval->nullVect = (BoolPtr)NULL; + retval->argOidVect = (Oid *) NULL; + retval->nullVect = (BoolPtr) NULL; } - - /* - * XXX this is the first varlena in the struct. If the order - * changes for some reason this will fail. - */ - if (procedureStruct->prolang == SQLlanguageId) + + /* + * XXX this is the first varlena in the struct. If the order changes + * for some reason this will fail. + */ + if (procedureStruct->prolang == SQLlanguageId) { - retval->src = textout(&(procedureStruct->prosrc)); - retval->bin = (char *) NULL; + retval->src = textout(&(procedureStruct->prosrc)); + retval->bin = (char *) NULL; } - else + else { - - /* - * I'm not sure that we even need to do this at all. - */ - - /* - * We do for untrusted functions. - */ - - if (procedureStruct->proistrusted) - retval->bin = (char *) NULL; - else { - tmp = (text *) - SearchSysCacheGetAttribute(PROOID, - Anum_pg_proc_probin, - ObjectIdGetDatum(foid), - 0,0,0); - retval->bin = textout(tmp); - } - retval->src = (char *) NULL; + + /* + * I'm not sure that we even need to do this at all. + */ + + /* + * We do for untrusted functions. + */ + + if (procedureStruct->proistrusted) + retval->bin = (char *) NULL; + else + { + tmp = (text *) + SearchSysCacheGetAttribute(PROOID, + Anum_pg_proc_probin, + ObjectIdGetDatum(foid), + 0, 0, 0); + retval->bin = textout(tmp); + } + retval->src = (char *) NULL; } - - - - - if (retval->language != SQLlanguageId) - fmgr_info(foid, &(retval->func), &(retval->nargs)); - else - retval->func = (func_ptr)NULL; - - - return(retval); + + + + + if (retval->language != SQLlanguageId) + fmgr_info(foid, &(retval->func), &(retval->nargs)); + else + retval->func = (func_ptr) NULL; + + + return (retval); } void -setFcache(Node *node, Oid foid, List *argList, ExprContext *econtext) +setFcache(Node * node, Oid foid, List * argList, ExprContext * econtext) { - Func *fnode; - Oper *onode; - FunctionCachePtr fcache; - - fcache = init_fcache(foid, true, argList, econtext); - - if (IsA(node,Oper)) { - onode = (Oper*) node; - onode->op_fcache = fcache; - }else if (IsA(node,Func)) { - fnode = (Func*) node; - fnode->func_fcache = fcache; - }else { - elog(WARN, "init_fcache: node must be Oper or Func!"); - } + Func *fnode; + Oper *onode; + FunctionCachePtr fcache; + + fcache = init_fcache(foid, true, argList, econtext); + + if (IsA(node, Oper)) + { + onode = (Oper *) node; + onode->op_fcache = fcache; + } + else if (IsA(node, Func)) + { + fnode = (Func *) node; + fnode->func_fcache = fcache; + } + else + { + elog(WARN, "init_fcache: node must be Oper or Func!"); + } } diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c index 4f52e4e5f4c..4fb8a5eb6ed 100644 --- a/src/backend/utils/cache/inval.c +++ b/src/backend/utils/cache/inval.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * inval.c-- - * POSTGRES cache invalidation dispatcher code. + * POSTGRES cache invalidation dispatcher code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.4 1997/08/19 21:35:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.5 1997/09/07 04:53:01 momjian Exp $ * * Note - this code is real crufty... * @@ -17,11 +17,11 @@ #include <miscadmin.h> -#include "access/heapam.h" /* XXX to support hacks below */ +#include "access/heapam.h" /* XXX to support hacks below */ #include "access/htup.h" #include "catalog/catalog.h" #include "storage/bufpage.h" -#include "storage/buf.h" /* XXX for InvalidBuffer */ +#include "storage/buf.h" /* XXX for InvalidBuffer */ #include "storage/ipc.h" #include "storage/sinval.h" #include "utils/catcache.h" @@ -29,593 +29,615 @@ #include "utils/rel.h" #include "utils/relcache.h" #include "catalog/catname.h" /* XXX to support hacks below */ -#include "utils/syscache.h" /* XXX to support the hacks below */ +#include "utils/syscache.h" /* XXX to support the hacks below */ static InvalidationEntry InvalidationEntryAllocate(uint16 size); -static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function)()); -static LocalInvalid LocalInvalidRegister(LocalInvalid invalid, +static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ()); +static LocalInvalid +LocalInvalidRegister(LocalInvalid invalid, InvalidationEntry entry); -static void getmyrelids(void); +static void getmyrelids(void); /* ---------------- - * private invalidation structures + * private invalidation structures * ---------------- */ -typedef struct CatalogInvalidationData { - Index cacheId; - Index hashIndex; - ItemPointerData pointerData; -} CatalogInvalidationData; +typedef struct CatalogInvalidationData +{ + Index cacheId; + Index hashIndex; + ItemPointerData pointerData; +} CatalogInvalidationData; -typedef struct RelationInvalidationData { - Oid relationId; - Oid objectId; -} RelationInvalidationData; +typedef struct RelationInvalidationData +{ + Oid relationId; + Oid objectId; +} RelationInvalidationData; -typedef union AnyInvalidation { - CatalogInvalidationData catalog; - RelationInvalidationData relation; -} AnyInvalidation; +typedef union AnyInvalidation +{ + CatalogInvalidationData catalog; + RelationInvalidationData relation; +} AnyInvalidation; -typedef struct InvalidationMessageData { - char kind; - AnyInvalidation any; -} InvalidationMessageData; +typedef struct InvalidationMessageData +{ + char kind; + AnyInvalidation any; +} InvalidationMessageData; -typedef InvalidationMessageData *InvalidationMessage; +typedef InvalidationMessageData *InvalidationMessage; /* ---------------- - * variables and macros + * variables and macros * ---------------- */ -static LocalInvalid Invalid = EmptyLocalInvalid; /* XXX global */ -static bool RefreshWhenInvalidate = false; +static LocalInvalid Invalid = EmptyLocalInvalid; /* XXX global */ +static bool RefreshWhenInvalidate = false; -Oid MyRelationRelationId = InvalidOid; -Oid MyAttributeRelationId = InvalidOid; -Oid MyAMRelationId = InvalidOid; -Oid MyAMOPRelationId = InvalidOid; +Oid MyRelationRelationId = InvalidOid; +Oid MyAttributeRelationId = InvalidOid; +Oid MyAMRelationId = InvalidOid; +Oid MyAMOPRelationId = InvalidOid; #define ValidateHacks() \ - if (!OidIsValid(MyRelationRelationId)) getmyrelids() + if (!OidIsValid(MyRelationRelationId)) getmyrelids() /* ---------------------------------------------------------------- - * "local" invalidation support functions + * "local" invalidation support functions * ---------------------------------------------------------------- */ /* -------------------------------- - * InvalidationEntryAllocate-- - * Allocates an invalidation entry. + * InvalidationEntryAllocate-- + * Allocates an invalidation entry. * -------------------------------- */ -static InvalidationEntry +static InvalidationEntry InvalidationEntryAllocate(uint16 size) { - InvalidationEntryData *entryDataP; - entryDataP = (InvalidationEntryData *) - malloc(sizeof (char *) + size); /* XXX alignment */ - entryDataP->nextP = NULL; - return ((Pointer) &entryDataP->userData); + InvalidationEntryData *entryDataP; + + entryDataP = (InvalidationEntryData *) + malloc(sizeof(char *) + size); /* XXX alignment */ + entryDataP->nextP = NULL; + return ((Pointer) & entryDataP->userData); } /* -------------------------------- - * LocalInvalidRegister -- - * Returns a new local cache invalidation state containing a new entry. + * LocalInvalidRegister -- + * Returns a new local cache invalidation state containing a new entry. * -------------------------------- */ -static LocalInvalid +static LocalInvalid LocalInvalidRegister(LocalInvalid invalid, - InvalidationEntry entry) + InvalidationEntry entry) { - Assert(PointerIsValid(entry)); - - ((InvalidationUserData *)entry)->dataP[-1] = - (InvalidationUserData *)invalid; - - return (entry); + Assert(PointerIsValid(entry)); + + ((InvalidationUserData *) entry)->dataP[-1] = + (InvalidationUserData *) invalid; + + return (entry); } /* -------------------------------- - * LocalInvalidInvalidate-- - * Processes, then frees all entries in a local cache - * invalidation state. + * LocalInvalidInvalidate-- + * Processes, then frees all entries in a local cache + * invalidation state. * -------------------------------- */ static void -LocalInvalidInvalidate(LocalInvalid invalid, void (*function)()) +LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ()) { - InvalidationEntryData *entryDataP; - - while (PointerIsValid(invalid)) { - entryDataP = (InvalidationEntryData *) - &((InvalidationUserData *)invalid)->dataP[-1]; - - if (PointerIsValid(function)) { - (*function)((Pointer) &entryDataP->userData); + InvalidationEntryData *entryDataP; + + while (PointerIsValid(invalid)) + { + entryDataP = (InvalidationEntryData *) + & ((InvalidationUserData *) invalid)->dataP[-1]; + + if (PointerIsValid(function)) + { + (*function) ((Pointer) & entryDataP->userData); + } + + invalid = (Pointer) entryDataP->nextP; + + /* help catch errors */ + entryDataP->nextP = (InvalidationUserData *) NULL; + + free((Pointer) entryDataP); } - - invalid = (Pointer) entryDataP->nextP; - - /* help catch errors */ - entryDataP->nextP = (InvalidationUserData *) NULL; - - free((Pointer)entryDataP); - } } /* ---------------------------------------------------------------- - * private support functions + * private support functions * ---------------------------------------------------------------- */ /* -------------------------------- - * CacheIdRegisterLocalInvalid + * CacheIdRegisterLocalInvalid * -------------------------------- */ #ifdef INVALIDDEBUG #define CacheIdRegisterLocalInvalid_DEBUG1 \ elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \ - cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \ - ItemPointerGetOffsetNumber(pointer)) + cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \ + ItemPointerGetOffsetNumber(pointer)) #else #define CacheIdRegisterLocalInvalid_DEBUG1 -#endif /* INVALIDDEBUG */ - +#endif /* INVALIDDEBUG */ + static void CacheIdRegisterLocalInvalid(Index cacheId, - Index hashIndex, - ItemPointer pointer) + Index hashIndex, + ItemPointer pointer) { - InvalidationMessage message; - - /* ---------------- - * debugging stuff - * ---------------- - */ - CacheIdRegisterLocalInvalid_DEBUG1; - - /* ---------------- - * create a message describing the system catalog tuple - * we wish to invalidate. - * ---------------- - */ - message = (InvalidationMessage) - InvalidationEntryAllocate(sizeof (InvalidationMessageData)); - - message->kind = 'c'; - message->any.catalog.cacheId = cacheId; - message->any.catalog.hashIndex = hashIndex; - - ItemPointerCopy(pointer, &message->any.catalog.pointerData); - - /* ---------------- - * Note: Invalid is a global variable - * ---------------- - */ - Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry)message); + InvalidationMessage message; + + /* ---------------- + * debugging stuff + * ---------------- + */ + CacheIdRegisterLocalInvalid_DEBUG1; + + /* ---------------- + * create a message describing the system catalog tuple + * we wish to invalidate. + * ---------------- + */ + message = (InvalidationMessage) + InvalidationEntryAllocate(sizeof(InvalidationMessageData)); + + message->kind = 'c'; + message->any.catalog.cacheId = cacheId; + message->any.catalog.hashIndex = hashIndex; + + ItemPointerCopy(pointer, &message->any.catalog.pointerData); + + /* ---------------- + * Note: Invalid is a global variable + * ---------------- + */ + Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message); } /* -------------------------------- - * RelationIdRegisterLocalInvalid + * RelationIdRegisterLocalInvalid * -------------------------------- */ static void RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId) { - InvalidationMessage message; - - /* ---------------- - * debugging stuff - * ---------------- - */ + InvalidationMessage message; + + /* ---------------- + * debugging stuff + * ---------------- + */ #ifdef INVALIDDEBUG - elog(DEBUG, "RelationRegisterLocalInvalid(%d, %d)", relationId, - objectId); -#endif /* defined(INVALIDDEBUG) */ - - /* ---------------- - * create a message describing the relation descriptor - * we wish to invalidate. - * ---------------- - */ - message = (InvalidationMessage) - InvalidationEntryAllocate(sizeof (InvalidationMessageData)); - - message->kind = 'r'; - message->any.relation.relationId = relationId; - message->any.relation.objectId = objectId; - - /* ---------------- - * Note: Invalid is a global variable - * ---------------- - */ - Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry)message); + elog(DEBUG, "RelationRegisterLocalInvalid(%d, %d)", relationId, + objectId); +#endif /* defined(INVALIDDEBUG) */ + + /* ---------------- + * create a message describing the relation descriptor + * we wish to invalidate. + * ---------------- + */ + message = (InvalidationMessage) + InvalidationEntryAllocate(sizeof(InvalidationMessageData)); + + message->kind = 'r'; + message->any.relation.relationId = relationId; + message->any.relation.objectId = objectId; + + /* ---------------- + * Note: Invalid is a global variable + * ---------------- + */ + Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message); } /* -------------------------------- - * getmyrelids + * getmyrelids * -------------------------------- */ static void getmyrelids() { - HeapTuple tuple; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(RelationRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyRelationRelationId = tuple->t_oid; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(AttributeRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyAttributeRelationId = tuple->t_oid; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(AccessMethodRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyAMRelationId = tuple->t_oid; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(AccessMethodOperatorRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyAMOPRelationId = tuple->t_oid; + HeapTuple tuple; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(RelationRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyRelationRelationId = tuple->t_oid; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(AttributeRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyAttributeRelationId = tuple->t_oid; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(AccessMethodRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyAMRelationId = tuple->t_oid; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(AccessMethodOperatorRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyAMOPRelationId = tuple->t_oid; } /* -------------------------------- - * CacheIdInvalidate + * CacheIdInvalidate * - * This routine can invalidate an tuple in a system catalog cache - * or a cached relation descriptor. You pay your money and you - * take your chances... + * This routine can invalidate an tuple in a system catalog cache + * or a cached relation descriptor. You pay your money and you + * take your chances... * -------------------------------- */ #ifdef INVALIDDEBUG #define CacheIdInvalidate_DEBUG1 \ elog(DEBUG, "CacheIdInvalidate(%d, %d, 0x%x[%d])", cacheId, hashIndex,\ - pointer, ItemPointerIsValid(pointer)) + pointer, ItemPointerIsValid(pointer)) #else #define CacheIdInvalidate_DEBUG1 -#endif /* defined(INVALIDDEBUG) */ - +#endif /* defined(INVALIDDEBUG) */ + static void CacheIdInvalidate(Index cacheId, - Index hashIndex, - ItemPointer pointer) + Index hashIndex, + ItemPointer pointer) { - /* ---------------- - * assume that if the item pointer is valid, then we are - * invalidating an item in the specified system catalog cache. - * ---------------- - */ - if (ItemPointerIsValid(pointer)) { - CatalogCacheIdInvalidate(cacheId, hashIndex, pointer); - return; - } - - CacheIdInvalidate_DEBUG1; - - ValidateHacks(); /* XXX */ - - /* ---------------- - * if the cacheId is the oid of any of the tuples in the - * following system relations, then assume we are invalidating - * a relation descriptor - * ---------------- - */ - if (cacheId == MyRelationRelationId) { - RelationIdInvalidateRelationCacheByRelationId(hashIndex); - return; - } - - if (cacheId == MyAttributeRelationId) { - RelationIdInvalidateRelationCacheByRelationId(hashIndex); - return; - } - - if (cacheId == MyAMRelationId) { - RelationIdInvalidateRelationCacheByAccessMethodId(hashIndex); - return; - } - - if (cacheId == MyAMOPRelationId) { - RelationIdInvalidateRelationCacheByAccessMethodId(InvalidOid); - return; - } - - /* ---------------- - * Yow! the caller asked us to invalidate something else. - * ---------------- - */ - elog(FATAL, "CacheIdInvalidate: cacheId=%d relation id?", cacheId); + /* ---------------- + * assume that if the item pointer is valid, then we are + * invalidating an item in the specified system catalog cache. + * ---------------- + */ + if (ItemPointerIsValid(pointer)) + { + CatalogCacheIdInvalidate(cacheId, hashIndex, pointer); + return; + } + + CacheIdInvalidate_DEBUG1; + + ValidateHacks(); /* XXX */ + + /* ---------------- + * if the cacheId is the oid of any of the tuples in the + * following system relations, then assume we are invalidating + * a relation descriptor + * ---------------- + */ + if (cacheId == MyRelationRelationId) + { + RelationIdInvalidateRelationCacheByRelationId(hashIndex); + return; + } + + if (cacheId == MyAttributeRelationId) + { + RelationIdInvalidateRelationCacheByRelationId(hashIndex); + return; + } + + if (cacheId == MyAMRelationId) + { + RelationIdInvalidateRelationCacheByAccessMethodId(hashIndex); + return; + } + + if (cacheId == MyAMOPRelationId) + { + RelationIdInvalidateRelationCacheByAccessMethodId(InvalidOid); + return; + } + + /* ---------------- + * Yow! the caller asked us to invalidate something else. + * ---------------- + */ + elog(FATAL, "CacheIdInvalidate: cacheId=%d relation id?", cacheId); } /* -------------------------------- - * ResetSystemCaches + * ResetSystemCaches * - * this blows away all tuples in the system catalog caches and - * all the cached relation descriptors (and closes the files too). + * this blows away all tuples in the system catalog caches and + * all the cached relation descriptors (and closes the files too). * -------------------------------- */ static void ResetSystemCaches() { - ResetSystemCache(); - RelationCacheInvalidate(false); + ResetSystemCache(); + RelationCacheInvalidate(false); } /* -------------------------------- - * InvalidationMessageRegisterSharedInvalid + * InvalidationMessageRegisterSharedInvalid * -------------------------------- */ #ifdef INVALIDDEBUG #define InvalidationMessageRegisterSharedInvalid_DEBUG1 \ elog(DEBUG,\ - "InvalidationMessageRegisterSharedInvalid(c, %d, %d, [%d, %d])",\ - message->any.catalog.cacheId,\ - message->any.catalog.hashIndex,\ - ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ - ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) + "InvalidationMessageRegisterSharedInvalid(c, %d, %d, [%d, %d])",\ + message->any.catalog.cacheId,\ + message->any.catalog.hashIndex,\ + ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ + ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) #define InvalidationMessageRegisterSharedInvalid_DEBUG2 \ - elog(DEBUG, \ - "InvalidationMessageRegisterSharedInvalid(r, %d, %d)", \ - message->any.relation.relationId, \ - message->any.relation.objectId) -#else + elog(DEBUG, \ + "InvalidationMessageRegisterSharedInvalid(r, %d, %d)", \ + message->any.relation.relationId, \ + message->any.relation.objectId) +#else #define InvalidationMessageRegisterSharedInvalid_DEBUG1 #define InvalidationMessageRegisterSharedInvalid_DEBUG2 -#endif /* INVALIDDEBUG */ - +#endif /* INVALIDDEBUG */ + static void InvalidationMessageRegisterSharedInvalid(InvalidationMessage message) { - Assert(PointerIsValid(message)); - - switch (message->kind) { - case 'c': /* cached system catalog tuple */ - InvalidationMessageRegisterSharedInvalid_DEBUG1; - - RegisterSharedInvalid(message->any.catalog.cacheId, - message->any.catalog.hashIndex, - &message->any.catalog.pointerData); - break; - - case 'r': /* cached relation descriptor */ - InvalidationMessageRegisterSharedInvalid_DEBUG2; - - RegisterSharedInvalid(message->any.relation.relationId, - message->any.relation.objectId, - (ItemPointer) NULL); - break; - - default: - elog(FATAL, - "InvalidationMessageRegisterSharedInvalid: `%c' kind", - message->kind); - } + Assert(PointerIsValid(message)); + + switch (message->kind) + { + case 'c': /* cached system catalog tuple */ + InvalidationMessageRegisterSharedInvalid_DEBUG1; + + RegisterSharedInvalid(message->any.catalog.cacheId, + message->any.catalog.hashIndex, + &message->any.catalog.pointerData); + break; + + case 'r': /* cached relation descriptor */ + InvalidationMessageRegisterSharedInvalid_DEBUG2; + + RegisterSharedInvalid(message->any.relation.relationId, + message->any.relation.objectId, + (ItemPointer) NULL); + break; + + default: + elog(FATAL, + "InvalidationMessageRegisterSharedInvalid: `%c' kind", + message->kind); + } } /* -------------------------------- - * InvalidationMessageCacheInvalidate + * InvalidationMessageCacheInvalidate * -------------------------------- */ #ifdef INVALIDDEBUG #define InvalidationMessageCacheInvalidate_DEBUG1 \ elog(DEBUG, "InvalidationMessageCacheInvalidate(c, %d, %d, [%d, %d])",\ - message->any.catalog.cacheId,\ - message->any.catalog.hashIndex,\ - ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ - ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) + message->any.catalog.cacheId,\ + message->any.catalog.hashIndex,\ + ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ + ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) #define InvalidationMessageCacheInvalidate_DEBUG2 \ - elog(DEBUG, "InvalidationMessageCacheInvalidate(r, %d, %d)", \ - message->any.relation.relationId, \ - message->any.relation.objectId) + elog(DEBUG, "InvalidationMessageCacheInvalidate(r, %d, %d)", \ + message->any.relation.relationId, \ + message->any.relation.objectId) #else #define InvalidationMessageCacheInvalidate_DEBUG1 #define InvalidationMessageCacheInvalidate_DEBUG2 -#endif /* defined(INVALIDDEBUG) */ - +#endif /* defined(INVALIDDEBUG) */ + static void InvalidationMessageCacheInvalidate(InvalidationMessage message) { - Assert(PointerIsValid(message)); - - switch (message->kind) { - case 'c': /* cached system catalog tuple */ - InvalidationMessageCacheInvalidate_DEBUG1; - - CatalogCacheIdInvalidate(message->any.catalog.cacheId, - message->any.catalog.hashIndex, - &message->any.catalog.pointerData); - break; - - case 'r': /* cached relation descriptor */ - InvalidationMessageCacheInvalidate_DEBUG2; - - /* XXX ignore this--is this correct ??? */ - break; - - default: - elog(FATAL, "InvalidationMessageCacheInvalidate: `%c' kind", - message->kind); - } + Assert(PointerIsValid(message)); + + switch (message->kind) + { + case 'c': /* cached system catalog tuple */ + InvalidationMessageCacheInvalidate_DEBUG1; + + CatalogCacheIdInvalidate(message->any.catalog.cacheId, + message->any.catalog.hashIndex, + &message->any.catalog.pointerData); + break; + + case 'r': /* cached relation descriptor */ + InvalidationMessageCacheInvalidate_DEBUG2; + + /* XXX ignore this--is this correct ??? */ + break; + + default: + elog(FATAL, "InvalidationMessageCacheInvalidate: `%c' kind", + message->kind); + } } /* -------------------------------- - * RelationInvalidateRelationCache + * RelationInvalidateRelationCache * -------------------------------- */ static void RelationInvalidateRelationCache(Relation relation, - HeapTuple tuple, - void (*function)()) + HeapTuple tuple, + void (*function) ()) { - Oid relationId; - Oid objectId = (Oid)0; - - /* ---------------- - * get the relation object id - * ---------------- - */ - ValidateHacks(); /* XXX */ - relationId = RelationGetRelationId(relation); - - /* ---------------- - * - * ---------------- - */ - if (relationId == MyRelationRelationId) { - objectId = tuple->t_oid; - } else if (relationId == MyAttributeRelationId) { - objectId = ((AttributeTupleForm)GETSTRUCT(tuple))->attrelid; - } else if (relationId == MyAMRelationId) { - objectId = tuple->t_oid; - } else if (relationId == MyAMOPRelationId) { - ; /* objectId is unused */ - } else - return; - - /* ---------------- - * can't handle immediate relation descriptor invalidation - * ---------------- - */ - Assert(PointerIsValid(function)); - - (*function)(relationId, objectId); + Oid relationId; + Oid objectId = (Oid) 0; + + /* ---------------- + * get the relation object id + * ---------------- + */ + ValidateHacks(); /* XXX */ + relationId = RelationGetRelationId(relation); + + /* ---------------- + * + * ---------------- + */ + if (relationId == MyRelationRelationId) + { + objectId = tuple->t_oid; + } + else if (relationId == MyAttributeRelationId) + { + objectId = ((AttributeTupleForm) GETSTRUCT(tuple))->attrelid; + } + else if (relationId == MyAMRelationId) + { + objectId = tuple->t_oid; + } + else if (relationId == MyAMOPRelationId) + { + ; /* objectId is unused */ + } + else + return; + + /* ---------------- + * can't handle immediate relation descriptor invalidation + * ---------------- + */ + Assert(PointerIsValid(function)); + + (*function) (relationId, objectId); } /* * DiscardInvalid -- - * Causes the invalidated cache state to be discarded. + * Causes the invalidated cache state to be discarded. * * Note: - * This should be called as the first step in processing a transaction. - * This should be called while waiting for a query from the front end - * when other backends are active. + * This should be called as the first step in processing a transaction. + * This should be called while waiting for a query from the front end + * when other backends are active. */ void DiscardInvalid() { - /* ---------------- - * debugging stuff - * ---------------- - */ + /* ---------------- + * debugging stuff + * ---------------- + */ #ifdef INVALIDDEBUG - elog(DEBUG, "DiscardInvalid called"); -#endif /* defined(INVALIDDEBUG) */ - - InvalidateSharedInvalid(CacheIdInvalidate, ResetSystemCaches); + elog(DEBUG, "DiscardInvalid called"); +#endif /* defined(INVALIDDEBUG) */ + + InvalidateSharedInvalid(CacheIdInvalidate, ResetSystemCaches); } /* * RegisterInvalid -- - * Causes registration of invalidated state with other backends iff true. + * Causes registration of invalidated state with other backends iff true. * * Note: - * This should be called as the last step in processing a transaction. + * This should be called as the last step in processing a transaction. */ void RegisterInvalid(bool send) { - /* ---------------- - * debugging stuff - * ---------------- - */ + /* ---------------- + * debugging stuff + * ---------------- + */ #ifdef INVALIDDEBUG - elog(DEBUG, "RegisterInvalid(%d) called", send); -#endif /* defined(INVALIDDEBUG) */ - - /* ---------------- - * Note: Invalid is a global variable - * ---------------- - */ - if (send) - LocalInvalidInvalidate(Invalid, - InvalidationMessageRegisterSharedInvalid); - else - LocalInvalidInvalidate(Invalid, - InvalidationMessageCacheInvalidate); - - Invalid = EmptyLocalInvalid; + elog(DEBUG, "RegisterInvalid(%d) called", send); +#endif /* defined(INVALIDDEBUG) */ + + /* ---------------- + * Note: Invalid is a global variable + * ---------------- + */ + if (send) + LocalInvalidInvalidate(Invalid, + InvalidationMessageRegisterSharedInvalid); + else + LocalInvalidInvalidate(Invalid, + InvalidationMessageCacheInvalidate); + + Invalid = EmptyLocalInvalid; } /* * SetRefreshWhenInvalidate -- - * Causes the local caches to be immediately refreshed iff true. + * Causes the local caches to be immediately refreshed iff true. */ void SetRefreshWhenInvalidate(bool on) { #ifdef INVALIDDEBUG - elog(DEBUG, "RefreshWhenInvalidate(%d) called", on); -#endif /* defined(INVALIDDEBUG) */ - - RefreshWhenInvalidate = on; + elog(DEBUG, "RefreshWhenInvalidate(%d) called", on); +#endif /* defined(INVALIDDEBUG) */ + + RefreshWhenInvalidate = on; } /* * RelationIdInvalidateHeapTuple -- - * Causes the given tuple in a relation to be invalidated. + * Causes the given tuple in a relation to be invalidated. * * Note: - * Assumes object id is valid. - * Assumes tuple is valid. + * Assumes object id is valid. + * Assumes tuple is valid. */ #ifdef INVALIDDEBUG #define RelationInvalidateHeapTuple_DEBUG1 \ elog(DEBUG, "RelationInvalidateHeapTuple(%.16s, [%d,%d])", \ - RelationGetRelationName(relation), \ - ItemPointerGetBlockNumber(&tuple->t_ctid), \ - ItemPointerGetOffsetNumber(&tuple->t_ctid)) + RelationGetRelationName(relation), \ + ItemPointerGetBlockNumber(&tuple->t_ctid), \ + ItemPointerGetOffsetNumber(&tuple->t_ctid)) #else #define RelationInvalidateHeapTuple_DEBUG1 -#endif /* defined(INVALIDDEBUG) */ - +#endif /* defined(INVALIDDEBUG) */ + void RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple) { - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - Assert(HeapTupleIsValid(tuple)); - - if (IsBootstrapProcessingMode()) - return; - /* ---------------- - * this only works for system relations now - * ---------------- - */ - if (! IsSystemRelationName(RelationGetRelationTupleForm(relation)->relname.data)) - return; - - /* ---------------- - * debugging stuff - * ---------------- - */ - RelationInvalidateHeapTuple_DEBUG1; - - /* ---------------- - * - * ---------------- - */ - RelationInvalidateCatalogCacheTuple(relation, - tuple, - CacheIdRegisterLocalInvalid); - - RelationInvalidateRelationCache(relation, - tuple, - RelationIdRegisterLocalInvalid); - - if (RefreshWhenInvalidate) + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(RelationIsValid(relation)); + Assert(HeapTupleIsValid(tuple)); + + if (IsBootstrapProcessingMode()) + return; + /* ---------------- + * this only works for system relations now + * ---------------- + */ + if (!IsSystemRelationName(RelationGetRelationTupleForm(relation)->relname.data)) + return; + + /* ---------------- + * debugging stuff + * ---------------- + */ + RelationInvalidateHeapTuple_DEBUG1; + + /* ---------------- + * + * ---------------- + */ RelationInvalidateCatalogCacheTuple(relation, - tuple, - (void (*)()) NULL); -} + tuple, + CacheIdRegisterLocalInvalid); + RelationInvalidateRelationCache(relation, + tuple, + RelationIdRegisterLocalInvalid); + + if (RefreshWhenInvalidate) + RelationInvalidateCatalogCacheTuple(relation, + tuple, + (void (*) ()) NULL); +} diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 9de0c3fb89b..37280036970 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -1,20 +1,20 @@ /*------------------------------------------------------------------------- * * lsyscache.c-- - * Routines to access information within system caches + * Routines to access information within system caches * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.3 1997/08/19 21:35:11 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.4 1997/09/07 04:53:04 momjian Exp $ * * NOTES - * Eventually, the index information should go through here, too. - * - * Most of these routines call SearchSysCacheStruct() and thus simply - * (1) allocate some space for the return struct and (2) call it. - * + * Eventually, the index information should go through here, too. + * + * Most of these routines call SearchSysCacheStruct() and thus simply + * (1) allocate some space for the return struct and (2) call it. + * *------------------------------------------------------------------------- */ #include <string.h> @@ -34,99 +34,100 @@ #include "catalog/pg_operator.h" #include "catalog/pg_type.h" -/* ---------- AMOP CACHES ---------- */ +/* ---------- AMOP CACHES ---------- */ -/* +/* * op_class - - * - * Return t iff operator 'opno' is in operator class 'opclass'. - * + * + * Return t iff operator 'opno' is in operator class 'opclass'. + * */ bool op_class(Oid opno, int32 opclass, Oid amopid) { - FormData_pg_amop amoptup; - - if (SearchSysCacheStruct(AMOPOPID, - (char *) &amoptup, - ObjectIdGetDatum(opclass), - ObjectIdGetDatum(opno), - ObjectIdGetDatum(amopid), - 0)) - return(true); - else - return(false); + FormData_pg_amop amoptup; + + if (SearchSysCacheStruct(AMOPOPID, + (char *) &amoptup, + ObjectIdGetDatum(opclass), + ObjectIdGetDatum(opno), + ObjectIdGetDatum(amopid), + 0)) + return (true); + else + return (false); } -/* ---------- ATTRIBUTE CACHES ---------- */ +/* ---------- ATTRIBUTE CACHES ---------- */ -/* +/* * get_attname - - * - * Given the relation id and the attribute number, - * return the "attname" field from the attribute relation. - * + * + * Given the relation id and the attribute number, + * return the "attname" field from the attribute relation. + * */ -char* +char * get_attname(Oid relid, AttrNumber attnum) { - FormData_pg_attribute att_tup; - char *retval; - - if (SearchSysCacheStruct(ATTNUM, - (char*)&att_tup, - ObjectIdGetDatum(relid), - UInt16GetDatum(attnum), - 0,0)) { - retval = pstrdup(att_tup.attname.data); - - return(retval); - } - else - return(NULL); + FormData_pg_attribute att_tup; + char *retval; + + if (SearchSysCacheStruct(ATTNUM, + (char *) &att_tup, + ObjectIdGetDatum(relid), + UInt16GetDatum(attnum), + 0, 0)) + { + retval = pstrdup(att_tup.attname.data); + + return (retval); + } + else + return (NULL); } -/* +/* * get_attnum - - * - * Given the relation id and the attribute name, - * return the "attnum" field from the attribute relation. - * + * + * Given the relation id and the attribute name, + * return the "attnum" field from the attribute relation. + * */ AttrNumber get_attnum(Oid relid, char *attname) { - FormData_pg_attribute att_tup; - - if (SearchSysCacheStruct(ATTNAME, (char *) &att_tup, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0,0)) - return(att_tup.attnum); - else - return(InvalidAttrNumber); + FormData_pg_attribute att_tup; + + if (SearchSysCacheStruct(ATTNAME, (char *) &att_tup, + ObjectIdGetDatum(relid), + PointerGetDatum(attname), + 0, 0)) + return (att_tup.attnum); + else + return (InvalidAttrNumber); } -/* +/* * get_atttype - - * - * Given the relation OID and the attribute number with the relation, - * return the attribute type OID. - * + * + * Given the relation OID and the attribute number with the relation, + * return the attribute type OID. + * */ Oid get_atttype(Oid relid, AttrNumber attnum) { - AttributeTupleForm att_tup = (AttributeTupleForm)palloc(sizeof(*att_tup)); - - if (SearchSysCacheStruct(ATTNUM, - (char *) att_tup, - ObjectIdGetDatum(relid), - UInt16GetDatum(attnum), - 0,0)) - return(att_tup->atttypid); - else - return((Oid)NULL); + AttributeTupleForm att_tup = (AttributeTupleForm) palloc(sizeof(*att_tup)); + + if (SearchSysCacheStruct(ATTNUM, + (char *) att_tup, + ObjectIdGetDatum(relid), + UInt16GetDatum(attnum), + 0, 0)) + return (att_tup->atttypid); + else + return ((Oid) NULL); } /* This routine uses the attname instead of the attnum because it @@ -136,353 +137,366 @@ get_atttype(Oid relid, AttrNumber attnum) bool get_attisset(Oid relid, char *attname) { - HeapTuple htup; - AttrNumber attno; - AttributeTupleForm att_tup; - - attno = get_attnum(relid, attname); - - htup = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0,0); - if (!HeapTupleIsValid(htup)) - elog(WARN, "get_attisset: no attribute %.16s in relation %d", - attname, relid); - if (heap_attisnull(htup, attno)) - return(false); - else { - att_tup = (AttributeTupleForm)GETSTRUCT(htup); - return(att_tup->attisset); - } + HeapTuple htup; + AttrNumber attno; + AttributeTupleForm att_tup; + + attno = get_attnum(relid, attname); + + htup = SearchSysCacheTuple(ATTNAME, + ObjectIdGetDatum(relid), + PointerGetDatum(attname), + 0, 0); + if (!HeapTupleIsValid(htup)) + elog(WARN, "get_attisset: no attribute %.16s in relation %d", + attname, relid); + if (heap_attisnull(htup, attno)) + return (false); + else + { + att_tup = (AttributeTupleForm) GETSTRUCT(htup); + return (att_tup->attisset); + } } -/* ---------- INDEX CACHE ---------- */ +/* ---------- INDEX CACHE ---------- */ -/* watch this space... +/* watch this space... */ -/* ---------- OPERATOR CACHE ---------- */ +/* ---------- OPERATOR CACHE ---------- */ -/* +/* * get_opcode - - * - * Returns the regproc id of the routine used to implement an - * operator given the operator uid. - * + * + * Returns the regproc id of the routine used to implement an + * operator given the operator uid. + * */ RegProcedure get_opcode(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprcode); - else - return((RegProcedure)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprcode); + else + return ((RegProcedure) NULL); } /* * get_opname - - * returns the name of the operator with the given opno + * returns the name of the operator with the given opno * * Note: return the struct so that it gets copied. */ -char* +char * get_opname(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return (pstrdup(optup.oprname.data)); - else { - elog(WARN, "can't look up operator %d\n", opno); - return NULL; - } + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (pstrdup(optup.oprname.data)); + else + { + elog(WARN, "can't look up operator %d\n", opno); + return NULL; + } } -/* +/* * op_mergesortable - - * - * Returns the left and right sort operators and types corresponding to a - * mergesortable operator, or nil if the operator is not mergesortable. - * + * + * Returns the left and right sort operators and types corresponding to a + * mergesortable operator, or nil if the operator is not mergesortable. + * */ bool -op_mergesortable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp) +op_mergesortable(Oid opno, Oid ltype, Oid rtype, Oid * leftOp, Oid * rightOp) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0) && - optup.oprlsortop && - optup.oprrsortop && - optup.oprleft == ltype && - optup.oprright == rtype) { - - *leftOp = ObjectIdGetDatum(optup.oprlsortop); - *rightOp = ObjectIdGetDatum(optup.oprrsortop); - return TRUE; - } else { - return FALSE; - } + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0) && + optup.oprlsortop && + optup.oprrsortop && + optup.oprleft == ltype && + optup.oprright == rtype) + { + + *leftOp = ObjectIdGetDatum(optup.oprlsortop); + *rightOp = ObjectIdGetDatum(optup.oprrsortop); + return TRUE; + } + else + { + return FALSE; + } } -/* +/* * op_hashjoinable-- - * - * Returns the hash operator corresponding to a hashjoinable operator, + * + * Returns the hash operator corresponding to a hashjoinable operator, * or nil if the operator is not hashjoinable. - * + * */ Oid op_hashjoinable(Oid opno, Oid ltype, Oid rtype) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0) && - optup.oprcanhash && - optup.oprleft == ltype && - optup.oprright == rtype) - return(opno); - else - return(InvalidOid); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0) && + optup.oprcanhash && + optup.oprleft == ltype && + optup.oprright == rtype) + return (opno); + else + return (InvalidOid); } -/* +/* * get_commutator - - * - * Returns the corresponding commutator of an operator. - * + * + * Returns the corresponding commutator of an operator. + * */ Oid get_commutator(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprcom); - else - return((Oid)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprcom); + else + return ((Oid) NULL); } HeapTuple get_operator_tuple(Oid opno) { - HeapTuple optup; - - if ((optup = SearchSysCacheTuple(OPROID, - ObjectIdGetDatum(opno), - 0,0,0))) - return(optup); - else - return((HeapTuple)NULL); + HeapTuple optup; + + if ((optup = SearchSysCacheTuple(OPROID, + ObjectIdGetDatum(opno), + 0, 0, 0))) + return (optup); + else + return ((HeapTuple) NULL); } -/* +/* * get_negator - - * - * Returns the corresponding negator of an operator. - * + * + * Returns the corresponding negator of an operator. + * */ Oid get_negator(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprnegate); - else - return((Oid)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprnegate); + else + return ((Oid) NULL); } -/* +/* * get_oprrest - - * - * Returns procedure id for computing selectivity of an operator. - * + * + * Returns procedure id for computing selectivity of an operator. + * */ RegProcedure get_oprrest(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprrest ); - else - return((RegProcedure) NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprrest); + else + return ((RegProcedure) NULL); } -/* +/* * get_oprjoin - - * - * Returns procedure id for computing selectivity of a join. - * + * + * Returns procedure id for computing selectivity of a join. + * */ RegProcedure get_oprjoin(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprjoin); - else - return((RegProcedure)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprjoin); + else + return ((RegProcedure) NULL); } -/* ---------- RELATION CACHE ---------- */ +/* ---------- RELATION CACHE ---------- */ -/* +/* * get_relnatts - - * - * Returns the number of attributes for a given relation. - * + * + * Returns the number of attributes for a given relation. + * */ int get_relnatts(Oid relid) { - FormData_pg_class reltup; - - if (SearchSysCacheStruct(RELOID, (char *) &reltup, - ObjectIdGetDatum(relid), - 0,0,0)) - return(reltup.relnatts); - else - return(InvalidAttrNumber); + FormData_pg_class reltup; + + if (SearchSysCacheStruct(RELOID, (char *) &reltup, + ObjectIdGetDatum(relid), + 0, 0, 0)) + return (reltup.relnatts); + else + return (InvalidAttrNumber); } -/* +/* * get_rel_name - - * - * Returns the name of a given relation. - * + * + * Returns the name of a given relation. + * */ -char* +char * get_rel_name(Oid relid) { - FormData_pg_class reltup; - - if ((SearchSysCacheStruct(RELOID, - (char*)&reltup, - ObjectIdGetDatum(relid), - 0,0,0))) { - return (pstrdup(reltup.relname.data)); - } else - return(NULL); + FormData_pg_class reltup; + + if ((SearchSysCacheStruct(RELOID, + (char *) &reltup, + ObjectIdGetDatum(relid), + 0, 0, 0))) + { + return (pstrdup(reltup.relname.data)); + } + else + return (NULL); } -/* ---------- TYPE CACHE ---------- */ +/* ---------- TYPE CACHE ---------- */ -/* +/* * get_typlen - - * - * Given the type OID, return the length of the type. - * + * + * Given the type OID, return the length of the type. + * */ int16 get_typlen(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) - return(typtup.typlen); - else - return((int16)NULL); + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + return (typtup.typlen); + else + return ((int16) NULL); } -/* +/* * get_typbyval - - * - * Given the type OID, determine whether the type is returned by value or - * not. Returns 1 if by value, 0 if by reference. - * + * + * Given the type OID, determine whether the type is returned by value or + * not. Returns 1 if by value, 0 if by reference. + * */ bool get_typbyval(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) - return((bool)typtup.typbyval); - else - return(false); + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + return ((bool) typtup.typbyval); + else + return (false); } -/* +/* * get_typbyval - - * - * Given the type OID, determine whether the type is returned by value or - * not. Returns 1 if by value, 0 if by reference. - * + * + * Given the type OID, determine whether the type is returned by value or + * not. Returns 1 if by value, 0 if by reference. + * */ #ifdef NOT_USED char get_typalign(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) - return(typtup.typalign); - else - return ('i'); + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + return (typtup.typalign); + else + return ('i'); } + #endif -/* - * get_typdefault - - * - * Given the type OID, return the default value of the ADT. - * +/* + * get_typdefault - + * + * Given the type OID, return the default value of the ADT. + * */ struct varlena * get_typdefault(Oid typid) { - struct varlena *typdefault = - (struct varlena *)TypeDefaultRetrieve (typid); - return(typdefault); + struct varlena *typdefault = + (struct varlena *) TypeDefaultRetrieve(typid); + + return (typdefault); } -/* +/* * get_typtype - - * - * Given the type OID, find if it is a basic type, a named relation - * or the generic type 'relation'. - * It returns the null char if the cache lookup fails... - * + * + * Given the type OID, find if it is a basic type, a named relation + * or the generic type 'relation'. + * It returns the null char if the cache lookup fails... + * */ #ifdef NOT_USED char get_typtype(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) { - return(typtup.typtype); - } else { - return('\0'); - } + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + { + return (typtup.typtype); + } + else + { + return ('\0'); + } } + #endif diff --git a/src/backend/utils/cache/rel.c b/src/backend/utils/cache/rel.c index 33eabad1a85..4e45138037c 100644 --- a/src/backend/utils/cache/rel.c +++ b/src/backend/utils/cache/rel.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * rel.c-- - * POSTGRES relation descriptor code. + * POSTGRES relation descriptor code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/rel.c,v 1.1.1.1 1996/07/09 06:22:06 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/rel.c,v 1.2 1997/09/07 04:53:07 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,57 +21,56 @@ #include "storage/fd.h" -/* - * RelationIsValid is now a macro in rel.h -cim 4/27/91 +/* + * RelationIsValid is now a macro in rel.h -cim 4/27/91 * - * Many of the RelationGet...() functions are now macros in rel.h - * -mer 3/2/92 + * Many of the RelationGet...() functions are now macros in rel.h + * -mer 3/2/92 */ /* * RelationGetIndexStrategy -- - * Returns index strategy for a relation. + * Returns index strategy for a relation. * * Note: - * Assumes relation descriptor is valid. - * Assumes relation descriptor is for an index relation. + * Assumes relation descriptor is valid. + * Assumes relation descriptor is for an index relation. */ IndexStrategy RelationGetIndexStrategy(Relation relation) { - return relation->rd_istrat; + return relation->rd_istrat; } /* * RelationSetIndexSupport -- - * Sets index strategy and support info for a relation. + * Sets index strategy and support info for a relation. * * Note: - * Assumes relation descriptor is a valid pointer to sufficient space. - * Assumes index strategy is valid. Assumes support is valid if non- - * NULL. + * Assumes relation descriptor is a valid pointer to sufficient space. + * Assumes index strategy is valid. Assumes support is valid if non- + * NULL. */ /* ---------------- - * RelationSetIndexSupport + * RelationSetIndexSupport * - * This routine saves two pointers -- one to the IndexStrategy, and - * one to the RegProcs that support the indexed access method. These - * pointers are stored in the space following the attribute data in the - * reldesc. + * This routine saves two pointers -- one to the IndexStrategy, and + * one to the RegProcs that support the indexed access method. These + * pointers are stored in the space following the attribute data in the + * reldesc. * - * NEW: the index strategy and support are now stored in real fields - * at the end of the structure - jolly + * NEW: the index strategy and support are now stored in real fields + * at the end of the structure - jolly * ---------------- */ void RelationSetIndexSupport(Relation relation, - IndexStrategy strategy, - RegProcedure *support) + IndexStrategy strategy, + RegProcedure * support) { - Assert(PointerIsValid(relation)); - Assert(IndexStrategyIsValid(strategy)); - - relation->rd_istrat = strategy; - relation->rd_support = support; -} + Assert(PointerIsValid(relation)); + Assert(IndexStrategyIsValid(strategy)); + relation->rd_istrat = strategy; + relation->rd_support = support; +} diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a54f1d81387..704d673279b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -1,41 +1,41 @@ /*------------------------------------------------------------------------- * * relcache.c-- - * POSTGRES relation descriptor cache code + * POSTGRES relation descriptor cache code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.20 1997/09/01 08:04:38 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.21 1997/09/07 04:53:08 momjian Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES - * RelationInitialize - initialize relcache - * RelationIdCacheGetRelation - get a reldesc from the cache (id) - * RelationNameCacheGetRelation - get a reldesc from the cache (name) - * RelationIdGetRelation - get a reldesc by relation id - * RelationNameGetRelation - get a reldesc by relation name - * RelationClose - close an open relation - * RelationFlushRelation - flush relation information + * RelationInitialize - initialize relcache + * RelationIdCacheGetRelation - get a reldesc from the cache (id) + * RelationNameCacheGetRelation - get a reldesc from the cache (name) + * RelationIdGetRelation - get a reldesc by relation id + * RelationNameGetRelation - get a reldesc by relation name + * RelationClose - close an open relation + * RelationFlushRelation - flush relation information * * NOTES - * This file is in the process of being cleaned up - * before I add system attribute indexing. -cim 1/13/91 + * This file is in the process of being cleaned up + * before I add system attribute indexing. -cim 1/13/91 * - * The following code contains many undocumented hacks. Please be - * careful.... + * The following code contains many undocumented hacks. Please be + * careful.... * */ #include <sys/types.h> -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <errno.h> #include <sys/file.h> #include <fcntl.h> #include <string.h> - + #include "postgres.h" #include "miscadmin.h" @@ -51,21 +51,21 @@ #include "access/tupdesc.h" #include "access/tupmacs.h" #include "access/xact.h" - + #include "storage/buf.h" -#include "storage/fd.h" /* for SEEK_ */ +#include "storage/fd.h" /* for SEEK_ */ #include "storage/lmgr.h" #include "storage/bufmgr.h" - + #include "lib/hasht.h" - + #include "utils/memutils.h" #include "utils/mcxt.h" #include "utils/rel.h" #include "utils/relcache.h" #include "utils/hsearch.h" #include "utils/relcache.h" - + #include "catalog/catname.h" #include "catalog/catalog.h" #include "utils/syscache.h" @@ -87,1744 +87,1813 @@ #include "catalog/index.h" #include "fmgr.h" -static void RelationFlushRelation(Relation *relationPtr, - bool onlyFlushReferenceCountZero); +static void +RelationFlushRelation(Relation * relationPtr, + bool onlyFlushReferenceCountZero); static Relation RelationNameCacheGetRelation(char *relationName); -static void init_irels(void); -static void write_irels(void); +static void init_irels(void); +static void write_irels(void); /* ---------------- - * defines + * defines * ---------------- */ #define private static #define INIT_FILENAME "pg_internal.init" /* ---------------- - * externs + * externs * ---------------- */ -extern bool AMI_OVERRIDE; /* XXX style */ +extern bool AMI_OVERRIDE; /* XXX style */ extern GlobalMemory CacheCxt; /* from utils/cache/catcache.c */ /* ---------------- - * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h + * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h * ---------------- */ -FormData_pg_attribute Desc_pg_class[Natts_pg_class] = { Schema_pg_class }; -FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = { Schema_pg_attribute }; -FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = { Schema_pg_proc }; -FormData_pg_attribute Desc_pg_type[Natts_pg_type] = { Schema_pg_type }; -FormData_pg_attribute Desc_pg_variable[Natts_pg_variable] = { Schema_pg_variable }; -FormData_pg_attribute Desc_pg_log[Natts_pg_log] = { Schema_pg_log }; -FormData_pg_attribute Desc_pg_time[Natts_pg_time] = { Schema_pg_time }; +FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class}; +FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute}; +FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc}; +FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type}; +FormData_pg_attribute Desc_pg_variable[Natts_pg_variable] = {Schema_pg_variable}; +FormData_pg_attribute Desc_pg_log[Natts_pg_log] = {Schema_pg_log}; +FormData_pg_attribute Desc_pg_time[Natts_pg_time] = {Schema_pg_time}; /* ---------------- - * global variables + * global variables * - * Relations are cached two ways, by name and by id, - * thus there are two hash tables for referencing them. + * Relations are cached two ways, by name and by id, + * thus there are two hash tables for referencing them. * ---------------- */ -HTAB *RelationNameCache; -HTAB *RelationIdCache; +HTAB *RelationNameCache; +HTAB *RelationIdCache; /* ---------------- - * RelationBuildDescInfo exists so code can be shared - * between RelationIdGetRelation() and RelationNameGetRelation() + * RelationBuildDescInfo exists so code can be shared + * between RelationIdGetRelation() and RelationNameGetRelation() * ---------------- */ -typedef struct RelationBuildDescInfo { - int infotype; /* lookup by id or by name */ +typedef struct RelationBuildDescInfo +{ + int infotype; /* lookup by id or by name */ #define INFO_RELID 1 #define INFO_RELNAME 2 - union { - Oid info_id; /* relation object id */ - char *info_name; /* relation name */ - } i; -} RelationBuildDescInfo; - -typedef struct relidcacheent { - Oid reloid; - Relation reldesc; -} RelIdCacheEnt; - -typedef struct relnamecacheent { - NameData relname; - Relation reldesc; -} RelNameCacheEnt; + union + { + Oid info_id;/* relation object id */ + char *info_name; /* relation name */ + } i; +} RelationBuildDescInfo; + +typedef struct relidcacheent +{ + Oid reloid; + Relation reldesc; +} RelIdCacheEnt; + +typedef struct relnamecacheent +{ + NameData relname; + Relation reldesc; +} RelNameCacheEnt; /* ----------------- - * macros to manipulate name cache and id cache + * macros to manipulate name cache and id cache * ----------------- */ #define RelationCacheInsert(RELATION) \ - { RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \ - char *relname; Oid reloid; bool found; \ - relname = (RELATION->rd_rel->relname).data; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - relname, \ - HASH_ENTER, \ - &found); \ - if (namehentry == NULL) { \ - elog(FATAL, "can't insert into relation descriptor cache"); \ - } \ - if (found && !IsBootstrapProcessingMode()) { \ - /* used to give notice -- now just keep quiet */ ; \ - } \ - namehentry->reldesc = RELATION; \ - reloid = RELATION->rd_id; \ - idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&reloid, \ - HASH_ENTER, \ - &found); \ - if (idhentry == NULL) { \ - elog(FATAL, "can't insert into relation descriptor cache"); \ - } \ - if (found && !IsBootstrapProcessingMode()) { \ - /* used to give notice -- now just keep quiet */ ; \ - } \ - idhentry->reldesc = RELATION; \ - } -#define RelationNameCacheLookup(NAME, RELATION) \ - { RelNameCacheEnt *hentry; bool found; \ - hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - (char *)NAME,HASH_FIND,&found); \ - if (hentry == NULL) { \ - elog(FATAL, "error in CACHE"); \ - } \ - if (found) { \ - RELATION = hentry->reldesc; \ - } \ - else { \ - RELATION = NULL; \ - } \ - } -#define RelationIdCacheLookup(ID, RELATION) \ - { RelIdCacheEnt *hentry; bool found; \ - hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&(ID),HASH_FIND, &found); \ - if (hentry == NULL) { \ - elog(FATAL, "error in CACHE"); \ - } \ - if (found) { \ - RELATION = hentry->reldesc; \ - } \ - else { \ - RELATION = NULL; \ - } \ - } + { RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \ + char *relname; Oid reloid; bool found; \ + relname = (RELATION->rd_rel->relname).data; \ + namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + relname, \ + HASH_ENTER, \ + &found); \ + if (namehentry == NULL) { \ + elog(FATAL, "can't insert into relation descriptor cache"); \ + } \ + if (found && !IsBootstrapProcessingMode()) { \ + /* used to give notice -- now just keep quiet */ ; \ + } \ + namehentry->reldesc = RELATION; \ + reloid = RELATION->rd_id; \ + idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&reloid, \ + HASH_ENTER, \ + &found); \ + if (idhentry == NULL) { \ + elog(FATAL, "can't insert into relation descriptor cache"); \ + } \ + if (found && !IsBootstrapProcessingMode()) { \ + /* used to give notice -- now just keep quiet */ ; \ + } \ + idhentry->reldesc = RELATION; \ + } +#define RelationNameCacheLookup(NAME, RELATION) \ + { RelNameCacheEnt *hentry; bool found; \ + hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + (char *)NAME,HASH_FIND,&found); \ + if (hentry == NULL) { \ + elog(FATAL, "error in CACHE"); \ + } \ + if (found) { \ + RELATION = hentry->reldesc; \ + } \ + else { \ + RELATION = NULL; \ + } \ + } +#define RelationIdCacheLookup(ID, RELATION) \ + { RelIdCacheEnt *hentry; bool found; \ + hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&(ID),HASH_FIND, &found); \ + if (hentry == NULL) { \ + elog(FATAL, "error in CACHE"); \ + } \ + if (found) { \ + RELATION = hentry->reldesc; \ + } \ + else { \ + RELATION = NULL; \ + } \ + } #define RelationCacheDelete(RELATION) \ - { RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \ - char *relname; Oid reloid; bool found; \ - relname = (RELATION->rd_rel->relname).data; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - relname, \ - HASH_REMOVE, \ - &found); \ - if (namehentry == NULL) { \ - elog(FATAL, "can't delete from relation descriptor cache"); \ - } \ - if (!found) { \ - elog(NOTICE, "trying to delete a reldesc that does not exist."); \ - } \ - reloid = RELATION->rd_id; \ - idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&reloid, \ - HASH_REMOVE, &found); \ - if (idhentry == NULL) { \ - elog(FATAL, "can't delete from relation descriptor cache"); \ - } \ - if (!found) { \ - elog(NOTICE, "trying to delete a reldesc that does not exist."); \ - } \ - } + { RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \ + char *relname; Oid reloid; bool found; \ + relname = (RELATION->rd_rel->relname).data; \ + namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + relname, \ + HASH_REMOVE, \ + &found); \ + if (namehentry == NULL) { \ + elog(FATAL, "can't delete from relation descriptor cache"); \ + } \ + if (!found) { \ + elog(NOTICE, "trying to delete a reldesc that does not exist."); \ + } \ + reloid = RELATION->rd_id; \ + idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&reloid, \ + HASH_REMOVE, &found); \ + if (idhentry == NULL) { \ + elog(FATAL, "can't delete from relation descriptor cache"); \ + } \ + if (!found) { \ + elog(NOTICE, "trying to delete a reldesc that does not exist."); \ + } \ + } /* non-export function prototypes */ -static void formrdesc(char *relationName, u_int natts, - FormData_pg_attribute att[]); +static void +formrdesc(char *relationName, u_int natts, + FormData_pg_attribute att[]); + +#if 0 /* See comments at line 1304 */ +static void RelationFlushIndexes(Relation * r, Oid accessMethodId); -#if 0 /* See comments at line 1304 */ -static void RelationFlushIndexes(Relation *r, Oid accessMethodId); #endif static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo); static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo); static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo); static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp); -static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); -static void build_tupdesc_seq(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); -static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); +static void +RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); +static void +build_tupdesc_seq(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); +static void +build_tupdesc_ind(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo); -static void IndexedAccessMethodInitialize(Relation relation); -static void AttrDefaultFetch (Relation relation); -static void RelCheckFetch (Relation relation); +static void IndexedAccessMethodInitialize(Relation relation); +static void AttrDefaultFetch(Relation relation); +static void RelCheckFetch(Relation relation); -extern void RelationBuildTriggers (Relation relation); -extern void FreeTriggerDesc (Relation relation); +extern void RelationBuildTriggers(Relation relation); +extern void FreeTriggerDesc(Relation relation); /* * newlyCreatedRelns - - * relations created during this transaction. We need to keep track of - * these. + * relations created during this transaction. We need to keep track of + * these. */ -static List *newlyCreatedRelns = NULL; +static List *newlyCreatedRelns = NULL; /* ---------------------------------------------------------------- - * RelationIdGetRelation() and RelationNameGetRelation() - * support functions + * RelationIdGetRelation() and RelationNameGetRelation() + * support functions * ---------------------------------------------------------------- */ - -#if NOT_USED /* XXX This doesn't seem to be used anywhere */ + +#if NOT_USED /* XXX This doesn't seem to be used + * anywhere */ /* -------------------------------- - * BuildDescInfoError returns a string appropriate to - * the buildinfo passed to it + * BuildDescInfoError returns a string appropriate to + * the buildinfo passed to it * -------------------------------- */ -static char * +static char * BuildDescInfoError(RelationBuildDescInfo buildinfo) { - static char errBuf[64]; - - memset(errBuf, 0, (int) sizeof(errBuf)); - switch(buildinfo.infotype) { - case INFO_RELID: - sprintf(errBuf, "(relation id %d)", buildinfo.i.info_id); - break; - case INFO_RELNAME: - sprintf(errBuf, "(relation name %s)", buildinfo.i.info_name); - break; - } - - return errBuf; + static char errBuf[64]; + + memset(errBuf, 0, (int) sizeof(errBuf)); + switch (buildinfo.infotype) + { + case INFO_RELID: + sprintf(errBuf, "(relation id %d)", buildinfo.i.info_id); + break; + case INFO_RELNAME: + sprintf(errBuf, "(relation name %s)", buildinfo.i.info_name); + break; + } + + return errBuf; } + #endif /* -------------------------------- - * ScanPgRelation + * ScanPgRelation * - * this is used by RelationBuildDesc to find a pg_class - * tuple matching either a relation name or a relation id - * as specified in buildinfo. + * this is used by RelationBuildDesc to find a pg_class + * tuple matching either a relation name or a relation id + * as specified in buildinfo. * -------------------------------- */ -static HeapTuple +static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo) { - /* - * If this is bootstrap time (initdb), then we can't use the system - * catalog indices, because they may not exist yet. Otherwise, we - * can, and do. - */ - - if (IsBootstrapProcessingMode()) - return (scan_pg_rel_seq(buildinfo)); - else - return (scan_pg_rel_ind(buildinfo)); + + /* + * If this is bootstrap time (initdb), then we can't use the system + * catalog indices, because they may not exist yet. Otherwise, we + * can, and do. + */ + + if (IsBootstrapProcessingMode()) + return (scan_pg_rel_seq(buildinfo)); + else + return (scan_pg_rel_ind(buildinfo)); } -static HeapTuple +static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo) { - HeapTuple pg_class_tuple; - HeapTuple return_tuple; - Relation pg_class_desc; - HeapScanDesc pg_class_scan; - ScanKeyData key; - Buffer buf; - - /* ---------------- - * form a scan key - * ---------------- - */ - switch (buildinfo.infotype) { - case INFO_RELID: - ScanKeyEntryInitialize(&key, 0, - ObjectIdAttributeNumber, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(buildinfo.i.info_id)); - break; - - case INFO_RELNAME: - ScanKeyEntryInitialize(&key, 0, - Anum_pg_class_relname, - Character16EqualRegProcedure, - NameGetDatum(buildinfo.i.info_name)); - break; - - default: - elog(WARN, "ScanPgRelation: bad buildinfo"); - return NULL; - } - - /* ---------------- - * open pg_class and fetch a tuple - * ---------------- - */ - pg_class_desc = heap_openr(RelationRelationName); - if (!IsInitProcessingMode()) - RelationSetLockForRead(pg_class_desc); - pg_class_scan = - heap_beginscan(pg_class_desc, 0, NowTimeQual, 1, &key); - pg_class_tuple = heap_getnext(pg_class_scan, 0, &buf); - - /* ---------------- - * get set to return tuple - * ---------------- - */ - if (! HeapTupleIsValid(pg_class_tuple)) { - return_tuple = pg_class_tuple; - } else { - /* ------------------ - * a satanic bug used to live here: pg_class_tuple used to be - * returned here without having the corresponding buffer pinned. - * so when the buffer gets replaced, all hell breaks loose. - * this bug is discovered and killed by wei on 9/27/91. - * ------------------- + HeapTuple pg_class_tuple; + HeapTuple return_tuple; + Relation pg_class_desc; + HeapScanDesc pg_class_scan; + ScanKeyData key; + Buffer buf; + + /* ---------------- + * form a scan key + * ---------------- */ - return_tuple = (HeapTuple) palloc((Size) pg_class_tuple->t_len); - memmove((char *) return_tuple, - (char *) pg_class_tuple, - (int) pg_class_tuple->t_len); - ReleaseBuffer(buf); - } - - /* all done */ - heap_endscan(pg_class_scan); - if (!IsInitProcessingMode()) - RelationUnsetLockForRead(pg_class_desc); - heap_close(pg_class_desc); - - return return_tuple; + switch (buildinfo.infotype) + { + case INFO_RELID: + ScanKeyEntryInitialize(&key, 0, + ObjectIdAttributeNumber, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(buildinfo.i.info_id)); + break; + + case INFO_RELNAME: + ScanKeyEntryInitialize(&key, 0, + Anum_pg_class_relname, + Character16EqualRegProcedure, + NameGetDatum(buildinfo.i.info_name)); + break; + + default: + elog(WARN, "ScanPgRelation: bad buildinfo"); + return NULL; + } + + /* ---------------- + * open pg_class and fetch a tuple + * ---------------- + */ + pg_class_desc = heap_openr(RelationRelationName); + if (!IsInitProcessingMode()) + RelationSetLockForRead(pg_class_desc); + pg_class_scan = + heap_beginscan(pg_class_desc, 0, NowTimeQual, 1, &key); + pg_class_tuple = heap_getnext(pg_class_scan, 0, &buf); + + /* ---------------- + * get set to return tuple + * ---------------- + */ + if (!HeapTupleIsValid(pg_class_tuple)) + { + return_tuple = pg_class_tuple; + } + else + { + /* ------------------ + * a satanic bug used to live here: pg_class_tuple used to be + * returned here without having the corresponding buffer pinned. + * so when the buffer gets replaced, all hell breaks loose. + * this bug is discovered and killed by wei on 9/27/91. + * ------------------- + */ + return_tuple = (HeapTuple) palloc((Size) pg_class_tuple->t_len); + memmove((char *) return_tuple, + (char *) pg_class_tuple, + (int) pg_class_tuple->t_len); + ReleaseBuffer(buf); + } + + /* all done */ + heap_endscan(pg_class_scan); + if (!IsInitProcessingMode()) + RelationUnsetLockForRead(pg_class_desc); + heap_close(pg_class_desc); + + return return_tuple; } -static HeapTuple +static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo) { - Relation pg_class_desc; - HeapTuple return_tuple; - - pg_class_desc = heap_openr(RelationRelationName); - if (!IsInitProcessingMode()) - RelationSetLockForRead(pg_class_desc); - - switch (buildinfo.infotype) { - case INFO_RELID: - return_tuple = ClassOidIndexScan(pg_class_desc, buildinfo.i.info_id); - break; - - case INFO_RELNAME: - return_tuple = ClassNameIndexScan(pg_class_desc, - buildinfo.i.info_name); - break; - - default: - elog(WARN, "ScanPgRelation: bad buildinfo"); - /* XXX I hope this is right. It seems better than returning - * an uninitialized value */ - return_tuple = NULL; - } - - /* all done */ - if (!IsInitProcessingMode()) - RelationUnsetLockForRead(pg_class_desc); - heap_close(pg_class_desc); - - return return_tuple; + Relation pg_class_desc; + HeapTuple return_tuple; + + pg_class_desc = heap_openr(RelationRelationName); + if (!IsInitProcessingMode()) + RelationSetLockForRead(pg_class_desc); + + switch (buildinfo.infotype) + { + case INFO_RELID: + return_tuple = ClassOidIndexScan(pg_class_desc, buildinfo.i.info_id); + break; + + case INFO_RELNAME: + return_tuple = ClassNameIndexScan(pg_class_desc, + buildinfo.i.info_name); + break; + + default: + elog(WARN, "ScanPgRelation: bad buildinfo"); + + /* + * XXX I hope this is right. It seems better than returning an + * uninitialized value + */ + return_tuple = NULL; + } + + /* all done */ + if (!IsInitProcessingMode()) + RelationUnsetLockForRead(pg_class_desc); + heap_close(pg_class_desc); + + return return_tuple; } /* ---------------- - * AllocateRelationDesc + * AllocateRelationDesc * - * This is used to allocate memory for a new relation descriptor - * and initialize the rd_rel field. + * This is used to allocate memory for a new relation descriptor + * and initialize the rd_rel field. * ---------------- */ -static Relation +static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp) { - Relation relation; - Size len; - Form_pg_class relationTupleForm; - - /* ---------------- - * allocate space for the relation tuple form - * ---------------- - */ - relationTupleForm = (Form_pg_class) - palloc((Size) (sizeof(FormData_pg_class))); - - memmove((char *) relationTupleForm, (char *) relp, CLASS_TUPLE_SIZE); - - /* ---------------- - * allocate space for new relation descriptor - */ - len = sizeof(RelationData) + 10; /* + 10 is voodoo XXX mao */ - - relation = (Relation) palloc(len); - - /* ---------------- - * clear new reldesc - * ---------------- - */ - memset((char *) relation, 0, len); - - /* initialize attribute tuple form */ - relation->rd_att = CreateTemplateTupleDesc(natts); - - /*and initialize relation tuple form */ - relation->rd_rel = relationTupleForm; - - return relation; + Relation relation; + Size len; + Form_pg_class relationTupleForm; + + /* ---------------- + * allocate space for the relation tuple form + * ---------------- + */ + relationTupleForm = (Form_pg_class) + palloc((Size) (sizeof(FormData_pg_class))); + + memmove((char *) relationTupleForm, (char *) relp, CLASS_TUPLE_SIZE); + + /* ---------------- + * allocate space for new relation descriptor + */ + len = sizeof(RelationData) + 10; /* + 10 is voodoo XXX mao */ + + relation = (Relation) palloc(len); + + /* ---------------- + * clear new reldesc + * ---------------- + */ + memset((char *) relation, 0, len); + + /* initialize attribute tuple form */ + relation->rd_att = CreateTemplateTupleDesc(natts); + + /* and initialize relation tuple form */ + relation->rd_rel = relationTupleForm; + + return relation; } /* -------------------------------- - * RelationBuildTupleDesc + * RelationBuildTupleDesc * - * Form the relation's tuple descriptor from information in - * the pg_attribute, pg_attrdef & pg_relcheck system cataloges. + * Form the relation's tuple descriptor from information in + * the pg_attribute, pg_attrdef & pg_relcheck system cataloges. * -------------------------------- */ static void -RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) +RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, + Relation relation, + u_int natts) { - /* - * If this is bootstrap time (initdb), then we can't use the system - * catalog indices, because they may not exist yet. Otherwise, we - * can, and do. - */ - - if (IsBootstrapProcessingMode()) - build_tupdesc_seq(buildinfo, relation, natts); - else - build_tupdesc_ind(buildinfo, relation, natts); + + /* + * If this is bootstrap time (initdb), then we can't use the system + * catalog indices, because they may not exist yet. Otherwise, we + * can, and do. + */ + + if (IsBootstrapProcessingMode()) + build_tupdesc_seq(buildinfo, relation, natts); + else + build_tupdesc_ind(buildinfo, relation, natts); } static void build_tupdesc_seq(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) + Relation relation, + u_int natts) { - HeapTuple pg_attribute_tuple; - Relation pg_attribute_desc; - HeapScanDesc pg_attribute_scan; - AttributeTupleForm attp; - ScanKeyData key; - int need; - - /* ---------------- - * form a scan key - * ---------------- - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_attribute_attrelid, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - /* ---------------- - * open pg_attribute and begin a scan - * ---------------- - */ - pg_attribute_desc = heap_openr(AttributeRelationName); - pg_attribute_scan = - heap_beginscan(pg_attribute_desc, 0, NowTimeQual, 1, &key); - - /* ---------------- - * add attribute data to relation->rd_att - * ---------------- - */ - need = natts; - - pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL); - while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) { - attp = (AttributeTupleForm) GETSTRUCT(pg_attribute_tuple); - - if (attp->attnum > 0) { - relation->rd_att->attrs[attp->attnum - 1] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - - memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]), - (char *) attp, - ATTRIBUTE_TUPLE_SIZE); - need--; + HeapTuple pg_attribute_tuple; + Relation pg_attribute_desc; + HeapScanDesc pg_attribute_scan; + AttributeTupleForm attp; + ScanKeyData key; + int need; + + /* ---------------- + * form a scan key + * ---------------- + */ + ScanKeyEntryInitialize(&key, 0, + Anum_pg_attribute_attrelid, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + /* ---------------- + * open pg_attribute and begin a scan + * ---------------- + */ + pg_attribute_desc = heap_openr(AttributeRelationName); + pg_attribute_scan = + heap_beginscan(pg_attribute_desc, 0, NowTimeQual, 1, &key); + + /* ---------------- + * add attribute data to relation->rd_att + * ---------------- + */ + need = natts; + + pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL); + while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) + { + attp = (AttributeTupleForm) GETSTRUCT(pg_attribute_tuple); + + if (attp->attnum > 0) + { + relation->rd_att->attrs[attp->attnum - 1] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]), + (char *) attp, + ATTRIBUTE_TUPLE_SIZE); + need--; + } + pg_attribute_tuple = heap_getnext(pg_attribute_scan, + 0, (Buffer *) NULL); } - pg_attribute_tuple = heap_getnext(pg_attribute_scan, - 0, (Buffer *) NULL); - } - - if (need > 0) - elog(WARN, "catalog is missing %d attribute%s for relid %d", - need, (need == 1 ? "" : "s"), relation->rd_id); - - /* ---------------- - * end the scan and close the attribute relation - * ---------------- - */ - heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc); + + if (need > 0) + elog(WARN, "catalog is missing %d attribute%s for relid %d", + need, (need == 1 ? "" : "s"), relation->rd_id); + + /* ---------------- + * end the scan and close the attribute relation + * ---------------- + */ + heap_endscan(pg_attribute_scan); + heap_close(pg_attribute_desc); } static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) + Relation relation, + u_int natts) { - Relation attrel; - HeapTuple atttup; - AttributeTupleForm attp; - TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); - AttrDefault *attrdef = NULL; - int ndef = 0; - int i; - - constr->has_not_null = false; - - attrel = heap_openr(AttributeRelationName); - - for (i = 1; i <= relation->rd_rel->relnatts; i++) { - - atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i); - - if (!HeapTupleIsValid(atttup)) - elog(WARN, "cannot find attribute %d of relation %.*s", i, - NAMEDATALEN, &(relation->rd_rel->relname.data[0])); - attp = (AttributeTupleForm) GETSTRUCT(atttup); - - relation->rd_att->attrs[i - 1] = - (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); - - memmove((char *) (relation->rd_att->attrs[i - 1]), - (char *) attp, - ATTRIBUTE_TUPLE_SIZE); - - /* Update if this attribute have a constraint */ - if (attp->attnotnull) - constr->has_not_null = true; - - if (attp->atthasdef) + Relation attrel; + HeapTuple atttup; + AttributeTupleForm attp; + TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); + AttrDefault *attrdef = NULL; + int ndef = 0; + int i; + + constr->has_not_null = false; + + attrel = heap_openr(AttributeRelationName); + + for (i = 1; i <= relation->rd_rel->relnatts; i++) { - if ( attrdef == NULL ) - attrdef = (AttrDefault*) palloc (relation->rd_rel->relnatts * - sizeof (AttrDefault)); - attrdef[ndef].adnum = i; - attrdef[ndef].adbin = NULL; - attrdef[ndef].adsrc = NULL; - ndef++; + + atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i); + + if (!HeapTupleIsValid(atttup)) + elog(WARN, "cannot find attribute %d of relation %.*s", i, + NAMEDATALEN, &(relation->rd_rel->relname.data[0])); + attp = (AttributeTupleForm) GETSTRUCT(atttup); + + relation->rd_att->attrs[i - 1] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memmove((char *) (relation->rd_att->attrs[i - 1]), + (char *) attp, + ATTRIBUTE_TUPLE_SIZE); + + /* Update if this attribute have a constraint */ + if (attp->attnotnull) + constr->has_not_null = true; + + if (attp->atthasdef) + { + if (attrdef == NULL) + attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts * + sizeof(AttrDefault)); + attrdef[ndef].adnum = i; + attrdef[ndef].adbin = NULL; + attrdef[ndef].adsrc = NULL; + ndef++; + } } - } - - heap_close(attrel); - - if ( constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks ) - { - relation->rd_att->constr = constr; - - if ( ndef > 0 ) /* DEFAULTs */ - { - if ( ndef < relation->rd_rel->relnatts ) - constr->defval = (AttrDefault*) - repalloc (attrdef, ndef * sizeof (AttrDefault)); - else - constr->defval = attrdef; - constr->num_defval = ndef; - AttrDefaultFetch (relation); - } - else - constr->num_defval = 0; - - if ( relation->rd_rel->relchecks > 0 ) /* CHECKs */ + + heap_close(attrel); + + if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks) { - constr->num_check = relation->rd_rel->relchecks; - constr->check = (ConstrCheck *) palloc (constr->num_check * - sizeof (ConstrCheck)); - memset (constr->check, 0, constr->num_check * sizeof (ConstrCheck)); - RelCheckFetch (relation); + relation->rd_att->constr = constr; + + if (ndef > 0) /* DEFAULTs */ + { + if (ndef < relation->rd_rel->relnatts) + constr->defval = (AttrDefault *) + repalloc(attrdef, ndef * sizeof(AttrDefault)); + else + constr->defval = attrdef; + constr->num_defval = ndef; + AttrDefaultFetch(relation); + } + else + constr->num_defval = 0; + + if (relation->rd_rel->relchecks > 0) /* CHECKs */ + { + constr->num_check = relation->rd_rel->relchecks; + constr->check = (ConstrCheck *) palloc(constr->num_check * + sizeof(ConstrCheck)); + memset(constr->check, 0, constr->num_check * sizeof(ConstrCheck)); + RelCheckFetch(relation); + } + else + constr->num_check = 0; } else - constr->num_check = 0; - } - else - { - pfree (constr); - relation->rd_att->constr = NULL; - } - + { + pfree(constr); + relation->rd_att->constr = NULL; + } + } /* -------------------------------- - * RelationBuildRuleLock + * RelationBuildRuleLock * - * Form the relation's rewrite rules from information in - * the pg_rewrite system catalog. + * Form the relation's rewrite rules from information in + * the pg_rewrite system catalog. * -------------------------------- */ static void RelationBuildRuleLock(Relation relation) { - HeapTuple pg_rewrite_tuple; - Relation pg_rewrite_desc; - TupleDesc pg_rewrite_tupdesc; - HeapScanDesc pg_rewrite_scan; - ScanKeyData key; - RuleLock *rulelock; - int numlocks; - RewriteRule **rules; - int maxlocks; - - /* ---------------- - * form an array to hold the rewrite rules (the array is extended if - * necessary) - * ---------------- - */ - maxlocks = 4; - rules = (RewriteRule **)palloc(sizeof(RewriteRule*)*maxlocks); - numlocks = 0; - - /* ---------------- - * form a scan key - * ---------------- - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_rewrite_ev_class, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - /* ---------------- - * open pg_attribute and begin a scan - * ---------------- - */ - pg_rewrite_desc = heap_openr(RewriteRelationName); - pg_rewrite_scan = - heap_beginscan(pg_rewrite_desc, 0, NowTimeQual, 1, &key); - pg_rewrite_tupdesc = - RelationGetTupleDescriptor(pg_rewrite_desc); - - /* ---------------- - * add attribute data to relation->rd_att - * ---------------- - */ - while ((pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0, - (Buffer *) NULL)) != NULL) { - bool isnull; - char *ruleaction = NULL; - char *rule_evqual_string; - RewriteRule *rule; - - rule = (RewriteRule *)palloc(sizeof(RewriteRule)); - - rule->ruleId = pg_rewrite_tuple->t_oid; - - rule->event = - (int)heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc, - &isnull) - 48; - rule->attrno = - (int)heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc, - &isnull); - rule->isInstead = - !!heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc, - &isnull); - - ruleaction = - heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_action, pg_rewrite_tupdesc, - &isnull); - rule_evqual_string = - heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc, - &isnull); - - ruleaction = textout((struct varlena *)ruleaction); - rule_evqual_string = textout((struct varlena *)rule_evqual_string); - - rule->actions = (List*)stringToNode(ruleaction); - rule->qual = (Node*)stringToNode(rule_evqual_string); - - rules[numlocks++] = rule; - if (numlocks==maxlocks) { - maxlocks *= 2; - rules = - (RewriteRule **)repalloc(rules, sizeof(RewriteRule*)*maxlocks); + HeapTuple pg_rewrite_tuple; + Relation pg_rewrite_desc; + TupleDesc pg_rewrite_tupdesc; + HeapScanDesc pg_rewrite_scan; + ScanKeyData key; + RuleLock *rulelock; + int numlocks; + RewriteRule **rules; + int maxlocks; + + /* ---------------- + * form an array to hold the rewrite rules (the array is extended if + * necessary) + * ---------------- + */ + maxlocks = 4; + rules = (RewriteRule **) palloc(sizeof(RewriteRule *) * maxlocks); + numlocks = 0; + + /* ---------------- + * form a scan key + * ---------------- + */ + ScanKeyEntryInitialize(&key, 0, + Anum_pg_rewrite_ev_class, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + /* ---------------- + * open pg_attribute and begin a scan + * ---------------- + */ + pg_rewrite_desc = heap_openr(RewriteRelationName); + pg_rewrite_scan = + heap_beginscan(pg_rewrite_desc, 0, NowTimeQual, 1, &key); + pg_rewrite_tupdesc = + RelationGetTupleDescriptor(pg_rewrite_desc); + + /* ---------------- + * add attribute data to relation->rd_att + * ---------------- + */ + while ((pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0, + (Buffer *) NULL)) != NULL) + { + bool isnull; + char *ruleaction = NULL; + char *rule_evqual_string; + RewriteRule *rule; + + rule = (RewriteRule *) palloc(sizeof(RewriteRule)); + + rule->ruleId = pg_rewrite_tuple->t_oid; + + rule->event = + (int) heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc, + &isnull) - 48; + rule->attrno = + (int) heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc, + &isnull); + rule->isInstead = + !!heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc, + &isnull); + + ruleaction = + heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_action, pg_rewrite_tupdesc, + &isnull); + rule_evqual_string = + heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc, + &isnull); + + ruleaction = textout((struct varlena *) ruleaction); + rule_evqual_string = textout((struct varlena *) rule_evqual_string); + + rule->actions = (List *) stringToNode(ruleaction); + rule->qual = (Node *) stringToNode(rule_evqual_string); + + rules[numlocks++] = rule; + if (numlocks == maxlocks) + { + maxlocks *= 2; + rules = + (RewriteRule **) repalloc(rules, sizeof(RewriteRule *) * maxlocks); + } } - } - - /* ---------------- - * end the scan and close the attribute relation - * ---------------- - */ - heap_endscan(pg_rewrite_scan); - heap_close(pg_rewrite_desc); - - /* ---------------- - * form a RuleLock and insert into relation - * ---------------- - */ - rulelock = (RuleLock *)palloc(sizeof(RuleLock)); - rulelock->numLocks = numlocks; - rulelock->rules = rules; - - relation->rd_rules = rulelock; - return; + + /* ---------------- + * end the scan and close the attribute relation + * ---------------- + */ + heap_endscan(pg_rewrite_scan); + heap_close(pg_rewrite_desc); + + /* ---------------- + * form a RuleLock and insert into relation + * ---------------- + */ + rulelock = (RuleLock *) palloc(sizeof(RuleLock)); + rulelock->numLocks = numlocks; + rulelock->rules = rules; + + relation->rd_rules = rulelock; + return; } /* -------------------------------- - * RelationBuildDesc - * - * To build a relation descriptor, we have to allocate space, - * open the underlying unix file and initialize the following - * fields: + * RelationBuildDesc + * + * To build a relation descriptor, we have to allocate space, + * open the underlying unix file and initialize the following + * fields: * - * File rd_fd; open file descriptor - * int rd_nblocks; number of blocks in rel - * it will be set in ambeginscan() - * uint16 rd_refcnt; reference count - * Form_pg_am rd_am; AM tuple - * Form_pg_class rd_rel; RELATION tuple - * Oid rd_id; relations's object id - * Pointer lockInfo; ptr. to misc. info. - * TupleDesc rd_att; tuple desciptor + * File rd_fd; open file descriptor + * int rd_nblocks; number of blocks in rel + * it will be set in ambeginscan() + * uint16 rd_refcnt; reference count + * Form_pg_am rd_am; AM tuple + * Form_pg_class rd_rel; RELATION tuple + * Oid rd_id; relations's object id + * Pointer lockInfo; ptr. to misc. info. + * TupleDesc rd_att; tuple desciptor * - * Note: rd_ismem (rel is in-memory only) is currently unused - * by any part of the system. someday this will indicate that - * the relation lives only in the main-memory buffer pool - * -cim 2/4/91 + * Note: rd_ismem (rel is in-memory only) is currently unused + * by any part of the system. someday this will indicate that + * the relation lives only in the main-memory buffer pool + * -cim 2/4/91 * -------------------------------- */ -static Relation +static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo) { - File fd; - Relation relation; - u_int natts; - Oid relid; - Oid relam; - Form_pg_class relp; - - MemoryContext oldcxt; - - HeapTuple pg_class_tuple; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * find the tuple in pg_class corresponding to the given relation id - * ---------------- - */ - pg_class_tuple = ScanPgRelation(buildinfo); - - /* ---------------- - * if no such tuple exists, return NULL - * ---------------- - */ - if (! HeapTupleIsValid(pg_class_tuple)) { - - MemoryContextSwitchTo(oldcxt); - - return NULL; - } - - /* ---------------- - * get information from the pg_class_tuple - * ---------------- - */ - relid = pg_class_tuple->t_oid; - relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); - natts = relp->relnatts; - - /* ---------------- - * allocate storage for the relation descriptor, - * initialize relation->rd_rel and get the access method id. - * ---------------- - */ - relation = AllocateRelationDesc(natts, relp); - relam = relation->rd_rel->relam; - - /* ---------------- - * initialize the relation's relation id (relation->rd_id) - * ---------------- - */ - relation->rd_id = relid; - - /* ---------------- - * initialize relation->rd_refcnt - * ---------------- - */ - RelationSetReferenceCount(relation, 1); - - /* ---------------- - * normal relations are not nailed into the cache - * ---------------- - */ - relation->rd_isnailed = false; - - /* ---------------- - * initialize the access method information (relation->rd_am) - * ---------------- - */ - if (OidIsValid(relam)) { - relation->rd_am = (Form_pg_am) - AccessMethodObjectIdGetAccessMethodTupleForm(relam); - } - - /* ---------------- - * initialize the tuple descriptor (relation->rd_att). - * remember, rd_att is an array of attribute pointers that lives - * off the end of the relation descriptor structure so space was - * already allocated for it by AllocateRelationDesc. - * ---------------- - */ - RelationBuildTupleDesc(buildinfo, relation, natts); - - /* ---------------- - * initialize rules that affect this relation - * ---------------- - */ - if (relp->relhasrules) { - RelationBuildRuleLock(relation); - } else { - relation->rd_rules = NULL; - } - - /* Triggers */ - if ( relp->reltriggers > 0 ) - RelationBuildTriggers (relation); - else - relation->trigdesc = NULL; - - /* ---------------- - * initialize index strategy and support information for this relation - * ---------------- - */ - if (OidIsValid(relam)) { - IndexedAccessMethodInitialize(relation); - } - - /* ---------------- - * initialize the relation lock manager information - * ---------------- - */ - RelationInitLockInfo(relation); /* see lmgr.c */ - - /* ---------------- - * open the relation and assign the file descriptor returned - * by the storage manager code to rd_fd. - * ---------------- - */ - fd = smgropen(relp->relsmgr, relation); - - Assert (fd >= -1); - if (fd == -1) - elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m", - &relp->relname); - - relation->rd_fd = fd; - - /* ---------------- - * insert newly created relation into proper relcaches, - * restore memory context and return the new reldesc. - * ---------------- - */ - - RelationCacheInsert(relation); - - /* ------------------- - * free the memory allocated for pg_class_tuple - * and for lock data pointed to by pg_class_tuple - * ------------------- - */ - pfree(pg_class_tuple); - - MemoryContextSwitchTo(oldcxt); - - return relation; + File fd; + Relation relation; + u_int natts; + Oid relid; + Oid relam; + Form_pg_class relp; + + MemoryContext oldcxt; + + HeapTuple pg_class_tuple; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * find the tuple in pg_class corresponding to the given relation id + * ---------------- + */ + pg_class_tuple = ScanPgRelation(buildinfo); + + /* ---------------- + * if no such tuple exists, return NULL + * ---------------- + */ + if (!HeapTupleIsValid(pg_class_tuple)) + { + + MemoryContextSwitchTo(oldcxt); + + return NULL; + } + + /* ---------------- + * get information from the pg_class_tuple + * ---------------- + */ + relid = pg_class_tuple->t_oid; + relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); + natts = relp->relnatts; + + /* ---------------- + * allocate storage for the relation descriptor, + * initialize relation->rd_rel and get the access method id. + * ---------------- + */ + relation = AllocateRelationDesc(natts, relp); + relam = relation->rd_rel->relam; + + /* ---------------- + * initialize the relation's relation id (relation->rd_id) + * ---------------- + */ + relation->rd_id = relid; + + /* ---------------- + * initialize relation->rd_refcnt + * ---------------- + */ + RelationSetReferenceCount(relation, 1); + + /* ---------------- + * normal relations are not nailed into the cache + * ---------------- + */ + relation->rd_isnailed = false; + + /* ---------------- + * initialize the access method information (relation->rd_am) + * ---------------- + */ + if (OidIsValid(relam)) + { + relation->rd_am = (Form_pg_am) + AccessMethodObjectIdGetAccessMethodTupleForm(relam); + } + + /* ---------------- + * initialize the tuple descriptor (relation->rd_att). + * remember, rd_att is an array of attribute pointers that lives + * off the end of the relation descriptor structure so space was + * already allocated for it by AllocateRelationDesc. + * ---------------- + */ + RelationBuildTupleDesc(buildinfo, relation, natts); + + /* ---------------- + * initialize rules that affect this relation + * ---------------- + */ + if (relp->relhasrules) + { + RelationBuildRuleLock(relation); + } + else + { + relation->rd_rules = NULL; + } + + /* Triggers */ + if (relp->reltriggers > 0) + RelationBuildTriggers(relation); + else + relation->trigdesc = NULL; + + /* ---------------- + * initialize index strategy and support information for this relation + * ---------------- + */ + if (OidIsValid(relam)) + { + IndexedAccessMethodInitialize(relation); + } + + /* ---------------- + * initialize the relation lock manager information + * ---------------- + */ + RelationInitLockInfo(relation); /* see lmgr.c */ + + /* ---------------- + * open the relation and assign the file descriptor returned + * by the storage manager code to rd_fd. + * ---------------- + */ + fd = smgropen(relp->relsmgr, relation); + + Assert(fd >= -1); + if (fd == -1) + elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m", + &relp->relname); + + relation->rd_fd = fd; + + /* ---------------- + * insert newly created relation into proper relcaches, + * restore memory context and return the new reldesc. + * ---------------- + */ + + RelationCacheInsert(relation); + + /* ------------------- + * free the memory allocated for pg_class_tuple + * and for lock data pointed to by pg_class_tuple + * ------------------- + */ + pfree(pg_class_tuple); + + MemoryContextSwitchTo(oldcxt); + + return relation; } static void IndexedAccessMethodInitialize(Relation relation) { - IndexStrategy strategy; - RegProcedure *support; - int natts; - Size stratSize; - Size supportSize; - uint16 relamstrategies; - uint16 relamsupport; - - natts = relation->rd_rel->relnatts; - relamstrategies = relation->rd_am->amstrategies; - stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); - strategy = (IndexStrategy) palloc(stratSize); - relamsupport = relation->rd_am->amsupport; - - if (relamsupport > 0) { - supportSize = natts * (relamsupport * sizeof (RegProcedure)); - support = (RegProcedure *) palloc(supportSize); - } else { - support = (RegProcedure *) NULL; - } - - IndexSupportInitialize(strategy, support, - relation->rd_att->attrs[0]->attrelid, - relation->rd_rel->relam, - relamstrategies, relamsupport, natts); - - RelationSetIndexSupport(relation, strategy, support); + IndexStrategy strategy; + RegProcedure *support; + int natts; + Size stratSize; + Size supportSize; + uint16 relamstrategies; + uint16 relamsupport; + + natts = relation->rd_rel->relnatts; + relamstrategies = relation->rd_am->amstrategies; + stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); + strategy = (IndexStrategy) palloc(stratSize); + relamsupport = relation->rd_am->amsupport; + + if (relamsupport > 0) + { + supportSize = natts * (relamsupport * sizeof(RegProcedure)); + support = (RegProcedure *) palloc(supportSize); + } + else + { + support = (RegProcedure *) NULL; + } + + IndexSupportInitialize(strategy, support, + relation->rd_att->attrs[0]->attrelid, + relation->rd_rel->relam, + relamstrategies, relamsupport, natts); + + RelationSetIndexSupport(relation, strategy, support); } /* -------------------------------- - * formrdesc + * formrdesc * - * This is a special version of RelationBuildDesc() - * used by RelationInitialize() in initializing the - * relcache. The system relation descriptors built - * here are all nailed in the descriptor caches, for - * bootstrapping. + * This is a special version of RelationBuildDesc() + * used by RelationInitialize() in initializing the + * relcache. The system relation descriptors built + * here are all nailed in the descriptor caches, for + * bootstrapping. * -------------------------------- */ static void formrdesc(char *relationName, - u_int natts, - FormData_pg_attribute att[]) + u_int natts, + FormData_pg_attribute att[]) { - Relation relation; - Size len; - int i; - - /* ---------------- - * allocate new relation desc - * ---------------- - */ - len = sizeof (RelationData); - relation = (Relation) palloc(len); - memset((char *)relation, 0,len); - - /* ---------------- - * don't open the unix file yet.. - * ---------------- - */ - relation->rd_fd = -1; - - /* ---------------- - * initialize reference count - * ---------------- - */ - RelationSetReferenceCount(relation, 1); - - /* ---------------- - * initialize relation tuple form - * ---------------- - */ - relation->rd_rel = (Form_pg_class) - palloc((Size) (sizeof(*relation->rd_rel))); - memset(relation->rd_rel, 0, sizeof(FormData_pg_class)); - namestrcpy(&relation->rd_rel->relname, relationName); - - /* ---------------- - initialize attribute tuple form - */ - relation->rd_att = CreateTemplateTupleDesc(natts); - - /* - * For debugging purposes, it's important to distinguish between - * shared and non-shared relations, even at bootstrap time. There's - * code in the buffer manager that traces allocations that has to - * know about this. - */ - - if (IsSystemRelationName(relationName)) { - relation->rd_rel->relowner = 6; /* XXX use sym const */ - relation->rd_rel->relisshared = - IsSharedSystemRelationName(relationName); - } else { - relation->rd_rel->relowner = InvalidOid; /* XXX incorrect*/ - relation->rd_rel->relisshared = false; - } - - relation->rd_rel->relpages = 1; /* XXX */ - relation->rd_rel->reltuples = 1; /* XXX */ - relation->rd_rel->relkind = RELKIND_RELATION; - relation->rd_rel->relarch = 'n'; - relation->rd_rel->relnatts = (uint16) natts; - relation->rd_isnailed = true; - - /* ---------------- - * initialize tuple desc info - * ---------------- - */ - for (i = 0; i < natts; i++) { - relation->rd_att->attrs[i] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - - memset((char *)relation->rd_att->attrs[i], 0, - ATTRIBUTE_TUPLE_SIZE); - memmove((char *)relation->rd_att->attrs[i], - (char *)&att[i], - ATTRIBUTE_TUPLE_SIZE); - } - - /* ---------------- - * initialize relation id - * ---------------- - */ - relation->rd_id = relation->rd_att->attrs[0]->attrelid; - - /* ---------------- - * add new reldesc to relcache - * ---------------- - */ - RelationCacheInsert(relation); - /* - * Determining this requires a scan on pg_class, but to do the - * scan the rdesc for pg_class must already exist. Therefore - * we must do the check (and possible set) after cache insertion. - */ - relation->rd_rel->relhasindex = - CatalogHasIndex(relationName, relation->rd_id); + Relation relation; + Size len; + int i; + + /* ---------------- + * allocate new relation desc + * ---------------- + */ + len = sizeof(RelationData); + relation = (Relation) palloc(len); + memset((char *) relation, 0, len); + + /* ---------------- + * don't open the unix file yet.. + * ---------------- + */ + relation->rd_fd = -1; + + /* ---------------- + * initialize reference count + * ---------------- + */ + RelationSetReferenceCount(relation, 1); + + /* ---------------- + * initialize relation tuple form + * ---------------- + */ + relation->rd_rel = (Form_pg_class) + palloc((Size) (sizeof(*relation->rd_rel))); + memset(relation->rd_rel, 0, sizeof(FormData_pg_class)); + namestrcpy(&relation->rd_rel->relname, relationName); + + /* ---------------- + initialize attribute tuple form + */ + relation->rd_att = CreateTemplateTupleDesc(natts); + + /* + * For debugging purposes, it's important to distinguish between + * shared and non-shared relations, even at bootstrap time. There's + * code in the buffer manager that traces allocations that has to know + * about this. + */ + + if (IsSystemRelationName(relationName)) + { + relation->rd_rel->relowner = 6; /* XXX use sym const */ + relation->rd_rel->relisshared = + IsSharedSystemRelationName(relationName); + } + else + { + relation->rd_rel->relowner = InvalidOid; /* XXX incorrect */ + relation->rd_rel->relisshared = false; + } + + relation->rd_rel->relpages = 1; /* XXX */ + relation->rd_rel->reltuples = 1; /* XXX */ + relation->rd_rel->relkind = RELKIND_RELATION; + relation->rd_rel->relarch = 'n'; + relation->rd_rel->relnatts = (uint16) natts; + relation->rd_isnailed = true; + + /* ---------------- + * initialize tuple desc info + * ---------------- + */ + for (i = 0; i < natts; i++) + { + relation->rd_att->attrs[i] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memset((char *) relation->rd_att->attrs[i], 0, + ATTRIBUTE_TUPLE_SIZE); + memmove((char *) relation->rd_att->attrs[i], + (char *) &att[i], + ATTRIBUTE_TUPLE_SIZE); + } + + /* ---------------- + * initialize relation id + * ---------------- + */ + relation->rd_id = relation->rd_att->attrs[0]->attrelid; + + /* ---------------- + * add new reldesc to relcache + * ---------------- + */ + RelationCacheInsert(relation); + + /* + * Determining this requires a scan on pg_class, but to do the scan + * the rdesc for pg_class must already exist. Therefore we must do + * the check (and possible set) after cache insertion. + */ + relation->rd_rel->relhasindex = + CatalogHasIndex(relationName, relation->rd_id); } /* ---------------------------------------------------------------- - * Relation Descriptor Lookup Interface + * Relation Descriptor Lookup Interface * ---------------------------------------------------------------- */ /* -------------------------------- - * RelationIdCacheGetRelation + * RelationIdCacheGetRelation * - * only try to get the reldesc by looking up the cache - * do not go to the disk. this is used by BlockPrepareFile() - * and RelationIdGetRelation below. + * only try to get the reldesc by looking up the cache + * do not go to the disk. this is used by BlockPrepareFile() + * and RelationIdGetRelation below. * -------------------------------- */ Relation RelationIdCacheGetRelation(Oid relationId) { - Relation rd; - - RelationIdCacheLookup(relationId, rd); - - if (RelationIsValid(rd)) { - if (rd->rd_fd == -1) { - rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); - Assert(rd->rd_fd != -1); + Relation rd; + + RelationIdCacheLookup(relationId, rd); + + if (RelationIsValid(rd)) + { + if (rd->rd_fd == -1) + { + rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); + Assert(rd->rd_fd != -1); + } + + RelationIncrementReferenceCount(rd); + RelationSetLockForDescriptorOpen(rd); + } - - RelationIncrementReferenceCount(rd); - RelationSetLockForDescriptorOpen(rd); - - } - - return(rd); + + return (rd); } /* -------------------------------- - * RelationNameCacheGetRelation + * RelationNameCacheGetRelation * -------------------------------- */ -static Relation +static Relation RelationNameCacheGetRelation(char *relationName) { - Relation rd; - NameData name; - - /* make sure that the name key used for hash lookup is properly - null-padded */ - namestrcpy(&name, relationName); - RelationNameCacheLookup(name.data, rd); - - if (RelationIsValid(rd)) { - if (rd->rd_fd == -1) { - rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); - Assert(rd->rd_fd != -1); + Relation rd; + NameData name; + + /* + * make sure that the name key used for hash lookup is properly + * null-padded + */ + namestrcpy(&name, relationName); + RelationNameCacheLookup(name.data, rd); + + if (RelationIsValid(rd)) + { + if (rd->rd_fd == -1) + { + rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); + Assert(rd->rd_fd != -1); + } + + RelationIncrementReferenceCount(rd); + RelationSetLockForDescriptorOpen(rd); + } - - RelationIncrementReferenceCount(rd); - RelationSetLockForDescriptorOpen(rd); - - } - - return(rd); + + return (rd); } /* -------------------------------- - * RelationIdGetRelation + * RelationIdGetRelation * - * return a relation descriptor based on its id. - * return a cached value if possible + * return a relation descriptor based on its id. + * return a cached value if possible * -------------------------------- */ Relation RelationIdGetRelation(Oid relationId) { - Relation rd; - RelationBuildDescInfo buildinfo; - - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_RelationIdGetRelation); - IncrHeapAccessStat(global_RelationIdGetRelation); - - /* ---------------- - * first try and get a reldesc from the cache - * ---------------- - */ - rd = RelationIdCacheGetRelation(relationId); - if (RelationIsValid(rd)) - return rd; - - /* ---------------- - * no reldesc in the cache, so have RelationBuildDesc() - * build one and add it. - * ---------------- - */ - buildinfo.infotype = INFO_RELID; - buildinfo.i.info_id = relationId; - - rd = RelationBuildDesc(buildinfo); - return - rd; + Relation rd; + RelationBuildDescInfo buildinfo; + + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_RelationIdGetRelation); + IncrHeapAccessStat(global_RelationIdGetRelation); + + /* ---------------- + * first try and get a reldesc from the cache + * ---------------- + */ + rd = RelationIdCacheGetRelation(relationId); + if (RelationIsValid(rd)) + return rd; + + /* ---------------- + * no reldesc in the cache, so have RelationBuildDesc() + * build one and add it. + * ---------------- + */ + buildinfo.infotype = INFO_RELID; + buildinfo.i.info_id = relationId; + + rd = RelationBuildDesc(buildinfo); + return + rd; } /* -------------------------------- - * RelationNameGetRelation + * RelationNameGetRelation * - * return a relation descriptor based on its name. - * return a cached value if possible + * return a relation descriptor based on its name. + * return a cached value if possible * -------------------------------- */ Relation RelationNameGetRelation(char *relationName) { - Relation rd; - RelationBuildDescInfo buildinfo; - - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_RelationNameGetRelation); - IncrHeapAccessStat(global_RelationNameGetRelation); - - /* ---------------- - * first try and get a reldesc from the cache - * ---------------- - */ - rd = RelationNameCacheGetRelation(relationName); - if (RelationIsValid(rd)) + Relation rd; + RelationBuildDescInfo buildinfo; + + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_RelationNameGetRelation); + IncrHeapAccessStat(global_RelationNameGetRelation); + + /* ---------------- + * first try and get a reldesc from the cache + * ---------------- + */ + rd = RelationNameCacheGetRelation(relationName); + if (RelationIsValid(rd)) + return rd; + + /* ---------------- + * no reldesc in the cache, so have RelationBuildDesc() + * build one and add it. + * ---------------- + */ + buildinfo.infotype = INFO_RELNAME; + buildinfo.i.info_name = relationName; + + rd = RelationBuildDesc(buildinfo); return rd; - - /* ---------------- - * no reldesc in the cache, so have RelationBuildDesc() - * build one and add it. - * ---------------- - */ - buildinfo.infotype = INFO_RELNAME; - buildinfo.i.info_name = relationName; - - rd = RelationBuildDesc(buildinfo); - return rd; } /* ---------------- - * old "getreldesc" interface. + * old "getreldesc" interface. * ---------------- */ #ifdef NOT_USED Relation getreldesc(char *relationName) { - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_getreldesc); - IncrHeapAccessStat(global_getreldesc); - - return RelationNameGetRelation(relationName); + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_getreldesc); + IncrHeapAccessStat(global_getreldesc); + + return RelationNameGetRelation(relationName); } + #endif /* ---------------------------------------------------------------- - * cache invalidation support routines + * cache invalidation support routines * ---------------------------------------------------------------- */ /* -------------------------------- - * RelationClose - close an open relation + * RelationClose - close an open relation * -------------------------------- */ void RelationClose(Relation relation) { - /* Note: no locking manipulations needed */ - RelationDecrementReferenceCount(relation); + /* Note: no locking manipulations needed */ + RelationDecrementReferenceCount(relation); } /* -------------------------------- * RelationFlushRelation * - * Actually blows away a relation... RelationFree doesn't do - * anything anymore. + * Actually blows away a relation... RelationFree doesn't do + * anything anymore. * -------------------------------- */ static void -RelationFlushRelation(Relation *relationPtr, - bool onlyFlushReferenceCountZero) +RelationFlushRelation(Relation * relationPtr, + bool onlyFlushReferenceCountZero) { - MemoryContext oldcxt; - Relation relation = *relationPtr; - - if (relation->rd_isnailed) { - /* this is a nailed special relation for bootstraping */ - return; - } - - if (!onlyFlushReferenceCountZero || - RelationHasReferenceCountZero(relation)) { - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - RelationCacheDelete(relation); - - FreeTupleDesc (relation->rd_att); - - FreeTriggerDesc (relation); + MemoryContext oldcxt; + Relation relation = *relationPtr; -#if 0 - if (relation->rd_rules) { - int j; - for(j=0; j < relation->rd_rules->numLocks; j++) { - pfree(relation->rd_rules->rules[j]); - } - pfree(relation->rd_rules->rules); - pfree(relation->rd_rules); + if (relation->rd_isnailed) + { + /* this is a nailed special relation for bootstraping */ + return; } + + if (!onlyFlushReferenceCountZero || + RelationHasReferenceCountZero(relation)) + { + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + RelationCacheDelete(relation); + + FreeTupleDesc(relation->rd_att); + + FreeTriggerDesc(relation); + +#if 0 + if (relation->rd_rules) + { + int j; + + for (j = 0; j < relation->rd_rules->numLocks; j++) + { + pfree(relation->rd_rules->rules[j]); + } + pfree(relation->rd_rules->rules); + pfree(relation->rd_rules); + } #endif - - pfree(RelationGetLockInfo(relation)); - pfree(RelationGetRelationTupleForm(relation)); - pfree(relation); - - MemoryContextSwitchTo(oldcxt); - } + + pfree(RelationGetLockInfo(relation)); + pfree(RelationGetRelationTupleForm(relation)); + pfree(relation); + + MemoryContextSwitchTo(oldcxt); + } } /* -------------------------------- - * RelationForgetRelation - - * RelationFlushRelation + if the relation is local then get rid of - * the relation descriptor from the newly created relation list. + * RelationForgetRelation - + * RelationFlushRelation + if the relation is local then get rid of + * the relation descriptor from the newly created relation list. * -------------------------------- */ void -RelationForgetRelation (Oid rid) +RelationForgetRelation(Oid rid) { - Relation relation; - - RelationIdCacheLookup (rid, relation); - Assert ( PointerIsValid (relation) ); - - if ( relation->rd_islocal ) - { - MemoryContext oldcxt; - List *curr; - List *prev = NIL; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - foreach (curr, newlyCreatedRelns) - { - Relation reln = lfirst(curr); - - Assert ( reln != NULL && reln->rd_islocal ); - if ( reln->rd_id == rid ) - break; - prev = curr; - } - if ( curr == NIL ) - elog (FATAL, "Local relation %s not found in list", - (RelationGetRelationName(relation))->data); - if ( prev == NIL ) - newlyCreatedRelns = lnext (newlyCreatedRelns); - else - lnext (prev) = lnext (curr); - pfree (curr); - MemoryContextSwitchTo(oldcxt); - } - - RelationFlushRelation (&relation, false); + Relation relation; + + RelationIdCacheLookup(rid, relation); + Assert(PointerIsValid(relation)); + + if (relation->rd_islocal) + { + MemoryContext oldcxt; + List *curr; + List *prev = NIL; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + foreach(curr, newlyCreatedRelns) + { + Relation reln = lfirst(curr); + + Assert(reln != NULL && reln->rd_islocal); + if (reln->rd_id == rid) + break; + prev = curr; + } + if (curr == NIL) + elog(FATAL, "Local relation %s not found in list", + (RelationGetRelationName(relation))->data); + if (prev == NIL) + newlyCreatedRelns = lnext(newlyCreatedRelns); + else + lnext(prev) = lnext(curr); + pfree(curr); + MemoryContextSwitchTo(oldcxt); + } + + RelationFlushRelation(&relation, false); } /* -------------------------------- - * RelationIdInvalidateRelationCacheByRelationId + * RelationIdInvalidateRelationCacheByRelationId * -------------------------------- */ void RelationIdInvalidateRelationCacheByRelationId(Oid relationId) { - Relation relation; - - RelationIdCacheLookup(relationId, relation); - - /* - * "local" relations are invalidated by RelationPurgeLocalRelation. - * (This is to make LocalBufferSync's life easier: want the descriptor - * to hang around for a while. In fact, won't we want this for - * BufferSync also? But I'll leave it for now since I don't want to - * break anything.) - ay 3/95 - */ - if (PointerIsValid(relation) && !relation->rd_islocal) { + Relation relation; + + RelationIdCacheLookup(relationId, relation); + /* - * The boolean onlyFlushReferenceCountZero in RelationFlushReln() - * should be set to true when we are incrementing the command - * counter and to false when we are starting a new xaction. This - * can be determined by checking the current xaction status. + * "local" relations are invalidated by RelationPurgeLocalRelation. + * (This is to make LocalBufferSync's life easier: want the descriptor + * to hang around for a while. In fact, won't we want this for + * BufferSync also? But I'll leave it for now since I don't want to + * break anything.) - ay 3/95 */ - RelationFlushRelation(&relation, CurrentXactInProgress()); - } + if (PointerIsValid(relation) && !relation->rd_islocal) + { + + /* + * The boolean onlyFlushReferenceCountZero in RelationFlushReln() + * should be set to true when we are incrementing the command + * counter and to false when we are starting a new xaction. This + * can be determined by checking the current xaction status. + */ + RelationFlushRelation(&relation, CurrentXactInProgress()); + } } -#if NOT_USED /* See comments at line 1304 */ +#if NOT_USED /* See comments at line 1304 */ /* -------------------------------- - * RelationIdInvalidateRelationCacheByAccessMethodId + * RelationIdInvalidateRelationCacheByAccessMethodId * - * RelationFlushIndexes is needed for use with HashTableWalk.. + * RelationFlushIndexes is needed for use with HashTableWalk.. * -------------------------------- */ static void -RelationFlushIndexes(Relation *r, - Oid accessMethodId) +RelationFlushIndexes(Relation * r, + Oid accessMethodId) { - Relation relation = *r; - - if (!RelationIsValid(relation)) { - elog(NOTICE, "inval call to RFI"); - return; - } - - if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */ - (!OidIsValid(accessMethodId) || - relation->rd_rel->relam == accessMethodId)) + Relation relation = *r; + + if (!RelationIsValid(relation)) + { + elog(NOTICE, "inval call to RFI"); + return; + } + + if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */ + (!OidIsValid(accessMethodId) || + relation->rd_rel->relam == accessMethodId)) { - RelationFlushRelation(&relation, false); + RelationFlushRelation(&relation, false); } } + #endif void RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId) { -# if 0 - /* - * 25 aug 1992: mao commented out the ht walk below. it should be - * doing the right thing, in theory, but flushing reldescs for index - * relations apparently doesn't work. we want to cut 4.0.1, and i - * don't want to introduce new bugs. this code never executed before, - * so i'm turning it off for now. after the release is cut, i'll - * fix this up. - */ - - HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes, - accessMethodId); -# else - return; -# endif +#if 0 + + /* + * 25 aug 1992: mao commented out the ht walk below. it should be + * doing the right thing, in theory, but flushing reldescs for index + * relations apparently doesn't work. we want to cut 4.0.1, and i + * don't want to introduce new bugs. this code never executed before, + * so i'm turning it off for now. after the release is cut, i'll fix + * this up. + */ + + HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes, + accessMethodId); +#else + return; +#endif } /* * RelationCacheInvalidate * - * Will blow away either all the cached relation descriptors or - * those that have a zero reference count. + * Will blow away either all the cached relation descriptors or + * those that have a zero reference count. * */ void RelationCacheInvalidate(bool onlyFlushReferenceCountZero) { - HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation, - onlyFlushReferenceCountZero); - - /* - * nailed-in reldescs will still be in the cache... - * 7 hardwired heaps + 3 hardwired indices == 10 total. - */ - if (!onlyFlushReferenceCountZero) { - Assert(RelationNameCache->hctl->nkeys == 10); - Assert(RelationIdCache->hctl->nkeys == 10); - } + HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation, + onlyFlushReferenceCountZero); + + /* + * nailed-in reldescs will still be in the cache... 7 hardwired heaps + * + 3 hardwired indices == 10 total. + */ + if (!onlyFlushReferenceCountZero) + { + Assert(RelationNameCache->hctl->nkeys == 10); + Assert(RelationIdCache->hctl->nkeys == 10); + } } - + /* -------------------------------- - * RelationRegisterRelation - - * register the Relation descriptor of a newly created relation - * with the relation descriptor Cache. + * RelationRegisterRelation - + * register the Relation descriptor of a newly created relation + * with the relation descriptor Cache. * -------------------------------- */ void RelationRegisterRelation(Relation relation) { - MemoryContext oldcxt; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - if (oldcxt != (MemoryContext)CacheCxt) - elog(NOIND,"RelationRegisterRelation: WARNING: Context != CacheCxt"); - - RelationCacheInsert(relation); - - RelationInitLockInfo(relation); - - /* - * we've just created the relation. It is invisible to anyone else - * before the transaction is committed. Setting rd_islocal allows us - * to use the local buffer manager for select/insert/etc before the end - * of transaction. (We also need to keep track of relations - * created during a transaction and does the necessary clean up at - * the end of the transaction.) - ay 3/95 - */ - relation->rd_islocal = TRUE; - newlyCreatedRelns = lcons(relation, newlyCreatedRelns); - - MemoryContextSwitchTo(oldcxt); + MemoryContext oldcxt; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + if (oldcxt != (MemoryContext) CacheCxt) + elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt"); + + RelationCacheInsert(relation); + + RelationInitLockInfo(relation); + + /* + * we've just created the relation. It is invisible to anyone else + * before the transaction is committed. Setting rd_islocal allows us + * to use the local buffer manager for select/insert/etc before the + * end of transaction. (We also need to keep track of relations + * created during a transaction and does the necessary clean up at the + * end of the transaction.) - ay 3/95 + */ + relation->rd_islocal = TRUE; + newlyCreatedRelns = lcons(relation, newlyCreatedRelns); + + MemoryContextSwitchTo(oldcxt); } /* * RelationPurgeLocalRelation - - * find all the Relation descriptors marked rd_islocal and reset them. - * This should be called at the end of a transaction (commit/abort) when - * the "local" relations will become visible to others and the multi-user - * buffer pool should be used. + * find all the Relation descriptors marked rd_islocal and reset them. + * This should be called at the end of a transaction (commit/abort) when + * the "local" relations will become visible to others and the multi-user + * buffer pool should be used. */ void RelationPurgeLocalRelation(bool xactCommitted) { - MemoryContext oldcxt; - - if (newlyCreatedRelns==NULL) - return; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - while (newlyCreatedRelns) { - List *l = newlyCreatedRelns; - Relation reln = lfirst(l); - - Assert(reln!=NULL && reln->rd_islocal); - - if (!xactCommitted) { - /* - * remove the file if we abort. This is so that files for - * tables created inside a transaction block get removed. - */ - if(reln->rd_istemp) { - if(!(reln->rd_tmpunlinked)) { - smgrunlink(reln->rd_rel->relsmgr, reln); - reln->rd_tmpunlinked = TRUE; - } - } else { - smgrunlink(reln->rd_rel->relsmgr, reln); - } - } - else if ( !IsBootstrapProcessingMode () && !(reln->rd_istemp) ) - /* - * RelationFlushRelation () below will flush relation information - * from the cache. We must call smgrclose to flush relation - * information from SMGR & FMGR, too. We assume that for temp - * relations smgrunlink is already called by heap_destroyr - * and we skip smgrclose for them. - vadim 05/22/97 - */ - smgrclose(reln->rd_rel->relsmgr, reln); - - reln->rd_islocal = FALSE; + MemoryContext oldcxt; - if (!IsBootstrapProcessingMode()) - RelationFlushRelation(&reln, FALSE); - - newlyCreatedRelns = lnext(newlyCreatedRelns); - pfree(l); - } + if (newlyCreatedRelns == NULL) + return; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); - MemoryContextSwitchTo(oldcxt); + while (newlyCreatedRelns) + { + List *l = newlyCreatedRelns; + Relation reln = lfirst(l); + + Assert(reln != NULL && reln->rd_islocal); + + if (!xactCommitted) + { + + /* + * remove the file if we abort. This is so that files for + * tables created inside a transaction block get removed. + */ + if (reln->rd_istemp) + { + if (!(reln->rd_tmpunlinked)) + { + smgrunlink(reln->rd_rel->relsmgr, reln); + reln->rd_tmpunlinked = TRUE; + } + } + else + { + smgrunlink(reln->rd_rel->relsmgr, reln); + } + } + else if (!IsBootstrapProcessingMode() && !(reln->rd_istemp)) + + /* + * RelationFlushRelation () below will flush relation + * information from the cache. We must call smgrclose to flush + * relation information from SMGR & FMGR, too. We assume that + * for temp relations smgrunlink is already called by + * heap_destroyr and we skip smgrclose for them. - + * vadim 05/22/97 + */ + smgrclose(reln->rd_rel->relsmgr, reln); + + reln->rd_islocal = FALSE; + + if (!IsBootstrapProcessingMode()) + RelationFlushRelation(&reln, FALSE); + + newlyCreatedRelns = lnext(newlyCreatedRelns); + pfree(l); + } + + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * RelationInitialize + * RelationInitialize * - * This initializes the relation descriptor cache. + * This initializes the relation descriptor cache. * -------------------------------- */ -#define INITRELCACHESIZE 400 +#define INITRELCACHESIZE 400 void RelationInitialize(void) { - MemoryContext oldcxt; - HASHCTL ctl; - - /* ---------------- - * switch to cache memory context - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * create global caches - * ---------------- - */ - memset(&ctl,0, (int) sizeof(ctl)); - ctl.keysize = sizeof(NameData); - ctl.datasize = sizeof(Relation); - RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM); - - ctl.keysize = sizeof(Oid); - ctl.hash = tag_hash; - RelationIdCache = hash_create(INITRELCACHESIZE, &ctl, - HASH_ELEM | HASH_FUNCTION); - - /* ---------------- - * initialize the cache with pre-made relation descriptors - * for some of the more important system relations. These - * relations should always be in the cache. - * ---------------- - */ - formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); - formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute); - formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc); - formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type); - formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable); - formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log); - formrdesc(TimeRelationName, Natts_pg_time, Desc_pg_time); - - /* - * If this isn't initdb time, then we want to initialize some index - * relation descriptors, as well. The descriptors are for pg_attnumind - * (to make building relation descriptors fast) and possibly others, - * as they're added. - */ - - if (!IsBootstrapProcessingMode()) - init_irels(); - - MemoryContextSwitchTo(oldcxt); + MemoryContext oldcxt; + HASHCTL ctl; + + /* ---------------- + * switch to cache memory context + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * create global caches + * ---------------- + */ + memset(&ctl, 0, (int) sizeof(ctl)); + ctl.keysize = sizeof(NameData); + ctl.datasize = sizeof(Relation); + RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM); + + ctl.keysize = sizeof(Oid); + ctl.hash = tag_hash; + RelationIdCache = hash_create(INITRELCACHESIZE, &ctl, + HASH_ELEM | HASH_FUNCTION); + + /* ---------------- + * initialize the cache with pre-made relation descriptors + * for some of the more important system relations. These + * relations should always be in the cache. + * ---------------- + */ + formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); + formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute); + formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc); + formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type); + formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable); + formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log); + formrdesc(TimeRelationName, Natts_pg_time, Desc_pg_time); + + /* + * If this isn't initdb time, then we want to initialize some index + * relation descriptors, as well. The descriptors are for + * pg_attnumind (to make building relation descriptors fast) and + * possibly others, as they're added. + */ + + if (!IsBootstrapProcessingMode()) + init_irels(); + + MemoryContextSwitchTo(oldcxt); } static void -AttrDefaultFetch (Relation relation) +AttrDefaultFetch(Relation relation) { - AttrDefault *attrdef = relation->rd_att->constr->defval; - int ndef = relation->rd_att->constr->num_defval; - Relation adrel; - Relation irel; - ScanKeyData skey; - HeapTuple tuple; - Form_pg_attrdef adform; - IndexScanDesc sd; - RetrieveIndexResult indexRes; - Buffer buffer; - ItemPointer iptr; - struct varlena *val; - bool isnull; - int found; - int i; - - ScanKeyEntryInitialize(&skey, - (bits16)0x0, - (AttrNumber)1, - (RegProcedure)ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - adrel = heap_openr(AttrDefaultRelationName); - irel = index_openr(AttrDefaultIndex); - sd = index_beginscan(irel, false, 1, &skey); - tuple = (HeapTuple)NULL; - - for (found = 0; ; ) - { - indexRes = index_getnext(sd, ForwardScanDirection); - if (!indexRes) - break; - - iptr = &indexRes->heap_iptr; - tuple = heap_fetch(adrel, NowTimeQual, iptr, &buffer); - pfree(indexRes); - if (!HeapTupleIsValid(tuple)) - continue; - found++; - adform = (Form_pg_attrdef) GETSTRUCT(tuple); - for (i = 0; i < ndef; i++) - { - if ( adform->adnum != attrdef[i].adnum ) - continue; - if ( attrdef[i].adsrc != NULL ) - elog (WARN, "AttrDefaultFetch: second record found for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_attrdef_adbin, - adrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "AttrDefaultFetch: adbin IS NULL for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - attrdef[i].adbin = textout (val); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_attrdef_adsrc, - adrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "AttrDefaultFetch: adsrc IS NULL for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - attrdef[i].adsrc = textout (val); - break; - } - - if ( i >= ndef ) - elog (WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s", - adform->adnum, - NAMEDATALEN, relation->rd_rel->relname.data); - ReleaseBuffer(buffer); - } - - if ( found < ndef ) - elog (WARN, "AttrDefaultFetch: %d record not found for rel %.*s", - ndef - found, - NAMEDATALEN, relation->rd_rel->relname.data); - - index_endscan (sd); - pfree (sd); - index_close (irel); - heap_close (adrel); - + AttrDefault *attrdef = relation->rd_att->constr->defval; + int ndef = relation->rd_att->constr->num_defval; + Relation adrel; + Relation irel; + ScanKeyData skey; + HeapTuple tuple; + Form_pg_attrdef adform; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + Buffer buffer; + ItemPointer iptr; + struct varlena *val; + bool isnull; + int found; + int i; + + ScanKeyEntryInitialize(&skey, + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + adrel = heap_openr(AttrDefaultRelationName); + irel = index_openr(AttrDefaultIndex); + sd = index_beginscan(irel, false, 1, &skey); + tuple = (HeapTuple) NULL; + + for (found = 0;;) + { + indexRes = index_getnext(sd, ForwardScanDirection); + if (!indexRes) + break; + + iptr = &indexRes->heap_iptr; + tuple = heap_fetch(adrel, NowTimeQual, iptr, &buffer); + pfree(indexRes); + if (!HeapTupleIsValid(tuple)) + continue; + found++; + adform = (Form_pg_attrdef) GETSTRUCT(tuple); + for (i = 0; i < ndef; i++) + { + if (adform->adnum != attrdef[i].adnum) + continue; + if (attrdef[i].adsrc != NULL) + elog(WARN, "AttrDefaultFetch: second record found for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_attrdef_adbin, + adrel->rd_att, &isnull); + if (isnull) + elog(WARN, "AttrDefaultFetch: adbin IS NULL for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + attrdef[i].adbin = textout(val); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_attrdef_adsrc, + adrel->rd_att, &isnull); + if (isnull) + elog(WARN, "AttrDefaultFetch: adsrc IS NULL for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + attrdef[i].adsrc = textout(val); + break; + } + + if (i >= ndef) + elog(WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s", + adform->adnum, + NAMEDATALEN, relation->rd_rel->relname.data); + ReleaseBuffer(buffer); + } + + if (found < ndef) + elog(WARN, "AttrDefaultFetch: %d record not found for rel %.*s", + ndef - found, + NAMEDATALEN, relation->rd_rel->relname.data); + + index_endscan(sd); + pfree(sd); + index_close(irel); + heap_close(adrel); + } static void -RelCheckFetch (Relation relation) +RelCheckFetch(Relation relation) { - ConstrCheck *check = relation->rd_att->constr->check; - int ncheck = relation->rd_att->constr->num_check; - Relation rcrel; - Relation irel; - ScanKeyData skey; - HeapTuple tuple; - IndexScanDesc sd; - RetrieveIndexResult indexRes; - Buffer buffer; - ItemPointer iptr; - Name rcname; - struct varlena *val; - bool isnull; - int found; - - ScanKeyEntryInitialize(&skey, - (bits16)0x0, - (AttrNumber)1, - (RegProcedure)ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - rcrel = heap_openr(RelCheckRelationName); - irel = index_openr(RelCheckIndex); - sd = index_beginscan(irel, false, 1, &skey); - tuple = (HeapTuple)NULL; - - for (found = 0; ; ) - { - indexRes = index_getnext(sd, ForwardScanDirection); - if (!indexRes) - break; - - iptr = &indexRes->heap_iptr; - tuple = heap_fetch(rcrel, NowTimeQual, iptr, &buffer); - pfree(indexRes); - if (!HeapTupleIsValid(tuple)) - continue; - if ( found == ncheck ) - elog (WARN, "RelCheckFetch: unexpected record found for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - - rcname = (Name) fastgetattr (tuple, - Anum_pg_relcheck_rcname, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcname IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccname = nameout (rcname); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_relcheck_rcbin, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcbin IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccbin = textout (val); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_relcheck_rcsrc, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcsrc IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccsrc = textout (val); - found++; - - ReleaseBuffer(buffer); - } - - if ( found < ncheck ) - elog (WARN, "RelCheckFetch: %d record not found for rel %.*s", - ncheck - found, - NAMEDATALEN, relation->rd_rel->relname.data); - - index_endscan (sd); - pfree (sd); - index_close (irel); - heap_close (rcrel); - + ConstrCheck *check = relation->rd_att->constr->check; + int ncheck = relation->rd_att->constr->num_check; + Relation rcrel; + Relation irel; + ScanKeyData skey; + HeapTuple tuple; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + Buffer buffer; + ItemPointer iptr; + Name rcname; + struct varlena *val; + bool isnull; + int found; + + ScanKeyEntryInitialize(&skey, + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + rcrel = heap_openr(RelCheckRelationName); + irel = index_openr(RelCheckIndex); + sd = index_beginscan(irel, false, 1, &skey); + tuple = (HeapTuple) NULL; + + for (found = 0;;) + { + indexRes = index_getnext(sd, ForwardScanDirection); + if (!indexRes) + break; + + iptr = &indexRes->heap_iptr; + tuple = heap_fetch(rcrel, NowTimeQual, iptr, &buffer); + pfree(indexRes); + if (!HeapTupleIsValid(tuple)) + continue; + if (found == ncheck) + elog(WARN, "RelCheckFetch: unexpected record found for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + + rcname = (Name) fastgetattr(tuple, + Anum_pg_relcheck_rcname, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcname IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccname = nameout(rcname); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_relcheck_rcbin, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcbin IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccbin = textout(val); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_relcheck_rcsrc, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcsrc IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccsrc = textout(val); + found++; + + ReleaseBuffer(buffer); + } + + if (found < ncheck) + elog(WARN, "RelCheckFetch: %d record not found for rel %.*s", + ncheck - found, + NAMEDATALEN, relation->rd_rel->relname.data); + + index_endscan(sd); + pfree(sd); + index_close(irel); + heap_close(rcrel); + } /* - * init_irels(), write_irels() -- handle special-case initialization of - * index relation descriptors. + * init_irels(), write_irels() -- handle special-case initialization of + * index relation descriptors. * - * In late 1992, we started regularly having databases with more than - * a thousand classes in them. With this number of classes, it became - * critical to do indexed lookups on the system catalogs. + * In late 1992, we started regularly having databases with more than + * a thousand classes in them. With this number of classes, it became + * critical to do indexed lookups on the system catalogs. * - * Bootstrapping these lookups is very hard. We want to be able to - * use an index on pg_attribute, for example, but in order to do so, - * we must have read pg_attribute for the attributes in the index, - * which implies that we need to use the index. + * Bootstrapping these lookups is very hard. We want to be able to + * use an index on pg_attribute, for example, but in order to do so, + * we must have read pg_attribute for the attributes in the index, + * which implies that we need to use the index. * - * In order to get around the problem, we do the following: + * In order to get around the problem, we do the following: * - * + When the database system is initialized (at initdb time), we - * don't use indices on pg_attribute. We do sequential scans. + * + When the database system is initialized (at initdb time), we + * don't use indices on pg_attribute. We do sequential scans. * - * + When the backend is started up in normal mode, we load an image - * of the appropriate relation descriptors, in internal format, - * from an initialization file in the data/base/... directory. + * + When the backend is started up in normal mode, we load an image + * of the appropriate relation descriptors, in internal format, + * from an initialization file in the data/base/... directory. * - * + If the initialization file isn't there, then we create the - * relation descriptor using sequential scans and write it to - * the initialization file for use by subsequent backends. + * + If the initialization file isn't there, then we create the + * relation descriptor using sequential scans and write it to + * the initialization file for use by subsequent backends. * - * This is complicated and interferes with system changes, but - * performance is so bad that we're willing to pay the tax. + * This is complicated and interferes with system changes, but + * performance is so bad that we're willing to pay the tax. */ /* pg_attnumind, pg_classnameind, pg_classoidind */ @@ -1833,268 +1902,288 @@ RelCheckFetch (Relation relation) static void init_irels(void) { - Size len; - int nread; - File fd; - Relation irel[Num_indices_bootstrap]; - Relation ird; - Form_pg_am am; - Form_pg_class relform; - IndexStrategy strat; - RegProcedure *support; - int i; - int relno; - - if ((fd = FileNameOpenFile(INIT_FILENAME, O_RDONLY, 0600)) < 0) { - write_irels(); - return; - } - - FileSeek(fd, 0L, SEEK_SET); - - for (relno = 0; relno < Num_indices_bootstrap; relno++) { - /* first read the relation descriptor length*/ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - ird = irel[relno] = (Relation) palloc(len); - memset(ird, 0, len); - - /* then, read the Relation structure */ - if ((nread = FileRead(fd, (char*)ird, len)) != len) { - write_irels(); - return; - } - - /* the file descriptor is not yet opened */ - ird->rd_fd = -1; - - /* lock info is not initialized */ - ird->lockInfo = (char *) NULL; - - /* next, read the access method tuple form */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - am = (Form_pg_am) palloc(len); - if ((nread = FileRead(fd, (char*)am, len)) != len) { - write_irels(); - return; - } - - ird->rd_am = am; - - /* next read the relation tuple form */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - relform = (Form_pg_class) palloc(len); - if ((nread = FileRead(fd, (char*)relform, len)) != len) { - write_irels(); - return; - } - - ird->rd_rel = relform; - - /* initialize attribute tuple forms */ - ird->rd_att = CreateTemplateTupleDesc(relform->relnatts); - - /* next read all the attribute tuple form data entries */ - len = ATTRIBUTE_TUPLE_SIZE; - for (i = 0; i < relform->relnatts; i++) { - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - ird->rd_att->attrs[i] = (AttributeTupleForm) palloc(len); - - if ((nread = FileRead(fd, (char*)ird->rd_att->attrs[i], len)) != len) { + Size len; + int nread; + File fd; + Relation irel[Num_indices_bootstrap]; + Relation ird; + Form_pg_am am; + Form_pg_class relform; + IndexStrategy strat; + RegProcedure *support; + int i; + int relno; + + if ((fd = FileNameOpenFile(INIT_FILENAME, O_RDONLY, 0600)) < 0) + { write_irels(); return; - } - } - - /* next, read the index strategy map */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - strat = (IndexStrategy) palloc(len); - if ((nread = FileRead(fd, (char*)strat, len)) != len) { - write_irels(); - return; } - - /* oh, for god's sake... */ + + FileSeek(fd, 0L, SEEK_SET); + + for (relno = 0; relno < Num_indices_bootstrap; relno++) + { + /* first read the relation descriptor length */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + ird = irel[relno] = (Relation) palloc(len); + memset(ird, 0, len); + + /* then, read the Relation structure */ + if ((nread = FileRead(fd, (char *) ird, len)) != len) + { + write_irels(); + return; + } + + /* the file descriptor is not yet opened */ + ird->rd_fd = -1; + + /* lock info is not initialized */ + ird->lockInfo = (char *) NULL; + + /* next, read the access method tuple form */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + am = (Form_pg_am) palloc(len); + if ((nread = FileRead(fd, (char *) am, len)) != len) + { + write_irels(); + return; + } + + ird->rd_am = am; + + /* next read the relation tuple form */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + relform = (Form_pg_class) palloc(len); + if ((nread = FileRead(fd, (char *) relform, len)) != len) + { + write_irels(); + return; + } + + ird->rd_rel = relform; + + /* initialize attribute tuple forms */ + ird->rd_att = CreateTemplateTupleDesc(relform->relnatts); + + /* next read all the attribute tuple form data entries */ + len = ATTRIBUTE_TUPLE_SIZE; + for (i = 0; i < relform->relnatts; i++) + { + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + ird->rd_att->attrs[i] = (AttributeTupleForm) palloc(len); + + if ((nread = FileRead(fd, (char *) ird->rd_att->attrs[i], len)) != len) + { + write_irels(); + return; + } + } + + /* next, read the index strategy map */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + strat = (IndexStrategy) palloc(len); + if ((nread = FileRead(fd, (char *) strat, len)) != len) + { + write_irels(); + return; + } + + /* oh, for god's sake... */ #define SMD(i) strat[0].strategyMapData[i].entry[0] - - /* have to reinit the function pointers in the strategy maps */ - for (i = 0; i < am->amstrategies; i++) - fmgr_info(SMD(i).sk_procedure, - &(SMD(i).sk_func), &(SMD(i).sk_nargs)); - - - /* use a real field called rd_istrat instead of the - bogosity of hanging invisible fields off the end of a structure - - jolly */ - ird->rd_istrat = strat; - - /* finally, read the vector of support procedures */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - support = (RegProcedure *) palloc(len); - if ((nread = FileRead(fd, (char*)support, len)) != len) { - write_irels(); - return; - } - - /* - p += sizeof(IndexStrategy); - *((RegProcedure **) p) = support; - */ - ird->rd_support = support; - - RelationCacheInsert(ird); - } + /* have to reinit the function pointers in the strategy maps */ + for (i = 0; i < am->amstrategies; i++) + fmgr_info(SMD(i).sk_procedure, + &(SMD(i).sk_func), &(SMD(i).sk_nargs)); + + + /* + * use a real field called rd_istrat instead of the bogosity of + * hanging invisible fields off the end of a structure - jolly + */ + ird->rd_istrat = strat; + + /* finally, read the vector of support procedures */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + support = (RegProcedure *) palloc(len); + if ((nread = FileRead(fd, (char *) support, len)) != len) + { + write_irels(); + return; + } + + /* + * p += sizeof(IndexStrategy); ((RegProcedure **) p) = support; + */ + + ird->rd_support = support; + + RelationCacheInsert(ird); + } } static void write_irels(void) { - int len; - int nwritten; - File fd; - Relation irel[Num_indices_bootstrap]; - Relation ird; - Form_pg_am am; - Form_pg_class relform; - IndexStrategy strat; - RegProcedure *support; - ProcessingMode oldmode; - int i; - int relno; - RelationBuildDescInfo bi; - - fd = FileNameOpenFile(INIT_FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600); - if (fd < 0) - elog(FATAL, "cannot create init file %s", INIT_FILENAME); - - FileSeek(fd, 0L, SEEK_SET); - - /* - * Build a relation descriptor for pg_attnumind without resort to the - * descriptor cache. In order to do this, we set ProcessingMode - * to Bootstrap. The effect of this is to disable indexed relation - * searches -- a necessary step, since we're trying to instantiate - * the index relation descriptors here. - */ - - oldmode = GetProcessingMode(); - SetProcessingMode(BootstrapProcessing); - - bi.infotype = INFO_RELNAME; - bi.i.info_name = AttributeNumIndex; - irel[0] = RelationBuildDesc(bi); - irel[0]->rd_isnailed = true; - - bi.i.info_name = ClassNameIndex; - irel[1] = RelationBuildDesc(bi); - irel[1]->rd_isnailed = true; - - bi.i.info_name = ClassOidIndex; - irel[2] = RelationBuildDesc(bi); - irel[2]->rd_isnailed = true; - - SetProcessingMode(oldmode); - - /* nail the descriptor in the cache */ - for (relno = 0; relno < Num_indices_bootstrap; relno++) { - ird = irel[relno]; - - /* save the volatile fields in the relation descriptor */ - am = ird->rd_am; - ird->rd_am = (Form_pg_am) NULL; - relform = ird->rd_rel; - ird->rd_rel = (Form_pg_class) NULL; - strat = ird->rd_istrat; - support = ird->rd_support; - - /* first write the relation descriptor , excluding strategy and support */ - len = sizeof(RelationData); - - /* first, write the relation descriptor length */ - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- descriptor length"); - - /* next, write out the Relation structure */ - if ((nwritten = FileWrite(fd, (char*) ird, len)) != len) - elog(FATAL, "cannot write init file -- reldesc"); - - /* next, write the access method tuple form */ - len = sizeof(FormData_pg_am); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- am tuple form length"); - - if ((nwritten = FileWrite(fd, (char*) am, len)) != len) - elog(FATAL, "cannot write init file -- am tuple form"); - - /* next write the relation tuple form */ - len = sizeof(FormData_pg_class); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- relation tuple form length"); - - if ((nwritten = FileWrite(fd, (char*) relform, len)) != len) - elog(FATAL, "cannot write init file -- relation tuple form"); - - /* next, do all the attribute tuple form data entries */ - len = ATTRIBUTE_TUPLE_SIZE; - for (i = 0; i < relform->relnatts; i++) { - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- length of attdesc %d", i); - if ((nwritten = FileWrite(fd, (char*) ird->rd_att->attrs[i], len)) - != len) - elog(FATAL, "cannot write init file -- attdesc %d", i); + int len; + int nwritten; + File fd; + Relation irel[Num_indices_bootstrap]; + Relation ird; + Form_pg_am am; + Form_pg_class relform; + IndexStrategy strat; + RegProcedure *support; + ProcessingMode oldmode; + int i; + int relno; + RelationBuildDescInfo bi; + + fd = FileNameOpenFile(INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + elog(FATAL, "cannot create init file %s", INIT_FILENAME); + + FileSeek(fd, 0L, SEEK_SET); + + /* + * Build a relation descriptor for pg_attnumind without resort to the + * descriptor cache. In order to do this, we set ProcessingMode to + * Bootstrap. The effect of this is to disable indexed relation + * searches -- a necessary step, since we're trying to instantiate the + * index relation descriptors here. + */ + + oldmode = GetProcessingMode(); + SetProcessingMode(BootstrapProcessing); + + bi.infotype = INFO_RELNAME; + bi.i.info_name = AttributeNumIndex; + irel[0] = RelationBuildDesc(bi); + irel[0]->rd_isnailed = true; + + bi.i.info_name = ClassNameIndex; + irel[1] = RelationBuildDesc(bi); + irel[1]->rd_isnailed = true; + + bi.i.info_name = ClassOidIndex; + irel[2] = RelationBuildDesc(bi); + irel[2]->rd_isnailed = true; + + SetProcessingMode(oldmode); + + /* nail the descriptor in the cache */ + for (relno = 0; relno < Num_indices_bootstrap; relno++) + { + ird = irel[relno]; + + /* save the volatile fields in the relation descriptor */ + am = ird->rd_am; + ird->rd_am = (Form_pg_am) NULL; + relform = ird->rd_rel; + ird->rd_rel = (Form_pg_class) NULL; + strat = ird->rd_istrat; + support = ird->rd_support; + + /* + * first write the relation descriptor , excluding strategy and + * support + */ + len = sizeof(RelationData); + + /* first, write the relation descriptor length */ + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- descriptor length"); + + /* next, write out the Relation structure */ + if ((nwritten = FileWrite(fd, (char *) ird, len)) != len) + elog(FATAL, "cannot write init file -- reldesc"); + + /* next, write the access method tuple form */ + len = sizeof(FormData_pg_am); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- am tuple form length"); + + if ((nwritten = FileWrite(fd, (char *) am, len)) != len) + elog(FATAL, "cannot write init file -- am tuple form"); + + /* next write the relation tuple form */ + len = sizeof(FormData_pg_class); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- relation tuple form length"); + + if ((nwritten = FileWrite(fd, (char *) relform, len)) != len) + elog(FATAL, "cannot write init file -- relation tuple form"); + + /* next, do all the attribute tuple form data entries */ + len = ATTRIBUTE_TUPLE_SIZE; + for (i = 0; i < relform->relnatts; i++) + { + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- length of attdesc %d", i); + if ((nwritten = FileWrite(fd, (char *) ird->rd_att->attrs[i], len)) + != len) + elog(FATAL, "cannot write init file -- attdesc %d", i); + } + + /* next, write the index strategy map */ + len = AttributeNumberGetIndexStrategySize(relform->relnatts, + am->amstrategies); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- strategy map length"); + + if ((nwritten = FileWrite(fd, (char *) strat, len)) != len) + elog(FATAL, "cannot write init file -- strategy map"); + + /* finally, write the vector of support procedures */ + len = relform->relnatts * (am->amsupport * sizeof(RegProcedure)); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- support vector length"); + + if ((nwritten = FileWrite(fd, (char *) support, len)) != len) + elog(FATAL, "cannot write init file -- support vector"); + + /* restore volatile fields */ + ird->rd_am = am; + ird->rd_rel = relform; } - - /* next, write the index strategy map */ - len = AttributeNumberGetIndexStrategySize(relform->relnatts, - am->amstrategies); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- strategy map length"); - - if ((nwritten = FileWrite(fd, (char*) strat, len)) != len) - elog(FATAL, "cannot write init file -- strategy map"); - - /* finally, write the vector of support procedures */ - len = relform->relnatts * (am->amsupport * sizeof(RegProcedure)); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- support vector length"); - - if ((nwritten = FileWrite(fd, (char*) support, len)) != len) - elog(FATAL, "cannot write init file -- support vector"); - - /* restore volatile fields */ - ird->rd_am = am; - ird->rd_rel = relform; - } - - FileClose(fd); + + FileClose(fd); } diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 460e8d40af0..5f6c22b95fc 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -1,37 +1,37 @@ /*------------------------------------------------------------------------- * * syscache.c-- - * System cache management routines + * System cache management routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.4 1996/11/06 10:31:29 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.5 1997/09/07 04:53:10 momjian Exp $ * * NOTES - * These routines allow the parser/planner/executor to perform - * rapid lookups on the contents of the system catalogs. + * These routines allow the parser/planner/executor to perform + * rapid lookups on the contents of the system catalogs. * - * see catalog/syscache.h for a list of the cache id's + * see catalog/syscache.h for a list of the cache id's * *------------------------------------------------------------------------- */ #include "postgres.h" - + #include "access/heapam.h" #include "access/htup.h" #include "catalog/catname.h" #include "utils/catcache.h" #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif - + /* ---------------- - * hardwired attribute information comes from system catalog files. + * hardwired attribute information comes from system catalog files. * ---------------- */ #include "catalog/pg_am.h" @@ -51,592 +51,625 @@ #include "catalog/pg_user.h" #include "storage/large_object.h" #include "catalog/pg_listener.h" - -extern bool AMI_OVERRIDE; /* XXX style */ - + +extern bool AMI_OVERRIDE; /* XXX style */ + #include "utils/syscache.h" #include "catalog/indexing.h" - -typedef HeapTuple (*ScanFunc)(); + +typedef HeapTuple(*ScanFunc) (); /* ---------------- - * Warning: cacheinfo[] below is changed, then be sure and - * update the magic constants in syscache.h! + * Warning: cacheinfo[] below is changed, then be sure and + * update the magic constants in syscache.h! * ---------------- */ static struct cachedesc cacheinfo[] = { - { AccessMethodOperatorRelationName, /* AMOPOPID */ - 3, - { Anum_pg_amop_amopclaid, - Anum_pg_amop_amopopr, - Anum_pg_amop_amopid, - 0 }, - sizeof(FormData_pg_amop), - NULL, - (ScanFunc) NULL }, - { AccessMethodOperatorRelationName, /* AMOPSTRATEGY */ - 3, - { Anum_pg_amop_amopid, - Anum_pg_amop_amopclaid, - Anum_pg_amop_amopstrategy, - 0 }, - sizeof(FormData_pg_amop), - NULL, - (ScanFunc) NULL }, - { AttributeRelationName, /* ATTNAME */ - 2, - { Anum_pg_attribute_attrelid, - Anum_pg_attribute_attname, - 0, - 0 }, - ATTRIBUTE_TUPLE_SIZE, - AttributeNameIndex, - (ScanFunc) AttributeNameIndexScan }, - { AttributeRelationName, /* ATTNUM */ - 2, - { Anum_pg_attribute_attrelid, - Anum_pg_attribute_attnum, - 0, - 0 }, - ATTRIBUTE_TUPLE_SIZE, - AttributeNumIndex, - (ScanFunc) AttributeNumIndexScan }, - { IndexRelationName, /* INDEXRELID */ - 1, - { Anum_pg_index_indexrelid, - 0, - 0, - 0 }, - offsetof(FormData_pg_index, indpred), - NULL, - NULL }, - { LanguageRelationName, /* LANNAME */ - 1, - { Anum_pg_language_lanname, - 0, - 0, - 0 }, - offsetof(FormData_pg_language, lancompiler), - NULL, - NULL }, - { OperatorRelationName, /* OPRNAME */ - 4, - { Anum_pg_operator_oprname, - Anum_pg_operator_oprleft, - Anum_pg_operator_oprright, - Anum_pg_operator_oprkind }, - sizeof(FormData_pg_operator), - NULL, - NULL }, - { OperatorRelationName, /* OPROID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - sizeof(FormData_pg_operator), - NULL, - (ScanFunc) NULL }, - { ProcedureRelationName, /* PRONAME */ - 3, - { Anum_pg_proc_proname, - Anum_pg_proc_pronargs, - Anum_pg_proc_proargtypes, - 0 }, - offsetof(FormData_pg_proc, prosrc), - ProcedureNameIndex, - (ScanFunc) ProcedureNameIndexScan }, - { ProcedureRelationName, /* PROOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - offsetof(FormData_pg_proc, prosrc), - ProcedureOidIndex, - (ScanFunc) ProcedureOidIndexScan }, - { RelationRelationName, /* RELNAME */ - 1, - { Anum_pg_class_relname, - 0, - 0, - 0 }, - CLASS_TUPLE_SIZE, - ClassNameIndex, - (ScanFunc) ClassNameIndexScan }, - { RelationRelationName, /* RELOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - CLASS_TUPLE_SIZE, - ClassOidIndex, - (ScanFunc) ClassOidIndexScan }, - { TypeRelationName, /* TYPNAME */ - 1, - { Anum_pg_type_typname, - 0, - 0, - 0 }, - offsetof(TypeTupleFormData,typalign)+sizeof(char), - TypeNameIndex, - TypeNameIndexScan }, - { TypeRelationName, /* TYPOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, + {AccessMethodOperatorRelationName, /* AMOPOPID */ + 3, + {Anum_pg_amop_amopclaid, + Anum_pg_amop_amopopr, + Anum_pg_amop_amopid, + 0}, + sizeof(FormData_pg_amop), + NULL, + (ScanFunc) NULL}, + {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */ + 3, + {Anum_pg_amop_amopid, + Anum_pg_amop_amopclaid, + Anum_pg_amop_amopstrategy, + 0}, + sizeof(FormData_pg_amop), + NULL, + (ScanFunc) NULL}, + {AttributeRelationName, /* ATTNAME */ + 2, + {Anum_pg_attribute_attrelid, + Anum_pg_attribute_attname, + 0, + 0}, + ATTRIBUTE_TUPLE_SIZE, + AttributeNameIndex, + (ScanFunc) AttributeNameIndexScan}, + {AttributeRelationName, /* ATTNUM */ + 2, + {Anum_pg_attribute_attrelid, + Anum_pg_attribute_attnum, + 0, + 0}, + ATTRIBUTE_TUPLE_SIZE, + AttributeNumIndex, + (ScanFunc) AttributeNumIndexScan}, + {IndexRelationName, /* INDEXRELID */ + 1, + {Anum_pg_index_indexrelid, + 0, + 0, + 0}, + offsetof(FormData_pg_index, indpred), + NULL, + NULL}, + {LanguageRelationName, /* LANNAME */ + 1, + {Anum_pg_language_lanname, + 0, + 0, + 0}, + offsetof(FormData_pg_language, lancompiler), + NULL, + NULL}, + {OperatorRelationName, /* OPRNAME */ + 4, + {Anum_pg_operator_oprname, + Anum_pg_operator_oprleft, + Anum_pg_operator_oprright, + Anum_pg_operator_oprkind}, + sizeof(FormData_pg_operator), + NULL, + NULL}, + {OperatorRelationName, /* OPROID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + sizeof(FormData_pg_operator), + NULL, + (ScanFunc) NULL}, + {ProcedureRelationName, /* PRONAME */ + 3, + {Anum_pg_proc_proname, + Anum_pg_proc_pronargs, + Anum_pg_proc_proargtypes, + 0}, + offsetof(FormData_pg_proc, prosrc), + ProcedureNameIndex, + (ScanFunc) ProcedureNameIndexScan}, + {ProcedureRelationName, /* PROOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + offsetof(FormData_pg_proc, prosrc), + ProcedureOidIndex, + (ScanFunc) ProcedureOidIndexScan}, + {RelationRelationName, /* RELNAME */ + 1, + {Anum_pg_class_relname, + 0, + 0, + 0}, + CLASS_TUPLE_SIZE, + ClassNameIndex, + (ScanFunc) ClassNameIndexScan}, + {RelationRelationName, /* RELOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + CLASS_TUPLE_SIZE, + ClassOidIndex, + (ScanFunc) ClassOidIndexScan}, + {TypeRelationName, /* TYPNAME */ + 1, + {Anum_pg_type_typname, + 0, + 0, + 0}, + offsetof(TypeTupleFormData, typalign) + sizeof(char), + TypeNameIndex, + TypeNameIndexScan}, + {TypeRelationName, /* TYPOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + offsetof(TypeTupleFormData, typalign) +sizeof(char), + TypeOidIndex, + TypeOidIndexScan}, + {AccessMethodRelationName, /* AMNAME */ + 1, + {Anum_pg_am_amname, + 0, + 0, + 0}, + sizeof(FormData_pg_am), + NULL, + NULL}, + {OperatorClassRelationName, /* CLANAME */ + 1, + {Anum_pg_opclass_opcname, + 0, + 0, + 0}, + sizeof(FormData_pg_opclass), + NULL, + NULL}, + {IndexRelationName, /* INDRELIDKEY */ + 2, + {Anum_pg_index_indrelid, + Anum_pg_index_indkey, + 0, + 0}, + offsetof(FormData_pg_index, indpred), + NULL, + (ScanFunc) NULL}, + {InheritsRelationName, /* INHRELID */ + 2, + {Anum_pg_inherits_inhrel, + Anum_pg_inherits_inhseqno, + 0, 0}, - offsetof(TypeTupleFormData,typalign)+sizeof(char), - TypeOidIndex, - TypeOidIndexScan }, - { AccessMethodRelationName, /* AMNAME */ - 1, - { Anum_pg_am_amname, - 0, - 0, + sizeof(FormData_pg_inherits), + NULL, + (ScanFunc) NULL}, + {RewriteRelationName, /* RULOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + offsetof(FormData_pg_rewrite, ev_qual), + NULL, + (ScanFunc) NULL}, + {AggregateRelationName, /* AGGNAME */ + 2, + {Anum_pg_aggregate_aggname, + Anum_pg_aggregate_aggbasetype, + 0, 0}, - sizeof(FormData_pg_am), - NULL, - NULL }, - { OperatorClassRelationName, /* CLANAME */ - 1, - { Anum_pg_opclass_opcname, - 0, - 0, + offsetof(FormData_pg_aggregate, agginitval1), + NULL, + (ScanFunc) NULL}, + {ListenerRelationName, /* LISTENREL */ + 2, + {Anum_pg_listener_relname, + Anum_pg_listener_pid, + 0, 0}, - sizeof(FormData_pg_opclass), - NULL, - NULL }, - { IndexRelationName, /* INDRELIDKEY */ - 2, - { Anum_pg_index_indrelid, - Anum_pg_index_indkey, - 0, + sizeof(FormData_pg_listener), + NULL, + (ScanFunc) NULL}, + {UserRelationName, /* USENAME */ + 1, + {Anum_pg_user_usename, + 0, + 0, 0}, - offsetof(FormData_pg_index, indpred), - NULL, - (ScanFunc) NULL }, - { InheritsRelationName, /* INHRELID */ - 2, - { Anum_pg_inherits_inhrel, - Anum_pg_inherits_inhseqno, - 0, + sizeof(FormData_pg_user), + NULL, + (ScanFunc) NULL}, + {UserRelationName, /* USESYSID */ + 1, + {Anum_pg_user_usesysid, + 0, + 0, + 0}, + sizeof(FormData_pg_user), + NULL, + (ScanFunc) NULL}, + {GroupRelationName, /* GRONAME */ + 1, + {Anum_pg_group_groname, + 0, + 0, + 0}, + offsetof(FormData_pg_group, grolist[0]), + NULL, + (ScanFunc) NULL}, + {GroupRelationName, /* GROSYSID */ + 1, + {Anum_pg_group_grosysid, + 0, + 0, 0}, - sizeof(FormData_pg_inherits), - NULL, - (ScanFunc) NULL }, - { RewriteRelationName, /* RULOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - offsetof(FormData_pg_rewrite, ev_qual), - NULL, - (ScanFunc) NULL }, - { AggregateRelationName, /*AGGNAME*/ - 2, - { Anum_pg_aggregate_aggname, - Anum_pg_aggregate_aggbasetype, - 0, - 0 }, - offsetof(FormData_pg_aggregate, agginitval1), - NULL, - (ScanFunc) NULL }, - { ListenerRelationName, /* LISTENREL */ - 2, - { Anum_pg_listener_relname, - Anum_pg_listener_pid, - 0, - 0 }, - sizeof(FormData_pg_listener), - NULL, - (ScanFunc) NULL }, - { UserRelationName, /* USENAME */ - 1, - { Anum_pg_user_usename, - 0, - 0, - 0 }, - sizeof(FormData_pg_user), - NULL, - (ScanFunc) NULL }, - { UserRelationName, /* USESYSID */ - 1, - { Anum_pg_user_usesysid, - 0, - 0, - 0 }, - sizeof(FormData_pg_user), - NULL, - (ScanFunc) NULL }, - { GroupRelationName, /* GRONAME */ - 1, - { Anum_pg_group_groname, - 0, - 0, - 0 }, - offsetof(FormData_pg_group, grolist[0]), - NULL, - (ScanFunc) NULL }, - { GroupRelationName, /* GROSYSID */ - 1, - { Anum_pg_group_grosysid, - 0, - 0, - 0 }, - offsetof(FormData_pg_group, grolist[0]), - NULL, - (ScanFunc) NULL }, - { RewriteRelationName, /* REWRITENAME */ - 1, - { Anum_pg_rewrite_rulename, - 0, - 0, - 0 }, - offsetof(FormData_pg_rewrite, ev_qual), - NULL, - (ScanFunc) NULL }, - { ProcedureRelationName, /* PROSRC */ - 1, - { Anum_pg_proc_prosrc, - 0, - 0, - 0 }, - offsetof(FormData_pg_proc, prosrc), - ProcedureSrcIndex, - (ScanFunc) ProcedureSrcIndexScan }, - { OperatorClassRelationName, /* CLADEFTYPE */ - 1, - { Anum_pg_opclass_opcdeftype, - 0, - 0, - 0 }, - sizeof(FormData_pg_opclass), - NULL, - (ScanFunc) NULL } + offsetof(FormData_pg_group, grolist[0]), + NULL, + (ScanFunc) NULL}, + {RewriteRelationName, /* REWRITENAME */ + 1, + {Anum_pg_rewrite_rulename, + 0, + 0, + 0}, + offsetof(FormData_pg_rewrite, ev_qual), + NULL, + (ScanFunc) NULL}, + {ProcedureRelationName, /* PROSRC */ + 1, + {Anum_pg_proc_prosrc, + 0, + 0, + 0}, + offsetof(FormData_pg_proc, prosrc), + ProcedureSrcIndex, + (ScanFunc) ProcedureSrcIndexScan}, + {OperatorClassRelationName, /* CLADEFTYPE */ + 1, + {Anum_pg_opclass_opcdeftype, + 0, + 0, + 0}, + sizeof(FormData_pg_opclass), + NULL, + (ScanFunc) NULL} }; - -static struct catcache *SysCache[lengthof(cacheinfo)]; -static int32 SysCacheSize = lengthof(cacheinfo); - - + +static struct catcache *SysCache[ + lengthof(cacheinfo)]; +static int32 SysCacheSize = lengthof(cacheinfo); + + /* * zerocaches-- * - * Make sure the SysCache structure is zero'd. + * Make sure the SysCache structure is zero'd. */ void zerocaches() { - memset((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *)); + memset((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *)); } /* * Note: - * This function was written because the initialized catalog caches - * are used to determine which caches may contain tuples which need - * to be invalidated in other backends. + * This function was written because the initialized catalog caches + * are used to determine which caches may contain tuples which need + * to be invalidated in other backends. */ void InitCatalogCache() { - int cacheId; /* XXX type */ - - if (!AMI_OVERRIDE) { - for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) { - - Assert(!PointerIsValid((Pointer)SysCache[cacheId])); - - SysCache[cacheId] = - InitSysCache(cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheId, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key, - cacheinfo[cacheId].iScanFunc); - if (!PointerIsValid((char *)SysCache[cacheId])) { - elog(WARN, - "InitCatalogCache: Can't init cache %.16s(%d)", - cacheinfo[cacheId].name, - cacheId); - } - + int cacheId; /* XXX type */ + + if (!AMI_OVERRIDE) + { + for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) + { + + Assert(!PointerIsValid((Pointer) SysCache[cacheId])); + + SysCache[cacheId] = + InitSysCache(cacheinfo[cacheId].name, + cacheinfo[cacheId].indname, + cacheId, + cacheinfo[cacheId].nkeys, + cacheinfo[cacheId].key, + cacheinfo[cacheId].iScanFunc); + if (!PointerIsValid((char *) SysCache[cacheId])) + { + elog(WARN, + "InitCatalogCache: Can't init cache %.16s(%d)", + cacheinfo[cacheId].name, + cacheId); + } + + } } - } } /* * SearchSysCacheTuple-- * - * A layer on top of SearchSysCache that does the initialization and - * key-setting for you. + * A layer on top of SearchSysCache that does the initialization and + * key-setting for you. * * Returns the tuple if one is found, NULL if not. * * XXX The tuple that is returned is NOT supposed to be pfree'd! */ HeapTuple -SearchSysCacheTuple(int cacheId, /* cache selection code */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) +SearchSysCacheTuple(int cacheId, /* cache selection code */ + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - register HeapTuple tp; - - if (cacheId < 0 || cacheId >= SysCacheSize) { - elog(WARN, "SearchSysCacheTuple: Bad cache id %d", cacheId); - return((HeapTuple) NULL); - } - - if (!AMI_OVERRIDE) { - Assert(PointerIsValid(SysCache[cacheId])); - } else { - if (!PointerIsValid(SysCache[cacheId])) { - SysCache[cacheId] = - InitSysCache(cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheId, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key, - cacheinfo[cacheId].iScanFunc); - if (!PointerIsValid(SysCache[cacheId])) { - elog(WARN, - "InitCatalogCache: Can't init cache %.16s(%d)", - cacheinfo[cacheId].name, - cacheId); - } - + register HeapTuple tp; + + if (cacheId < 0 || cacheId >= SysCacheSize) + { + elog(WARN, "SearchSysCacheTuple: Bad cache id %d", cacheId); + return ((HeapTuple) NULL); + } + + if (!AMI_OVERRIDE) + { + Assert(PointerIsValid(SysCache[cacheId])); + } + else + { + if (!PointerIsValid(SysCache[cacheId])) + { + SysCache[cacheId] = + InitSysCache(cacheinfo[cacheId].name, + cacheinfo[cacheId].indname, + cacheId, + cacheinfo[cacheId].nkeys, + cacheinfo[cacheId].key, + cacheinfo[cacheId].iScanFunc); + if (!PointerIsValid(SysCache[cacheId])) + { + elog(WARN, + "InitCatalogCache: Can't init cache %.16s(%d)", + cacheinfo[cacheId].name, + cacheId); + } + + } } - } - - tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4); - if (!HeapTupleIsValid(tp)) { + + tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4); + if (!HeapTupleIsValid(tp)) + { #ifdef CACHEDEBUG - elog(DEBUG, - "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed", - (*cacheinfo[cacheId].name)->data, - cacheId, key1, key2, key3, key4); + elog(DEBUG, + "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed", + (*cacheinfo[cacheId].name)->data, + cacheId, key1, key2, key3, key4); #endif - return((HeapTuple) NULL); - } - return(tp); + return ((HeapTuple) NULL); + } + return (tp); } /* * SearchSysCacheStruct-- - * Fills 's' with the information retrieved by calling SearchSysCache() - * with arguments key1...key4. Retrieves only the portion of the tuple - * which is not variable-length. + * Fills 's' with the information retrieved by calling SearchSysCache() + * with arguments key1...key4. Retrieves only the portion of the tuple + * which is not variable-length. * * NOTE: we are assuming that non-variable-length fields in the system - * catalogs will always be defined! + * catalogs will always be defined! * * Returns 1L if a tuple was found, 0L if not. */ int32 SearchSysCacheStruct(int cacheId, /* cache selection code */ - char *returnStruct, /* (preallocated!) */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) + char *returnStruct, /* (preallocated!) */ + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - HeapTuple tp; - - if (!PointerIsValid(returnStruct)) { - elog(WARN, "SearchSysCacheStruct: No receiving struct"); - return(0); - } - tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); - if (!HeapTupleIsValid(tp)) - return(0); - memmove(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size); - return(1); + HeapTuple tp; + + if (!PointerIsValid(returnStruct)) + { + elog(WARN, "SearchSysCacheStruct: No receiving struct"); + return (0); + } + tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); + if (!HeapTupleIsValid(tp)) + return (0); + memmove(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size); + return (1); } /* * SearchSysCacheGetAttribute-- - * Returns the attribute corresponding to 'attributeNumber' for - * a given cached tuple. + * Returns the attribute corresponding to 'attributeNumber' for + * a given cached tuple. * * XXX This re-opens a relation, so this is slower. * * [callers all assume this returns a (struct varlena *). -ay 10/94] */ -void * +void * SearchSysCacheGetAttribute(int cacheId, - AttrNumber attributeNumber, - Datum key1, - Datum key2, - Datum key3, - Datum key4) + AttrNumber attributeNumber, + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - HeapTuple tp; - char *cacheName; - Relation relation; - int32 attributeLength, attributeByValue; - bool isNull; - char *attributeValue; - void *returnValue; - - tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); - cacheName = cacheinfo[cacheId].name; - - if (!HeapTupleIsValid(tp)) { + HeapTuple tp; + char *cacheName; + Relation relation; + int32 attributeLength, + attributeByValue; + bool isNull; + char *attributeValue; + void *returnValue; + + tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); + cacheName = cacheinfo[cacheId].name; + + if (!HeapTupleIsValid(tp)) + { #ifdef CACHEDEBUG - elog(DEBUG, - "SearchSysCacheGetAttribute: Lookup in %s(%d) failed", - cacheName, cacheId); -#endif /* defined(CACHEDEBUG) */ - return(NULL); - } - - relation = heap_openr(cacheName); - - if (attributeNumber < 0 && - attributeNumber > FirstLowInvalidHeapAttributeNumber) { - attributeLength = heap_sysattrlen(attributeNumber); - attributeByValue = heap_sysattrbyval(attributeNumber); - } else if (attributeNumber > 0 && - attributeNumber <= relation->rd_rel->relnatts) { - attributeLength = - relation->rd_att->attrs[attributeNumber-1]->attlen; - attributeByValue = - relation->rd_att->attrs[attributeNumber-1]->attbyval; - } else { - elog(WARN, - "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)", - attributeNumber, cacheName, cacheId); - return(NULL); - } - - attributeValue = heap_getattr(tp, - (Buffer) 0, - attributeNumber, - RelationGetTupleDescriptor(relation), - &isNull); - - if (isNull) { - /* - * Used to be an elog(DEBUG, ...) here and a claim that it should - * be a FATAL error, I don't think either is warranted -mer 6/9/92 - */ - return(NULL); - } - - if (attributeByValue) { - returnValue = (void *)attributeValue; - } else { - char *tmp; - int size = (attributeLength < 0) - ? VARSIZE((struct varlena *) attributeValue) /* variable length */ - : attributeLength; /* fixed length */ - - tmp = (char *) palloc(size); - memmove(tmp, attributeValue, size); - returnValue = (void *)tmp; - } - - heap_close(relation); - return(returnValue); + elog(DEBUG, + "SearchSysCacheGetAttribute: Lookup in %s(%d) failed", + cacheName, cacheId); +#endif /* defined(CACHEDEBUG) */ + return (NULL); + } + + relation = heap_openr(cacheName); + + if (attributeNumber < 0 && + attributeNumber > FirstLowInvalidHeapAttributeNumber) + { + attributeLength = heap_sysattrlen(attributeNumber); + attributeByValue = heap_sysattrbyval(attributeNumber); + } + else if (attributeNumber > 0 && + attributeNumber <= relation->rd_rel->relnatts) + { + attributeLength = + relation->rd_att->attrs[attributeNumber - 1]->attlen; + attributeByValue = + relation->rd_att->attrs[attributeNumber - 1]->attbyval; + } + else + { + elog(WARN, + "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)", + attributeNumber, cacheName, cacheId); + return (NULL); + } + + attributeValue = heap_getattr(tp, + (Buffer) 0, + attributeNumber, + RelationGetTupleDescriptor(relation), + &isNull); + + if (isNull) + { + + /* + * Used to be an elog(DEBUG, ...) here and a claim that it should + * be a FATAL error, I don't think either is warranted -mer 6/9/92 + */ + return (NULL); + } + + if (attributeByValue) + { + returnValue = (void *) attributeValue; + } + else + { + char *tmp; + int size = (attributeLength < 0) + ? VARSIZE((struct varlena *) attributeValue) /* variable length */ + : attributeLength; /* fixed length */ + + tmp = (char *) palloc(size); + memmove(tmp, attributeValue, size); + returnValue = (void *) tmp; + } + + heap_close(relation); + return (returnValue); } /* * TypeDefaultRetrieve-- * - * Given a type OID, return the typdefault field associated with that - * type. The typdefault is returned as the car of a dotted pair which - * is passed to TypeDefaultRetrieve by the calling routine. + * Given a type OID, return the typdefault field associated with that + * type. The typdefault is returned as the car of a dotted pair which + * is passed to TypeDefaultRetrieve by the calling routine. * * Returns a fixnum for types which are passed by value and a ppreserve'd * vectori for types which are not. * * [identical to get_typdefault, expecting a (struct varlena *) as ret val. - * some day, either of the functions should be removed -ay 10/94] + * some day, either of the functions should be removed -ay 10/94] */ -void * +void * TypeDefaultRetrieve(Oid typId) { - HeapTuple typeTuple; - TypeTupleForm type; - int32 typByVal, typLen; - struct varlena *typDefault; - int32 dataSize; - void *returnValue; - - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(typId), - 0,0,0); - - if (!HeapTupleIsValid(typeTuple)) { -#ifdef CACHEDEBUG - elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed", - (*cacheinfo[TYPOID].name)->data, TYPOID); -#endif /* defined(CACHEDEBUG) */ - return(NULL); - } - - type = (TypeTupleForm) GETSTRUCT(typeTuple); - typByVal = type->typbyval; - typLen = type->typlen; - - typDefault = (struct varlena *) - SearchSysCacheGetAttribute(TYPOID, - Anum_pg_type_typdefault, - ObjectIdGetDatum(typId), - 0,0,0); - - if (typDefault == (struct varlena *)NULL) { + HeapTuple typeTuple; + TypeTupleForm type; + int32 typByVal, + typLen; + struct varlena *typDefault; + int32 dataSize; + void *returnValue; + + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(typId), + 0, 0, 0); + + if (!HeapTupleIsValid(typeTuple)) + { #ifdef CACHEDEBUG - elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault", - (*cacheinfo[TYPOID].name)->data, TYPOID); -#endif /* defined(CACHEDEBUG) */ - return (NULL); - - } - - dataSize = VARSIZE(typDefault) - VARHDRSZ; - - if (typByVal) { - int8 i8; - int16 i16; - int32 i32; - - if (dataSize == typLen) { - switch (typLen) { - case sizeof(int8): - memmove((char *) &i8, VARDATA(typDefault), sizeof(int8)); - i32 = i8; - break; - case sizeof(int16): - memmove((char *) &i16, VARDATA(typDefault), sizeof(int16)); - i32 = i16; - break; - case sizeof(int32): - memmove((char *) &i32, VARDATA(typDefault), sizeof(int32)); - break; - } - returnValue = (void *)i32; - } else { - returnValue = NULL; + elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed", + (*cacheinfo[TYPOID].name)->data, TYPOID); +#endif /* defined(CACHEDEBUG) */ + return (NULL); } - } else { - if ((typLen < 0 && dataSize < 0) || dataSize != typLen) - returnValue = NULL; - else { - returnValue = (void *)palloc(VARSIZE(typDefault)); - memmove((char *) returnValue, - (char *) typDefault, - (int) VARSIZE(typDefault)); + + type = (TypeTupleForm) GETSTRUCT(typeTuple); + typByVal = type->typbyval; + typLen = type->typlen; + + typDefault = (struct varlena *) + SearchSysCacheGetAttribute(TYPOID, + Anum_pg_type_typdefault, + ObjectIdGetDatum(typId), + 0, 0, 0); + + if (typDefault == (struct varlena *) NULL) + { +#ifdef CACHEDEBUG + elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault", + (*cacheinfo[TYPOID].name)->data, TYPOID); +#endif /* defined(CACHEDEBUG) */ + return (NULL); + } - } - - return(returnValue); -} + dataSize = VARSIZE(typDefault) - VARHDRSZ; + if (typByVal) + { + int8 i8; + int16 i16; + int32 i32; + + if (dataSize == typLen) + { + switch (typLen) + { + case sizeof(int8): + memmove((char *) &i8, VARDATA(typDefault), sizeof(int8)); + i32 = i8; + break; + case sizeof(int16): + memmove((char *) &i16, VARDATA(typDefault), sizeof(int16)); + i32 = i16; + break; + case sizeof(int32): + memmove((char *) &i32, VARDATA(typDefault), sizeof(int32)); + break; + } + returnValue = (void *) i32; + } + else + { + returnValue = NULL; + } + } + else + { + if ((typLen < 0 && dataSize < 0) || dataSize != typLen) + returnValue = NULL; + else + { + returnValue = (void *) palloc(VARSIZE(typDefault)); + memmove((char *) returnValue, + (char *) typDefault, + (int) VARSIZE(typDefault)); + } + } + + return (returnValue); +} |