summaryrefslogtreecommitdiff
path: root/strings/ctype-ucs2.c
diff options
context:
space:
mode:
authorunknown <bar@mysql.com/bar.myoffice.izhnet.ru>2007-06-28 13:34:44 +0500
committerunknown <bar@mysql.com/bar.myoffice.izhnet.ru>2007-06-28 13:34:44 +0500
commit54344f681dfc75170867c3e92dd726f9c28a3f41 (patch)
treeda899a52dc4bbef9ed8e4bc182401319f6095505 /strings/ctype-ucs2.c
parent9b940d0cb70508ca295bc68a8bab5832d79ededd (diff)
downloadmariadb-git-54344f681dfc75170867c3e92dd726f9c28a3f41.tar.gz
Bug#27345 Incorrect data returned when range-read from utf8_danish_ci indexes
Problem: like_range() returned wrong ranges for contractions (like 'ch' in Czech'). Fix: adding a special code to handle tricky cases: - contraction head followed by a wild character - full contraction - contraction part followed by another contraction part, but they are not a contraction together. mysql-test/r/ctype_uca.result: Adding test case mysql-test/t/ctype_uca.test: Adding test case strings/ctype-mb.c: Adding test case strings/ctype-uca.c: Allocate additional 256 bytes for flags "is contraction part". strings/ctype-ucs2.c: Adding test case
Diffstat (limited to 'strings/ctype-ucs2.c')
-rw-r--r--strings/ctype-ucs2.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index f3abbaa6e7e..b5353c55e4c 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1524,6 +1524,8 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
char *min_org=min_str;
char *min_end=min_str+res_length;
uint charlen= res_length / cs->mbmaxlen;
+ const char *contraction_flags= cs->contractions ?
+ ((const char*) cs->contractions) + 0x40*0x40 : NULL;
for ( ; ptr + 1 < end && min_str + 1 < min_end && charlen > 0
; ptr+=2, charlen--)
@@ -1545,6 +1547,7 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
}
if (ptr[0] == '\0' && ptr[1] == w_many) /* '%' in SQL */
{
+fill_max_and_min:
/*
Calculate length of keys:
'a\0\0... is the smallest possible string when we have space expand
@@ -1561,6 +1564,38 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
} while (min_str + 1 < min_end);
return 0;
}
+
+ if (contraction_flags && ptr + 3 < end &&
+ ptr[0] == '\0' && contraction_flags[(uchar) ptr[1]])
+ {
+ /* Contraction head found */
+ if (ptr[2] == '\0' && (ptr[3] == w_one || ptr[3] == w_many))
+ {
+ /* Contraction head followed by a wildcard, quit */
+ goto fill_max_and_min;
+ }
+
+ /*
+ Check if the second letter can be contraction part,
+ and if two letters really produce a contraction.
+ */
+ if (ptr[2] == '\0' && contraction_flags[(uchar) ptr[3]] &&
+ cs->contractions[(ptr[1]-0x40)*0x40 + ptr[3] - 0x40])
+ {
+ /* Contraction found */
+ if (charlen == 1 || min_str + 2 >= min_end)
+ {
+ /* Full contraction doesn't fit, quit */
+ goto fill_max_and_min;
+ }
+
+ /* Put contraction head */
+ *min_str++= *max_str++= *ptr++;
+ *min_str++= *max_str++= *ptr++;
+ charlen--;
+ }
+ }
+ /* Put contraction tail, or a single character */
*min_str++= *max_str++ = ptr[0];
*min_str++= *max_str++ = ptr[1];
}