Skip to content

Commit 9a14d83

Browse files
Steinar H. Gundersondahlerlend
authored andcommitted
Bug #30220791: INCORRECT RESULT WHEN THE ITERATOR EXECUTOR IS USED
Handle first match "split jumps" correctly in the iterator executor, by way of our usual fallback strategy of rewriting them to weedout. These are set up whenever the join optimizer inserts otherwise irrelevant tables in the middle of a first match segment. Not handling them leads to potentially wrong result in such queries (depending on row order in the input tables), removing rows that should have been there. Change-Id: I44e600d40bed62af520ca1f80d153784d3281412
1 parent 2836ba5 commit 9a14d83

12 files changed

+201
-54
lines changed

mysql-test/r/explain_tree.result

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,3 +747,38 @@ EXPLAIN
747747
-> Index scan on t1 using PRIMARY (cost=0.55 rows=3)
748748

749749
DROP TABLE t1;
750+
CREATE TABLE t1 (
751+
b INTEGER,
752+
UNIQUE KEY ix1 (b)
753+
);
754+
INSERT INTO t1 VALUES (5),(7);
755+
CREATE TABLE t2 (
756+
a INTEGER NOT NULL,
757+
b INTEGER DEFAULT NULL,
758+
KEY ix1 (b)
759+
);
760+
INSERT INTO t2 VALUES (40, 1), (45, 12), (11, 23), (10, 7);
761+
ANALYZE TABLE t1, t2;
762+
Table Op Msg_type Msg_text
763+
test.t1 analyze status OK
764+
test.t2 analyze status OK
765+
EXPLAIN SELECT * FROM t1 AS table1
766+
WHERE EXISTS ( SELECT * FROM t1 LEFT JOIN t2 USING (b) WHERE t2.a = t2.a AND t2.b <= 7 );
767+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
768+
1 SIMPLE t2 NULL range ix1 ix1 5 NULL 2 25.00 Using index condition; Using where; Using MRR; FirstMatch
769+
1 SIMPLE table1 NULL index NULL ix1 5 NULL 2 100.00 Using index
770+
1 SIMPLE t1 NULL eq_ref ix1 ix1 5 test.t2.b 1 100.00 Using index; FirstMatch(table1)
771+
Warnings:
772+
Note 1003 /* select#1 */ select `test`.`table1`.`b` AS `b` from `test`.`t1` `table1` semi join (`test`.`t1` join `test`.`t2`) where ((`test`.`t1`.`b` = `test`.`t2`.`b`) and (`test`.`t2`.`a` = `test`.`t2`.`a`) and (`test`.`t2`.`b` <= 7))
773+
EXPLAIN FORMAT=tree SELECT * FROM t1 AS table1
774+
WHERE EXISTS ( SELECT * FROM t1 LEFT JOIN t2 USING (b) WHERE t2.a = t2.a AND t2.b <= 7 );
775+
EXPLAIN
776+
-> Remove duplicate table1 rows using temporary table (weedout)
777+
-> Nested loop inner join (cost=1.55 rows=1)
778+
-> Nested loop inner join (cost=1.32 rows=1)
779+
-> Filter: (t2.a = t2.a) (cost=1.10 rows=0)
780+
-> Index range scan on t2 using ix1, with index condition: ((t2.b <= 7) and (t2.b is not null)) (cost=1.10 rows=2)
781+
-> Index scan on table1 using ix1 (cost=0.65 rows=2)
782+
-> Single-row index lookup on t1 using ix1 (b=t2.b) (cost=0.11 rows=1)
783+
784+
DROP TABLE t1, t2;

mysql-test/r/subquery_bugs.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -631,8 +631,8 @@ test.t2 analyze status OK
631631
EXPLAIN FORMAT=tree SELECT * FROM t1 LEFT JOIN t1 AS t3 ON t1.pk = t3.pk AND t1.f2 IN ( SELECT f2 FROM t2 )
632632
WHERE EXISTS ( SELECT * FROM t1 AS t4, t2 AS t5 ) AND t1.f1 = 80 AND t1.pk > t1.f1;
633633
EXPLAIN
634-
-> Remove duplicate (t1, t3, t4) rows using temporary table (weedout)
635-
-> Nested loop semijoin (cost=1.04 rows=1)
634+
-> Remove duplicate (t1, t3) rows using temporary table (weedout)
635+
-> Nested loop inner join (cost=1.04 rows=1)
636636
-> Nested loop left join (cost=0.81 rows=0)
637637
-> Nested loop inner join (cost=0.64 rows=0)
638638
-> Filter: ((t1.f1 = 80) and (t1.pk > 80)) (cost=0.46 rows=0)

mysql-test/r/subquery_sj_all.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12896,12 +12896,11 @@ test.t1 analyze status OK
1289612896
test.t2 analyze status OK
1289712897
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1289812898
EXPLAIN
12899-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12900-
-> Nested loop left join
12901-
-> Nested loop left join
12902-
-> Nested loop inner join
12903-
-> Limit: 1 row(s)
12904-
-> Table scan on t2 (cost=0.45 rows=2)
12899+
-> Remove duplicate t1 rows using temporary table (weedout)
12900+
-> Nested loop left join (cost=14.75 rows=54)
12901+
-> Nested loop left join (cost=4.85 rows=18)
12902+
-> Nested loop inner join (cost=1.55 rows=6)
12903+
-> Table scan on t2 (cost=0.45 rows=2)
1290512904
-> Table scan on t1 (cost=0.40 rows=3)
1290612905
-> Filter: true (cost=0.30 rows=3)
1290712906
-> Table scan on t1 (cost=0.30 rows=3)

mysql-test/r/subquery_sj_all_bka.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12902,12 +12902,11 @@ test.t1 analyze status OK
1290212902
test.t2 analyze status OK
1290312903
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1290412904
EXPLAIN
12905-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12906-
-> Nested loop left join
12907-
-> Nested loop left join
12908-
-> Nested loop inner join
12909-
-> Limit: 1 row(s)
12910-
-> Table scan on t2 (cost=0.45 rows=2)
12905+
-> Remove duplicate t1 rows using temporary table (weedout)
12906+
-> Nested loop left join (cost=14.75 rows=54)
12907+
-> Nested loop left join (cost=4.85 rows=18)
12908+
-> Nested loop inner join (cost=1.55 rows=6)
12909+
-> Table scan on t2 (cost=0.45 rows=2)
1291112910
-> Table scan on t1 (cost=0.40 rows=3)
1291212911
-> Filter: true (cost=0.30 rows=3)
1291312912
-> Table scan on t1 (cost=0.30 rows=3)

mysql-test/r/subquery_sj_all_bka_nixbnl.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12905,12 +12905,11 @@ test.t1 analyze status OK
1290512905
test.t2 analyze status OK
1290612906
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1290712907
EXPLAIN
12908-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12909-
-> Nested loop left join
12910-
-> Nested loop left join
12911-
-> Nested loop inner join
12912-
-> Limit: 1 row(s)
12913-
-> Table scan on t2 (cost=0.45 rows=2)
12908+
-> Remove duplicate t1 rows using temporary table (weedout)
12909+
-> Nested loop left join (cost=14.75 rows=54)
12910+
-> Nested loop left join (cost=4.85 rows=18)
12911+
-> Nested loop inner join (cost=1.55 rows=6)
12912+
-> Table scan on t2 (cost=0.45 rows=2)
1291412913
-> Table scan on t1 (cost=0.40 rows=3)
1291512914
-> Filter: true (cost=0.30 rows=3)
1291612915
-> Table scan on t1 (cost=0.30 rows=3)

mysql-test/r/subquery_sj_all_bkaunique.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12838,12 +12838,11 @@ test.t1 analyze status OK
1283812838
test.t2 analyze status OK
1283912839
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1284012840
EXPLAIN
12841-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12842-
-> Nested loop left join
12843-
-> Nested loop left join
12844-
-> Nested loop inner join
12845-
-> Limit: 1 row(s)
12846-
-> Table scan on t2 (cost=0.45 rows=2)
12841+
-> Remove duplicate t1 rows using temporary table (weedout)
12842+
-> Nested loop left join (cost=14.75 rows=54)
12843+
-> Nested loop left join (cost=4.85 rows=18)
12844+
-> Nested loop inner join (cost=1.55 rows=6)
12845+
-> Table scan on t2 (cost=0.45 rows=2)
1284712846
-> Table scan on t1 (cost=0.40 rows=3)
1284812847
-> Filter: true (cost=0.30 rows=3)
1284912848
-> Table scan on t1 (cost=0.30 rows=3)

mysql-test/r/subquery_sj_firstmatch.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12758,12 +12758,11 @@ test.t1 analyze status OK
1275812758
test.t2 analyze status OK
1275912759
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1276012760
EXPLAIN
12761-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12762-
-> Nested loop left join
12763-
-> Nested loop left join
12764-
-> Nested loop inner join
12765-
-> Limit: 1 row(s)
12766-
-> Table scan on t2 (cost=0.45 rows=2)
12761+
-> Remove duplicate t1 rows using temporary table (weedout)
12762+
-> Nested loop left join (cost=14.75 rows=54)
12763+
-> Nested loop left join (cost=4.85 rows=18)
12764+
-> Nested loop inner join (cost=1.55 rows=6)
12765+
-> Table scan on t2 (cost=0.45 rows=2)
1276712766
-> Table scan on t1 (cost=0.40 rows=3)
1276812767
-> Filter: true (cost=0.30 rows=3)
1276912768
-> Table scan on t1 (cost=0.30 rows=3)

mysql-test/r/subquery_sj_firstmatch_bka.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12759,12 +12759,11 @@ test.t1 analyze status OK
1275912759
test.t2 analyze status OK
1276012760
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1276112761
EXPLAIN
12762-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12763-
-> Nested loop left join
12764-
-> Nested loop left join
12765-
-> Nested loop inner join
12766-
-> Limit: 1 row(s)
12767-
-> Table scan on t2 (cost=0.45 rows=2)
12762+
-> Remove duplicate t1 rows using temporary table (weedout)
12763+
-> Nested loop left join (cost=14.75 rows=54)
12764+
-> Nested loop left join (cost=4.85 rows=18)
12765+
-> Nested loop inner join (cost=1.55 rows=6)
12766+
-> Table scan on t2 (cost=0.45 rows=2)
1276812767
-> Table scan on t1 (cost=0.40 rows=3)
1276912768
-> Filter: true (cost=0.30 rows=3)
1277012769
-> Table scan on t1 (cost=0.30 rows=3)

mysql-test/r/subquery_sj_firstmatch_bka_nixbnl.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12749,12 +12749,11 @@ test.t1 analyze status OK
1274912749
test.t2 analyze status OK
1275012750
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1275112751
EXPLAIN
12752-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12753-
-> Nested loop left join
12754-
-> Nested loop left join
12755-
-> Nested loop inner join
12756-
-> Limit: 1 row(s)
12757-
-> Table scan on t2 (cost=0.45 rows=2)
12752+
-> Remove duplicate t1 rows using temporary table (weedout)
12753+
-> Nested loop left join (cost=14.75 rows=54)
12754+
-> Nested loop left join (cost=4.85 rows=18)
12755+
-> Nested loop inner join (cost=1.55 rows=6)
12756+
-> Table scan on t2 (cost=0.45 rows=2)
1275812757
-> Table scan on t1 (cost=0.40 rows=3)
1275912758
-> Filter: true (cost=0.30 rows=3)
1276012759
-> Table scan on t1 (cost=0.30 rows=3)

mysql-test/r/subquery_sj_firstmatch_bkaunique.result

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12760,12 +12760,11 @@ test.t1 analyze status OK
1276012760
test.t2 analyze status OK
1276112761
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE EXISTS ( SELECT alias1.f2 FROM t2 LEFT JOIN t1 ON 1 LEFT JOIN t1 AS alias1 ON 1 );
1276212762
EXPLAIN
12763-
-> Remove duplicate (t2, t1) rows using temporary table (weedout)
12764-
-> Nested loop left join
12765-
-> Nested loop left join
12766-
-> Nested loop inner join
12767-
-> Limit: 1 row(s)
12768-
-> Table scan on t2 (cost=0.45 rows=2)
12763+
-> Remove duplicate t1 rows using temporary table (weedout)
12764+
-> Nested loop left join (cost=14.75 rows=54)
12765+
-> Nested loop left join (cost=4.85 rows=18)
12766+
-> Nested loop inner join (cost=1.55 rows=6)
12767+
-> Table scan on t2 (cost=0.45 rows=2)
1276912768
-> Table scan on t1 (cost=0.40 rows=3)
1277012769
-> Filter: true (cost=0.30 rows=3)
1277112770
-> Table scan on t1 (cost=0.30 rows=3)

0 commit comments

Comments
 (0)