Commit c57c5be1 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-5745 analyze MySQL fix for bug#12368495

parent 01faff02
...@@ -4277,5 +4277,38 @@ COALESCE(c1) ...@@ -4277,5 +4277,38 @@ COALESCE(c1)
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-5745 analyze MySQL fix for bug#12368495
#
SELECT CHAR_LENGTH(TRIM(LEADING 0x000000 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(LEADING 0x000000 FROM _ucs2 0x0061))
2
SELECT CHAR_LENGTH(TRIM(LEADING 0x0001 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(LEADING 0x0001 FROM _ucs2 0x0061))
2
SELECT CHAR_LENGTH(TRIM(LEADING 0x00 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(LEADING 0x00 FROM _ucs2 0x0061))
1
SELECT CHAR_LENGTH(TRIM(TRAILING 0x000000 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(TRAILING 0x000000 FROM _ucs2 0x0061))
2
SELECT CHAR_LENGTH(TRIM(TRAILING 0x0001 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(TRAILING 0x0001 FROM _ucs2 0x0061))
2
SELECT CHAR_LENGTH(TRIM(TRAILING 0x61 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(TRAILING 0x61 FROM _ucs2 0x0061))
1
SELECT CHAR_LENGTH(TRIM(BOTH 0x000000 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(BOTH 0x000000 FROM _ucs2 0x0061))
2
SELECT CHAR_LENGTH(TRIM(BOTH 0x0001 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(BOTH 0x0001 FROM _ucs2 0x0061))
2
SELECT CHAR_LENGTH(TRIM(BOTH 0x61 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(BOTH 0x61 FROM _ucs2 0x0061))
1
SELECT CHAR_LENGTH(TRIM(BOTH 0x00 FROM _ucs2 0x0061));
CHAR_LENGTH(TRIM(BOTH 0x00 FROM _ucs2 0x0061))
1
#
# End of 5.5 tests # End of 5.5 tests
# #
...@@ -1237,5 +1237,38 @@ SELECT '2010-10-10 10:10:10' + INTERVAL GeometryType(GeomFromText('POINT(1 1)')) ...@@ -1237,5 +1237,38 @@ SELECT '2010-10-10 10:10:10' + INTERVAL GeometryType(GeomFromText('POINT(1 1)'))
'2010-10-10 10:10:10' + INTERVAL GeometryType(GeomFromText('POINT(1 1)')) hour_second '2010-10-10 10:10:10' + INTERVAL GeometryType(GeomFromText('POINT(1 1)')) hour_second
2010-10-10 10:10:10 2010-10-10 10:10:10
# #
# MDEV-5745 analyze MySQL fix for bug#12368495
#
SELECT CHAR_LENGTH(TRIM(LEADING 0x0000000000 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(LEADING 0x0000000000 FROM _utf32 0x00000061))
4
SELECT CHAR_LENGTH(TRIM(LEADING 0x0001 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(LEADING 0x0001 FROM _utf32 0x00000061))
4
SELECT CHAR_LENGTH(TRIM(LEADING 0x00 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(LEADING 0x00 FROM _utf32 0x00000061))
1
SELECT CHAR_LENGTH(TRIM(TRAILING 0x0000000000 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(TRAILING 0x0000000000 FROM _utf32 0x00000061))
4
SELECT CHAR_LENGTH(TRIM(TRAILING 0x0001 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(TRAILING 0x0001 FROM _utf32 0x00000061))
4
SELECT CHAR_LENGTH(TRIM(TRAILING 0x61 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(TRAILING 0x61 FROM _utf32 0x00000061))
3
SELECT CHAR_LENGTH(TRIM(BOTH 0x0000000000 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(BOTH 0x0000000000 FROM _utf32 0x00000061))
4
SELECT CHAR_LENGTH(TRIM(BOTH 0x0001 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(BOTH 0x0001 FROM _utf32 0x00000061))
4
SELECT CHAR_LENGTH(TRIM(BOTH 0x61 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(BOTH 0x61 FROM _utf32 0x00000061))
3
SELECT CHAR_LENGTH(TRIM(BOTH 0x00 FROM _utf32 0x00000061));
CHAR_LENGTH(TRIM(BOTH 0x00 FROM _utf32 0x00000061))
1
#
# End of 5.5 tests # End of 5.5 tests
# #
...@@ -837,6 +837,23 @@ SELECT COALESCE(c1) FROM t1 ORDER BY 1; ...@@ -837,6 +837,23 @@ SELECT COALESCE(c1) FROM t1 ORDER BY 1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-5745 analyze MySQL fix for bug#12368495
--echo #
SELECT CHAR_LENGTH(TRIM(LEADING 0x000000 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(LEADING 0x0001 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(LEADING 0x00 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(TRAILING 0x000000 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(TRAILING 0x0001 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(TRAILING 0x61 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x000000 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x0001 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x61 FROM _ucs2 0x0061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x00 FROM _ucs2 0x0061));
--echo # --echo #
--echo # End of 5.5 tests --echo # End of 5.5 tests
--echo # --echo #
...@@ -860,6 +860,22 @@ ORDER BY l DESC; ...@@ -860,6 +860,22 @@ ORDER BY l DESC;
SELECT '2010-10-10 10:10:10' + INTERVAL GeometryType(GeomFromText('POINT(1 1)')) hour_second; SELECT '2010-10-10 10:10:10' + INTERVAL GeometryType(GeomFromText('POINT(1 1)')) hour_second;
--echo #
--echo # MDEV-5745 analyze MySQL fix for bug#12368495
--echo #
SELECT CHAR_LENGTH(TRIM(LEADING 0x0000000000 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(LEADING 0x0001 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(LEADING 0x00 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(TRAILING 0x0000000000 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(TRAILING 0x0001 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(TRAILING 0x61 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x0000000000 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x0001 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x61 FROM _utf32 0x00000061));
SELECT CHAR_LENGTH(TRIM(BOTH 0x00 FROM _utf32 0x00000061));
--echo # --echo #
--echo # End of 5.5 tests --echo # End of 5.5 tests
--echo # --echo #
...@@ -2074,7 +2074,7 @@ bool agg_item_collations(DTCollation &c, const char *fname, ...@@ -2074,7 +2074,7 @@ bool agg_item_collations(DTCollation &c, const char *fname,
bool unknown_cs= 0; bool unknown_cs= 0;
c.set(av[0]->collation); c.set(av[0]->collation);
for (i= 1, arg= &av[item_sep]; i < count; i++, arg++) for (i= 1, arg= &av[item_sep]; i < count; i++, arg+= item_sep)
{ {
if (c.aggregate((*arg)->collation, flags)) if (c.aggregate((*arg)->collation, flags))
{ {
......
...@@ -1624,7 +1624,7 @@ String *Item_func_ltrim::val_str(String *str) ...@@ -1624,7 +1624,7 @@ String *Item_func_ltrim::val_str(String *str)
if ((remove_length= remove_str->length()) == 0 || if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length()) remove_length > res->length())
return res; return non_trimmed_value(res);
ptr= (char*) res->ptr(); ptr= (char*) res->ptr();
end= ptr+res->length(); end= ptr+res->length();
...@@ -1643,9 +1643,8 @@ String *Item_func_ltrim::val_str(String *str) ...@@ -1643,9 +1643,8 @@ String *Item_func_ltrim::val_str(String *str)
end+=remove_length; end+=remove_length;
} }
if (ptr == res->ptr()) if (ptr == res->ptr())
return res; return non_trimmed_value(res);
tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr)); return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr));
return &tmp_value;
} }
...@@ -1671,7 +1670,7 @@ String *Item_func_rtrim::val_str(String *str) ...@@ -1671,7 +1670,7 @@ String *Item_func_rtrim::val_str(String *str)
if ((remove_length= remove_str->length()) == 0 || if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length()) remove_length > res->length())
return res; return non_trimmed_value(res);
ptr= (char*) res->ptr(); ptr= (char*) res->ptr();
end= ptr+res->length(); end= ptr+res->length();
...@@ -1683,11 +1682,11 @@ String *Item_func_rtrim::val_str(String *str) ...@@ -1683,11 +1682,11 @@ String *Item_func_rtrim::val_str(String *str)
{ {
char chr=(*remove_str)[0]; char chr=(*remove_str)[0];
#ifdef USE_MB #ifdef USE_MB
if (use_mb(res->charset())) if (use_mb(collation.collation))
{ {
while (ptr < end) while (ptr < end)
{ {
if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l,p=ptr; if ((l= my_ismbchar(collation.collation, ptr, end))) ptr+= l, p=ptr;
else ++ptr; else ++ptr;
} }
ptr=p; ptr=p;
...@@ -1700,12 +1699,12 @@ String *Item_func_rtrim::val_str(String *str) ...@@ -1700,12 +1699,12 @@ String *Item_func_rtrim::val_str(String *str)
{ {
const char *r_ptr=remove_str->ptr(); const char *r_ptr=remove_str->ptr();
#ifdef USE_MB #ifdef USE_MB
if (use_mb(res->charset())) if (use_mb(collation.collation))
{ {
loop: loop:
while (ptr + remove_length < end) while (ptr + remove_length < end)
{ {
if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l; if ((l= my_ismbchar(collation.collation, ptr, end))) ptr+= l;
else ++ptr; else ++ptr;
} }
if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length)) if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
...@@ -1724,9 +1723,8 @@ String *Item_func_rtrim::val_str(String *str) ...@@ -1724,9 +1723,8 @@ String *Item_func_rtrim::val_str(String *str)
} }
} }
if (end == res->ptr()+res->length()) if (end == res->ptr()+res->length())
return res; return non_trimmed_value(res);
tmp_value.set(*res,0,(uint) (end-res->ptr())); return trimmed_value(res, 0, (uint32) (end - res->ptr()));
return &tmp_value;
} }
...@@ -1753,37 +1751,22 @@ String *Item_func_trim::val_str(String *str) ...@@ -1753,37 +1751,22 @@ String *Item_func_trim::val_str(String *str)
if ((remove_length= remove_str->length()) == 0 || if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length()) remove_length > res->length())
return res; return non_trimmed_value(res);
ptr= (char*) res->ptr(); ptr= (char*) res->ptr();
end= ptr+res->length(); end= ptr+res->length();
r_ptr= remove_str->ptr(); r_ptr= remove_str->ptr();
while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
ptr+=remove_length;
#ifdef USE_MB #ifdef USE_MB
if (use_mb(res->charset())) if (use_mb(collation.collation))
{ {
while (ptr + remove_length <= end)
{
uint num_bytes= 0;
while (num_bytes < remove_length)
{
uint len;
if ((len= my_ismbchar(res->charset(), ptr + num_bytes, end)))
num_bytes+= len;
else
++num_bytes;
}
if (num_bytes != remove_length)
break;
if (memcmp(ptr, r_ptr, remove_length))
break;
ptr+= remove_length;
}
char *p=ptr; char *p=ptr;
register uint32 l; register uint32 l;
loop: loop:
while (ptr + remove_length < end) while (ptr + remove_length < end)
{ {
if ((l= my_ismbchar(res->charset(), ptr,end))) if ((l= my_ismbchar(collation.collation, ptr, end)))
ptr+= l; ptr+= l;
else else
++ptr; ++ptr;
...@@ -1799,16 +1782,13 @@ String *Item_func_trim::val_str(String *str) ...@@ -1799,16 +1782,13 @@ String *Item_func_trim::val_str(String *str)
else else
#endif /* USE_MB */ #endif /* USE_MB */
{ {
while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
ptr+=remove_length;
while (ptr + remove_length <= end && while (ptr + remove_length <= end &&
!memcmp(end-remove_length,r_ptr,remove_length)) !memcmp(end-remove_length,r_ptr,remove_length))
end-=remove_length; end-=remove_length;
} }
if (ptr == res->ptr() && end == ptr+res->length()) if (ptr == res->ptr() && end == ptr+res->length())
return res; return non_trimmed_value(res);
tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr)); return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr));
return &tmp_value;
} }
void Item_func_trim::fix_length_and_dec() void Item_func_trim::fix_length_and_dec()
......
...@@ -270,6 +270,21 @@ class Item_func_trim :public Item_str_func ...@@ -270,6 +270,21 @@ class Item_func_trim :public Item_str_func
protected: protected:
String tmp_value; String tmp_value;
String remove; String remove;
String *trimmed_value(String *res, uint32 offset, uint32 length)
{
tmp_value.set(*res, offset, length);
/*
Make sure to return correct charset and collation:
TRIM(0x000000 FROM _ucs2 0x0061)
should set charset to "binary" rather than to "ucs2".
*/
tmp_value.set_charset(collation.collation);
return &tmp_value;
}
String *non_trimmed_value(String *res)
{
return trimmed_value(res, 0, res->length());
}
public: public:
Item_func_trim(Item *a,Item *b) :Item_str_func(a,b) {} Item_func_trim(Item *a,Item *b) :Item_str_func(a,b) {}
Item_func_trim(Item *a) :Item_str_func(a) {} Item_func_trim(Item *a) :Item_str_func(a) {}
......
...@@ -1983,10 +1983,10 @@ my_strnxfrmlen_utf32(CHARSET_INFO *cs __attribute__((unused)), size_t len) ...@@ -1983,10 +1983,10 @@ my_strnxfrmlen_utf32(CHARSET_INFO *cs __attribute__((unused)), size_t len)
static uint static uint
my_ismbchar_utf32(CHARSET_INFO *cs __attribute__((unused)), my_ismbchar_utf32(CHARSET_INFO *cs __attribute__((unused)),
const char *b __attribute__((unused)), const char *b,
const char *e __attribute__((unused))) const char *e)
{ {
return 4; return b + 4 > e ? 0 : 4;
} }
...@@ -2895,10 +2895,10 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)), ...@@ -2895,10 +2895,10 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
static uint my_ismbchar_ucs2(CHARSET_INFO *cs __attribute__((unused)), static uint my_ismbchar_ucs2(CHARSET_INFO *cs __attribute__((unused)),
const char *b __attribute__((unused)), const char *b,
const char *e __attribute__((unused))) const char *e)
{ {
return 2; return b + 2 > e ? 0 : 2;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment