diff options
-rw-r--r-- | client/mysqltest.cc | 12 | ||||
-rw-r--r-- | mysql-test/r/ctype_partitions.result | 51 | ||||
-rw-r--r-- | mysql-test/suite/multi_source/gtid.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/multi_source/gtid.test | 2 | ||||
-rw-r--r-- | mysql-test/suite/multi_source/gtid_ignore_duplicates.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/multi_source/gtid_ignore_duplicates.test | 4 | ||||
-rw-r--r-- | mysql-test/suite/multi_source/load_data.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/multi_source/load_data.test | 1 | ||||
-rw-r--r-- | mysql-test/t/ctype_partitions.test | 29 | ||||
-rw-r--r-- | storage/heap/hp_write.c | 3 | ||||
-rw-r--r-- | storage/maria/ma_check.c | 2 | ||||
-rw-r--r-- | strings/ctype-bin.c | 8 | ||||
-rw-r--r-- | strings/ctype-latin1.c | 10 | ||||
-rw-r--r-- | strings/ctype-mb.c | 8 | ||||
-rw-r--r-- | strings/ctype-simple.c | 46 | ||||
-rw-r--r-- | strings/ctype-uca.c | 38 | ||||
-rw-r--r-- | strings/ctype-ucs2.c | 56 | ||||
-rw-r--r-- | strings/ctype-utf8.c | 28 | ||||
-rw-r--r-- | strings/strings_def.h | 16 |
19 files changed, 237 insertions, 83 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 41f1d074dd9..80bb24765a7 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -7719,6 +7719,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) { uint count; MYSQL_RES *warn_res; + DYNAMIC_STRING res; DBUG_ENTER("append_warnings"); if (!(count= mysql_warning_count(mysql))) @@ -7738,11 +7739,18 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) die("Warning count is %u but didn't get any warnings", count); - append_result(ds, warn_res); + init_dynamic_string(&res, "", 1024, 1024); + + append_result(&res, warn_res); mysql_free_result(warn_res); - DBUG_PRINT("warnings", ("%s", ds->str)); + DBUG_PRINT("warnings", ("%s", res.str)); + if (display_result_sorted) + dynstr_append_sorted(ds, &res, 0); + else + dynstr_append_mem(ds, res.str, res.length); + dynstr_free(&res); DBUG_RETURN(count); } diff --git a/mysql-test/r/ctype_partitions.result b/mysql-test/r/ctype_partitions.result new file mode 100644 index 00000000000..a39ecc11529 --- /dev/null +++ b/mysql-test/r/ctype_partitions.result @@ -0,0 +1,51 @@ +# +# MDEV-6255 DUPLICATE KEY Errors on SELECT .. GROUP BY that uses temporary and filesort +# +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1251 COLLATE cp1251_ukrainian_ci); +INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060); +SELECT HEX(a) FROM t1 WHERE a=0x60; +HEX(a) +20 +60 +6060 +606060 +ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3; +SELECT HEX(a) FROM t1 WHERE a=0x60; +HEX(a) +20 +60 +6060 +606060 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET koi8u COLLATE koi8u_general_ci); +INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060); +SELECT HEX(a) FROM t1 WHERE a=0x60; +HEX(a) +20 +60 +6060 +606060 +ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3; +SELECT HEX(a) FROM t1 WHERE a=0x60; +HEX(a) +20 +60 +6060 +606060 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1250 COLLATE cp1250_general_ci); +INSERT INTO t1 VALUES (0x20),(0xA0),(0xA0A0),(0xA0A0A0); +SELECT HEX(a) FROM t1 WHERE a=0xA0; +HEX(a) +20 +A0 +A0A0 +A0A0A0 +ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3; +SELECT HEX(a) FROM t1 WHERE a=0xA0; +HEX(a) +20 +A0 +A0A0 +A0A0A0 +DROP TABLE t1; diff --git a/mysql-test/suite/multi_source/gtid.result b/mysql-test/suite/multi_source/gtid.result index 8e6028afa17..ce926ddc995 100644 --- a/mysql-test/suite/multi_source/gtid.result +++ b/mysql-test/suite/multi_source/gtid.result @@ -141,8 +141,8 @@ include/reset_master_slave.inc SET GLOBAL gtid_domain_id=0; STOP ALL SLAVES; Warnings: -Note 1938 SLAVE 'slave2' stopped Note 1938 SLAVE 'slave1' stopped +Note 1938 SLAVE 'slave2' stopped include/reset_master_slave.inc SET GLOBAL gtid_domain_id=0; include/reset_master_slave.inc diff --git a/mysql-test/suite/multi_source/gtid.test b/mysql-test/suite/multi_source/gtid.test index 0ab486b1f41..7a085823693 100644 --- a/mysql-test/suite/multi_source/gtid.test +++ b/mysql-test/suite/multi_source/gtid.test @@ -141,12 +141,14 @@ DROP TABLE t3; SET GLOBAL gtid_domain_id=0; --let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.tables WHERE table_name IN ("t1", "t2", "t3") AND table_schema = "test" --source include/wait_condition.inc +--sorted_result STOP ALL SLAVES; --source reset_master_slave.inc --disconnect slave1 --connection slave2 SET GLOBAL gtid_domain_id=0; +--sorted_result STOP ALL SLAVES; --source reset_master_slave.inc --disconnect slave2 diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result index 9bd09330ae7..5426091b635 100644 --- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result +++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result @@ -245,8 +245,8 @@ a SET GLOBAL gtid_domain_id=0; STOP ALL SLAVES; Warnings: -Note 1938 SLAVE 'c2a' stopped Note 1938 SLAVE 'b2a' stopped +Note 1938 SLAVE 'c2a' stopped SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; SET GLOBAL gtid_domain_id=0; diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test index 3e98d7c76cb..cf1c750fc19 100644 --- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test +++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test @@ -261,24 +261,28 @@ SELECT * FROM t1 WHERE a >= 20 ORDER BY a; # Clean up. --connection server_1 SET GLOBAL gtid_domain_id=0; +--sorted_result STOP ALL SLAVES; SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; --connection server_2 SET GLOBAL gtid_domain_id=0; +--sorted_result STOP ALL SLAVES; SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; --connection server_3 SET GLOBAL gtid_domain_id=0; +--sorted_result STOP ALL SLAVES; SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; --connection server_4 SET GLOBAL gtid_domain_id=0; +--sorted_result STOP ALL SLAVES; SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; diff --git a/mysql-test/suite/multi_source/load_data.result b/mysql-test/suite/multi_source/load_data.result index ef55abc5321..3a04156ce6a 100644 --- a/mysql-test/suite/multi_source/load_data.result +++ b/mysql-test/suite/multi_source/load_data.result @@ -23,8 +23,8 @@ drop table t1; drop table t2; stop all slaves; Warnings: -Note 1938 SLAVE 'master2' stopped Note 1938 SLAVE '' stopped +Note 1938 SLAVE 'master2' stopped include/reset_master_slave.inc include/reset_master_slave.inc include/reset_master_slave.inc diff --git a/mysql-test/suite/multi_source/load_data.test b/mysql-test/suite/multi_source/load_data.test index e6e1399cbf3..ca2391a9c8d 100644 --- a/mysql-test/suite/multi_source/load_data.test +++ b/mysql-test/suite/multi_source/load_data.test @@ -58,6 +58,7 @@ drop table t2; --sync_with_master 0,'master2' --connection slave +--sorted_result stop all slaves; --source reset_master_slave.inc diff --git a/mysql-test/t/ctype_partitions.test b/mysql-test/t/ctype_partitions.test new file mode 100644 index 00000000000..f80a2c98a1b --- /dev/null +++ b/mysql-test/t/ctype_partitions.test @@ -0,0 +1,29 @@ +--source include/have_partition.inc + +--echo # +--echo # MDEV-6255 DUPLICATE KEY Errors on SELECT .. GROUP BY that uses temporary and filesort +--echo # + +# cp1251_ukrainian_ci: 0x20 SPACE is equal to 0x60 GRAVE ACCENT +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1251 COLLATE cp1251_ukrainian_ci); +INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060); +SELECT HEX(a) FROM t1 WHERE a=0x60; +ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3; +SELECT HEX(a) FROM t1 WHERE a=0x60; +DROP TABLE t1; + +# koi8u_general_ci: 0x20 SPACE is equal to 0x60 GRAVE ACCENT +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET koi8u COLLATE koi8u_general_ci); +INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060); +SELECT HEX(a) FROM t1 WHERE a=0x60; +ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3; +SELECT HEX(a) FROM t1 WHERE a=0x60; +DROP TABLE t1; + +# cp1250_general_ci: 0x20 SPACE is equal to 0xA0 NO-BREAK SPACE +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1250 COLLATE cp1250_general_ci); +INSERT INTO t1 VALUES (0x20),(0xA0),(0xA0A0),(0xA0A0A0); +SELECT HEX(a) FROM t1 WHERE a=0xA0; +ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3; +SELECT HEX(a) FROM t1 WHERE a=0xA0; +DROP TABLE t1; diff --git a/storage/heap/hp_write.c b/storage/heap/hp_write.c index 6b96e1c31a3..c6205508a90 100644 --- a/storage/heap/hp_write.c +++ b/storage/heap/hp_write.c @@ -385,7 +385,8 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, pos=empty; do { - if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1)) + if (pos->hash_of_key == hash_of_key && + ! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1)) { DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY); } diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 4ac267ffb8a..0a89babb205 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -5515,6 +5515,8 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a) } if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0) { + DBUG_EXECUTE("key", _ma_print_keydata(DBUG_FILE, sort_param->seg, a, + USE_WHOLE_KEY);); sort_info->dupp++; sort_info->info->cur_row.lastpos= get_record_for_key(sort_param->keyinfo, a); diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 4beb7047d00..3ca4ba2b430 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -288,9 +288,7 @@ void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)), for (; key < end ; key++) { - tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) * - ((uint) *key)) + (tmp1 << 8); - tmp2+= 3; + MY_HASH_ADD(tmp1, tmp2, (uint) *key); } *nr1= tmp1; @@ -307,9 +305,7 @@ void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)), for (; key < end ; key++) { - tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) * - ((uint) *key)) + (tmp1 << 8); - tmp2+= 3; + MY_HASH_ADD(tmp1, tmp2, (uint) *key); } *nr1= tmp1; diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 2c84f86fad0..babf74599ea 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -691,6 +691,8 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)), ulong *nr1, ulong *nr2) { const uchar *end; + register ulong m1= *nr1, m2= *nr2; + /* Remove end space. We have to do this to be able to compare 'AE' and 'Ä' as identical @@ -700,14 +702,14 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)), for (; key < end ; key++) { uint X= (uint) combo1map[(uint) *key]; - nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * X) + (nr1[0] << 8); - nr2[0]+=3; + MY_HASH_ADD(m1, m2, X); if ((X= combo2map[*key])) { - nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * X) + (nr1[0] << 8); - nr2[0]+=3; + MY_HASH_ADD(m1, m2, X); } } + *nr1= m1; + *nr2= m2; } diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index f4e70fd1dd5..1ef772e1d5e 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -680,6 +680,8 @@ void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), const uchar *key, size_t len,ulong *nr1, ulong *nr2) { + register ulong m1= *nr1, m2= *nr2; + /* Remove trailing spaces. We have to do this to be able to compare 'A ' and 'A' as identical @@ -688,10 +690,10 @@ my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), for (; key < end ; key++) { - nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * - ((uint)*key)) + (nr1[0] << 8); - nr2[0]+=3; + MY_HASH_ADD(m1, m2, (uint)*key); } + *nr1= m1; + *nr2= m2; } diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index f5484965314..0785ba35700 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -306,24 +306,48 @@ void my_hash_sort_simple(CHARSET_INFO *cs, { register const uchar *sort_order=cs->sort_order; const uchar *end; - ulong n1, n2; + register ulong m1= *nr1, m2= *nr2; + uint16 space_weight= sort_order[' ']; /* - Remove end space. We have to do this to be able to compare - 'A ' and 'A' as identical + Remove all trailing characters that are equal to space. + We have to do this to be able to compare 'A ' and 'A' as identical. + + If the key is long enough, cut the trailing spaces (0x20) using an + optimized function implemented in skip_trailing_spaces(). + + "len > 16" is just some heuristic here. + Calling skip_triling_space() for short values is not desirable, + because its initialization block may be more expensive than the + performance gained. + */ + + end= len > 16 ? skip_trailing_space(key, len) : key + len; + + /* + We removed all trailing characters that are binary equal to space 0x20. + Now remove all trailing characters that have weights equal to space. + Some 8bit simple collations may have such characters: + - cp1250_general_ci 0xA0 NO-BREAK SPACE == 0x20 SPACE + - cp1251_ukrainian_ci 0x60 GRAVE ACCENT == 0x20 SPACE + - koi8u_general_ci 0x60 GRAVE ACCENT == 0x20 SPACE */ - end= skip_trailing_space(key, len); - n1= *nr1; - n2= *nr2; + for ( ; key < end ; ) + { + if (sort_order[*--end] != space_weight) + { + end++; + break; + } + } + for (; key < (uchar*) end ; key++) { - n1^=(ulong) ((((uint) n1 & 63)+n2) * - ((uint) sort_order[(uint) *key])) + (n1 << 8); - n2+=3; + MY_HASH_ADD(m1, m2, (uint) sort_order[(uint) *key]); } - *nr1= n1; - *nr2= n2; + *nr1= m1; + *nr2= m2; } diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 5165a43e852..19ce17c3856 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -20873,21 +20873,45 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs, static void my_hash_sort_uca(CHARSET_INFO *cs, my_uca_scanner_handler *scanner_handler, const uchar *s, size_t slen, - ulong *n1, ulong *n2) + ulong *nr1, ulong *nr2) { int s_res; my_uca_scanner scanner; - - slen= cs->cset->lengthsp(cs, (char*) s, slen); + int space_weight= my_space_weight(cs); + register ulong m1= *nr1, m2= *nr2; + scanner_handler->init(&scanner, cs, &cs->uca->level[0], s, slen); while ((s_res= scanner_handler->next(&scanner)) >0) { - n1[0]^= (((n1[0] & 63)+n2[0])*(s_res >> 8))+ (n1[0] << 8); - n2[0]+=3; - n1[0]^= (((n1[0] & 63)+n2[0])*(s_res & 0xFF))+ (n1[0] << 8); - n2[0]+=3; + if (s_res == space_weight) + { + /* Combine all spaces to be able to skip end spaces */ + uint count= 0; + do + { + count++; + if ((s_res= scanner_handler->next(&scanner)) <= 0) + { + /* Skip strings at end of string */ + goto end; + } + } + while (s_res == space_weight); + + /* Add back that has for the space characters */ + do + { + MY_HASH_ADD_16(m1, m2, space_weight); + } + while (--count != 0); + + } + MY_HASH_ADD_16(m1, m2, s_res); } +end: + *nr1= m1; + *nr2= m2; } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index d2f7d34f0aa..593f9a12950 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1222,23 +1222,23 @@ my_caseup_utf16(CHARSET_INFO *cs, char *src, size_t srclen, static void my_hash_sort_utf16(CHARSET_INFO *cs, const uchar *s, size_t slen, - ulong *n1, ulong *n2) + ulong *nr1, ulong *nr2) { my_wc_t wc; my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc; int res; const uchar *e= s + cs->cset->lengthsp(cs, (const char *) s, slen); MY_UNICASE_INFO *uni_plane= cs->caseinfo; + register ulong m1= *nr1, m2= *nr2; while ((s < e) && (res= mb_wc(cs, &wc, (uchar *) s, (uchar *) e)) > 0) { my_tosort_utf16(uni_plane, &wc); - n1[0]^= (((n1[0] & 63) + n2[0]) * (wc & 0xFF)) + (n1[0] << 8); - n2[0]+= 3; - n1[0]^= (((n1[0] & 63) + n2[0]) * (wc >> 8)) + (n1[0] << 8); - n2[0]+= 3; + MY_HASH_ADD_16(m1, m2, wc); s+= res; } + *nr1= m1; + *nr2= m2; } @@ -1611,12 +1611,14 @@ my_hash_sort_utf16_bin(CHARSET_INFO *cs, const uchar *pos, size_t len, ulong *nr1, ulong *nr2) { const uchar *end= pos + cs->cset->lengthsp(cs, (const char *) pos, len); + register ulong m1= *nr1, m2= *nr2; + for ( ; pos < end ; pos++) { - nr1[0]^= (ulong) ((((uint) nr1[0] & 63) + nr2[0]) * - ((uint)*pos)) + (nr1[0] << 8); - nr2[0]+= 3; + MY_HASH_ADD(m1, m2, (uint)*pos); } + *nr1= m1; + *nr2= m2; } @@ -2007,22 +2009,15 @@ my_caseup_utf32(CHARSET_INFO *cs, char *src, size_t srclen, } -static inline void -my_hash_add(ulong *n1, ulong *n2, uint ch) -{ - n1[0]^= (((n1[0] & 63) + n2[0]) * (ch)) + (n1[0] << 8); - n2[0]+= 3; -} - - static void my_hash_sort_utf32(CHARSET_INFO *cs, const uchar *s, size_t slen, - ulong *n1, ulong *n2) + ulong *nr1, ulong *nr2) { my_wc_t wc; int res; const uchar *e= s + slen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; + register ulong m1= *nr1, m2= *nr2; /* Skip trailing spaces */ while (e > s + 3 && e[-1] == ' ' && !e[-2] && !e[-3] && !e[-4]) @@ -2031,12 +2026,14 @@ my_hash_sort_utf32(CHARSET_INFO *cs, const uchar *s, size_t slen, while ((res= my_utf32_uni(cs, &wc, (uchar*) s, (uchar*) e)) > 0) { my_tosort_utf32(uni_plane, &wc); - my_hash_add(n1, n2, (uint) (wc >> 24)); - my_hash_add(n1, n2, (uint) (wc >> 16) & 0xFF); - my_hash_add(n1, n2, (uint) (wc >> 8) & 0xFF); - my_hash_add(n1, n2, (uint) (wc & 0xFF)); + MY_HASH_ADD(m1, m2, (uint) (wc >> 24)); + MY_HASH_ADD(m1, m2, (uint) (wc >> 16) & 0xFF); + MY_HASH_ADD(m1, m2, (uint) (wc >> 8) & 0xFF); + MY_HASH_ADD(m1, m2, (uint) (wc & 0xFF)); s+= res; } + *nr1= m1; + *nr2= m2; } @@ -2976,12 +2973,13 @@ static size_t my_caseup_ucs2(CHARSET_INFO *cs, char *src, size_t srclen, static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, size_t slen, - ulong *n1, ulong *n2) + ulong *nr1, ulong *nr2) { my_wc_t wc; int res; const uchar *e=s+slen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; + register ulong m1= *nr1, m2= *nr2; while (e > s+1 && e[-1] == ' ' && e[-2] == '\0') e-= 2; @@ -2989,12 +2987,11 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, size_t slen, while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e)) >0) { my_tosort_ucs2(uni_plane, &wc); - n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8); - n2[0]+=3; - n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8); - n2[0]+=3; + MY_HASH_ADD_16(m1, m2, wc); s+=res; } + *nr1= m1; + *nr2= m2; } @@ -3312,16 +3309,17 @@ void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), const uchar *key, size_t len,ulong *nr1, ulong *nr2) { const uchar *end = key + len; + register ulong m1= *nr1, m2= *nr2; while (end > key+1 && end[-1] == ' ' && end[-2] == '\0') end-= 2; for (; key < (uchar*) end ; key++) { - nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * - ((uint)*key)) + (nr1[0] << 8); - nr2[0]+=3; + MY_HASH_ADD(m1, m2, (uint)*key); } + *nr1= m1; + *nr2= m2; } diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 96d5ea26a3c..d0a64d11c84 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -5087,12 +5087,13 @@ static size_t my_caseup_utf8(CHARSET_INFO *cs, char *src, size_t srclen, static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, size_t slen, - ulong *n1, ulong *n2) + ulong *nr1, ulong *nr2) { my_wc_t wc; int res; const uchar *e=s+slen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; + register ulong m1= *nr1, m2= *nr2; /* Remove end space. We have to do this to be able to compare @@ -5104,12 +5105,11 @@ static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, size_t slen, while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 ) { my_tosort_unicode(uni_plane, &wc, cs->state); - n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8); - n2[0]+=3; - n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8); - n2[0]+=3; + MY_HASH_ADD_16(m1, m2, wc); s+=res; } + *nr1= m1; + *nr2= m2; } @@ -7597,22 +7597,15 @@ my_caseup_utf8mb4(CHARSET_INFO *cs, char *src, size_t srclen, } -static inline void -my_hash_add(ulong *n1, ulong *n2, uint ch) -{ - n1[0]^= (((n1[0] & 63) + n2[0]) * (ch)) + (n1[0] << 8); - n2[0]+= 3; -} - - static void my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen, - ulong *n1, ulong *n2) + ulong *nr1, ulong *nr2) { my_wc_t wc; int res; const uchar *e= s + slen; MY_UNICASE_INFO *uni_plane= cs->caseinfo; + register ulong m1= *nr1, m2= *nr2; /* Remove end space. We do this to be able to compare @@ -7624,8 +7617,7 @@ my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen, while ((res= my_mb_wc_utf8mb4(cs, &wc, (uchar*) s, (uchar*) e)) > 0) { my_tosort_unicode(uni_plane, &wc, cs->state); - my_hash_add(n1, n2, (uint) (wc & 0xFF)); - my_hash_add(n1, n2, (uint) (wc >> 8) & 0xFF); + MY_HASH_ADD_16(m1, m2, (uint) (wc & 0xFFFF)); if (wc > 0xFFFF) { /* @@ -7635,10 +7627,12 @@ my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen, This is useful to keep order of records in test results, e.g. for "SHOW GRANTS". */ - my_hash_add(n1, n2, (uint) (wc >> 16) & 0xFF); + MY_HASH_ADD(m1, m2, (uint) ((wc >> 16) & 0xFF)); } s+= res; } + *nr1= m1; + *nr2= m2; } diff --git a/strings/strings_def.h b/strings/strings_def.h index 6bd8e8f5575..d601f5ca697 100644 --- a/strings/strings_def.h +++ b/strings/strings_def.h @@ -100,4 +100,20 @@ static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len) end--; return (end); } + +/* Macros for hashing characters */ + +#define MY_HASH_ADD(A, B, value) \ + do { A^= (((A & 63)+B)*((value)))+ (A << 8); B+=3; } while(0) + +#define MY_HASH_ADD_16(A, B, value) \ + do { MY_HASH_ADD(A, B, ((value) & 0xFF)) ; MY_HASH_ADD(A, B, ((value >>8 ))); } while(0) + +/* + This one is needed to ensure we get the exact same hash as MariaDB 5.1 + This is needed to ensure that old partitioned tables still work as before. +*/ +#define MY_HASH_ADD_16_INV(A, B, value) \ + do { MY_HASH_ADD(A, B, ((value >> 8))) ; MY_HASH_ADD(A, B, ((value & 0xFF ))); } while(0) + #endif |