diff options
author | unknown <bar@mysql.com> | 2004-09-06 20:04:22 +0500 |
---|---|---|
committer | unknown <bar@mysql.com> | 2004-09-06 20:04:22 +0500 |
commit | 7e7dfcccd64472c9d46b319e997181d0354b668c (patch) | |
tree | 37f32fcc90ab70fa87eb76249ab0d732a15b3ad4 /strings | |
parent | 4011f819e21f3bc586cb5d9a8b3ad8e2781fa298 (diff) | |
download | mariadb-git-7e7dfcccd64472c9d46b319e997181d0354b668c.tar.gz |
Bug #5324 Bug in UCA collations with LIKE comparisons and INDEX
Diffstat (limited to 'strings')
-rw-r--r-- | strings/ctype-mb.c | 86 | ||||
-rw-r--r-- | strings/ctype-uca.c | 7 |
2 files changed, 90 insertions, 3 deletions
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 25ee85d62b4..3bfc66029ce 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -458,6 +458,92 @@ static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), } } +/* +** Calculate min_str and max_str that ranges a LIKE string. +** Arguments: +** ptr Pointer to LIKE string. +** ptr_length Length of LIKE string. +** escape Escape character in LIKE. (Normally '\'). +** All escape characters should be removed from min_str and max_str +** res_length Length of min_str and max_str. +** min_str Smallest case sensitive string that ranges LIKE. +** Should be space padded to res_length. +** max_str Largest case sensitive string that ranges LIKE. +** Normally padded with the biggest character sort value. +** +** The function should return 0 if ok and 1 if the LIKE string can't be +** optimized ! +*/ + +my_bool my_like_range_mb(CHARSET_INFO *cs, + const char *ptr,uint ptr_length, + pbool escape, pbool w_one, pbool w_many, + uint res_length, + char *min_str,char *max_str, + uint *min_length,uint *max_length) +{ + const char *end=ptr+ptr_length; + char *min_org=min_str; + char *min_end=min_str+res_length; + char *max_end=max_str+res_length; + + for (; ptr != end && min_str != min_end ; ptr++) + { + if (*ptr == escape && ptr+1 != end) + { + ptr++; /* Skip escape */ + *min_str++= *max_str++ = *ptr; + continue; + } + if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */ + { + char buf[10]; + uint buflen; + + /* Write min key */ + *min_length= (uint) (min_str - min_org); + *max_length=res_length; + do + { + *min_str++= (char) cs->min_sort_char; + } while (min_str != min_end); + + /* + Write max key: create a buffer with multibyte + representation of the max_sort_char character, + and copy it into max_str in a loop. + */ + buflen= cs->cset->wc_mb(cs, cs->max_sort_char, buf, buf + sizeof(buf)); + DBUG_ASSERT(buflen > 0); + do + { + if ((max_str + buflen) <= max_end) + { + /* Enough space for max characer */ + memcpy(max_str, buf, buflen); + max_str+= buflen; + } + else + { + /* + There is no space for whole multibyte + character, then add trailing spaces. + */ + + *max_str++= ' '; + } + } while (max_str != max_end); + return 0; + } + *min_str++= *max_str++ = *ptr; + } + *min_length= *max_length = (uint) (min_str - min_org); + + while (min_str != min_end) + *min_str++ = *max_str++ = ' '; /* Because if key compression */ + return 0; +} + static int my_wildcmp_mb_bin(CHARSET_INFO *cs, const char *str,const char *str_end, const char *wildstr,const char *wildend, diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index cecc3be5045..edb84dbf225 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -6876,7 +6876,8 @@ static int my_uca_scanner_next_any(my_uca_scanner *scanner) int mblen; if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, &wc, - scanner->sbeg, scanner->send)) < 0)) + scanner->sbeg, + scanner->send)) <= 0)) return -1; scanner->page= wc >> 8; @@ -7918,7 +7919,7 @@ MY_COLLATION_HANDLER my_collation_ucs2_uca_handler = my_strnncoll_ucs2_uca, my_strnncollsp_ucs2_uca, my_strnxfrm_ucs2_uca, - my_like_range_simple, + my_like_range_ucs2, my_wildcmp_uca, NULL, my_instr_mb, @@ -8369,7 +8370,7 @@ MY_COLLATION_HANDLER my_collation_any_uca_handler = my_strnncoll_any_uca, my_strnncollsp_any_uca, my_strnxfrm_any_uca, - my_like_range_simple, + my_like_range_mb, my_wildcmp_uca, NULL, my_instr_mb, |