aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-01-30 01:33:36 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-01-30 01:33:36 +0000
commita635c08fa10fe545d723bcec6eb73bfdca07e2c0 (patch)
tree83ac01972011232d6841e60cd830fe34ac2463d5 /src
parente8cd6f14a26bbecd3d8abcf36235a033cb035678 (diff)
downloadpostgresql-a635c08fa10fe545d723bcec6eb73bfdca07e2c0.tar.gz
postgresql-a635c08fa10fe545d723bcec6eb73bfdca07e2c0.zip
Add support for cross-type hashing in hash index searches and hash joins.
Hashing for aggregation purposes still needs work, so it's not time to mark any cross-type operators as hashable for general use, but these cases work if the operators are so marked by hand in the system catalogs.
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/hash/hashsearch.c26
-rw-r--r--src/backend/access/hash/hashutil.c31
-rw-r--r--src/backend/executor/execGrouping.c13
-rw-r--r--src/backend/executor/nodeHash.c28
-rw-r--r--src/backend/executor/nodeHashjoin.c3
-rw-r--r--src/backend/executor/nodeSubplan.c15
-rw-r--r--src/backend/optimizer/plan/createplan.c13
-rw-r--r--src/backend/utils/cache/lsyscache.c168
-rw-r--r--src/include/access/hash.h3
-rw-r--r--src/include/executor/hashjoin.h11
-rw-r--r--src/include/executor/nodeHash.h3
-rw-r--r--src/include/utils/lsyscache.h8
12 files changed, 240 insertions, 82 deletions
diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c
index 5582c036417..52e867e3605 100644
--- a/src/backend/access/hash/hashsearch.c
+++ b/src/backend/access/hash/hashsearch.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.47 2007/01/20 18:43:35 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.48 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -115,6 +115,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
{
Relation rel = scan->indexRelation;
HashScanOpaque so = (HashScanOpaque) scan->opaque;
+ ScanKey cur;
uint32 hashkey;
Bucket bucket;
BlockNumber blkno;
@@ -143,18 +144,37 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("hash indexes do not support whole-index scans")));
+ /* There may be more than one index qual, but we hash only the first */
+ cur = &scan->keyData[0];
+
+ /* We support only single-column hash indexes */
+ Assert(cur->sk_attno == 1);
+ /* And there's only one operator strategy, too */
+ Assert(cur->sk_strategy == HTEqualStrategyNumber);
+
/*
* If the constant in the index qual is NULL, assume it cannot match any
* items in the index.
*/
- if (scan->keyData[0].sk_flags & SK_ISNULL)
+ if (cur->sk_flags & SK_ISNULL)
return false;
/*
* Okay to compute the hash key. We want to do this before acquiring any
* locks, in case a user-defined hash function happens to be slow.
+ *
+ * If scankey operator is not a cross-type comparison, we can use the
+ * cached hash function; otherwise gotta look it up in the catalogs.
+ *
+ * We support the convention that sk_subtype == InvalidOid means the
+ * opclass input type; this is a hack to simplify life for ScanKeyInit().
*/
- hashkey = _hash_datum2hashkey(rel, scan->keyData[0].sk_argument);
+ if (cur->sk_subtype == rel->rd_opcintype[0] ||
+ cur->sk_subtype == InvalidOid)
+ hashkey = _hash_datum2hashkey(rel, cur->sk_argument);
+ else
+ hashkey = _hash_datum2hashkey_type(rel, cur->sk_argument,
+ cur->sk_subtype);
/*
* Acquire shared split lock so we can compute the target bucket safely
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index eadbe7aabe5..afa7c09a53d 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.50 2007/01/05 22:19:22 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.51 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include "access/hash.h"
#include "access/reloptions.h"
#include "executor/execdebug.h"
+#include "utils/lsyscache.h"
/*
@@ -63,6 +64,9 @@ _hash_checkqual(IndexScanDesc scan, IndexTuple itup)
/*
* _hash_datum2hashkey -- given a Datum, call the index's hash procedure
+ *
+ * The Datum is assumed to be of the index's column type, so we can use the
+ * "primary" hash procedure that's tracked for us by the generic index code.
*/
uint32
_hash_datum2hashkey(Relation rel, Datum key)
@@ -76,6 +80,31 @@ _hash_datum2hashkey(Relation rel, Datum key)
}
/*
+ * _hash_datum2hashkey_type -- given a Datum of a specified type,
+ * hash it in a fashion compatible with this index
+ *
+ * This is much more expensive than _hash_datum2hashkey, so use it only in
+ * cross-type situations.
+ */
+uint32
+_hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype)
+{
+ RegProcedure hash_proc;
+
+ /* XXX assumes index has only one attribute */
+ hash_proc = get_opfamily_proc(rel->rd_opfamily[0],
+ keytype,
+ keytype,
+ HASHPROC);
+ if (!RegProcedureIsValid(hash_proc))
+ elog(ERROR, "missing support function %d(%u,%u) for index \"%s\"",
+ HASHPROC, keytype, keytype,
+ RelationGetRelationName(rel));
+
+ return DatumGetUInt32(OidFunctionCall1(hash_proc, key));
+}
+
+/*
* _hash_hashkey2bucket -- determine which bucket the hashkey maps to.
*/
Bucket
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index f84c1120db2..08391bcc459 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execGrouping.c,v 1.23 2007/01/10 18:06:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execGrouping.c,v 1.24 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -224,15 +224,18 @@ execTuplesHashPrepare(int numCols,
{
Oid eq_opr = eqOperators[i];
Oid eq_function;
- Oid hash_function;
+ Oid left_hash_function;
+ Oid right_hash_function;
eq_function = get_opcode(eq_opr);
- hash_function = get_op_hash_function(eq_opr);
- if (!OidIsValid(hash_function)) /* should not happen */
+ if (!get_op_hash_functions(eq_opr,
+ &left_hash_function, &right_hash_function))
elog(ERROR, "could not find hash function for hash operator %u",
eq_opr);
+ /* For the moment, we're not supporting cross-type cases here */
+ Assert(left_hash_function == right_hash_function);
fmgr_info(eq_function, &(*eqFunctions)[i]);
- fmgr_info(hash_function, &(*hashFunctions)[i]);
+ fmgr_info(right_hash_function, &(*hashFunctions)[i]);
}
}
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index dffe8cb0d30..88d9360e422 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.109 2007/01/28 23:21:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.110 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -94,7 +94,7 @@ MultiExecHash(HashState *node)
break;
/* We have to compute the hash value */
econtext->ecxt_innertuple = slot;
- if (ExecHashGetHashValue(hashtable, econtext, hashkeys, false,
+ if (ExecHashGetHashValue(hashtable, econtext, hashkeys, false, false,
&hashvalue))
{
ExecHashTableInsert(hashtable, slot, hashvalue);
@@ -267,19 +267,23 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
* Also remember whether the join operators are strict.
*/
nkeys = list_length(hashOperators);
- hashtable->hashfunctions = (FmgrInfo *) palloc(nkeys * sizeof(FmgrInfo));
+ hashtable->outer_hashfunctions =
+ (FmgrInfo *) palloc(nkeys * sizeof(FmgrInfo));
+ hashtable->inner_hashfunctions =
+ (FmgrInfo *) palloc(nkeys * sizeof(FmgrInfo));
hashtable->hashStrict = (bool *) palloc(nkeys * sizeof(bool));
i = 0;
foreach(ho, hashOperators)
{
Oid hashop = lfirst_oid(ho);
- Oid hashfn;
+ Oid left_hashfn;
+ Oid right_hashfn;
- hashfn = get_op_hash_function(hashop);
- if (!OidIsValid(hashfn))
+ if (!get_op_hash_functions(hashop, &left_hashfn, &right_hashfn))
elog(ERROR, "could not find hash function for hash operator %u",
hashop);
- fmgr_info(hashfn, &hashtable->hashfunctions[i]);
+ fmgr_info(left_hashfn, &hashtable->outer_hashfunctions[i]);
+ fmgr_info(right_hashfn, &hashtable->inner_hashfunctions[i]);
hashtable->hashStrict[i] = op_strict(hashop);
i++;
}
@@ -674,10 +678,12 @@ bool
ExecHashGetHashValue(HashJoinTable hashtable,
ExprContext *econtext,
List *hashkeys,
+ bool outer_tuple,
bool keep_nulls,
uint32 *hashvalue)
{
uint32 hashkey = 0;
+ FmgrInfo *hashfunctions;
ListCell *hk;
int i = 0;
MemoryContext oldContext;
@@ -690,6 +696,11 @@ ExecHashGetHashValue(HashJoinTable hashtable,
oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+ if (outer_tuple)
+ hashfunctions = hashtable->outer_hashfunctions;
+ else
+ hashfunctions = hashtable->inner_hashfunctions;
+
foreach(hk, hashkeys)
{
ExprState *keyexpr = (ExprState *) lfirst(hk);
@@ -728,8 +739,7 @@ ExecHashGetHashValue(HashJoinTable hashtable,
/* Compute the hash function */
uint32 hkey;
- hkey = DatumGetUInt32(FunctionCall1(&hashtable->hashfunctions[i],
- keyval));
+ hkey = DatumGetUInt32(FunctionCall1(&hashfunctions[i], keyval));
hashkey ^= hkey;
}
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index b03086fb364..4960e2d8c69 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.87 2007/01/28 23:21:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.88 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -569,6 +569,7 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode,
econtext->ecxt_outertuple = slot;
if (ExecHashGetHashValue(hashtable, econtext,
hjstate->hj_OuterHashKeys,
+ true, /* outer tuple */
(hjstate->js.jointype == JOIN_LEFT),
hashvalue))
{
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index c2d4dbea37a..c5c35697c0b 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.82 2007/01/05 22:19:28 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.83 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -792,7 +792,8 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
Expr *expr;
TargetEntry *tle;
GenericExprState *tlestate;
- Oid hashfn;
+ Oid left_hashfn;
+ Oid right_hashfn;
Assert(IsA(fstate, FuncExprState));
Assert(IsA(opexpr, OpExpr));
@@ -830,12 +831,14 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
fmgr_info(opexpr->opfuncid, &node->eqfunctions[i - 1]);
node->eqfunctions[i - 1].fn_expr = (Node *) opexpr;
- /* Lookup the associated hash function */
- hashfn = get_op_hash_function(opexpr->opno);
- if (!OidIsValid(hashfn))
+ /* Lookup the associated hash functions */
+ if (!get_op_hash_functions(opexpr->opno,
+ &left_hashfn, &right_hashfn))
elog(ERROR, "could not find hash function for hash operator %u",
opexpr->opno);
- fmgr_info(hashfn, &node->hashfunctions[i - 1]);
+ /* For the moment, not supporting cross-type cases */
+ Assert(left_hashfn == right_hashfn);
+ fmgr_info(right_hashfn, &node->hashfunctions[i - 1]);
i++;
}
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 36f22c881c8..fdaed3d472e 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.223 2007/01/22 01:35:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.224 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -716,10 +716,10 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
numGroups = (long) Min(best_path->rows, (double) LONG_MAX);
/*
- * Get the (presumed hashable) equality operators for the Agg node
- * to use. Normally these are the same as the IN clause operators,
- * but if those are cross-type operators then the equality operators
- * are the ones for the IN clause operators' RHS datatype.
+ * Get the hashable equality operators for the Agg node to use.
+ * Normally these are the same as the IN clause operators, but if
+ * those are cross-type operators then the equality operators are
+ * the ones for the IN clause operators' RHS datatype.
*/
groupOperators = (Oid *) palloc(numGroupCols * sizeof(Oid));
groupColPos = 0;
@@ -728,8 +728,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
Oid in_oper = lfirst_oid(l);
Oid eq_oper;
- eq_oper = get_compatible_hash_operator(in_oper, false);
- if (!OidIsValid(eq_oper)) /* shouldn't happen */
+ if (!get_compatible_hash_operators(in_oper, NULL, &eq_oper))
elog(ERROR, "could not find compatible hash operator for operator %u",
in_oper);
groupOperators[groupColPos++] = eq_oper;
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index c449ad6e742..8946cb73151 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
- * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.146 2007/01/22 01:35:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.147 2007/01/30 01:33:36 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -389,23 +389,34 @@ get_mergejoin_opfamilies(Oid opno)
}
/*
- * get_compatible_hash_operator
- * Get the OID of a hash equality operator compatible with the given
- * operator, but operating on its LHS or RHS datatype as specified.
+ * get_compatible_hash_operators
+ * Get the OID(s) of hash equality operator(s) compatible with the given
+ * operator, but operating on its LHS and/or RHS datatype.
*
- * If the given operator is not cross-type, the result should be the same
- * operator, but in cross-type situations it is different.
+ * An operator for the LHS type is sought and returned into *lhs_opno if
+ * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
+ * and returned into *rhs_opno if rhs_opno isn't NULL.
*
- * Returns InvalidOid if no compatible operator can be found. (This indicates
- * that the operator should not have been marked oprcanhash.)
+ * If the given operator is not cross-type, the results should be the same
+ * operator, but in cross-type situations they will be different.
+ *
+ * Returns true if able to find the requested operator(s), false if not.
+ * (This indicates that the operator should not have been marked oprcanhash.)
*/
-Oid
-get_compatible_hash_operator(Oid opno, bool use_lhs_type)
+bool
+get_compatible_hash_operators(Oid opno,
+ Oid *lhs_opno, Oid *rhs_opno)
{
- Oid result = InvalidOid;
+ bool result = false;
CatCList *catlist;
int i;
+ /* Ensure output args are initialized on failure */
+ if (lhs_opno)
+ *lhs_opno = InvalidOid;
+ if (rhs_opno)
+ *rhs_opno = InvalidOid;
+
/*
* Search pg_amop to see if the target operator is registered as the "="
* operator of any hash opfamily. If the operator is registered in
@@ -423,22 +434,53 @@ get_compatible_hash_operator(Oid opno, bool use_lhs_type)
if (aform->amopmethod == HASH_AM_OID &&
aform->amopstrategy == HTEqualStrategyNumber)
{
- /* Found a suitable opfamily, get matching single-type operator */
- Oid typid;
-
/* No extra lookup needed if given operator is single-type */
if (aform->amoplefttype == aform->amoprighttype)
{
- result = opno;
+ if (lhs_opno)
+ *lhs_opno = opno;
+ if (rhs_opno)
+ *rhs_opno = opno;
+ result = true;
break;
}
- typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
- result = get_opfamily_member(aform->amopfamily,
- typid, typid,
- HTEqualStrategyNumber);
- if (OidIsValid(result))
+ /*
+ * Get the matching single-type operator(s). Failure probably
+ * shouldn't happen --- it implies a bogus opfamily --- but
+ * continue looking if so.
+ */
+ if (lhs_opno)
+ {
+ *lhs_opno = get_opfamily_member(aform->amopfamily,
+ aform->amoplefttype,
+ aform->amoplefttype,
+ HTEqualStrategyNumber);
+ if (!OidIsValid(*lhs_opno))
+ continue;
+ /* Matching LHS found, done if caller doesn't want RHS */
+ if (!rhs_opno)
+ {
+ result = true;
+ break;
+ }
+ }
+ if (rhs_opno)
+ {
+ *rhs_opno = get_opfamily_member(aform->amopfamily,
+ aform->amoprighttype,
+ aform->amoprighttype,
+ HTEqualStrategyNumber);
+ if (!OidIsValid(*rhs_opno))
+ {
+ /* Forget any LHS operator from this opfamily */
+ if (lhs_opno)
+ *lhs_opno = InvalidOid;
+ continue;
+ }
+ /* Matching RHS found, so done */
+ result = true;
break;
- /* failure probably shouldn't happen, but keep looking if so */
+ }
}
}
@@ -448,28 +490,38 @@ get_compatible_hash_operator(Oid opno, bool use_lhs_type)
}
/*
- * get_op_hash_function
- * Get the OID of the datatype-specific hash function associated with
- * a hashable equality operator.
+ * get_op_hash_functions
+ * Get the OID(s) of hash support function(s) compatible with the given
+ * operator, operating on its LHS and/or RHS datatype as required.
*
- * XXX API needs to be generalized for the case of different left and right
- * datatypes.
+ * A function for the LHS type is sought and returned into *lhs_procno if
+ * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
+ * and returned into *rhs_procno if rhs_procno isn't NULL.
*
- * Returns InvalidOid if no hash function can be found. (This indicates
- * that the operator should not have been marked oprcanhash.)
+ * If the given operator is not cross-type, the results should be the same
+ * function, but in cross-type situations they will be different.
+ *
+ * Returns true if able to find the requested function(s), false if not.
+ * (This indicates that the operator should not have been marked oprcanhash.)
*/
-Oid
-get_op_hash_function(Oid opno)
+bool
+get_op_hash_functions(Oid opno,
+ RegProcedure *lhs_procno, RegProcedure *rhs_procno)
{
- Oid result = InvalidOid;
+ bool result = false;
CatCList *catlist;
int i;
+ /* Ensure output args are initialized on failure */
+ if (lhs_procno)
+ *lhs_procno = InvalidOid;
+ if (rhs_procno)
+ *rhs_procno = InvalidOid;
+
/*
* Search pg_amop to see if the target operator is registered as the "="
* operator of any hash opfamily. If the operator is registered in
- * multiple opfamilies, assume we can use the associated hash function from
- * any one.
+ * multiple opfamilies, assume we can use any one.
*/
catlist = SearchSysCacheList(AMOPOPID, 1,
ObjectIdGetDatum(opno),
@@ -483,12 +535,50 @@ get_op_hash_function(Oid opno)
if (aform->amopmethod == HASH_AM_OID &&
aform->amopstrategy == HTEqualStrategyNumber)
{
- /* Found a suitable opfamily, get matching hash support function */
- result = get_opfamily_proc(aform->amopfamily,
- aform->amoplefttype,
- aform->amoprighttype,
- HASHPROC);
- break;
+ /*
+ * Get the matching support function(s). Failure probably
+ * shouldn't happen --- it implies a bogus opfamily --- but
+ * continue looking if so.
+ */
+ if (lhs_procno)
+ {
+ *lhs_procno = get_opfamily_proc(aform->amopfamily,
+ aform->amoplefttype,
+ aform->amoplefttype,
+ HASHPROC);
+ if (!OidIsValid(*lhs_procno))
+ continue;
+ /* Matching LHS found, done if caller doesn't want RHS */
+ if (!rhs_procno)
+ {
+ result = true;
+ break;
+ }
+ /* Only one lookup needed if given operator is single-type */
+ if (aform->amoplefttype == aform->amoprighttype)
+ {
+ *rhs_procno = *lhs_procno;
+ result = true;
+ break;
+ }
+ }
+ if (rhs_procno)
+ {
+ *rhs_procno = get_opfamily_proc(aform->amopfamily,
+ aform->amoprighttype,
+ aform->amoprighttype,
+ HASHPROC);
+ if (!OidIsValid(*rhs_procno))
+ {
+ /* Forget any LHS function from this opfamily */
+ if (lhs_procno)
+ *lhs_procno = InvalidOid;
+ continue;
+ }
+ /* Matching RHS found, so done */
+ result = true;
+ break;
+ }
}
}
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index 40c86b74552..baed9fdb4b7 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.75 2007/01/20 18:43:35 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.76 2007/01/30 01:33:36 tgl Exp $
*
* NOTES
* modeled after Margo Seltzer's hash implementation for unix.
@@ -308,6 +308,7 @@ extern bool _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir);
/* hashutil.c */
extern bool _hash_checkqual(IndexScanDesc scan, IndexTuple itup);
extern uint32 _hash_datum2hashkey(Relation rel, Datum key);
+extern uint32 _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype);
extern Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
uint32 highmask, uint32 lowmask);
extern uint32 _hash_log2(uint32 num);
diff --git a/src/include/executor/hashjoin.h b/src/include/executor/hashjoin.h
index ba086407679..19cfb1c473b 100644
--- a/src/include/executor/hashjoin.h
+++ b/src/include/executor/hashjoin.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.43 2007/01/28 23:21:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.44 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -102,12 +102,11 @@ typedef struct HashJoinTableData
/*
* Info about the datatype-specific hash functions for the datatypes being
- * hashed. We assume that the inner and outer sides of each hashclause
- * are the same type, or at least share the same hash function. This is an
- * array of the same length as the number of hash keys.
+ * hashed. These are arrays of the same length as the number of hash join
+ * clauses (hash keys).
*/
- FmgrInfo *hashfunctions; /* lookup data for hash functions */
-
+ FmgrInfo *outer_hashfunctions; /* lookup data for hash functions */
+ FmgrInfo *inner_hashfunctions; /* lookup data for hash functions */
bool *hashStrict; /* is each hash join operator strict? */
Size spaceUsed; /* memory space currently used by tuples */
diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h
index bf7292e8156..7c210bf99a0 100644
--- a/src/include/executor/nodeHash.h
+++ b/src/include/executor/nodeHash.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.43 2007/01/28 23:21:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.44 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,6 +31,7 @@ extern void ExecHashTableInsert(HashJoinTable hashtable,
extern bool ExecHashGetHashValue(HashJoinTable hashtable,
ExprContext *econtext,
List *hashkeys,
+ bool outer_tuple,
bool keep_nulls,
uint32 *hashvalue);
extern void ExecHashGetBucketAndBatch(HashJoinTable hashtable,
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 28bb03eca64..8e9bfaa1edc 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.115 2007/01/22 01:35:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.116 2007/01/30 01:33:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,8 +42,10 @@ extern bool get_compare_function_for_ordering_op(Oid opno,
extern Oid get_equality_op_for_ordering_op(Oid opno);
extern Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type);
extern List *get_mergejoin_opfamilies(Oid opno);
-extern Oid get_compatible_hash_operator(Oid opno, bool use_lhs_type);
-extern Oid get_op_hash_function(Oid opno);
+extern bool get_compatible_hash_operators(Oid opno,
+ Oid *lhs_opno, Oid *rhs_opno);
+extern bool get_op_hash_functions(Oid opno,
+ RegProcedure *lhs_procno, RegProcedure *rhs_procno);
extern void get_op_btree_interpretation(Oid opno,
List **opfamilies, List **opstrats);
extern bool ops_in_same_btree_opfamily(Oid opno1, Oid opno2);