diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result index 2bdac08e7fd..9033e2b2252 100644 --- a/mysql-test/r/join_nested.result +++ b/mysql-test/r/join_nested.result @@ -1743,4 +1743,62 @@ ON t4.carrier = t1.carrier; COUNT(*) 6 DROP TABLE t1,t2,t3,t4,t5; +CREATE TABLE t1 ( +pk int NOT NULL AUTO_INCREMENT PRIMARY KEY, +a int DEFAULT NULL, +KEY idx(a) +); +CREATE TABLE t2 ( +pk int NOT NULL AUTO_INCREMENT PRIMARY KEY, +a int DEFAULT NULL, +KEY idx(a) +); +CREATE TABLE t3 ( +pk int NOT NULL AUTO_INCREMENT PRIMARY KEY, +a int DEFAULT NULL, +KEY idx(a) +); +INSERT INTO t1 VALUES +(1,2), (2,7), (3,5), (4,7), (5,5), (6,NULL), (7,NULL), (8,9); +INSERT INTO t2 VALUES +(1,NULL), (4,2), (5,2), (3,4), (2,8); +INSERT INTO t3 VALUES +(1,9), (2,2), (3,5), (4,2), (5,7), (6,0), (7,5); +SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a +FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t3.a=t2.a) ON t2.a=t1.a; +pk a pk a pk a +1 2 4 2 2 2 +1 2 4 2 4 2 +1 2 5 2 2 2 +1 2 5 2 4 2 +2 7 NULL NULL NULL NULL +3 5 NULL NULL NULL NULL +4 7 NULL NULL NULL NULL +5 5 NULL NULL NULL NULL +6 NULL NULL NULL NULL NULL +7 NULL NULL NULL NULL NULL +8 9 NULL NULL NULL NULL +SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a +FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t3.a=t2.a) ON t2.a=t1.a +WHERE t2.pk IS NULL; +pk a pk a pk a +2 7 NULL NULL NULL NULL +3 5 NULL NULL NULL NULL +4 7 NULL NULL NULL NULL +5 5 NULL NULL NULL NULL +6 NULL NULL NULL NULL NULL +7 NULL NULL NULL NULL NULL +8 9 NULL NULL NULL NULL +SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a +FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t3.a=t2.a) ON t2.a=t1.a +WHERE t3.pk IS NULL; +pk a pk a pk a +2 7 NULL NULL NULL NULL +3 5 NULL NULL NULL NULL +4 7 NULL NULL NULL NULL +5 5 NULL NULL NULL NULL +6 NULL NULL NULL NULL NULL +7 NULL NULL NULL NULL NULL +8 9 NULL NULL NULL NULL +DROP TABLE t1, t2, t3; End of 5.0 tests diff --git a/mysql-test/t/join_nested.test b/mysql-test/t/join_nested.test index 5b07d8966f1..6ae7fb6dfee 100644 --- a/mysql-test/t/join_nested.test +++ b/mysql-test/t/join_nested.test @@ -1196,5 +1196,45 @@ SELECT COUNT(*) DROP TABLE t1,t2,t3,t4,t5; +# +# BUG#49322: Nested left joins + not-exist optimization +# + +CREATE TABLE t1 ( + pk int NOT NULL AUTO_INCREMENT PRIMARY KEY, + a int DEFAULT NULL, + KEY idx(a) +); +CREATE TABLE t2 ( + pk int NOT NULL AUTO_INCREMENT PRIMARY KEY, + a int DEFAULT NULL, + KEY idx(a) +); +CREATE TABLE t3 ( + pk int NOT NULL AUTO_INCREMENT PRIMARY KEY, + a int DEFAULT NULL, + KEY idx(a) +); + +INSERT INTO t1 VALUES + (1,2), (2,7), (3,5), (4,7), (5,5), (6,NULL), (7,NULL), (8,9); +INSERT INTO t2 VALUES + (1,NULL), (4,2), (5,2), (3,4), (2,8); +INSERT INTO t3 VALUES + (1,9), (2,2), (3,5), (4,2), (5,7), (6,0), (7,5); + +SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a + FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t3.a=t2.a) ON t2.a=t1.a; + +SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a + FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t3.a=t2.a) ON t2.a=t1.a + WHERE t2.pk IS NULL; + +SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a + FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t3.a=t2.a) ON t2.a=t1.a + WHERE t3.pk IS NULL; + +DROP TABLE t1, t2, t3; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8381e257e26..a939213566e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11738,6 +11738,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, condition is true => a match is found. */ bool found= 1; + bool use_not_exists_opt= 0; while (join_tab->first_unmatched && found) { /* @@ -11754,7 +11755,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++) { if (tab->table->reginfo.not_exists_optimize) - return NESTED_LOOP_NO_MORE_ROWS; + use_not_exists_opt= 1; /* Check all predicates that has just been activated. */ /* Actually all predicates non-guarded by first_unmatched->found @@ -11787,6 +11788,9 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, join_tab->first_unmatched= first_unmatched; } + if (use_not_exists_opt) + return NESTED_LOOP_NO_MORE_ROWS; + /* It was not just a return to lower loop level when one of the newly activated predicates is evaluated as false