Commit 0dfda658 authored by Igor Babaev's avatar Igor Babaev

Fixed LP bug #669382.

When probing into the hash table of a hashed join cache is performed
the key value should not constructed in the buffer used to build keys
in the hash tables. The constant parts of these keys copied only once,
so they should not be ever overwritten. Otherwise wrong results
can be produced by queries that employ hashed join buffers.
parent 3d8c7a2c
...@@ -5589,4 +5589,30 @@ i ...@@ -5589,4 +5589,30 @@ i
6 6
SET SESSION join_cache_level = DEFAULT; SET SESSION join_cache_level = DEFAULT;
DROP TABLE t1,t2; 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; set @@optimizer_switch=@save_optimizer_switch;
...@@ -2286,5 +2286,34 @@ SET SESSION join_cache_level = DEFAULT; ...@@ -2286,5 +2286,34 @@ SET SESSION join_cache_level = DEFAULT;
DROP TABLE t1,t2; 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 # this must be the last command in the file
set @@optimizer_switch=@save_optimizer_switch; set @@optimizer_switch=@save_optimizer_switch;
...@@ -2500,6 +2500,9 @@ int JOIN_CACHE_HASHED::init() ...@@ -2500,6 +2500,9 @@ int JOIN_CACHE_HASHED::init()
if ((rc= JOIN_CACHE::init())) if ((rc= JOIN_CACHE::init()))
DBUG_RETURN (rc); 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 */ /* Take into account a reference to the next record in the key chain */
pack_length+= get_size_of_rec_offset(); pack_length+= get_size_of_rec_offset();
pack_length_with_blob_ptrs+= 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() ...@@ -3300,9 +3303,9 @@ uchar *JOIN_CACHE_BNLH::get_matching_chain_by_join_key()
TABLE_REF *ref= &join_tab->ref; TABLE_REF *ref= &join_tab->ref;
KEY *keyinfo= table->key_info+ref->key; KEY *keyinfo= table->key_info+ref->key;
/* Build the join key value out of the record in the record buffer */ /* 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 */ /* 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 0;
return key_ref_ptr+get_size_of_key_offset(); return key_ref_ptr+get_size_of_key_offset();
} }
......
...@@ -1133,11 +1133,6 @@ class JOIN_CACHE_HASHED: public JOIN_CACHE ...@@ -1133,11 +1133,6 @@ class JOIN_CACHE_HASHED: public JOIN_CACHE
/* Size of the offset of a key entry in the hash table */ /* Size of the offset of a key entry in the hash table */
uint size_of_key_ofs; 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. Length of the key entry in the hash table.
A key entry either contains the key value, or it contains a reference A key entry either contains the key value, or it contains a reference
...@@ -1164,6 +1159,14 @@ class JOIN_CACHE_HASHED: public JOIN_CACHE ...@@ -1164,6 +1159,14 @@ class JOIN_CACHE_HASHED: public JOIN_CACHE
protected: 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) */ /* Number of key entries in the hash table (number of distinct keys) */
uint key_entries; uint key_entries;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment