diff options
Diffstat (limited to 'src/backend/utils/cache')
| -rw-r--r-- | src/backend/utils/cache/catcache.c | 78 | ||||
| -rw-r--r-- | src/backend/utils/cache/lsyscache.c | 96 |
2 files changed, 139 insertions, 35 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 65d716f6ba..8c0df3dfc2 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.103 2003/05/27 17:49:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.104 2003/06/22 22:04:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -81,22 +81,6 @@ /* Cache management header --- pointer is NULL until created */ static CatCacheHeader *CacheHdr = NULL; -/* - * 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... - */ -static const Oid eqproc[] = { - F_BOOLEQ, InvalidOid, F_CHAREQ, F_NAMEEQ, InvalidOid, - F_INT2EQ, F_INT2VECTOREQ, F_INT4EQ, F_OIDEQ, F_TEXTEQ, - F_OIDEQ, InvalidOid, InvalidOid, InvalidOid, F_OIDVECTOREQ -}; - -#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-BOOLOID] - static uint32 CatalogCacheComputeHashValue(CatCache *cache, int nkeys, ScanKey cur_skey); @@ -119,24 +103,46 @@ static HeapTuple build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys); * internal support functions */ -static PGFunction -GetCCHashFunc(Oid keytype) +/* + * Look up the hash and equality functions for system types that are used + * as cache key fields. + * + * XXX this should be replaced by catalog lookups, + * but that seems to pose considerable risk of circularity... + */ +static void +GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc) { switch (keytype) { case BOOLOID: + *hashfunc = hashchar; + *eqfunc = F_BOOLEQ; + break; case CHAROID: - return hashchar; + *hashfunc = hashchar; + *eqfunc = F_CHAREQ; + break; case NAMEOID: - return hashname; + *hashfunc = hashname; + *eqfunc = F_NAMEEQ; + break; case INT2OID: - return hashint2; + *hashfunc = hashint2; + *eqfunc = F_INT2EQ; + break; case INT2VECTOROID: - return hashint2vector; + *hashfunc = hashint2vector; + *eqfunc = F_INT2VECTOREQ; + break; case INT4OID: - return hashint4; + *hashfunc = hashint4; + *eqfunc = F_INT4EQ; + break; case TEXTOID: - return hashvarlena; + *hashfunc = hashtext; + *eqfunc = F_TEXTEQ; + break; case OIDOID: case REGPROCOID: case REGPROCEDUREOID: @@ -144,13 +150,17 @@ GetCCHashFunc(Oid keytype) case REGOPERATOROID: case REGCLASSOID: case REGTYPEOID: - return hashoid; + *hashfunc = hashoid; + *eqfunc = F_OIDEQ; + break; case OIDVECTOROID: - return hashoidvector; + *hashfunc = hashoidvector; + *eqfunc = F_OIDVECTOREQ; + break; default: - elog(FATAL, "GetCCHashFunc: type %u unsupported as catcache key", + elog(FATAL, "GetCCHashEqFuncs: type %u unsupported as catcache key", keytype); - return (PGFunction) NULL; + break; } } @@ -941,16 +951,16 @@ CatalogCacheInitializeCache(CatCache *cache) keytype = OIDOID; } - cache->cc_hashfunc[i] = GetCCHashFunc(keytype); + GetCCHashEqFuncs(keytype, + &cache->cc_hashfunc[i], + &cache->cc_skey[i].sk_procedure); cache->cc_isname[i] = (keytype == NAMEOID); /* - * If GetCCHashFunc liked the type, safe to index into eqproc[] + * Do equality-function lookup (we assume this won't need a catalog + * lookup for any supported type) */ - cache->cc_skey[i].sk_procedure = EQPROC(keytype); - - /* Do function lookup */ fmgr_info_cxt(cache->cc_skey[i].sk_procedure, &cache->cc_skey[i].sk_func, CacheMemoryContext); diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index fcd9dc2f59..095c5e6a8a 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.95 2003/05/26 00:11:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.96 2003/06/22 22:04:54 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -16,8 +16,10 @@ #include "postgres.h" #include "miscadmin.h" +#include "access/hash.h" #include "access/tupmacs.h" #include "catalog/pg_amop.h" +#include "catalog/pg_amproc.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" @@ -28,6 +30,7 @@ #include "nodes/makefuncs.h" #include "utils/array.h" #include "utils/builtins.h" +#include "utils/catcache.h" #include "utils/datum.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -106,6 +109,72 @@ get_opclass_member(Oid opclass, int16 strategy) return result; } +/* + * get_op_hash_function + * Get the OID of the datatype-specific hash function associated with + * a hashable equality operator. + * + * Returns InvalidOid if no hash function can be found. (This indicates + * that the operator should not have been marked oprcanhash.) + */ +Oid +get_op_hash_function(Oid opno) +{ + CatCList *catlist; + int i; + HeapTuple tuple; + Oid opclass = InvalidOid; + + /* + * Search pg_amop to see if the target operator is registered as the "=" + * operator of any hash opclass. If the operator is registered in + * multiple opclasses, assume we can use the associated hash function + * from any one. + */ + catlist = SearchSysCacheList(AMOPOPID, 1, + ObjectIdGetDatum(opno), + 0, 0, 0); + + for (i = 0; i < catlist->n_members; i++) + { + Form_pg_amop aform; + + tuple = &catlist->members[i]->tuple; + aform = (Form_pg_amop) GETSTRUCT(tuple); + + if (aform->amopstrategy == HTEqualStrategyNumber && + opclass_is_hash(aform->amopclaid)) + { + opclass = aform->amopclaid; + break; + } + } + + ReleaseSysCacheList(catlist); + + if (OidIsValid(opclass)) + { + /* Found a suitable opclass, get its hash support function */ + tuple = SearchSysCache(AMPROCNUM, + ObjectIdGetDatum(opclass), + Int16GetDatum(HASHPROC), + 0, 0); + if (HeapTupleIsValid(tuple)) + { + Form_pg_amproc aform = (Form_pg_amproc) GETSTRUCT(tuple); + RegProcedure result; + + result = aform->amproc; + ReleaseSysCache(tuple); + Assert(RegProcedureIsValid(result)); + return result; + } + } + + /* Didn't find a match... */ + return InvalidOid; +} + /* ---------- ATTRIBUTE CACHES ---------- */ @@ -284,6 +353,31 @@ opclass_is_btree(Oid opclass) return result; } +/* + * opclass_is_hash + * + * Returns TRUE iff the specified opclass is associated with the + * hash index access method. + */ +bool +opclass_is_hash(Oid opclass) +{ + HeapTuple tp; + Form_pg_opclass cla_tup; + bool result; + + tp = SearchSysCache(CLAOID, + ObjectIdGetDatum(opclass), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for opclass %u", opclass); + cla_tup = (Form_pg_opclass) GETSTRUCT(tp); + + result = (cla_tup->opcamid == HASH_AM_OID); + ReleaseSysCache(tp); + return result; +} + /* ---------- OPERATOR CACHE ---------- */ /* |
