diff options
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r-- | src/backend/utils/cache/catcache.c | 174 |
1 files changed, 79 insertions, 95 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index c6c8763c706..297c92b56e7 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,12 +8,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.61 2000/02/18 09:28:53 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.62 2000/02/21 03:36:49 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" + #include "access/genam.h" +#include "access/hash.h" #include "access/heapam.h" #include "access/valid.h" #include "catalog/pg_operator.h" @@ -28,10 +30,11 @@ static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e); static Index CatalogCacheComputeHashIndex(struct catcache * cacheInP); static Index CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP, - Relation relation, HeapTuple tuple); + Relation relation, + HeapTuple tuple); static void CatalogCacheInitializeCache(struct catcache * cache, - Relation relation); -static long comphash(long l, char *v); + Relation relation); +static uint32 cc_hashname(NameData *n); /* ---------------- * variables, macros and other stuff @@ -63,6 +66,7 @@ GlobalMemory CacheCxt; /* context in which caches are allocated */ /* ---------------- * EQPROC is used in CatalogCacheInitializeCache to find the equality * functions for system types that are used as cache key fields. + * See also GetCCHashFunc, which should support the same set of types. * * XXX this should be replaced by catalog lookups, * but that seems to pose considerable risk of circularity... @@ -70,7 +74,7 @@ GlobalMemory CacheCxt; /* context in which caches are allocated */ */ static const Oid eqproc[] = { F_BOOLEQ, InvalidOid, F_CHAREQ, F_NAMEEQ, InvalidOid, - F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, F_OIDEQ, F_TEXTEQ, + F_INT2EQ, F_INT2VECTOREQ, F_INT4EQ, F_OIDEQ, F_TEXTEQ, F_OIDEQ, InvalidOid, InvalidOid, InvalidOid, F_OIDVECTOREQ }; @@ -80,6 +84,54 @@ static const Oid eqproc[] = { * internal support functions * ---------------------------------------------------------------- */ + +static CCHashFunc +GetCCHashFunc(Oid keytype) +{ + switch (keytype) + { + case BOOLOID: + case CHAROID: + return (CCHashFunc) hashchar; + case NAMEOID: + return (CCHashFunc) cc_hashname; + case INT2OID: + return (CCHashFunc) hashint2; + case INT2VECTOROID: + return (CCHashFunc) hashint2vector; + case INT4OID: + return (CCHashFunc) hashint4; + case TEXTOID: + return (CCHashFunc) hashtext; + case REGPROCOID: + case OIDOID: + return (CCHashFunc) hashoid; + case OIDVECTOROID: + return (CCHashFunc) hashoidvector; + default: + elog(FATAL, "GetCCHashFunc: type %u unsupported as catcache key", + keytype); + return NULL; + } +} + +static uint32 +cc_hashname(NameData *n) +{ + /* + * We need our own variant of hashname because we want to accept + * null-terminated C strings as search values for name fields. + * So, we have to make sure the data is correctly padded before + * we compute the hash value. + */ + NameData my_n; + + namestrcpy(&my_n, NameStr(*n)); + + return hashname(&my_n); +} + + /* -------------------------------- * CatalogCacheInitializeCache * -------------------------------- @@ -190,31 +242,20 @@ CatalogCacheInitializeCache(struct catcache * cache, if (cache->cc_key[i] > 0) { + Oid keytype = tupdesc->attrs[cache->cc_key[i] - 1]->atttypid; - /* - * Yoiks. The implementation of the hashing code and the - * implementation of int2vector's are at loggerheads. The right - * thing to do is to throw out the implementation of int2vector'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. - */ + cache->cc_hashfunc[i] = GetCCHashFunc(keytype); - if (tupdesc->attrs[cache->cc_key[i] - 1]->atttypid == INT2VECTOROID) - 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); + /* If GetCCHashFunc liked the type, safe to index into eqproc[] */ + cache->cc_skey[i].sk_procedure = EQPROC(keytype); fmgr_info(cache->cc_skey[i].sk_procedure, &cache->cc_skey[i].sk_func); cache->cc_skey[i].sk_nargs = cache->cc_skey[i].sk_func.fn_nargs; - CACHE5_elog(DEBUG, "CatalogCacheInit %s %d %d %x", + CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %x", RelationGetRelationName(relation), i, - tupdesc->attrs[cache->cc_key[i] - 1]->attlen, cache); } } @@ -255,53 +296,6 @@ CatalogCacheInitializeCache(struct catcache * cache, MemoryContextSwitchTo(oldcxt); } -/* ---------------- - * comphash - * Compute a hash value, somehow. - * - * XXX explain algorithm here. - * - * l is length of the attribute value, v - * v is the attribute value ("Datum") - * ---------------- - */ -static long -comphash(long l, 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 = NameStr(n); - } - else if (l < 0) - l = VARSIZE(v); - - i = 0; - while (l--) - i += *v++; - return i; -} - /* -------------------------------- * CatalogCacheComputeHashIndex * -------------------------------- @@ -309,40 +303,37 @@ comphash(long l, char *v) static Index CatalogCacheComputeHashIndex(struct catcache * cacheInP) { - Index hashIndex; + uint32 hashIndex = 0; - hashIndex = 0x0; - CACHE6_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %d %d %x", + CACHE4_elog(DEBUG, "CatalogCacheComputeHashIndex %s %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; + hashIndex ^= + (*cacheInP->cc_hashfunc[3])(cacheInP->cc_skey[3].sk_argument) << 9; /* FALLTHROUGH */ case 3: - hashIndex ^= comphash(cacheInP->cc_klen[2], - (char *) cacheInP->cc_skey[2].sk_argument) << 6; + hashIndex ^= + (*cacheInP->cc_hashfunc[2])(cacheInP->cc_skey[2].sk_argument) << 6; /* FALLTHROUGH */ case 2: - hashIndex ^= comphash(cacheInP->cc_klen[1], - (char *) cacheInP->cc_skey[1].sk_argument) << 3; + hashIndex ^= + (*cacheInP->cc_hashfunc[1])(cacheInP->cc_skey[1].sk_argument) << 3; /* FALLTHROUGH */ case 1: - hashIndex ^= comphash(cacheInP->cc_klen[0], - (char *) cacheInP->cc_skey[0].sk_argument); + hashIndex ^= + (*cacheInP->cc_hashfunc[0])(cacheInP->cc_skey[0].sk_argument); break; default: elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); break; } - hashIndex %= cacheInP->cc_size; - return hashIndex; + hashIndex %= (uint32) cacheInP->cc_size; + return (Index) hashIndex; } /* -------------------------------- @@ -645,8 +636,8 @@ do { \ 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], \ + elog(DEBUG, "InitSysCache: key=%d skey=[%d %d %d %d]\n", \ + cp->cc_key[i], \ cp->cc_skey[i].sk_flags, \ cp->cc_skey[i].sk_attno, \ cp->cc_skey[i].sk_procedure, \ @@ -742,7 +733,8 @@ InitSysCache(char *relname, cp->cc_iscanfunc = iScanfuncP; /* ---------------- - * initialize the cache's key information + * partially initialize the cache's key information + * CatalogCacheInitializeCache() will do the rest * ---------------- */ for (i = 0; i < nkeys; ++i) @@ -756,15 +748,7 @@ InitSysCache(char *relname, 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 - */ + cp->cc_hashfunc[i] = GetCCHashFunc(OIDOID); ScanKeyEntryInitialize(&cp->cc_skey[i], (bits16) 0, (AttrNumber) key[i], |