summaryrefslogtreecommitdiff
path: root/strings
diff options
context:
space:
mode:
authorigor@rurik.mysql.com <>2006-06-20 19:57:21 -0700
committerigor@rurik.mysql.com <>2006-06-20 19:57:21 -0700
commit2893d11c5e502bb303bea1cd47445d96a48c7413 (patch)
treef11d15c22a771479b818063644dc2507f3c7b027 /strings
parent217faf569ec4880d5096a9e2e869e07ac101271f (diff)
downloadmariadb-git-2893d11c5e502bb303bea1cd47445d96a48c7413.tar.gz
Fixed bug #16674.
The length of the prefix of the pattern string in the LIKE predicate that determined the index range to be scanned was calculated incorrectly for multi-byte character sets. As a result of this in 4. 1 the the scanned range was wider then necessary if the prefix contained not only one-byte characters. In 5.0 additionally it caused missing some rows from the result set.
Diffstat (limited to 'strings')
-rw-r--r--strings/ctype-mb.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index eb032759d25..4f57f7c78e4 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -502,21 +502,19 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
char *min_str,char *max_str,
uint *min_length,uint *max_length)
{
+ uint mblen;
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;
- uint charlen= res_length / cs->mbmaxlen;
+ uint maxcharlen= res_length / cs->mbmaxlen;
- for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--)
+ for (; ptr != end && min_str != min_end && maxcharlen ; maxcharlen--)
{
+ /* We assume here that escape, w_any, w_namy are one-byte characters */
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 */
+ ptr++; /* Skip escape */
+ else if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */
{
/* Write min key */
*min_length= (uint) (min_str - min_org);
@@ -534,7 +532,16 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
pad_max_char(cs, max_str, max_end);
return 0;
}
- *min_str++= *max_str++ = *ptr;
+ if ((mblen= my_ismbchar(cs, ptr, end)) > 1)
+ {
+ if (ptr+mblen > end || min_str+mblen > min_end)
+ break;
+ while (mblen--)
+ *min_str++= *max_str++= *ptr++;
+ }
+ else
+ *min_str++= *max_str++= *ptr++;
+
}
*min_length= *max_length = (uint) (min_str - min_org);