Fixed LP bug #694443.
One of the hash functions employed by the BNLH join algorithm calculates the the value of hash index for key value utilizing every byte of the key buffer. To make this calculation valid one has to ensure that for any key value unused bytes of the buffer are filled with with a certain filler. We choose 0 as a filler for these bytes. Added an optional boolean parameter with_zerofill to the function key_copy. If the value of the parameter is TRUE all unused bytes of the key buffer is filled with 0.
This commit is contained in:
parent
1eb21dc4be
commit
18dc64eca2
@ -6122,4 +6122,50 @@ f1 f3 f3 f2 f4
|
||||
SET SESSION join_cache_level = DEFAULT;
|
||||
SET SESSION optimizer_switch = DEFAULT;
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# Bug #694443: hash join using IS NULL the an equi-join condition
|
||||
#
|
||||
CREATE TABLE t1 (a int PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES
|
||||
(7), (4), (9), (1), (3), (8), (2);
|
||||
CREATE TABLE t2 (a int, b int, INDEX idx (a));
|
||||
INSERT INTO t2 VALUES
|
||||
(NULL,10), (4,80), (7,70), (6,11), (7,90), (NULL,40),
|
||||
(4,77), (4,50), (NULL,41), (7,99), (7,88), (8,12),
|
||||
(1,21), (4,90), (7,91), (8,22), (6,92), (NULL,42),
|
||||
(2,78), (2,51), (1,43), (5,97), (5,89);
|
||||
SET SESSION join_cache_level = 1;
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using index
|
||||
1 SIMPLE t2 ref idx idx 5 const 4 Using index condition
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
a a b
|
||||
1 NULL 10
|
||||
1 NULL 40
|
||||
1 NULL 41
|
||||
1 NULL 42
|
||||
2 NULL 10
|
||||
2 NULL 40
|
||||
2 NULL 41
|
||||
2 NULL 42
|
||||
SET SESSION join_cache_level = 4;
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using index
|
||||
1 SIMPLE t2 ref idx idx 5 const 4 Using where; Using join buffer (flat, BNLH join)
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
a a b
|
||||
1 NULL 10
|
||||
2 NULL 10
|
||||
1 NULL 40
|
||||
2 NULL 40
|
||||
1 NULL 41
|
||||
2 NULL 41
|
||||
1 NULL 42
|
||||
2 NULL 42
|
||||
SET SESSION join_cache_level = DEFAULT;
|
||||
DROP TABLE t1,t2;
|
||||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
|
@ -2759,5 +2759,36 @@ SET SESSION optimizer_switch = DEFAULT;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # Bug #694443: hash join using IS NULL the an equi-join condition
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a int PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES
|
||||
(7), (4), (9), (1), (3), (8), (2);
|
||||
|
||||
CREATE TABLE t2 (a int, b int, INDEX idx (a));
|
||||
INSERT INTO t2 VALUES
|
||||
(NULL,10), (4,80), (7,70), (6,11), (7,90), (NULL,40),
|
||||
(4,77), (4,50), (NULL,41), (7,99), (7,88), (8,12),
|
||||
(1,21), (4,90), (7,91), (8,22), (6,92), (NULL,42),
|
||||
(2,78), (2,51), (1,43), (5,97), (5,89);
|
||||
|
||||
SET SESSION join_cache_level = 1;
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
|
||||
SET SESSION join_cache_level = 4;
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
SELECT * FROM t1,t2 WHERE t1.a < 3 and t2.a IS NULL;
|
||||
|
||||
|
||||
SET SESSION join_cache_level = DEFAULT;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
|
||||
# this must be the last command in the file
|
||||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
|
@ -103,10 +103,11 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field,
|
||||
@param from_record full record to be copied from
|
||||
@param key_info descriptor of the index
|
||||
@param key_length specifies length of all keyparts that will be copied
|
||||
@param with_zerofill skipped bytes in the key buffer to be filled with 0
|
||||
*/
|
||||
|
||||
void key_copy(uchar *to_key, uchar *from_record, KEY *key_info,
|
||||
uint key_length)
|
||||
uint key_length, bool with_zerofill)
|
||||
{
|
||||
uint length;
|
||||
KEY_PART_INFO *key_part;
|
||||
@ -129,6 +130,8 @@ void key_copy(uchar *to_key, uchar *from_record, KEY *key_info,
|
||||
The -1 below is to subtract the null byte which is already handled
|
||||
*/
|
||||
length= min(key_length, (uint) key_part->store_length-1);
|
||||
if (with_zerofill)
|
||||
bzero((char*) to_key, length);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -137,7 +140,9 @@ void key_copy(uchar *to_key, uchar *from_record, KEY *key_info,
|
||||
{
|
||||
key_length-= HA_KEY_BLOB_LENGTH;
|
||||
length= min(key_length, key_part->length);
|
||||
key_part->field->get_key_image(to_key, length, Field::itRAW);
|
||||
uint bytes= key_part->field->get_key_image(to_key, length, Field::itRAW);
|
||||
if (with_zerofill && bytes < length)
|
||||
bzero((char*) to_key + bytes, length - bytes);
|
||||
to_key+= HA_KEY_BLOB_LENGTH;
|
||||
}
|
||||
else
|
||||
|
@ -1876,7 +1876,8 @@ void mysql_print_status();
|
||||
/* key.cc */
|
||||
int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field,
|
||||
uint *key_length, uint *keypart);
|
||||
void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, uint key_length);
|
||||
void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, uint key_length,
|
||||
bool with_zerofill= FALSE);
|
||||
void key_restore(uchar *to_record, uchar *from_key, KEY *key_info,
|
||||
uint key_length);
|
||||
bool key_cmp_if_same(TABLE *form,const uchar *key,uint index,uint key_length);
|
||||
|
@ -3429,7 +3429,7 @@ 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(key_buff, table->record[0], keyinfo, key_length);
|
||||
key_copy(key_buff, table->record[0], keyinfo, key_length, TRUE);
|
||||
/* Look for this key in the join buffer */
|
||||
if (!key_search(key_buff, key_length, &key_ref_ptr))
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user