7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
9
*
10
- * $Id: nodeHash.c,v 1.56 2001/03/22 06:16:12 momjian Exp $
10
+ * $Id: nodeHash.c,v 1.56.2.1 2001/08/13 19:54:00 tgl Exp $
11
11
*
12
12
*-------------------------------------------
8000
------------------------------
13
13
*/
@@ -507,19 +507,23 @@ ExecHashGetBucket(HashJoinTable hashtable,
507
507
int bucketno ;
508
508
Datum keyval ;
509
509
bool isNull ;
510
+ MemoryContext oldContext ;
510
511
511
512
/*
512
- * Get the join attribute value of the tuple
513
- *
514
- * We reset the eval context each time to avoid any possibility of memory
515
- * leaks in the hash function.
513
+ * We reset the eval context each time to reclaim any memory leaked
514
+ * in the hashkey expression or hashFunc itself.
516
515
*/
517
516
ResetExprContext (econtext );
518
517
519
- keyval = ExecEvalExprSwitchContext ( hashkey , econtext , & isNull , NULL );
518
+ oldContext = MemoryContextSwitchTo ( econtext -> ecxt_per_tuple_memory );
520
519
521
520
/*
522
- * compute the hash function
521
+ * Get the join attribute value of the tuple
522
+ */
523
+ keyval = ExecEvalExpr (hashkey , econtext , & isNull , NULL );
524
+
525
+ /*
526
+ * Compute the hash function
523
527
*/
524
528
if (isNull )
525
529
bucketno = 0 ;
@@ -538,6 +542,8 @@ ExecHashGetBucket(HashJoinTable hashtable,
538
542
printf ("hash(%ld) = %d\n" , (long ) keyval , bucketno );
539
543
#endif
540
544
545
+ MemoryContextSwitchTo (oldContext );
546
+
541
547
return bucketno ;
542
548
}
543
549
@@ -598,17 +604,18 @@ ExecScanHashBucket(HashJoinState *hjstate,
598
604
* hashFunc
599
605
*
600
606
* the hash function, copied from Margo
607
+ *
608
+ * XXX this probably ought to be replaced with datatype-specific
609
+ * hash functions, such as those already implemented for hash indexes.
601
610
* ----------------------------------------------------------------
602
611
*/
603
612
static int
604
613
hashFunc (Datum key , int len , bool byVal )
605
614
{
606
615
unsigned int h = 0 ;
607
- unsigned char * k ;
608
616
609
617
if (byVal )
610
618
{
611
-
612
619
/*
613
620
* If it's a by-value data type, use the 'len' least significant
614
621
* bytes of the Datum value. This should do the right thing on
@@ -623,22 +630,29 @@ hashFunc(Datum key, int len, bool byVal)
623
630
}
624
631
else
625
632
{
626
-
627
633
/*
628
- * If this is a variable length type, then 'k ' points to a "struct
629
- * varlena" and len == -1. NOTE: VARSIZE returns the "real" data
634
+ * If this is a variable length type, then 'key ' points to a "struct
635
+ * varlena" and len == -1. NOTE: VARSIZE returns the "real" data
630
636
* length plus the sizeof the "vl_len" attribute of varlena (the
631
- * length information). 'k ' points to the beginning of the varlena
637
+ * length information). 'key ' points to the beginning of the varlena
632
638
* struct, so we have to use "VARDATA" to find the beginning of
633
- * the "real" data.
<
8000
/td>639
+ * the "real" data. Also, we have to be careful to detoast the
640
+ * datum if it's toasted. (We don't worry about freeing the detoasted
641
+ * copy; that happens for free when the per-tuple memory context
642
+ * is reset in ExecHashGetBucket.)
634
643
*/
635
- if (len == -1 )
644
+ unsigned char * k ;
645
+
646
+ if (len < 0 )
636
647
{
637
- len = VARSIZE (key ) - VARHDRSZ ;
638
- k = (unsigned char * ) VARDATA (key );
648
+ struct varlena * vkey = PG_DETOAST_DATUM (key );
649
+
650
+ len = VARSIZE (vkey ) - VARHDRSZ ;
651
+ k = (unsigned char * ) VARDATA (vkey );
639
652
}
640
653
else
641
- k = (unsigned char * ) key ;
654
+ k = (unsigned char * ) DatumGetPointer (key );
655
+
642
656
while (len -- > 0 )
643
657
h = (h * PRIME1 ) ^ (* k ++ );
644
658
}
0 commit comments