8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.108 2007/01/05 22:19:28 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.109 2007/01/28 23:21:26 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -92,11 +92,14 @@ MultiExecHash(HashState *node)
92
92
slot = ExecProcNode (outerNode );
93
93
if (TupIsNull (slot ))
94
94
break ;
95
- hashtable -> totalTuples += 1 ;
96
95
/* We have to compute the hash value */
97
96
econtext -> ecxt_innertuple = slot ;
98
- hashvalue = ExecHashGetHashValue (hashtable , econtext , hashkeys );
99
- ExecHashTableInsert (hashtable , slot , hashvalue );
97
+ if (ExecHashGetHashValue (hashtable , econtext , hashkeys , false,
98
+ & hashvalue ))
99
+ {
100
+ ExecHashTableInsert (hashtable , slot , hashvalue );
101
+ hashtable -> totalTuples += 1 ;
102
+ }
100
103
}
101
104
102
105
/* must provide our own instrumentation support */
@@ -261,19 +264,23 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
261
264
262
265
/*
263
266
* Get info about the hash functions to be used for each hash key.
267
+ * Also remember whether the join operators are strict.
264
268
*/
265
269
nkeys = list_length (hashOperators );
266
270
hashtable -> hashfunctions = (FmgrInfo * ) palloc (nkeys * sizeof (FmgrInfo ));
271
+ hashtable -> hashStrict = (bool * ) palloc (nkeys * sizeof (bool ));
267
272
i = 0 ;
268
273
foreach (ho , hashOperators )
269
274
{
275
+ Oid hashop = lfirst_oid (ho );
270
276
Oid hashfn ;
271
277
272
- hashfn = get_op_hash_function (lfirst_oid ( ho ) );
278
+ hashfn = get_op_hash_function (hashop );
273
279
if (!OidIsValid (hashfn ))
274
280
elog (ERROR , "could not find hash function for hash operator %u" ,
275
- lfirst_oid ( ho ) );
281
+ hashop );
276
282
fmgr_info (hashfn , & hashtable -> hashfunctions [i ]);
283
+ hashtable -> hashStrict [i ] = op_strict (hashop );
277
284
i ++ ;
278
285
}
279
286
@@ -657,11 +664,18 @@ ExecHashTableInsert(HashJoinTable hashtable,
657
664
* The tuple to be tested must be in either econtext->ecxt_outertuple or
658
665
* econtext->ecxt_innertuple. Vars in the hashkeys expressions reference
659
666
* either OUTER or INNER.
667
+ *
668
+ * A TRUE result means the tuple's hash value has been successfully computed
669
+ * and stored at *hashvalue. A FALSE result means the tuple cannot match
670
+ * because it contains a null attribute, and hence it should be discarded
671
+ * immediately. (If keep_nulls is true then FALSE is never returned.)
660
672
*/
661
- uint32
673
+ bool
662
674
ExecHashGetHashValue (HashJoinTable hashtable ,
663
675
ExprContext * econtext ,
664
- List * hashkeys )
676
+ List * hashkeys ,
677
+ bool keep_nulls ,
678
+ uint32 * hashvalue )
665
679
{
666
680
uint32 hashkey = 0 ;
667
681
ListCell * hk ;
@@ -691,10 +705,27 @@ ExecHashGetHashValue(HashJoinTable hashtable,
691
705
keyval = ExecEvalExpr (keyexpr , econtext , & isNull , NULL );
692
706
693
707
/*
694
- * Compute the hash function
708
+ * If the attribute is NULL, and the join operator is strict, then
709
+ * this tuple cannot pass the join qual so we can reject it
710
+ * immediately (unless we're scanning the outside of an outer join,
711
+ * in which case we must not reject it). Otherwise we act like the
712
+ * hashcode of NULL is zero (this will support operators that act like
713
+ * IS NOT DISTINCT, though not any more-random behavior). We treat
714
+ * the hash support function as strict even if the operator is not.
715
+ *
716
+ * Note: currently, all hashjoinable operators must be strict since
717
+ * the hash index AM assumes that. However, it takes so little
718
+ * extra code here to allow non-strict that we may as well do it.
695
719
*/
696
- if (!isNull ) /* treat nulls as having hash key 0 */
720
+ if (isNull )
721
+ {
722
+ if (hashtable -> hashStrict [i ] && !keep_nulls )
723
+ return false; /* cannot match */
724
+ /* else, leave hashkey unmodified, equivalent to hashcode 0 */
725
+ }
726
+ else
697
727
{
728
+ /* Compute the hash function */
698
729
uint32 hkey ;
699
730
700
731
hkey = DatumGetUInt32 (FunctionCall1 (& hashtable -> hashfunctions [i ],
@@ -707,7 +738,8 @@ ExecHashGetHashValue(HashJoinTable hashtable,
707
738
708
739
MemoryContextSwitchTo (oldContext );
709
740
710
- return hashkey ;
741
+ * hashvalue = hashkey ;
742
+ return true;
711
743
}
712
744
713
745
/*
0 commit comments