diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index 3c352386b8a..d04a1aaf6a2 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -5589,4 +5589,30 @@ i 6 SET SESSION join_cache_level = DEFAULT; DROP TABLE t1,t2; +# +# Bug #669382: hash join using a ref with constant key parts +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES +(9), (11), (7), (8), (4), (1), (12), (3), (5); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +CREATE TABLE t2 (a int, b int, c int, INDEX idx (a,b)); +INSERT INTO t2 VALUES +(8, 80, 800), (1, 10, 100), (1, 11, 101), (3, 30, 300), +(1, 12, 102), (8, 81, 801), (7, 70, 700), (12, 120, 1200), +(8, 82, 802), (1, 13, 103), (1, 14, 104), (3, 31, 301), +(1, 15, 105), (8, 83, 803), (7, 71, 701); +SET SESSION join_cache_level = 4; +SET SESSION join_buffer_size = 192; +EXPLAIN +SELECT t1.a, t2.c FROM t1,t2 WHERE t1.a=t2.a AND t2.b=99; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 36 Using where +1 SIMPLE t2 ref idx idx 10 test.t1.a,const 2 Using join buffer (flat, BNLH join) +SELECT t1.a, t2.c FROM t1,t2 WHERE t1.a=t2.a AND t2.b=99; +a c +SET SESSION join_cache_level = DEFAULT; +SET SESSION join_buffer_size = DEFAULT; +DROP TABLE t1,t2; set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 48a2cd1d4a8..16bd2d515ad 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -2286,5 +2286,34 @@ SET SESSION join_cache_level = DEFAULT; DROP TABLE t1,t2; +--echo # +--echo # Bug #669382: hash join using a ref with constant key parts +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES + (9), (11), (7), (8), (4), (1), (12), (3), (5); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; + +CREATE TABLE t2 (a int, b int, c int, INDEX idx (a,b)); +INSERT INTO t2 VALUES + (8, 80, 800), (1, 10, 100), (1, 11, 101), (3, 30, 300), + (1, 12, 102), (8, 81, 801), (7, 70, 700), (12, 120, 1200), + (8, 82, 802), (1, 13, 103), (1, 14, 104), (3, 31, 301), + (1, 15, 105), (8, 83, 803), (7, 71, 701); + +SET SESSION join_cache_level = 4; +SET SESSION join_buffer_size = 192; + +EXPLAIN +SELECT t1.a, t2.c FROM t1,t2 WHERE t1.a=t2.a AND t2.b=99; +SELECT t1.a, t2.c FROM t1,t2 WHERE t1.a=t2.a AND t2.b=99; + +SET SESSION join_cache_level = DEFAULT; +SET SESSION join_buffer_size = DEFAULT; + +DROP TABLE t1,t2; + # 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 3586426419d..6dce5884c9a 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -2500,6 +2500,9 @@ int JOIN_CACHE_HASHED::init() if ((rc= JOIN_CACHE::init())) DBUG_RETURN (rc); + if (!(key_buff= (uchar*) sql_alloc(key_length))) + DBUG_RETURN(1); + /* Take into account a reference to the next record in the key chain */ pack_length+= get_size_of_rec_offset(); pack_length_with_blob_ptrs+= get_size_of_rec_offset(); @@ -3300,9 +3303,9 @@ uchar *JOIN_CACHE_BNLH::get_matching_chain_by_join_key() TABLE_REF *ref= &join_tab->ref; KEY *keyinfo= table->key_info+ref->key; /* Build the join key value out of the record in the record buffer */ - key_copy(ref->key_buff, table->record[0], keyinfo, ref->key_length); + key_copy(key_buff, table->record[0], keyinfo, key_length); /* Look for this key in the join buffer */ - if (!key_search(ref->key_buff, ref->key_length, &key_ref_ptr)) + if (!key_search(key_buff, key_length, &key_ref_ptr)) return 0; return key_ref_ptr+get_size_of_key_offset(); } diff --git a/sql/sql_select.h b/sql/sql_select.h index 74b93c1d37c..10122b02e04 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1133,11 +1133,6 @@ private: /* Size of the offset of a key entry in the hash table */ uint size_of_key_ofs; - /* - Length of a key value. - It is assumed that all key values have the same length. - */ - uint key_length; /* Length of the key entry in the hash table. A key entry either contains the key value, or it contains a reference @@ -1164,6 +1159,14 @@ private: protected: + /* + Length of a key value. + It is assumed that all key values have the same length. + */ + uint key_length; + /* Buffer to store key values for probing */ + uchar *key_buff; + /* Number of key entries in the hash table (number of distinct keys) */ uint key_entries;