diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result old mode 100755 new mode 100644 index 22ec45e6d25..f19243961b8 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -5174,3 +5174,31 @@ a b set join_cache_level=default; drop table t1,t2,t3; set @@optimizer_switch=@save_optimizer_switch; +# +# Bug #52394: using join buffer for 3 table join with ref access +# LP #623209: and no references to the columns of the middle table +# +set join_cache_level=6; +CREATE TABLE t1 (a int(11), b varchar(1)); +INSERT INTO t1 VALUES (6,'r'),(27,'o'); +CREATE TABLE t2(a int); +INSERT INTO t2 VALUES(1),(2),(3),(4),(5); +CREATE TABLE t3 (a int(11) primary key, b varchar(1)); +INSERT INTO t3 VALUES +(14,'d'),(15,'z'),(16,'e'),(17,'h'),(18,'b'),(19,'s'),(20,'e'), +(21,'j'),(22,'e'),(23,'f'),(24,'v'),(25,'x'),(26,'m'),(27,'o'); +EXPLAIN +SELECT t3.a FROM t1,t2,t3 WHERE t1.a = t3.a AND t1.b = t3.b; +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 5 Using join buffer +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where; Using join buffer +SELECT t3.a FROM t1,t2,t3 WHERE t1.a = t3.a AND t1.b = t3.b; +a +27 +27 +27 +27 +27 +DROP TABLE t1,t2,t3; +set join_cache_level=default; diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 68693fe70eb..7bc22fd4f23 100755 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -1956,3 +1956,31 @@ set join_cache_level=default; drop table t1,t2,t3; set @@optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # Bug #52394: using join buffer for 3 table join with ref access +--echo # LP #623209: and no references to the columns of the middle table +--echo # + + +set join_cache_level=6; + +CREATE TABLE t1 (a int(11), b varchar(1)); +INSERT INTO t1 VALUES (6,'r'),(27,'o'); + +CREATE TABLE t2(a int); +INSERT INTO t2 VALUES(1),(2),(3),(4),(5); + +CREATE TABLE t3 (a int(11) primary key, b varchar(1)); +INSERT INTO t3 VALUES +(14,'d'),(15,'z'),(16,'e'),(17,'h'),(18,'b'),(19,'s'),(20,'e'), +(21,'j'),(22,'e'),(23,'f'),(24,'v'),(25,'x'),(26,'m'),(27,'o'); + +EXPLAIN +SELECT t3.a FROM t1,t2,t3 WHERE t1.a = t3.a AND t1.b = t3.b; +SELECT t3.a FROM t1,t2,t3 WHERE t1.a = t3.a AND t1.b = t3.b; + +DROP TABLE t1,t2,t3; + +set join_cache_level=default; + diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index f48db588fa6..947e3b3c9f1 100755 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -3391,8 +3391,12 @@ int JOIN_TAB_SCAN_MRR::next() uint rc= join_tab->table->file->multi_range_read_next(ptr) ? -1 : 0; if (!rc) { + /* + If a record in in an incremental cache contains no fields then the + association for the last record in cache will be equal to cache->end_pos + */ DBUG_ASSERT(cache->buff <= (uchar *) (*ptr) && - (uchar *) (*ptr) < cache->end_pos); + (uchar *) (*ptr) <= cache->end_pos); update_virtual_fields(join_tab->table); } return rc; @@ -3728,12 +3732,12 @@ uint JOIN_CACHE_BKA::get_next_key(uchar ** key) uchar *init_pos; JOIN_CACHE *cache; - if (pos > last_rec_pos || !records) - return 0; - /* Any record in a BKA cache is prepended with its length */ DBUG_ASSERT(with_length); + if ((pos+size_of_rec_len) > last_rec_pos || !records) + return 0; + /* Read the length of the record */ rec_len= get_rec_length(pos); pos+= size_of_rec_len;