summaryrefslogtreecommitdiff
path: root/src/backend/utils/cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r--src/backend/utils/cache/catcache.c78
-rw-r--r--src/backend/utils/cache/lsyscache.c96
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 ---------- */
/*