Commit 103c4461 authored by Igor Babaev's avatar Igor Babaev

Fixed LP bug #817360.

This problem could be observed for queries with nested outer joins
for which the not_exist optimization were applicable. 
The problem was caused by the code of the patch for bug #49322
that erroneously forced the return to the previous nested loop
level when the join algorithm successfully builds a partial record
for an embedded outer to which the not_exist optimization could be
applied.
Actually the immediate return to the previous nested loops level
is correct only if this partial record is rejected by a predicate
pushed down to one of the inner tables of this outer join. Otherwise
attempts to find extensions of this record must be made.
parent cfa08e8d
...@@ -1801,4 +1801,35 @@ pk a pk a pk a ...@@ -1801,4 +1801,35 @@ pk a pk a pk a
7 NULL NULL NULL NULL NULL 7 NULL NULL NULL NULL NULL
8 9 NULL NULL NULL NULL 8 9 NULL NULL NULL NULL
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
CREATE TABLE t1 (a int NOT NULL );
INSERT INTO t1 VALUES (9), (9);
CREATE TABLE t2 (a int NOT NULL );
INSERT INTO t2 VALUES (9);
CREATE TABLE t3 (a int NOT NULL, b int);
INSERT INTO t3 VALUES (19,9);
CREATE TABLE t4 (b int) ;
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a;
a a a b b
9 9 19 9 NULL
9 9 19 9 NULL
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a
WHERE t3.a IS NULL;
a a a b b
EXPLAIN EXTENDED
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a
WHERE t3.a IS NULL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
1 SIMPLE t2 ALL NULL NULL NULL NULL 1 100.00 Using where
1 SIMPLE t3 ALL NULL NULL NULL NULL 1 100.00 Using where; Not exists
1 SIMPLE t4 ALL NULL NULL NULL NULL 0 0.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`b` AS `b` from `test`.`t1` left join (`test`.`t2` left join `test`.`t3` on(((`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t3`.`b` = `test`.`t1`.`a`))) left join `test`.`t4` on((`test`.`t4`.`b` = `test`.`t3`.`a`))) on((`test`.`t2`.`a` = `test`.`t1`.`a`)) where isnull(`test`.`t3`.`a`)
DROP TABLE t1,t2,t3,t4;
End of 5.0 tests End of 5.0 tests
...@@ -1810,6 +1810,37 @@ pk a pk a pk a ...@@ -1810,6 +1810,37 @@ pk a pk a pk a
7 NULL NULL NULL NULL NULL 7 NULL NULL NULL NULL NULL
8 9 NULL NULL NULL NULL 8 9 NULL NULL NULL NULL
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
CREATE TABLE t1 (a int NOT NULL );
INSERT INTO t1 VALUES (9), (9);
CREATE TABLE t2 (a int NOT NULL );
INSERT INTO t2 VALUES (9);
CREATE TABLE t3 (a int NOT NULL, b int);
INSERT INTO t3 VALUES (19,9);
CREATE TABLE t4 (b int) ;
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a;
a a a b b
9 9 19 9 NULL
9 9 19 9 NULL
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a
WHERE t3.a IS NULL;
a a a b b
EXPLAIN EXTENDED
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a
WHERE t3.a IS NULL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
1 SIMPLE t2 hash_ALL NULL #hash#$hj 4 test.t1.a 1 100.00 Using where; Using join buffer (flat, BNLH join)
1 SIMPLE t3 hash_ALL NULL #hash#$hj 5 test.t1.a 1 100.00 Using where; Not exists; Using join buffer (incremental, BNLH join)
1 SIMPLE t4 hash_ALL NULL #hash#$hj 5 test.t3.a 0 0.00 Using where; Using join buffer (incremental, BNLH join)
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`b` AS `b` from `test`.`t1` left join (`test`.`t2` left join `test`.`t3` on(((`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t3`.`b` = `test`.`t1`.`a`))) left join `test`.`t4` on(((`test`.`t4`.`b` = `test`.`t3`.`a`) and (`test`.`t3`.`a` is not null)))) on((`test`.`t2`.`a` = `test`.`t1`.`a`)) where isnull(`test`.`t3`.`a`)
DROP TABLE t1,t2,t3,t4;
End of 5.0 tests End of 5.0 tests
CREATE TABLE t5 (a int, b int, c int, PRIMARY KEY(a), KEY b_i (b)); CREATE TABLE t5 (a int, b int, c int, PRIMARY KEY(a), KEY b_i (b));
CREATE TABLE t6 (a int, b int, c int, PRIMARY KEY(a), KEY b_i (b)); CREATE TABLE t6 (a int, b int, c int, PRIMARY KEY(a), KEY b_i (b));
......
...@@ -1236,5 +1236,35 @@ SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a ...@@ -1236,5 +1236,35 @@ SELECT t1.pk, t1.a, t2.pk, t2.a,t3.pk, t3.a
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# LP BUG#817360: Nested left joins + not-exist optimization
#
CREATE TABLE t1 (a int NOT NULL );
INSERT INTO t1 VALUES (9), (9);
CREATE TABLE t2 (a int NOT NULL );
INSERT INTO t2 VALUES (9);
CREATE TABLE t3 (a int NOT NULL, b int);
INSERT INTO t3 VALUES (19,9);
CREATE TABLE t4 (b int) ;
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a;
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a
WHERE t3.a IS NULL;
EXPLAIN EXTENDED
SELECT * FROM t1 LEFT JOIN
((t2 LEFT JOIN t3 ON t2.a=t3.b) LEFT JOIN t4 ON t3.a=t4.b)
ON t1.a=t2.a
WHERE t3.a IS NULL;
DROP TABLE t1,t2,t3,t4;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -15114,7 +15114,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, ...@@ -15114,7 +15114,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
condition is true => a match is found. condition is true => a match is found.
*/ */
bool found= 1; bool found= 1;
bool use_not_exists_opt= 0;
while (join_tab->first_unmatched && found) while (join_tab->first_unmatched && found)
{ {
/* /*
...@@ -15130,8 +15129,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, ...@@ -15130,8 +15129,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
first_unmatched->found= 1; first_unmatched->found= 1;
for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++) for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
{ {
if (tab->table->reginfo.not_exists_optimize)
use_not_exists_opt= 1;
/* Check all predicates that has just been activated. */ /* Check all predicates that has just been activated. */
/* /*
Actually all predicates non-guarded by first_unmatched->found Actually all predicates non-guarded by first_unmatched->found
...@@ -15142,7 +15139,11 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, ...@@ -15142,7 +15139,11 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
{ {
/* The condition attached to table tab is false */ /* The condition attached to table tab is false */
if (tab == join_tab) if (tab == join_tab)
{
found= 0; found= 0;
if (tab->table->reginfo.not_exists_optimize)
DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
}
else else
{ {
/* /*
...@@ -15150,7 +15151,10 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, ...@@ -15150,7 +15151,10 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
not to the last table of the current nest level. not to the last table of the current nest level.
*/ */
join->return_tab= tab; join->return_tab= tab;
DBUG_RETURN(NESTED_LOOP_OK); if (tab->table->reginfo.not_exists_optimize)
DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
else
DBUG_RETURN(NESTED_LOOP_OK);
} }
} }
} }
...@@ -15164,8 +15168,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, ...@@ -15164,8 +15168,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
join_tab->first_unmatched= first_unmatched; join_tab->first_unmatched= first_unmatched;
} }
if (use_not_exists_opt)
DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
JOIN_TAB *return_tab= join->return_tab; JOIN_TAB *return_tab= join->return_tab;
join_tab->found_match= TRUE; join_tab->found_match= TRUE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment