Skip to content

Commit 38cfc95

Browse files
committed
Make hashjoin give the right answer with toasted input data.
1 parent 95f8901 commit 38cfc95

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

src/backend/executor/nodeHash.c

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
*
10-
* $Id: nodeHash.c,v 1.58 2001/06/11 00:17:07 tgl Exp $
10+
* $Id: nodeHash.c,v 1.59 2001/08/13 19:50:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -533,19 +533,23 @@ ExecHashGetBucket(HashJoinTable hashtable,
533533
int bucketno;
534534
Datum keyval;
535535
bool isNull;
536+
MemoryContext oldContext;
536537

537538
/*
538-
* Get the join attribute value of the tuple
539-
*
540-
* We reset the eval context each time to avoid any possibility of memory
541-
* leaks in the hash function.
539+
* We reset the eval context each time to reclaim any memory leaked
540+
* in the hashkey expression or hashFunc itself.
542541
*/
543542
ResetExprContext(econtext);
544543

545-
keyval = ExecEvalExprSwitchContext(hashkey, econtext, &isNull, NULL);
544+
oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
546545

547546
/*
548-
* compute the hash function
547+
* Get the join attribute value of the tuple
548+
*/
549+
keyval = ExecEvalExpr(hashkey, econtext, &isNull, NULL);
550+
551+
/*
552+
* Compute the hash function
549553
*/
550554
if (isNull)
551555
bucketno = 0;
@@ -564,6 +568,8 @@ ExecHashGetBucket(HashJoinTable hashtable,
564568
printf("hash(%ld) = %d\n", (long) keyval, bucketno);
565569
#endif
566570

571+
MemoryContextSwitchTo(oldContext);
572+
567573
return bucketno;
568574
}
569575

@@ -624,17 +630,18 @@ ExecScanHashBucket(HashJoinState *hjstate,
624630
* hashFunc
625631
*
626632
* the hash function, copied from Margo
633+
*
634+
* XXX this probably ought to be replaced with datatype-specific
635+
* hash functions, such as those already implemented for hash indexes.
627636
* ----------------------------------------------------------------
628637
*/
629638
static int
630639
hashFunc(Datum key, int len, bool byVal)
631640
{
632641
unsigned int h = 0;
633-
unsigned char *k;
634642

635643
if (byVal)
636644
{
637-
638645
/*
639646
* If it's a by-value data type, use the 'len' least significant
640647
* bytes of the Datum value. This should do the right thing on
@@ -649,22 +656,29 @@ hashFunc(Datum key, int len, bool byVal)
649656
}
650657
else
651658
{
652-
653659
/*
654-
* If this is a variable length type, then 'k' points to a "struct
655-
* varlena" and len == -1. NOTE: VARSIZE returns the "real" data
660+
* If this is a variable length type, then 'key' points to a "struct
661+
* varlena" and len == -1. NOTE: VARSIZE returns the "real" data
656662
* length plus the sizeof the "vl_len" attribute of varlena (the
657-
* length information). 'k' points to the beginning of the varlena
663+
* length information). 'key' points to the beginning of the varlena
658664
* struct, so we have to use "VARDATA" to find the beginning of
659-
* the "real" data.
665+
* the "real" data. Also, we have to be careful to detoast the
666+
* datum if it's toasted. (We don't worry about freeing the detoasted
667+
* copy; that happens for free when the per-tuple memory context
668+
* is reset in ExecHashGetBucket.)
660669
*/
661-
if (len == -1)
670+
unsigned char *k;
671+
672+
if (len < 0)
662673
{
663-
len = VARSIZE(key) - VARHDRSZ;
664-
k = (unsigned char *) VARDATA(key);
674+
struct varlena *vkey = PG_DETOAST_DATUM(key);
675+
676+
len = VARSIZE(vkey) - VARHDRSZ;
677+
k = (unsigned char *) VARDATA(vkey);
665678
}
666679
else
667-
k = (unsigned char *) key;
680+
k = (unsigned char *) DatumGetPointer(key);
681+
668682
while (len-- > 0)
669683
h = (h * PRIME1) ^ (*k++);
670684
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy