diff options
author | Alexander Barkov <bar@mariadb.com> | 2021-04-27 14:58:52 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2021-04-27 14:59:36 +0400 |
commit | 9b0df8eee7b8298fead770da083ab9916e0267ec (patch) | |
tree | d7098d301613a55e59f63f6be4b7c9f278b20658 | |
parent | 23e090626a9138f44905a5a8e681e8952f98aac7 (diff) | |
download | mariadb-git-bb-10.3-bar-MDEV-25449.tar.gz |
MDEV-25449 Add MY_COLLATION_HANDLER::strnncollsp_nchars()bb-10.3-bar-MDEV-25449
-rw-r--r-- | include/m_ctype.h | 26 | ||||
-rw-r--r-- | sql/field.cc | 47 | ||||
-rw-r--r-- | strings/ctype-big5.c | 4 | ||||
-rw-r--r-- | strings/ctype-bin.c | 36 | ||||
-rw-r--r-- | strings/ctype-cp932.c | 4 | ||||
-rw-r--r-- | strings/ctype-czech.c | 1 | ||||
-rw-r--r-- | strings/ctype-euc_kr.c | 4 | ||||
-rw-r--r-- | strings/ctype-eucjpms.c | 4 | ||||
-rw-r--r-- | strings/ctype-gb2312.c | 4 | ||||
-rw-r--r-- | strings/ctype-gbk.c | 4 | ||||
-rw-r--r-- | strings/ctype-latin1.c | 1 | ||||
-rw-r--r-- | strings/ctype-simple.c | 14 | ||||
-rw-r--r-- | strings/ctype-sjis.c | 4 | ||||
-rw-r--r-- | strings/ctype-tis620.c | 2 | ||||
-rw-r--r-- | strings/ctype-uca.c | 8 | ||||
-rw-r--r-- | strings/ctype-ucs2.c | 16 | ||||
-rw-r--r-- | strings/ctype-ujis.c | 4 | ||||
-rw-r--r-- | strings/ctype-utf8.c | 11 | ||||
-rw-r--r-- | strings/ctype-win1250ch.c | 1 | ||||
-rw-r--r-- | strings/ctype.c | 27 | ||||
-rw-r--r-- | strings/strcoll.ic | 113 | ||||
-rw-r--r-- | strings/strings_def.h | 10 |
22 files changed, 312 insertions, 33 deletions
diff --git a/include/m_ctype.h b/include/m_ctype.h index 1cdff1f54cc..82243855dd1 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -330,6 +330,32 @@ struct my_collation_handler_st const uchar *, size_t, const uchar *, size_t, my_bool); int (*strnncollsp)(CHARSET_INFO *, const uchar *, size_t, const uchar *, size_t); + /* + strncollsp_nchars() - similar to strnncollsp() but compares not more + than nchars characters only. + This function is usually used to compare CHAR(N) values stored in records. + These record values are padded with trailing spaces up to the maximum + possible octet length. For example, a column of the data type + `CHAR(3) CHARACTER SET utf8mb4` + reserves 12 octets. If we store ASCII 'abc', the record we'll contain + 'abc' followed by 9 space characters. Trailing spaces are just fillers here, + they are not actual data! To compare such buffers with CHAR(3) values, + we cannot use strncollsp(a,12,b,12) - it may return a wrong result in case + of a NOPAD collation of a multi-byte character set. + In such scenarios we should use strnncollsp_nchars(a,12,b,12,3). + + Note, this function counts contraction parts as individual characters. + For example, the Czech letter 'ch' (in Czech collations) + is ordinary counted by "nchars" as TWO characters (not as one). + Also, we presume that the "nchars" limit will ignore only + trailing filler space characters (not important data). So the limit + will never tear apart contractions like 'ch' in the way that + 'c' takes part in comparison while 'h' is ignored. + */ + int (*strnncollsp_nchars)(CHARSET_INFO *, + const uchar *str1, size_t len1, + const uchar *str2, size_t len2, + size_t nchars); size_t (*strnxfrm)(CHARSET_INFO *, uchar *dst, size_t dstlen, uint nweights, const uchar *src, size_t srclen, uint flags); diff --git a/sql/field.cc b/sql/field.cc index 76d9a3ccf95..4bbbc740b39 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7304,23 +7304,10 @@ Field_string::compatible_field_size(uint field_metadata, int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) { - size_t a_len, b_len; - - if (field_charset->mbmaxlen != 1) - { - size_t char_len= field_length/field_charset->mbmaxlen; - a_len= my_charpos(field_charset, a_ptr, a_ptr + field_length, char_len); - b_len= my_charpos(field_charset, b_ptr, b_ptr + field_length, char_len); - } - else - a_len= b_len= field_length; - /* - We have to remove end space to be able to compare multi-byte-characters - like in latin_de 'ae' and 0xe4 - */ - return field_charset->coll->strnncollsp(field_charset, - a_ptr, a_len, - b_ptr, b_len); + return field_charset->coll->strnncollsp_nchars(field_charset, + a_ptr, field_length, + b_ptr, field_length, + Field_string::char_length()); } @@ -7718,19 +7705,6 @@ int Field_varstring::cmp(const uchar *a_ptr, const uchar *b_ptr) } -static int cmp_str_prefix(const uchar *ua, size_t alen, const uchar *ub, - size_t blen, size_t prefix, CHARSET_INFO *cs) -{ - const char *a= (char*)ua, *b= (char*)ub; - MY_STRCOPY_STATUS status; - prefix/= cs->mbmaxlen; - alen= cs->cset->well_formed_char_length(cs, a, a + alen, prefix, &status); - blen= cs->cset->well_formed_char_length(cs, b, b + blen, prefix, &status); - return cs->coll->strnncollsp(cs, ua, alen, ub, blen); -} - - - int Field_varstring::cmp_prefix(const uchar *a_ptr, const uchar *b_ptr, size_t prefix_len) { @@ -7750,8 +7724,12 @@ int Field_varstring::cmp_prefix(const uchar *a_ptr, const uchar *b_ptr, a_length= uint2korr(a_ptr); b_length= uint2korr(b_ptr); } - return cmp_str_prefix(a_ptr+length_bytes, a_length, b_ptr+length_bytes, - b_length, prefix_len, field_charset); + return field_charset->coll->strnncollsp_nchars(field_charset, + a_ptr + length_bytes, + a_length, + b_ptr + length_bytes, + b_length, + prefix_len / field_charset->mbmaxlen); } @@ -8535,7 +8513,10 @@ int Field_blob::cmp_prefix(const uchar *a_ptr, const uchar *b_ptr, memcpy(&blob1, a_ptr+packlength, sizeof(char*)); memcpy(&blob2, b_ptr+packlength, sizeof(char*)); size_t a_len= get_length(a_ptr), b_len= get_length(b_ptr); - return cmp_str_prefix(blob1, a_len, blob2, b_len, prefix_len, field_charset); + return field_charset->coll->strnncollsp_nchars(field_charset, + blob1, a_len, + blob2, b_len, + prefix_len / field_charset->mbmaxlen); } diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 3991a219ab5..fdaa34eeaf0 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6711,6 +6711,7 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_chinese_ci= NULL, /* init */ my_strnncoll_big5_chinese_ci, my_strnncollsp_big5_chinese_ci, + my_strnncollsp_nchars_big5_chinese_ci, my_strnxfrm_big5_chinese_ci, my_strnxfrmlen_simple, my_like_range_mb, @@ -6727,6 +6728,7 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_bin= NULL, /* init */ my_strnncoll_big5_bin, my_strnncollsp_big5_bin, + my_strnncollsp_nchars_big5_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -6743,6 +6745,7 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_chinese_nopad_ci= NULL, /* init */ my_strnncoll_big5_chinese_ci, my_strnncollsp_big5_chinese_nopad_ci, + my_strnncollsp_nchars_big5_chinese_nopad_ci, my_strnxfrm_big5_chinese_nopad_ci, my_strnxfrmlen_simple, my_like_range_mb, @@ -6759,6 +6762,7 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_nopad_bin= NULL, /* init */ my_strnncoll_big5_bin, my_strnncollsp_big5_nopad_bin, + my_strnncollsp_nchars_big5_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index c052e427322..e70111da89b 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -125,6 +125,17 @@ static int my_strnncollsp_binary(CHARSET_INFO * cs __attribute__((unused)), } +static int my_strnncollsp_nchars_binary(CHARSET_INFO * cs __attribute__((unused)), + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + size_t nchars) +{ + set_if_smaller(slen, nchars); + set_if_smaller(tlen, nchars); + return my_strnncoll_binary(cs, s, slen, t, tlen, 0); +} + + static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)), const uchar *s, size_t slen, const uchar *t, size_t tlen, @@ -199,6 +210,17 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)), } +static int my_strnncollsp_nchars_8bit_bin(CHARSET_INFO * cs, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + size_t nchars) +{ + set_if_smaller(a_length, nchars); + set_if_smaller(b_length, nchars); + return my_strnncollsp_8bit_bin(cs, a, a_length, b, b_length); +} + + static int my_strnncollsp_8bit_nopad_bin(CHARSET_INFO * cs __attribute__((unused)), const uchar *a, size_t a_length, @@ -208,6 +230,17 @@ static int my_strnncollsp_8bit_nopad_bin(CHARSET_INFO * cs } +static int my_strnncollsp_nchars_8bit_nopad_bin(CHARSET_INFO * cs, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + size_t nchars) +{ + set_if_smaller(a_length, nchars); + set_if_smaller(b_length, nchars); + return my_strnncollsp_8bit_nopad_bin(cs, a, a_length, b, b_length); +} + + /* This function is used for all conversion functions */ static size_t my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)), @@ -487,6 +520,7 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler = my_coll_init_8bit_bin, my_strnncoll_8bit_bin, my_strnncollsp_8bit_bin, + my_strnncollsp_nchars_8bit_bin, my_strnxfrm_8bit_bin, my_strnxfrmlen_simple, my_like_range_simple, @@ -503,6 +537,7 @@ MY_COLLATION_HANDLER my_collation_8bit_nopad_bin_handler = my_coll_init_8bit_bin, my_strnncoll_8bit_bin, my_strnncollsp_8bit_nopad_bin, + my_strnncollsp_nchars_8bit_nopad_bin, my_strnxfrm_8bit_nopad_bin, my_strnxfrmlen_simple, my_like_range_simple, @@ -519,6 +554,7 @@ static MY_COLLATION_HANDLER my_collation_binary_handler = NULL, /* init */ my_strnncoll_binary, my_strnncollsp_binary, + my_strnncollsp_nchars_binary, my_strnxfrm_8bit_bin, my_strnxfrmlen_simple, my_like_range_simple, diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index bf97d1feb83..94450af4b91 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -34667,6 +34667,7 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_japanese_ci= NULL, /* init */ my_strnncoll_cp932_japanese_ci, my_strnncollsp_cp932_japanese_ci, + my_strnncollsp_nchars_cp932_japanese_ci, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -34683,6 +34684,7 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_bin= NULL, /* init */ my_strnncoll_cp932_bin, my_strnncollsp_cp932_bin, + my_strnncollsp_nchars_cp932_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -34699,6 +34701,7 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_japanese_nopad_ci= NULL, /* init */ my_strnncoll_cp932_japanese_ci, my_strnncollsp_cp932_japanese_nopad_ci, + my_strnncollsp_nchars_cp932_japanese_nopad_ci, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, @@ -34715,6 +34718,7 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_nopad_bin= NULL, /* init */ my_strnncoll_cp932_bin, my_strnncollsp_cp932_nopad_bin, + my_strnncollsp_nchars_cp932_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c index 17c4c98c24e..33d43d4dd4e 100644 --- a/strings/ctype-czech.c +++ b/strings/ctype-czech.c @@ -610,6 +610,7 @@ static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler = NULL, /* init */ my_strnncoll_czech, my_strnncollsp_czech, + my_strnncollsp_nchars_generic_8bit, my_strnxfrm_czech, my_strnxfrmlen_czech, my_like_range_czech, diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index deb13957900..22f8c4ec7c0 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -9957,6 +9957,7 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_korean_ci= NULL, /* init */ my_strnncoll_euckr_korean_ci, my_strnncollsp_euckr_korean_ci, + my_strnncollsp_nchars_euckr_korean_ci, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -9973,6 +9974,7 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_bin= NULL, /* init */ my_strnncoll_euckr_bin, my_strnncollsp_euckr_bin, + my_strnncollsp_nchars_euckr_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -9989,6 +9991,7 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_korean_nopad_ci= NULL, /* init */ my_strnncoll_euckr_korean_ci, my_strnncollsp_euckr_korean_nopad_ci, + my_strnncollsp_nchars_euckr_korean_nopad_ci, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, @@ -10005,6 +10008,7 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_nopad_bin= NULL, /* init */ my_strnncoll_euckr_bin, my_strnncollsp_euckr_nopad_bin, + my_strnncollsp_nchars_euckr_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 118e8286703..58ea37d36e6 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -67495,6 +67495,7 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_japanese_ci_handler = NULL, /* init */ my_strnncoll_eucjpms_japanese_ci, my_strnncollsp_eucjpms_japanese_ci, + my_strnncollsp_nchars_eucjpms_japanese_ci, my_strnxfrm_mb, /* strnxfrm */ my_strnxfrmlen_simple, my_like_range_mb, /* like_range */ @@ -67511,6 +67512,7 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_bin_handler = NULL, /* init */ my_strnncoll_eucjpms_bin, my_strnncollsp_eucjpms_bin, + my_strnncollsp_nchars_eucjpms_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -67527,6 +67529,7 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_japanese_nopad_ci_handler = NULL, /* init */ my_strnncoll_eucjpms_japanese_ci, my_strnncollsp_eucjpms_japanese_nopad_ci, + my_strnncollsp_nchars_eucjpms_japanese_nopad_ci, my_strnxfrm_mb_nopad, /* strnxfrm */ my_strnxfrmlen_simple, my_like_range_mb, /* like_range */ @@ -67543,6 +67546,7 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_nopad_bin_handler = NULL, /* init */ my_strnncoll_eucjpms_bin, my_strnncollsp_eucjpms_nopad_bin, + my_strnncollsp_nchars_eucjpms_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 166619bf5cc..84246ad6671 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -6362,6 +6362,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_chinese_ci= NULL, /* init */ my_strnncoll_gb2312_chinese_ci, my_strnncollsp_gb2312_chinese_ci, + my_strnncollsp_nchars_gb2312_chinese_ci, my_strnxfrm_mb, /* strnxfrm */ my_strnxfrmlen_simple, my_like_range_mb, /* like_range */ @@ -6378,6 +6379,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_bin= NULL, /* init */ my_strnncoll_gb2312_bin, my_strnncollsp_gb2312_bin, + my_strnncollsp_nchars_gb2312_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -6394,6 +6396,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_chinese_nopad_ci= NULL, /* init */ my_strnncoll_gb2312_chinese_ci, my_strnncollsp_gb2312_chinese_nopad_ci, + my_strnncollsp_nchars_gb2312_chinese_nopad_ci, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, @@ -6410,6 +6413,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_nopad_bin= NULL, /* init */ my_strnncoll_gb2312_bin, my_strnncollsp_gb2312_nopad_bin, + my_strnncollsp_nchars_gb2312_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index efaa2e5c728..d7ea47c409f 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -10645,6 +10645,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_chinese_ci= NULL, /* init */ my_strnncoll_gbk_chinese_ci, my_strnncollsp_gbk_chinese_ci, + my_strnncollsp_nchars_gbk_chinese_ci, my_strnxfrm_gbk_chinese_ci, my_strnxfrmlen_simple, my_like_range_mb, @@ -10661,6 +10662,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_bin= NULL, /* init */ my_strnncoll_gbk_bin, my_strnncollsp_gbk_bin, + my_strnncollsp_nchars_gbk_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -10677,6 +10679,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_chinese_nopad_ci= NULL, /* init */ my_strnncoll_gbk_chinese_ci, my_strnncollsp_gbk_chinese_nopad_ci, + my_strnncollsp_nchars_gbk_chinese_nopad_ci, my_strnxfrm_gbk_chinese_nopad_ci, my_strnxfrmlen_simple, my_like_range_mb, @@ -10693,6 +10696,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_nopad_bin= NULL, /* init */ my_strnncoll_gbk_bin, my_strnncollsp_gbk_nopad_bin, + my_strnncollsp_nchars_gbk_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index f9fa1488aa6..bcf1cc6c9f1 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -726,6 +726,7 @@ static MY_COLLATION_HANDLER my_collation_german2_ci_handler= NULL, /* init */ my_strnncoll_latin1_de, my_strnncollsp_latin1_de, + my_strnncollsp_nchars_generic_8bit, my_strnxfrm_latin1_de, my_strnxfrmlen_simple, my_like_range_simple, diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 17cb51ff8cb..2227f595885 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -208,6 +208,18 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, size_t a_length, } +static int +my_strnncollsp_nchars_simple(CHARSET_INFO * cs, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + size_t nchars) +{ + set_if_smaller(a_length, nchars); + set_if_smaller(b_length, nchars); + return my_strnncollsp_simple(cs, a, a_length, b, b_length); +} + + int my_strnncollsp_simple_nopad(CHARSET_INFO * cs, const uchar *a, size_t a_length, const uchar *b, size_t b_length) @@ -2095,6 +2107,7 @@ MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler = my_coll_init_simple, /* init */ my_strnncoll_simple, my_strnncollsp_simple, + my_strnncollsp_nchars_simple, my_strnxfrm_simple, my_strnxfrmlen_simple, my_like_range_simple, @@ -2111,6 +2124,7 @@ MY_COLLATION_HANDLER my_collation_8bit_simple_nopad_ci_handler = my_coll_init_simple, /* init */ my_strnncoll_simple, my_strnncollsp_simple_nopad, + my_strnncollsp_nchars_generic_8bit, my_strnxfrm_simple_nopad, my_strnxfrmlen_simple, my_like_range_simple, diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 902034b435d..bd2bf432a34 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -34046,6 +34046,7 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_japanese_ci= NULL, /* init */ my_strnncoll_sjis_japanese_ci, my_strnncollsp_sjis_japanese_ci, + my_strnncollsp_nchars_sjis_japanese_ci, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -34062,6 +34063,7 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_bin= NULL, /* init */ my_strnncoll_sjis_bin, my_strnncollsp_sjis_bin, + my_strnncollsp_nchars_sjis_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -34078,6 +34080,7 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_japanese_nopad_ci= NULL, /* init */ my_strnncoll_sjis_japanese_ci, my_strnncollsp_sjis_japanese_nopad_ci, + my_strnncollsp_nchars_sjis_japanese_nopad_ci, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, @@ -34094,6 +34097,7 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_nopad_bin= NULL, /* init */ my_strnncoll_sjis_bin, my_strnncollsp_sjis_nopad_bin, + my_strnncollsp_nchars_sjis_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index afc5771d6c5..1013922b0f9 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -852,6 +852,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = NULL, /* init */ my_strnncoll_tis620, my_strnncollsp_tis620, + my_strnncollsp_nchars_generic_8bit, my_strnxfrm_tis620, my_strnxfrmlen_simple, my_like_range_simple, @@ -867,6 +868,7 @@ static MY_COLLATION_HANDLER my_collation_nopad_ci_handler = NULL, /* init */ my_strnncoll_tis620, my_strnncollsp_tis620_nopad, + my_strnncollsp_nchars_generic_8bit, my_strnxfrm_tis620_nopad, my_strnxfrmlen_simple, my_like_range_simple, diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 5fbbbec7874..6f505c1394a 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -34466,6 +34466,7 @@ MY_COLLATION_HANDLER my_collation_mb_uca_nopad_handler = my_coll_init_uca, my_strnncoll_any_uca, my_strnncollsp_generic_uca_nopad, + my_strnncollsp_nchars_generic, my_strnxfrm_generic_uca_nopad, my_strnxfrmlen_any_uca, my_like_range_mb, @@ -34483,6 +34484,7 @@ MY_COLLATION_HANDLER my_collation_generic_uca_nopad_handler = my_coll_init_uca, my_strnncoll_any_uca, my_strnncollsp_generic_uca_nopad, + my_strnncollsp_nchars_generic, my_strnxfrm_generic_uca_nopad, my_strnxfrmlen_any_uca, my_like_range_generic, @@ -34499,6 +34501,7 @@ MY_COLLATION_HANDLER my_collation_any_uca_handler_multilevel= my_coll_init_uca, my_strnncoll_any_uca_multilevel, my_strnncollsp_any_uca_multilevel, + my_strnncollsp_nchars_generic, my_strnxfrm_any_uca_multilevel, my_strnxfrmlen_any_uca_multilevel, my_like_range_generic, @@ -34515,6 +34518,7 @@ MY_COLLATION_HANDLER my_collation_generic_uca_nopad_handler_multilevel = my_coll_init_uca, my_strnncoll_any_uca_multilevel, my_strnncollsp_generic_uca_nopad_multilevel, + my_strnncollsp_nchars_generic, my_strnxfrm_any_uca_multilevel, my_strnxfrmlen_any_uca_multilevel, my_like_range_generic, @@ -34566,6 +34570,7 @@ MY_COLLATION_HANDLER my_collation_ucs2_uca_handler = my_coll_init_uca, /* init */ my_strnncoll_ucs2_uca, my_strnncollsp_ucs2_uca, + my_strnncollsp_nchars_generic, my_strnxfrm_ucs2_uca, my_strnxfrmlen_any_uca, my_like_range_generic, @@ -35531,6 +35536,7 @@ MY_COLLATION_HANDLER my_collation_any_uca_handler = my_coll_init_uca, /* init */ my_strnncoll_any_uca, my_strnncollsp_any_uca, + my_strnncollsp_nchars_generic, my_strnxfrm_any_uca, my_strnxfrmlen_any_uca, my_like_range_mb, @@ -37465,6 +37471,7 @@ MY_COLLATION_HANDLER my_collation_utf32_uca_handler = my_coll_init_uca, /* init */ my_strnncoll_any_uca, my_strnncollsp_any_uca, + my_strnncollsp_nchars_generic, my_strnxfrm_any_uca, my_strnxfrmlen_any_uca, my_like_range_generic, @@ -38430,6 +38437,7 @@ MY_COLLATION_HANDLER my_collation_utf16_uca_handler = my_coll_init_uca, /* init */ my_strnncoll_any_uca, my_strnncollsp_any_uca, + my_strnncollsp_nchars_generic, my_strnxfrm_any_uca, my_strnxfrmlen_any_uca, my_like_range_generic, diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 48e9f501cd9..4a3fa813a8d 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1549,6 +1549,7 @@ static MY_COLLATION_HANDLER my_collation_utf16_general_ci_handler = NULL, /* init */ my_strnncoll_utf16_general_ci, my_strnncollsp_utf16_general_ci, + my_strnncollsp_nchars_utf16_general_ci, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_generic, @@ -1565,6 +1566,7 @@ static MY_COLLATION_HANDLER my_collation_utf16_bin_handler = NULL, /* init */ my_strnncoll_utf16_bin, my_strnncollsp_utf16_bin, + my_strnncollsp_nchars_utf16_bin, my_strnxfrm_unicode_full_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_generic, @@ -1581,6 +1583,7 @@ static MY_COLLATION_HANDLER my_collation_utf16_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf16_general_ci, my_strnncollsp_utf16_general_nopad_ci, + my_strnncollsp_nchars_utf16_general_nopad_ci, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_generic, @@ -1597,6 +1600,7 @@ static MY_COLLATION_HANDLER my_collation_utf16_nopad_bin_handler = NULL, /* init */ my_strnncoll_utf16_bin, my_strnncollsp_utf16_nopad_bin, + my_strnncollsp_nchars_utf16_nopad_bin, my_strnxfrm_unicode_full_nopad_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_generic, @@ -1882,6 +1886,7 @@ static MY_COLLATION_HANDLER my_collation_utf16le_general_ci_handler = NULL, /* init */ my_strnncoll_utf16le_general_ci, my_strnncollsp_utf16le_general_ci, + my_strnncollsp_nchars_utf16le_general_ci, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_generic, @@ -1898,6 +1903,7 @@ static MY_COLLATION_HANDLER my_collation_utf16le_bin_handler = NULL, /* init */ my_strnncoll_utf16le_bin, my_strnncollsp_utf16le_bin, + my_strnncollsp_nchars_utf16le_bin, my_strnxfrm_unicode_full_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_generic, @@ -1914,6 +1920,7 @@ static MY_COLLATION_HANDLER my_collation_utf16le_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf16le_general_ci, my_strnncollsp_utf16le_general_nopad_ci, + my_strnncollsp_nchars_utf16le_general_nopad_ci, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_generic, @@ -1930,6 +1937,7 @@ static MY_COLLATION_HANDLER my_collation_utf16le_nopad_bin_handler = NULL, /* init */ my_strnncoll_utf16le_bin, my_strnncollsp_utf16le_nopad_bin, + my_strnncollsp_nchars_utf16le_nopad_bin, my_strnxfrm_unicode_full_nopad_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_generic, @@ -2704,6 +2712,7 @@ static MY_COLLATION_HANDLER my_collation_utf32_general_ci_handler = NULL, /* init */ my_strnncoll_utf32_general_ci, my_strnncollsp_utf32_general_ci, + my_strnncollsp_nchars_utf32_general_ci, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_generic, @@ -2720,6 +2729,7 @@ static MY_COLLATION_HANDLER my_collation_utf32_bin_handler = NULL, /* init */ my_strnncoll_utf32_bin, my_strnncollsp_utf32_bin, + my_strnncollsp_nchars_utf32_bin, my_strnxfrm_unicode_full_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_generic, @@ -2736,6 +2746,7 @@ static MY_COLLATION_HANDLER my_collation_utf32_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf32_general_ci, my_strnncollsp_utf32_general_nopad_ci, + my_strnncollsp_nchars_utf32_general_nopad_ci, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_generic, @@ -2752,6 +2763,7 @@ static MY_COLLATION_HANDLER my_collation_utf32_nopad_bin_handler = NULL, /* init */ my_strnncoll_utf32_bin, my_strnncollsp_utf32_nopad_bin, + my_strnncollsp_nchars_utf32_nopad_bin, my_strnxfrm_unicode_full_nopad_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_generic, @@ -3286,6 +3298,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler = NULL, /* init */ my_strnncoll_ucs2_general_ci, my_strnncollsp_ucs2_general_ci, + my_strnncollsp_nchars_ucs2_general_ci, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_generic, @@ -3302,6 +3315,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler = NULL, /* init */ my_strnncoll_ucs2_bin, my_strnncollsp_ucs2_bin, + my_strnncollsp_nchars_ucs2_bin, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_generic, @@ -3318,6 +3332,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_ucs2_general_ci, my_strnncollsp_ucs2_general_nopad_ci, + my_strnncollsp_nchars_ucs2_general_nopad_ci, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_generic, @@ -3334,6 +3349,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_nopad_bin_handler = NULL, /* init */ my_strnncoll_ucs2_bin, my_strnncollsp_ucs2_nopad_bin, + my_strnncollsp_nchars_ucs2_nopad_bin, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_generic, diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 949f3aadc36..34600eda1a5 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -67239,6 +67239,7 @@ static MY_COLLATION_HANDLER my_collation_ujis_japanese_ci_handler = NULL, /* init */ my_strnncoll_ujis_japanese_ci, my_strnncollsp_ujis_japanese_ci, + my_strnncollsp_nchars_ujis_japanese_ci, my_strnxfrm_mb, /* strnxfrm */ my_strnxfrmlen_simple, my_like_range_mb, /* like_range */ @@ -67255,6 +67256,7 @@ static MY_COLLATION_HANDLER my_collation_ujis_bin_handler = NULL, /* init */ my_strnncoll_ujis_bin, my_strnncollsp_ujis_bin, + my_strnncollsp_nchars_ujis_bin, my_strnxfrm_mb, my_strnxfrmlen_simple, my_like_range_mb, @@ -67271,6 +67273,7 @@ static MY_COLLATION_HANDLER my_collation_ujis_japanese_nopad_ci_handler = NULL, /* init */ my_strnncoll_ujis_japanese_ci, my_strnncollsp_ujis_japanese_nopad_ci, + my_strnncollsp_nchars_ujis_japanese_nopad_ci, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, @@ -67287,6 +67290,7 @@ static MY_COLLATION_HANDLER my_collation_ujis_nopad_bin_handler = NULL, /* init */ my_strnncoll_ujis_bin, my_strnncollsp_ujis_nopad_bin, + my_strnncollsp_nchars_ujis_nopad_bin, my_strnxfrm_mb_nopad, my_strnxfrmlen_simple, my_like_range_mb, diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 1d0295000e4..5ab9007c81d 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -5532,6 +5532,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_general_ci_handler = NULL, /* init */ my_strnncoll_utf8_general_ci, my_strnncollsp_utf8_general_ci, + my_strnncollsp_nchars_utf8_general_ci, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_mb, @@ -5548,6 +5549,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_general_mysql500_ci_handler = NULL, /* init */ my_strnncoll_utf8_general_mysql500_ci, my_strnncollsp_utf8_general_mysql500_ci, + my_strnncollsp_nchars_utf8_general_mysql500_ci, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_mb, @@ -5564,6 +5566,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_bin_handler = NULL, /* init */ my_strnncoll_utf8_bin, my_strnncollsp_utf8_bin, + my_strnncollsp_nchars_utf8_bin, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_mb, @@ -5580,6 +5583,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf8_general_ci, my_strnncollsp_utf8_general_nopad_ci, + my_strnncollsp_nchars_utf8_general_nopad_ci, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_mb, @@ -5596,6 +5600,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_nopad_bin_handler = NULL, /* init */ my_strnncoll_utf8_bin, my_strnncollsp_utf8_nopad_bin, + my_strnncollsp_nchars_utf8_nopad_bin, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_mb, @@ -5925,6 +5930,7 @@ static MY_COLLATION_HANDLER my_collation_cs_handler = NULL, /* init */ my_strnncoll_utf8_cs, my_strnncollsp_utf8_cs, + my_strnncollsp_nchars_generic, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_simple, @@ -7216,6 +7222,7 @@ static MY_COLLATION_HANDLER my_collation_filename_handler = NULL, /* init */ my_strnncoll_simple, my_strnncollsp_simple, + my_strnncollsp_nchars_generic, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_mb, @@ -7893,6 +7900,7 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_general_ci_handler= NULL, /* init */ my_strnncoll_utf8mb4_general_ci, my_strnncollsp_utf8mb4_general_ci, + my_strnncollsp_nchars_utf8mb4_general_ci, my_strnxfrm_unicode, my_strnxfrmlen_unicode, my_like_range_mb, @@ -7909,6 +7917,7 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_bin_handler = NULL, /* init */ my_strnncoll_utf8mb4_bin, my_strnncollsp_utf8mb4_bin, + my_strnncollsp_nchars_utf8mb4_bin, my_strnxfrm_unicode_full_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_mb, @@ -7925,6 +7934,7 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_general_nopad_ci_handler= NULL, /* init */ my_strnncoll_utf8mb4_general_ci, my_strnncollsp_utf8mb4_general_nopad_ci, + my_strnncollsp_nchars_utf8mb4_general_nopad_ci, my_strnxfrm_unicode_nopad, my_strnxfrmlen_unicode, my_like_range_mb, @@ -7941,6 +7951,7 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_nopad_bin_handler = NULL, /* init */ my_strnncoll_utf8mb4_bin, my_strnncollsp_utf8mb4_nopad_bin, + my_strnncollsp_nchars_utf8mb4_nopad_bin, my_strnxfrm_unicode_full_nopad_bin, my_strnxfrmlen_unicode_full_bin, my_like_range_mb, diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index f33a83294d6..15fa6299e4e 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -674,6 +674,7 @@ static MY_COLLATION_HANDLER my_collation_czech_ci_handler = NULL, /* init */ my_strnncoll_win1250ch, my_strnncollsp_win1250ch, + my_strnncollsp_nchars_generic_8bit, my_strnxfrm_win1250ch, my_strnxfrmlen_simple, my_like_range_win1250ch, diff --git a/strings/ctype.c b/strings/ctype.c index 32c41e6e9e7..b396ef53b12 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -1210,3 +1210,30 @@ outp: copy_status->m_source_end_pos= from; return to - to_start; } + + +int my_strnncollsp_nchars_generic(CHARSET_INFO *cs, + const uchar *str1, size_t len1, + const uchar *str2, size_t len2, + size_t nchars) +{ + int error; + len1= my_well_formed_length(cs, (const char *) str1, + (const char *) str1 + len1, + nchars, &error); + len2= my_well_formed_length(cs, (const char *) str2, + (const char *) str2 + len2, + nchars, &error); + return cs->coll->strnncollsp(cs, str1, len1, str2, len2); +} + + +int my_strnncollsp_nchars_generic_8bit(CHARSET_INFO *cs, + const uchar *str1, size_t len1, + const uchar *str2, size_t len2, + size_t nchars) +{ + set_if_smaller(len1, nchars); + set_if_smaller(len2, nchars); + return cs->coll->strnncollsp(cs, str1, len1, str2, len2); +} diff --git a/strings/strcoll.ic b/strings/strcoll.ic index eb5b3d5fe9b..ac041512735 100644 --- a/strings/strcoll.ic +++ b/strings/strcoll.ic @@ -221,6 +221,67 @@ MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), { return MY_FUNCTION_NAME(strnncoll)(cs, a, a_length, b, b_length, FALSE); } + +/** + Compare two strings according to the collation, + using the NOPAD comparison style. + + @param cs - the character set and collation + @param a - the left string + @param a_length - the length of the left string + @param b - the right string + @param b_length - the length of the right string + @param nchars - compare this amount of characters only + @return - the comparison result +*/ +static int +MY_FUNCTION_NAME(strnncollsp_nchars)(CHARSET_INFO *cs __attribute__((unused)), + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + size_t nchars) +{ + const uchar *a_end= a + a_length; + const uchar *b_end= b + b_length; + for ( ; ; nchars--) + { + int a_weight, b_weight, res; + uint a_wlen, b_wlen; + + if (!nchars) + return 0; + + a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end); + b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end); + /* + a_wlen b_wlen Comment + ------ ------ ------- + 0 0 Strings ended simultaneously, "a" and "b" are equal. + 0 >0 "a" is a prefix of "b", so "a" is smaller. + >0 0 "b" is a prefix of "a", so "b" is smaller. + >0 >0 Two weights were scanned, check weight difference. + */ + if (!a_wlen) + return b_wlen ? -b_weight : 0; + + if (!b_wlen) + return a_weight; + + if ((res= (a_weight - b_weight))) + return res; + /* + None of the strings has ended yet. + */ + DBUG_ASSERT(a < a_end); + DBUG_ASSERT(b < b_end); + a+= a_wlen; + b+= b_wlen; + } + DBUG_ASSERT(0); + return 0; +} + + + #else /** Compare two strings according to the collation, with PAD SPACE handling. @@ -276,6 +337,58 @@ MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), DBUG_ASSERT(0); return 0; } + +/** + Compare two strings according to the collation, with nchars limit, + with PAD SPACE comparison style. + + @param cs - the character set and collation + @param a - the left string + @param a_length - the length of the left string + @param b - the right string + @param b_length - the length of the right string + @param nchars - compare this amount of characters only + @return - the comparison result +*/ +static int +MY_FUNCTION_NAME(strnncollsp_nchars)(CHARSET_INFO *cs __attribute__((unused)), + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + size_t nchars) +{ + const uchar *a_end= a + a_length; + const uchar *b_end= b + b_length; + for ( ; ; nchars--) + { + int a_weight, b_weight, res; + uint a_wlen, b_wlen; + if (!nchars) + return 0; + a_wlen= MY_FUNCTION_NAME(scan_weight)(&a_weight, a, a_end); + b_wlen= MY_FUNCTION_NAME(scan_weight)(&b_weight, b, b_end); + if ((res= (a_weight - b_weight))) + { + /* Got two different weights. See comments in strnncollsp above. */ + return res; + } + if (!a_wlen && !b_wlen) + { + /* Got two auto-generated trailing spaces. */ + DBUG_ASSERT(a == a_end); + DBUG_ASSERT(b == b_end); + return 0; + } + /* + At least one of the strings has not ended yet, continue comparison. + */ + DBUG_ASSERT(a < a_end || b < b_end); + a+= a_wlen; + b+= b_wlen; + } + DBUG_ASSERT(0); + return 0; +} + #endif diff --git a/strings/strings_def.h b/strings/strings_def.h index b3727321e19..8bf089ec695 100644 --- a/strings/strings_def.h +++ b/strings/strings_def.h @@ -105,6 +105,16 @@ static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len) } +int my_strnncollsp_nchars_generic(CHARSET_INFO *cs, + const uchar *str1, size_t len1, + const uchar *str2, size_t len2, + size_t nchars); + +int my_strnncollsp_nchars_generic_8bit(CHARSET_INFO *cs, + const uchar *str1, size_t len1, + const uchar *str2, size_t len2, + size_t nchars); + uint my_8bit_charset_flags_from_data(CHARSET_INFO *cs); uint my_8bit_collation_flags_from_data(CHARSET_INFO *cs); |