mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Fixed LP bug #670380.
Lifted the limitation that hash join could not be used over varchar fields with non-binary collation.
This commit is contained in:
@@ -2520,6 +2520,24 @@ int JOIN_CACHE_HASHED::init()
|
||||
pack_length+= get_size_of_rec_offset();
|
||||
pack_length_with_blob_ptrs+= get_size_of_rec_offset();
|
||||
|
||||
ref_key_info= join_tab->table->key_info+join_tab->ref.key;
|
||||
ref_used_key_parts= join_tab->ref.key_parts;
|
||||
|
||||
hash_func= &JOIN_CACHE_HASHED::get_hash_idx_simple;
|
||||
hash_cmp_func= &JOIN_CACHE_HASHED::equal_keys_simple;
|
||||
|
||||
KEY_PART_INFO *key_part= ref_key_info->key_part;
|
||||
KEY_PART_INFO *key_part_end= key_part+ref_used_key_parts;
|
||||
for ( ; key_part < key_part_end; key_part++)
|
||||
{
|
||||
if (!key_part->field->eq_cmp_as_binary())
|
||||
{
|
||||
hash_func= &JOIN_CACHE_HASHED::get_hash_idx_complex;
|
||||
hash_cmp_func= &JOIN_CACHE_HASHED::equal_keys_complex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
init_hash_table();
|
||||
|
||||
rec_fields_offset= get_size_of_rec_offset()+get_size_of_rec_length()+
|
||||
@@ -2903,7 +2921,7 @@ bool JOIN_CACHE_HASHED::key_search(uchar *key, uint key_len,
|
||||
uchar **key_ref_ptr)
|
||||
{
|
||||
bool is_found= FALSE;
|
||||
uint idx= get_hash_idx(key, key_length);
|
||||
uint idx= (this->*hash_func)(key, key_length);
|
||||
uchar *ref_ptr= hash_table+size_of_key_ofs*idx;
|
||||
while (!is_null_key_ref(ref_ptr))
|
||||
{
|
||||
@@ -2912,7 +2930,7 @@ bool JOIN_CACHE_HASHED::key_search(uchar *key, uint key_len,
|
||||
next_key= use_emb_key ? get_emb_key(ref_ptr-get_size_of_rec_offset()) :
|
||||
ref_ptr-key_length;
|
||||
|
||||
if (memcmp(next_key, key, key_len) == 0)
|
||||
if ((this->*hash_cmp_func)(next_key, key, key_len))
|
||||
{
|
||||
is_found= TRUE;
|
||||
break;
|
||||
@@ -2924,22 +2942,24 @@ bool JOIN_CACHE_HASHED::key_search(uchar *key, uint key_len,
|
||||
|
||||
|
||||
/*
|
||||
Calclulate hash value for a key in the hash table of the join buffer
|
||||
Hash function that considers a key in the hash table as byte array
|
||||
|
||||
SYNOPSIS
|
||||
get_hash_idx()
|
||||
get_hash_idx_simple()
|
||||
key pointer to the key value
|
||||
key_len key value length
|
||||
|
||||
DESCRIPTION
|
||||
The function calculates an index of the hash entry in the hash table
|
||||
of the join buffer for the given key
|
||||
of the join buffer for the given key. It considers the key just as
|
||||
a sequence of bytes of the length key_len.
|
||||
|
||||
RETURN VALUE
|
||||
the calculated index of the hash entry for the given key.
|
||||
the calculated index of the hash entry for the given key
|
||||
*/
|
||||
|
||||
uint JOIN_CACHE_HASHED::get_hash_idx(uchar* key, uint key_len)
|
||||
inline
|
||||
uint JOIN_CACHE_HASHED::get_hash_idx_simple(uchar* key, uint key_len)
|
||||
{
|
||||
ulong nr= 1;
|
||||
ulong nr2= 4;
|
||||
@@ -2954,6 +2974,93 @@ uint JOIN_CACHE_HASHED::get_hash_idx(uchar* key, uint key_len)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Hash function that takes into account collations of the components of the key
|
||||
|
||||
SYNOPSIS
|
||||
get_hash_idx_complex()
|
||||
key pointer to the key value
|
||||
key_len key value length
|
||||
|
||||
DESCRIPTION
|
||||
The function calculates an index of the hash entry in the hash table
|
||||
of the join buffer for the given key. It takes into account that the
|
||||
components of the key may be of a varchar type with different collations.
|
||||
The function guarantees that the same hash value for any two equal
|
||||
keys that may differ as byte sequences.
|
||||
The function takes the info about the components of the key, their
|
||||
types and used collations from the class member ref_key_info containing
|
||||
a pointer to the descriptor of the index that can be used for the join
|
||||
operation.
|
||||
|
||||
RETURN VALUE
|
||||
the calculated index of the hash entry for the given key
|
||||
*/
|
||||
|
||||
inline
|
||||
uint JOIN_CACHE_HASHED::get_hash_idx_complex(uchar *key, uint key_len)
|
||||
{
|
||||
return
|
||||
(uint) (key_hashnr(ref_key_info, ref_used_key_parts, key) % hash_entries);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Compare two key entries in the hash table as sequence of bytes
|
||||
|
||||
SYNOPSIS
|
||||
equal_keys_simple()
|
||||
key1 pointer to the first key entry
|
||||
key2 pointer to the second key entry
|
||||
key_len the length of the key values
|
||||
|
||||
DESCRIPTION
|
||||
The function compares two key entries in the hash table key1 and key2
|
||||
as two sequences bytes of the length key_len
|
||||
|
||||
RETURN VALUE
|
||||
TRUE key1 coincides with key2
|
||||
FALSE otherwise
|
||||
*/
|
||||
|
||||
inline
|
||||
bool JOIN_CACHE_HASHED::equal_keys_simple(uchar *key1, uchar *key2,
|
||||
uint key_len)
|
||||
{
|
||||
return memcmp(key1, key2, key_len) == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Compare two key entries taking into account the used collation
|
||||
|
||||
SYNOPSIS
|
||||
equal_keys_complex()
|
||||
key1 pointer to the first key entry
|
||||
key2 pointer to the second key entry
|
||||
key_len the length of the key values
|
||||
|
||||
DESCRIPTION
|
||||
The function checks whether two key entries in the hash table
|
||||
key1 and key2 are equal as, possibly, compound keys of a certain
|
||||
structure whose components may be of a varchar type and may
|
||||
employ different collations.
|
||||
The descriptor of the key structure is taken from the class
|
||||
member ref_key_info.
|
||||
|
||||
RETURN VALUE
|
||||
TRUE key1 is equal tokey2
|
||||
FALSE otherwise
|
||||
*/
|
||||
|
||||
inline
|
||||
bool JOIN_CACHE_HASHED::equal_keys_complex(uchar *key1, uchar *key2,
|
||||
uint key_len)
|
||||
{
|
||||
return key_buf_cmp(ref_key_info, ref_used_key_parts, key1, key2) == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Clean up the hash table of the join buffer
|
||||
|
||||
|
Reference in New Issue
Block a user