diff --git a/include/my_murmur3.h b/include/my_murmur3.h index 9ef4286..ca6989c 100644 --- a/include/my_murmur3.h +++ b/include/my_murmur3.h @@ -20,7 +20,8 @@ C_MODE_START -uint32 murmur3_32(const uchar * key, size_t len, uint32 seed); +uint32 murmur3_32(const uchar * key, size_t len, uint32 seed, + bool case_sensitive= true); C_MODE_END diff --git a/mysys_ssl/my_murmur3.cc b/mysys_ssl/my_murmur3.cc index 82dccb6..8fbd415 100644 --- a/mysys_ssl/my_murmur3.cc +++ b/mysys_ssl/my_murmur3.cc @@ -19,8 +19,13 @@ domain code by Austin Appleby. */ +#include #include +#define uint4korr_tolower(A) (uint32) (((uint32) ((uchar) tolower((A)[0]))) +\ + (((uint32) ((uchar) tolower((A)[1]))) << 8) +\ + (((uint32) ((uchar) tolower((A)[2]))) << 16) +\ + (((uint32) ((uchar) tolower((A)[3]))) << 24)) /* Platform-specific implementations of ROTL32 helper. @@ -63,6 +68,7 @@ inline uint32 rotl32 (uint32 x, char r) @param key Key for which hash value to be computed. @param len Key length. @param seed Seed for hash computation. + @param case_sentitive Whether key is case sensitive @note WARNING! Since MurmurHash3 is known to be susceptible to "hash DoS" attack it should not be used in any situation where attacker has @@ -72,7 +78,8 @@ inline uint32 rotl32 (uint32 x, char r) @returns Hash value for the key. */ -uint32 murmur3_32(const uchar *key, size_t len, uint32 seed) +uint32 murmur3_32(const uchar *key, size_t len, uint32 seed, + bool case_sensitive) { const uchar *tail= key + (len - len % 4); @@ -86,7 +93,11 @@ uint32 murmur3_32(const uchar *key, size_t len, uint32 seed) for (const uchar *data= key; data != tail; data+= 4) { - uint32 k1= uint4korr(data); + uint32 k1= 0; + if (case_sensitive) + k1= uint4korr(data); + else + k1= uint4korr_tolower(data); k1*= c1; k1= ROTL32(k1, 15); @@ -104,13 +115,22 @@ uint32 murmur3_32(const uchar *key, size_t len, uint32 seed) switch(len % 4) { case 3: - k1^= static_cast(tail[2]) << 16; + if (case_sensitive) + k1^= static_cast(tail[2]) << 16; + else + k1^= static_cast(tolower(tail[2])) << 16; /* Fall through. */ case 2: - k1^= static_cast(tail[1]) << 8; + if (case_sensitive) + k1^= static_cast(tail[1]) << 8; + else + k1^= static_cast(tolower(tail[1])) << 8; /* Fall through. */ case 1: - k1^= tail[0]; + if (case_sensitive) + k1^= tail[0]; + else + k1^= tolower(tail[0]); k1*= c1; k1= ROTL32(k1, 15); k1*= c2; diff --git a/sql/table.cc b/sql/table.cc index ed531b0..05f1729 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -40,6 +40,7 @@ #include "opt_trace.h" // opt_trace_disable_if_no_security_... #include "table_cache.h" // table_cache_manager #include "sql_view.h" +#include /* INFORMATION_SCHEMA name */ LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")}; @@ -83,6 +84,13 @@ inline bool is_system_table_name(const char *name, uint length); static ulong get_form_pos(File file, uchar *head); +extern "C" my_hash_value_type murmur3_case_insensitive_adapter(const HASH*, + const uchar* key, + size_t length) +{ + return murmur3_32(key, length, 0, false); +} + /************************************************************************** Object_creation_ctx implementation. **************************************************************************/ @@ -1591,11 +1599,11 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH; if (use_hash) - use_hash= !my_hash_init(&share->name_hash, - system_charset_info, - share->fields,0,0, - (my_hash_get_key) get_field_name,0,0); - + { + use_hash= !my_hash_init3(&share->name_hash, + 0, system_charset_info, murmur3_case_insensitive_adapter, + share->fields, 0, 0, (my_hash_get_key)get_field_name, 0, 0); + } for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++) { uint pack_flag, interval_nr, unireg_type, recpos, field_length;