From 1c7ba7ba2f1daeeeb6ab507c4ee3209690119c51 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 6 Mar 2010 11:14:55 -0800 Subject: [PATCH] Fixed bug #51092. The function JOIN_CACHE::read_all_record_fields could return 0 for an incremental join cache in two cases: 1. there were no more records in the associated join buffer 2. there was no table fields stored in the join buffer. As a result the function JOIN_CACHE::get_record() could return prematurely and did not read all needed fields from join buffers into the record buffer. Now the function JOIN_CACHE::read_all_record_fields returns -1 if there are no more records in the associated join buffer. --- mysql-test/r/join_cache.result | 43 ++++++++++++++++++++++++++++++++++ mysql-test/t/join_cache.test | 24 +++++++++++++++++++ sql/sql_join_cache.cc | 9 ++++--- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index b9c182fb8c4..5437538023c 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -4142,3 +4142,46 @@ c1 c2 c1 c2 LENGTH(t2.c1) LENGTH(t2.c2) 2 2 tt uu 2 2 set join_cache_level=default; DROP TABLE t1,t2; +# +# Bug #51092: linked join buffer is used for a 3-way cross join query +# that selects only records of the first table +# +create table t1 (a int, b int); +insert into t1 values (1,1),(2,2); +create table t2 (a int, b int); +insert into t2 values (1,1),(2,2); +create table t3 (a int, b int); +insert into t3 values (1,1),(2,2); +explain select t1.* from t1,t2,t3; +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 2 Using join buffer +1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using join buffer +select t1.* from t1,t2,t3; +a b +1 1 +2 2 +1 1 +2 2 +1 1 +2 2 +1 1 +2 2 +set join_cache_level=2; +explain select t1.* from t1,t2,t3; +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 2 Using join buffer +1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using join buffer +select t1.* from t1,t2,t3; +a b +1 1 +2 2 +1 1 +2 2 +1 1 +2 2 +1 1 +2 2 +set join_cache_level=default; +drop table t1,t2,t3; diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 82fc37db641..0cb1c139161 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -1823,3 +1823,27 @@ SELECT t1.*, t2.*, LENGTH(t2.c1), LENGTH(t2.c2) FROM t1,t2 set join_cache_level=default; DROP TABLE t1,t2; + +--echo # +--echo # Bug #51092: linked join buffer is used for a 3-way cross join query +--echo # that selects only records of the first table +--echo # + +create table t1 (a int, b int); +insert into t1 values (1,1),(2,2); +create table t2 (a int, b int); +insert into t2 values (1,1),(2,2); +create table t3 (a int, b int); +insert into t3 values (1,1),(2,2); + +explain select t1.* from t1,t2,t3; +select t1.* from t1,t2,t3; + +set join_cache_level=2; + +explain select t1.* from t1,t2,t3; +select t1.* from t1,t2,t3; + +set join_cache_level=default; + +drop table t1,t2,t3; diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index bccb6005792..5c8c7ae7af7 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -31,6 +31,8 @@ #include "sql_select.h" #include "opt_subselect.h" +#define NO_MORE_RECORDS_IN_BUFFER (uint)(-1) + /***************************************************************************** * Join cache module @@ -1237,7 +1239,7 @@ bool JOIN_CACHE::get_record() prev_rec_ptr= prev_cache->get_rec_ref(pos); } curr_rec_pos= pos; - if (!(res= read_all_record_fields() == 0)) + if (!(res= read_all_record_fields() == NO_MORE_RECORDS_IN_BUFFER)) { pos+= referenced_fields*size_of_fld_ofs; if (prev_cache) @@ -1326,7 +1328,8 @@ bool JOIN_CACHE::get_match_flag_by_pos(uchar *rec_ptr) read data. RETURN - length of the data read from the join buffer + (-1) - if there is no more records in the join buffer + length of the data read from the join buffer - otherwise */ uint JOIN_CACHE::read_all_record_fields() @@ -1334,7 +1337,7 @@ uint JOIN_CACHE::read_all_record_fields() uchar *init_pos= pos; if (pos > last_rec_pos || !records) - return 0; + return NO_MORE_RECORDS_IN_BUFFER; /* First match flag, read null bitmaps and null_row flag for each table */ read_flag_fields();