From 0aebdc115f9966d8356da3c384ad442699712ad5 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 14 Jan 2011 22:55:56 -0800 Subject: [PATCH] Ported the fix for LP bug #702310 / bug #59493. An assertion failure was triggered for a 6-way join query that used two join buffers. The failure happened because every call of JOIN_CACHE::join_matching_records saved and restored status of all tables that were accessed before the table join_tab. It must do it only for those of them that follow the last table using a join buffer. --- mysql-test/r/select.result | 79 ++++++++++++++++++++++++++++ mysql-test/r/select_jcl6.result | 79 ++++++++++++++++++++++++++++ mysql-test/r/select_pkeycache.result | 79 ++++++++++++++++++++++++++++ mysql-test/t/select.test | 33 ++++++++++++ sql/sql_join_cache.cc | 9 ++-- 5 files changed, 276 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 6d3a3717c67..48fcc646d28 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4796,4 +4796,83 @@ SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; 1 1 DROP TABLE t1; +# +# Bug #702310: usage of 2 join buffers after ref access to an empty table +# +CREATE TABLE t1 (f1 int) ; +INSERT INTO t1 VALUES (9); +CREATE TABLE t2 (f1 int); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +CREATE TABLE t3 (f1 int); +INSERT INTO t3 VALUES (17); +CREATE TABLE t4 (f1 int PRIMARY KEY, f2 varchar(1024)) ; +CREATE TABLE t5 (f1 int) ; +INSERT INTO t5 VALUES (20),(5); +CREATE TABLE t6(f1 int); +INSERT INTO t6 VALUES (9),(7); +SET SESSION join_buffer_size = 2048; +EXPLAIN +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +1 SIMPLE t2 ALL NULL NULL NULL NULL 12 +1 SIMPLE t3 ALL NULL NULL NULL NULL 1 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 const 1 +1 SIMPLE t5 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +1 SIMPLE t6 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; +f1 f1 f1 f1 f2 f1 f1 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +SET SESSION join_buffer_size = DEFAULT; +DROP TABLE t1,t2,t3,t4,t5,t6; End of 5.1 tests diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result index ba5d3cddacb..4b32b27fe7e 100644 --- a/mysql-test/r/select_jcl6.result +++ b/mysql-test/r/select_jcl6.result @@ -4803,6 +4803,85 @@ SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; 1 1 DROP TABLE t1; +# +# Bug #702310: usage of 2 join buffers after ref access to an empty table +# +CREATE TABLE t1 (f1 int) ; +INSERT INTO t1 VALUES (9); +CREATE TABLE t2 (f1 int); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +CREATE TABLE t3 (f1 int); +INSERT INTO t3 VALUES (17); +CREATE TABLE t4 (f1 int PRIMARY KEY, f2 varchar(1024)) ; +CREATE TABLE t5 (f1 int) ; +INSERT INTO t5 VALUES (20),(5); +CREATE TABLE t6(f1 int); +INSERT INTO t6 VALUES (9),(7); +SET SESSION join_buffer_size = 2048; +EXPLAIN +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +1 SIMPLE t2 ALL NULL NULL NULL NULL 12 +1 SIMPLE t3 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 const 1 Using join buffer (incremental, BKA join) +1 SIMPLE t5 ALL NULL NULL NULL NULL 2 Using join buffer (incremental, BNL join) +1 SIMPLE t6 ALL NULL NULL NULL NULL 2 Using join buffer (incremental, BNL join) +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; +f1 f1 f1 f1 f2 f1 f1 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +SET SESSION join_buffer_size = DEFAULT; +DROP TABLE t1,t2,t3,t4,t5,t6; End of 5.1 tests set join_cache_level=default; show variables like 'join_cache_level'; diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result index 6d3a3717c67..48fcc646d28 100644 --- a/mysql-test/r/select_pkeycache.result +++ b/mysql-test/r/select_pkeycache.result @@ -4796,4 +4796,83 @@ SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; 1 1 DROP TABLE t1; +# +# Bug #702310: usage of 2 join buffers after ref access to an empty table +# +CREATE TABLE t1 (f1 int) ; +INSERT INTO t1 VALUES (9); +CREATE TABLE t2 (f1 int); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +CREATE TABLE t3 (f1 int); +INSERT INTO t3 VALUES (17); +CREATE TABLE t4 (f1 int PRIMARY KEY, f2 varchar(1024)) ; +CREATE TABLE t5 (f1 int) ; +INSERT INTO t5 VALUES (20),(5); +CREATE TABLE t6(f1 int); +INSERT INTO t6 VALUES (9),(7); +SET SESSION join_buffer_size = 2048; +EXPLAIN +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +1 SIMPLE t2 ALL NULL NULL NULL NULL 12 +1 SIMPLE t3 ALL NULL NULL NULL NULL 1 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 const 1 +1 SIMPLE t5 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +1 SIMPLE t6 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; +f1 f1 f1 f1 f2 f1 f1 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 20 9 +3 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 7 +3 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 5 9 +3 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 7 +3 9 NULL NULL NULL 5 7 +7 9 NULL NULL NULL 20 9 +18 9 NULL NULL NULL 20 9 +7 9 NULL NULL NULL 20 7 +18 9 NULL NULL NULL 20 7 +7 9 NULL NULL NULL 5 9 +18 9 NULL NULL NULL 5 9 +7 9 NULL NULL NULL 5 7 +18 9 NULL NULL NULL 5 7 +SET SESSION join_buffer_size = DEFAULT; +DROP TABLE t1,t2,t3,t4,t5,t6; End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index db08aad0df0..da38dde2bdf 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -4087,5 +4087,38 @@ EXPLAIN SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; DROP TABLE t1; +--echo # +--echo # Bug #702310: usage of 2 join buffers after ref access to an empty table +--echo # + +CREATE TABLE t1 (f1 int) ; +INSERT INTO t1 VALUES (9); + +CREATE TABLE t2 (f1 int); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); +INSERT INTO t2 VALUES (3),(7),(18); + +CREATE TABLE t3 (f1 int); +INSERT INTO t3 VALUES (17); + +CREATE TABLE t4 (f1 int PRIMARY KEY, f2 varchar(1024)) ; + +CREATE TABLE t5 (f1 int) ; +INSERT INTO t5 VALUES (20),(5); + +CREATE TABLE t6(f1 int); +INSERT INTO t6 VALUES (9),(7); + +SET SESSION join_buffer_size = 2048; + +EXPLAIN +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; +SELECT STRAIGHT_JOIN * FROM t2, (t1 LEFT JOIN (t3,t4) ON t1.f1 = t4.f1), t5, t6; + +SET SESSION join_buffer_size = DEFAULT; + +DROP TABLE t1,t2,t3,t4,t5,t6; --echo End of 5.1 tests diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 6c94ccede47..6e24af7a95e 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -3171,7 +3171,8 @@ uint JOIN_CACHE_HASHED::get_next_key(uchar ** key) int JOIN_TAB_SCAN::open() { - for (JOIN_TAB *tab= join->join_tab; tab != join_tab ; tab++) + JOIN_TAB *bound= join_tab-cache->tables; + for (JOIN_TAB *tab= join_tab-1; tab != bound && !tab->cache; tab--) { tab->status= tab->table->status; tab->table->status= 0; @@ -3246,7 +3247,8 @@ int JOIN_TAB_SCAN::next() void JOIN_TAB_SCAN::close() { - for (JOIN_TAB *tab= join->join_tab; tab != join_tab ; tab++) + JOIN_TAB *bound= join_tab-cache->tables; + for (JOIN_TAB *tab= join_tab-1; tab != bound && !tab->cache; tab--) tab->table->status= tab->status; } @@ -3647,7 +3649,8 @@ int JOIN_TAB_SCAN_MRR::open() /* Dynamic range access is never used with BKA */ DBUG_ASSERT(join_tab->use_quick != 2); - for (JOIN_TAB *tab =join->join_tab; tab != join_tab ; tab++) + JOIN_TAB *bound= join_tab-cache->tables; + for (JOIN_TAB *tab= join_tab-1; tab != bound && !tab->cache; tab--) { tab->status= tab->table->status; tab->table->status= 0;