[Commits] Rev 2857: Fixed LP bug #675095. in file:///home/igor/maria/maria-5.3-mwl128-bug675095/

Igor Babaev igor at askmonty.org
Mon Nov 15 09:12:39 EET 2010


At file:///home/igor/maria/maria-5.3-mwl128-bug675095/

------------------------------------------------------------
revno: 2857
revision-id: igor at askmonty.org-20101115071238-q3o94y1ua2acglkd
parent: igor at askmonty.org-20101113154743-nwdowwt4cycyyprl
committer: Igor Babaev <igor at askmonty.org>
branch nick: maria-5.3-mwl128-bug675095
timestamp: Sun 2010-11-14 23:12:38 -0800
message:
  Fixed LP bug #675095.
  The condition over outer tables extracted from the on expression
  for a outer join must be ANDed to the condition pushed to the
  first inner table of this outer join only.
  Nested outer joins cannot use flat join buffers. So if join_cache_level
  is set to 1 then any join algorithm employing join buffers cannot be used
  for nested outer joins.
-------------- next part --------------
=== modified file 'mysql-test/r/join_cache.result'
--- a/mysql-test/r/join_cache.result	2010-11-13 15:47:43 +0000
+++ b/mysql-test/r/join_cache.result	2010-11-15 07:12:38 +0000
@@ -5838,4 +5838,87 @@
 SET SESSION optimizer_switch = 'outer_join_with_cache=off';
 SET SESSION join_cache_level = DEFAULT;
 DROP TABLE t1,t2;
+#
+# Bug #675095: nested outer join using join buffer 
+#
+CREATE TABLE t1 (pk int, a1 int) ;
+INSERT IGNORE INTO t1 VALUES (2,NULL), (8,0);
+CREATE TABLE t2 (pk int, a2 int, c2 int, d2 int) ;
+INSERT IGNORE INTO t2 VALUES  (9,0,0,2), (1,0,0,7);
+CREATE TABLE t3 (pk int, a3 int, c3 int, d3 int) ;
+INSERT IGNORE INTO t3 VALUES  (9,0,0,2), (1,0,0,7);
+CREATE TABLE t4 (pk int, a4 int, INDEX idx(a4)) ;
+INSERT IGNORE INTO t4 VALUES (2,NULL), (8,0);
+CREATE TABLE t5 (pk int, a5 int) ;
+INSERT IGNORE INTO t5 VALUES (2,0), (8,0);
+SET SESSION optimizer_switch = 'outer_join_with_cache=on';
+SET SESSION join_cache_level = 0;
+EXPLAIN EXTENDED
+SELECT *
+FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+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	2	100.00	Using where
+1	SIMPLE	t3	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
+1	SIMPLE	t4	ref	idx	idx	5	test.t1.a1	2	100.00	Using where
+1	SIMPLE	t5	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
+Warnings:
+Note	1003	select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`a1` AS `a1`,`test`.`t2`.`pk` AS `pk`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`c2` AS `c2`,`test`.`t2`.`d2` AS `d2`,`test`.`t3`.`pk` AS `pk`,`test`.`t3`.`a3` AS `a3`,`test`.`t3`.`c3` AS `c3`,`test`.`t3`.`d3` AS `d3`,`test`.`t4`.`pk` AS `pk`,`test`.`t4`.`a4` AS `a4`,`test`.`t5`.`pk` AS `pk`,`test`.`t5`.`a5` AS `a5` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t2`.`d2` = `test`.`t1`.`pk`) and (`test`.`t3`.`a3` = `test`.`t2`.`c2`))) left join `test`.`t4` on(((`test`.`t4`.`a4` = `test`.`t1`.`a1`) and (`test`.`t1`.`a1` is not null))) left join `test`.`t5` on((`test`.`t5`.`a5` = `test`.`t3`.`a3`)) where 1
+SELECT *
+FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+pk	a1	pk	a2	c2	d2	pk	a3	c3	d3	pk	a4	pk	a5
+2	NULL	9	0	0	2	9	0	0	2	NULL	NULL	2	0
+2	NULL	9	0	0	2	9	0	0	2	NULL	NULL	8	0
+2	NULL	9	0	0	2	1	0	0	7	NULL	NULL	2	0
+2	NULL	9	0	0	2	1	0	0	7	NULL	NULL	8	0
+8	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	8	0	NULL	NULL
+SET SESSION join_cache_level = 2;
+EXPLAIN EXTENDED
+SELECT *
+FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+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	2	100.00	Using where; Using join buffer (flat, BNL join)
+1	SIMPLE	t3	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where; Using join buffer (incremental, BNL join)
+1	SIMPLE	t4	ref	idx	idx	5	test.t1.a1	2	100.00	Using where
+1	SIMPLE	t5	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note	1003	select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`a1` AS `a1`,`test`.`t2`.`pk` AS `pk`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`c2` AS `c2`,`test`.`t2`.`d2` AS `d2`,`test`.`t3`.`pk` AS `pk`,`test`.`t3`.`a3` AS `a3`,`test`.`t3`.`c3` AS `c3`,`test`.`t3`.`d3` AS `d3`,`test`.`t4`.`pk` AS `pk`,`test`.`t4`.`a4` AS `a4`,`test`.`t5`.`pk` AS `pk`,`test`.`t5`.`a5` AS `a5` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t2`.`d2` = `test`.`t1`.`pk`) and (`test`.`t3`.`a3` = `test`.`t2`.`c2`))) left join `test`.`t4` on(((`test`.`t4`.`a4` = `test`.`t1`.`a1`) and (`test`.`t1`.`a1` is not null))) left join `test`.`t5` on((`test`.`t5`.`a5` = `test`.`t3`.`a3`)) where 1
+SELECT *
+FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+pk	a1	pk	a2	c2	d2	pk	a3	c3	d3	pk	a4	pk	a5
+2	NULL	9	0	0	2	9	0	0	2	NULL	NULL	2	0
+2	NULL	9	0	0	2	1	0	0	7	NULL	NULL	2	0
+2	NULL	9	0	0	2	9	0	0	2	NULL	NULL	8	0
+2	NULL	9	0	0	2	1	0	0	7	NULL	NULL	8	0
+8	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	8	0	NULL	NULL
+SET SESSION join_cache_level = 1;
+EXPLAIN EXTENDED
+SELECT *
+FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+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	2	100.00	Using where
+1	SIMPLE	t3	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
+1	SIMPLE	t4	ref	idx	idx	5	test.t1.a1	2	100.00	Using where
+1	SIMPLE	t5	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note	1003	select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`a1` AS `a1`,`test`.`t2`.`pk` AS `pk`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`c2` AS `c2`,`test`.`t2`.`d2` AS `d2`,`test`.`t3`.`pk` AS `pk`,`test`.`t3`.`a3` AS `a3`,`test`.`t3`.`c3` AS `c3`,`test`.`t3`.`d3` AS `d3`,`test`.`t4`.`pk` AS `pk`,`test`.`t4`.`a4` AS `a4`,`test`.`t5`.`pk` AS `pk`,`test`.`t5`.`a5` AS `a5` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t2`.`d2` = `test`.`t1`.`pk`) and (`test`.`t3`.`a3` = `test`.`t2`.`c2`))) left join `test`.`t4` on(((`test`.`t4`.`a4` = `test`.`t1`.`a1`) and (`test`.`t1`.`a1` is not null))) left join `test`.`t5` on((`test`.`t5`.`a5` = `test`.`t3`.`a3`)) where 1
+SELECT *
+FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+pk	a1	pk	a2	c2	d2	pk	a3	c3	d3	pk	a4	pk	a5
+2	NULL	9	0	0	2	9	0	0	2	NULL	NULL	2	0
+2	NULL	9	0	0	2	1	0	0	7	NULL	NULL	2	0
+2	NULL	9	0	0	2	9	0	0	2	NULL	NULL	8	0
+2	NULL	9	0	0	2	1	0	0	7	NULL	NULL	8	0
+8	0	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	8	0	NULL	NULL
+SET SESSION optimizer_switch = 'outer_join_with_cache=off';
+SET SESSION join_cache_level = DEFAULT;
+DROP TABLE t1,t2,t3,t4,t5;
 set @@optimizer_switch=@save_optimizer_switch;

=== modified file 'mysql-test/t/join_cache.test'
--- a/mysql-test/t/join_cache.test	2010-11-13 15:47:43 +0000
+++ b/mysql-test/t/join_cache.test	2010-11-15 07:12:38 +0000
@@ -2522,5 +2522,62 @@
 
 DROP TABLE t1,t2;
 
+--echo #
+--echo # Bug #675095: nested outer join using join buffer 
+--echo #
+
+CREATE TABLE t1 (pk int, a1 int) ;
+INSERT IGNORE INTO t1 VALUES (2,NULL), (8,0);
+
+CREATE TABLE t2 (pk int, a2 int, c2 int, d2 int) ;
+INSERT IGNORE INTO t2 VALUES  (9,0,0,2), (1,0,0,7);
+
+CREATE TABLE t3 (pk int, a3 int, c3 int, d3 int) ;
+INSERT IGNORE INTO t3 VALUES  (9,0,0,2), (1,0,0,7);
+
+CREATE TABLE t4 (pk int, a4 int, INDEX idx(a4)) ;
+INSERT IGNORE INTO t4 VALUES (2,NULL), (8,0);
+
+CREATE TABLE t5 (pk int, a5 int) ;
+INSERT IGNORE INTO t5 VALUES (2,0), (8,0);
+
+
+SET SESSION optimizer_switch = 'outer_join_with_cache=on';
+
+SET SESSION join_cache_level = 0;
+
+EXPLAIN EXTENDED
+SELECT *
+  FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+        LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+SELECT *
+  FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+        LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+
+SET SESSION join_cache_level = 2;
+
+EXPLAIN EXTENDED
+SELECT *
+  FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+        LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+SELECT *
+  FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+        LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+
+SET SESSION join_cache_level = 1;
+
+EXPLAIN EXTENDED
+SELECT *
+  FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+        LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+SELECT *
+  FROM ((t1 LEFT JOIN (t2 JOIN t3 ON t2.c2 = t3.a3) ON t1.pk = t2.d2)
+        LEFT JOIN t4 ON t1.a1 = t4.a4) LEFT JOIN t5 ON t3.a3 = t5.a5;
+
+SET SESSION optimizer_switch = 'outer_join_with_cache=off';
+SET SESSION join_cache_level = DEFAULT;
+
+DROP TABLE t1,t2,t3,t4,t5;
+
 # this must be the last command in the file
 set @@optimizer_switch=@save_optimizer_switch;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-11-13 14:13:34 +0000
+++ b/sql/sql_select.cc	2010-11-15 07:12:38 +0000
@@ -7149,7 +7149,8 @@
           used_tables2|= current_map;
           COND *tmp_cond= make_cond_for_table(on_expr, used_tables2,
                                               current_map, FALSE, FALSE);
-          add_cond_and_fix(&tmp_cond, tab->on_precond);
+          if (tab == first_inner_tab && tab->on_precond)
+            add_cond_and_fix(&tmp_cond, tab->on_precond);
           if (tmp_cond)
           {
             JOIN_TAB *cond_tab= tab < first_inner_tab ? first_inner_tab : tab;
@@ -7657,7 +7658,7 @@
   /*
     Non-linked join buffers can't guarantee one match
   */
-  if (force_unlinked_cache &&  
+  if ((force_unlinked_cache || cache_level == 1) &&  
       ((tab->is_inner_table_of_semi_join_with_first_match() &&
         !tab->is_single_inner_of_semi_join_with_first_match()) ||
        (tab->is_inner_table_of_outer_join() &&



More information about the commits mailing list