Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 558c9d7

Browse files
committed
Fix PHJ match bit initialization.
Hash join tuples reuse the HOT status bit to indicate match status during hash join execution. Correct reuse requires clearing the bit in all tuples. Serial hash join and parallel multi-batch hash join do so upon inserting the tuple into the hashtable. Single batch parallel hash join and batch 0 of unexpected multi-batch hash joins forgot to do this. It hadn't come up before because hashtable tuple match bits are only used for right and full outer joins and parallel ROJ and FOJ were unsupported. 11c2d6f introduced support for parallel ROJ/FOJ but neglected to ensure the match bits were reset. Author: Melanie Plageman <melanieplageman@gmail.com> Reported-by: Richard Guo <guofenglinux@gmail.com> Discussion: https://postgr.es/m/flat/CAMbWs48Nde1Mv%3DBJv6_vXmRKHMuHZm2Q_g4F6Z3_pn%2B3EV6BGQ%40mail.gmail.com
1 parent a282697 commit 558c9d7

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

src/backend/executor/nodeHash.c

+1
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,7 @@ ExecParallelHashTableInsert(HashJoinTable hashtable,
17241724
/* Store the hash value in the HashJoinTuple header. */
17251725
hashTuple->hashvalue = hashvalue;
17261726
memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
1727+
HeapTupleHeaderClearMatch(HJTUPLE_MINTUPLE(hashTuple));
17271728

17281729
/* Push it onto the front of the bucket's list */
17291730
ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],

src/test/regress/expected/join_hash.out

+37
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,43 @@ $$);
955955
(1 row)
956956

957957
rollback to settings;
958+
-- Hash join reuses the HOT status bit to indicate match status. This can only
959+
-- be guaranteed to produce correct results if all the hash join tuple match
960+
-- bits are reset before reuse. This is done upon loading them into the
961+
-- hashtable.
962+
SAVEPOINT settings;
963+
SET enable_parallel_hash = on;
964+
SET min_parallel_table_scan_size = 0;
965+
SET parallel_setup_cost = 0;
966+
SET parallel_tuple_cost = 0;
967+
CREATE TABLE hjtest_matchbits_t1(id int);
968+
CREATE TABLE hjtest_matchbits_t2(id int);
969+
INSERT INTO hjtest_matchbits_t1 VALUES (1);
970+
INSERT INTO hjtest_matchbits_t2 VALUES (2);
971+
-- Update should create a HOT tuple. If this status bit isn't cleared, we won't
972+
-- correctly emit the NULL-extended unmatching tuple in full hash join.
973+
UPDATE hjtest_matchbits_t2 set id = 2;
974+
SELECT * FROM hjtest_matchbits_t1 t1 FULL JOIN hjtest_matchbits_t2 t2 ON t1.id = t2.id;
975+
id | id
976+
----+----
977+
1 |
978+
| 2
979+
(2 rows)
980+
981+
-- Test serial full hash join.
982+
-- Resetting parallel_setup_cost should force a serial plan.
983+
-- Just to be safe, however, set enable_parallel_hash to off, as parallel full
984+
-- hash joins are only supported with shared hashtables.
985+
RESET parallel_setup_cost;
986+
SET enable_parallel_hash = off;
987+
SELECT * FROM hjtest_matchbits_t1 t1 FULL JOIN hjtest_matchbits_t2 t2 ON t1.id = t2.id;
988+
id | id
989+
----+----
990+
1 |
991+
| 2
992+
(2 rows)
993+
994+
ROLLBACK TO settings;
958995
rollback;
959996
-- Verify that hash key expressions reference the correct
960997
-- nodes. Hashjoin's hashkeys need to reference its outer plan, Hash's

src/test/regress/sql/join_hash.sql

+27-1
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,34 @@ $$
506506
$$);
507507
rollback to settings;
508508

509-
rollback;
510509

510+
-- Hash join reuses the HOT status bit to indicate match status. This can only
511+
-- be guaranteed to produce correct results if all the hash join tuple match
512+
-- bits are reset before reuse. This is done upon loading them into the
513+
-- hashtable.
514+
SAVEPOINT settings;
515+
SET enable_parallel_hash = on;
516+
SET min_parallel_table_scan_size = 0;
517+
SET parallel_setup_cost = 0;
518+
SET parallel_tuple_cost = 0;
519+
CREATE TABLE hjtest_matchbits_t1(id int);
520+
CREATE TABLE hjtest_matchbits_t2(id int);
521+
INSERT INTO hjtest_matchbits_t1 VALUES (1);
522+
INSERT INTO hjtest_matchbits_t2 VALUES (2);
523+
-- Update should create a HOT tuple. If this status bit isn't cleared, we won't
524+
-- correctly emit the NULL-extended unmatching tuple in full hash join.
525+
UPDATE hjtest_matchbits_t2 set id = 2;
526+
SELECT * FROM hjtest_matchbits_t1 t1 FULL JOIN hjtest_matchbits_t2 t2 ON t1.id = t2.id;
527+
-- Test serial full hash join.
528+
-- Resetting parallel_setup_cost should force a serial plan.
529+
-- Just to be safe, however, set enable_parallel_hash to off, as parallel full
530+
-- hash joins are only supported with shared hashtables.
531+
RESET parallel_setup_cost;
532+
SET enable_parallel_hash = off;
533+
SELECT * FROM hjtest_matchbits_t1 t1 FULL JOIN hjtest_matchbits_t2 t2 ON t1.id = t2.id;
534+
ROLLBACK TO settings;
535+
536+
rollback;
511537

512538
-- Verify that hash key expressions reference the correct
513539
-- nodes. Hashjoin's hashkeys need to reference its outer plan, Hash's

0 commit comments

Comments
 (0)