From c8bbe06ac7fd536b3e756afc0e2e8c8dc0724119 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 13 Feb 2012 23:46:57 -0800 Subject: [PATCH] Fixed LP bug #925985. If the flag 'optimize_join_buffer_size' is set to 'off' and the value of the system variable 'join_buffer_size' is greater than the value of the system variable 'join_buffer_space_limit' than no join cache can be employed to join tables of the executed query. A bug in the function JOIN_CACHE::alloc_buffer allowed to use join buffer even in this case while another bug in the function revise_cache_usage could cause a crash of the server in this case if the chosen execution plan for the query contained outer join or semi-join operation. --- mysql-test/r/join_cache.result | 35 ++++++++++++++++++++++++++++++++++ mysql-test/t/join_cache.test | 35 ++++++++++++++++++++++++++++++++++ sql/sql_join_cache.cc | 2 ++ sql/sql_select.cc | 4 ++-- 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index 11114a032f9..dda0f4c8f66 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -5534,4 +5534,39 @@ we set join_cache_level = default; set optimizer_switch=@tmp_optimizer_switch; DROP TABLE t1,t2,t3; +# +# Bug #925985: LEFT JOIN with optimize_join_buffer_size=off + +# join_buffer_size > join_buffer_space_limit +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (5), (3); +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES +(3,30), (1,10), (7,70), (2,20), +(3,31), (1,11), (7,71), (2,21), +(3,32), (1,12), (7,72), (2,22); +CREATE TABLE t3 (b int, c int); +INSERT INTO t3 VALUES (32, 302), (42,400), (30,300); +set @tmp_optimizer_switch=@@optimizer_switch; +set optimizer_switch='optimize_join_buffer_size=off'; +set join_buffer_space_limit=4096; +set join_buffer_size=4096*2; +set join_cache_level=2; +set optimizer_switch='outer_join_with_cache=on'; +EXPLAIN +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +1 SIMPLE t2 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (incremental, BNL join) +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; +a a b b c +3 3 30 30 300 +3 3 31 NULL NULL +3 3 32 32 302 +set join_buffer_space_limit=default; +set join_buffer_size=default; +set join_cache_level=default; +set optimizer_switch=@tmp_optimizer_switch; +DROP TABLE t1,t2,t3; set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 8a61c00b7d4..9d7b07f6b9e 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -3547,5 +3547,40 @@ set optimizer_switch=@tmp_optimizer_switch; DROP TABLE t1,t2,t3; +--echo # +--echo # Bug #925985: LEFT JOIN with optimize_join_buffer_size=off + +--echo # join_buffer_size > join_buffer_space_limit +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (5), (3); + +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES + (3,30), (1,10), (7,70), (2,20), + (3,31), (1,11), (7,71), (2,21), + (3,32), (1,12), (7,72), (2,22); + +CREATE TABLE t3 (b int, c int); +INSERT INTO t3 VALUES (32, 302), (42,400), (30,300); + +set @tmp_optimizer_switch=@@optimizer_switch; +set optimizer_switch='optimize_join_buffer_size=off'; +set join_buffer_space_limit=4096; +set join_buffer_size=4096*2; +set join_cache_level=2; +set optimizer_switch='outer_join_with_cache=on'; + +EXPLAIN +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; + +set join_buffer_space_limit=default; +set join_buffer_size=default; +set join_cache_level=default; +set optimizer_switch=@tmp_optimizer_switch; + +DROP TABLE t1,t2,t3; + # this must be the last command in the file set @@optimizer_switch=@save_optimizer_switch; diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 2a8db8b4fd1..78f95a7ac7e 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -898,6 +898,8 @@ int JOIN_CACHE::alloc_buffer() curr_buff_space_sz+= cache->get_join_buffer_size(); } } + curr_min_buff_space_sz+= min_buff_size; + curr_buff_space_sz+= buff_size; if (curr_min_buff_space_sz > join_buff_space_limit || (curr_buff_space_sz > join_buff_space_limit && diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 05fba45792b..aa1090fb03b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8903,7 +8903,7 @@ void revise_cache_usage(JOIN_TAB *join_tab) first_inner; first_inner= first_inner->first_upper) { - for (tab= end_tab-1; tab >= first_inner; tab--) + for (tab= end_tab; tab >= first_inner; tab--) set_join_cache_denial(tab); end_tab= first_inner; } @@ -8911,7 +8911,7 @@ void revise_cache_usage(JOIN_TAB *join_tab) else if (join_tab->first_sj_inner_tab) { first_inner= join_tab->first_sj_inner_tab; - for (tab= join_tab-1; tab >= first_inner; tab--) + for (tab= join_tab; tab >= first_inner; tab--) { set_join_cache_denial(tab); }