summaryrefslogtreecommitdiff
path: root/strings
diff options
context:
space:
mode:
authorunknown <bar@mysql.com>2004-09-06 20:04:22 +0500
committerunknown <bar@mysql.com>2004-09-06 20:04:22 +0500
commit7e7dfcccd64472c9d46b319e997181d0354b668c (patch)
tree37f32fcc90ab70fa87eb76249ab0d732a15b3ad4 /strings
parent4011f819e21f3bc586cb5d9a8b3ad8e2781fa298 (diff)
downloadmariadb-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.c86
-rw-r--r--strings/ctype-uca.c7
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,