← Back to team overview

maria-developers team mailing list archive

please review mdev-5745 analyze MySQL fix for bug#12368495

 

Hi Serg,

please review a patch for mdev-5745.

Thanks.
=== modified file 'mysql-test/r/ctype_ucs.result'
--- mysql-test/r/ctype_ucs.result	2014-04-28 11:56:31 +0000
+++ mysql-test/r/ctype_ucs.result	2014-07-23 15:08:56 +0000
@@ -4277,5 +4277,38 @@ COALESCE(c1)
 
 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
 #

=== modified file 'mysql-test/r/ctype_utf32.result'
--- mysql-test/r/ctype_utf32.result	2014-02-17 10:00:51 +0000
+++ mysql-test/r/ctype_utf32.result	2014-07-23 15:11:36 +0000
@@ -1237,5 +1237,38 @@ SELECT '2010-10-10 10:10:10' + INTERVAL
 '2010-10-10 10:10:10' + INTERVAL GeometryType(GeomFromText('POINT(1 1)')) hour_second
 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
 #

=== modified file 'mysql-test/t/ctype_ucs.test'
--- mysql-test/t/ctype_ucs.test	2013-11-08 10:30:35 +0000
+++ mysql-test/t/ctype_ucs.test	2014-07-23 15:08:20 +0000
@@ -838,5 +838,22 @@ 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 # End of 5.5 tests
 --echo #

=== modified file 'mysql-test/t/ctype_utf32.test'
--- mysql-test/t/ctype_utf32.test	2012-08-09 16:25:47 +0000
+++ mysql-test/t/ctype_utf32.test	2014-07-23 15:10:59 +0000
@@ -861,5 +861,21 @@ ORDER BY l DESC;
 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 # End of 5.5 tests
 --echo #

=== modified file 'sql/item.cc'
--- sql/item.cc	2014-06-04 17:53:15 +0000
+++ sql/item.cc	2014-07-23 14:41:01 +0000
@@ -2074,7 +2074,7 @@ bool agg_item_collations(DTCollation &c,
   bool unknown_cs= 0;
 
   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))
     {

=== modified file 'sql/item_strfunc.cc'
--- sql/item_strfunc.cc	2014-06-04 17:53:15 +0000
+++ sql/item_strfunc.cc	2014-07-23 15:14:11 +0000
@@ -1624,7 +1624,7 @@ String *Item_func_ltrim::val_str(String
 
   if ((remove_length= remove_str->length()) == 0 ||
       remove_length > res->length())
-    return res;
+    return non_trimmed_value(res);
 
   ptr= (char*) res->ptr();
   end= ptr+res->length();
@@ -1643,9 +1643,8 @@ String *Item_func_ltrim::val_str(String
     end+=remove_length;
   }
   if (ptr == res->ptr())
-    return res;
-  tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
-  return &tmp_value;
+    return non_trimmed_value(res);
+  return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr));
 }
 
 
@@ -1671,7 +1670,7 @@ String *Item_func_rtrim::val_str(String
 
   if ((remove_length= remove_str->length()) == 0 ||
       remove_length > res->length())
-    return res;
+    return non_trimmed_value(res);
 
   ptr= (char*) res->ptr();
   end= ptr+res->length();
@@ -1683,11 +1682,11 @@ String *Item_func_rtrim::val_str(String
   {
     char chr=(*remove_str)[0];
 #ifdef USE_MB
-    if (use_mb(res->charset()))
+    if (use_mb(collation.collation))
     {
       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;
       }
       ptr=p;
@@ -1700,12 +1699,12 @@ String *Item_func_rtrim::val_str(String
   {
     const char *r_ptr=remove_str->ptr();
 #ifdef USE_MB
-    if (use_mb(res->charset()))
+    if (use_mb(collation.collation))
     {
   loop:
       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;
       }
       if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
@@ -1724,9 +1723,8 @@ String *Item_func_rtrim::val_str(String
     }
   }
   if (end == res->ptr()+res->length())
-    return res;
-  tmp_value.set(*res,0,(uint) (end-res->ptr()));
-  return &tmp_value;
+    return non_trimmed_value(res);
+  return trimmed_value(res, 0, (uint32) (end - res->ptr()));
 }
 
 
@@ -1753,37 +1751,22 @@ String *Item_func_trim::val_str(String *
 
   if ((remove_length= remove_str->length()) == 0 ||
       remove_length > res->length())
-    return res;
+    return non_trimmed_value(res);
 
   ptr= (char*) res->ptr();
   end= ptr+res->length();
   r_ptr= remove_str->ptr();
+  while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
+    ptr+=remove_length;
 #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;
     register uint32 l;
  loop:
     while (ptr + remove_length < end)
     {
-      if ((l= my_ismbchar(res->charset(), ptr,end)))
+      if ((l= my_ismbchar(collation.collation, ptr, end)))
         ptr+= l;
       else
         ++ptr;
@@ -1799,16 +1782,13 @@ String *Item_func_trim::val_str(String *
   else
 #endif /* USE_MB */
   {
-    while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
-      ptr+=remove_length;
     while (ptr + remove_length <= end &&
 	   !memcmp(end-remove_length,r_ptr,remove_length))
       end-=remove_length;
   }
   if (ptr == res->ptr() && end == ptr+res->length())
-    return res;
-  tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
-  return &tmp_value;
+    return non_trimmed_value(res);
+  return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr));
 }
 
 void Item_func_trim::fix_length_and_dec()

=== modified file 'sql/item_strfunc.h'
--- sql/item_strfunc.h	2014-03-25 10:09:12 +0000
+++ sql/item_strfunc.h	2014-07-23 14:45:51 +0000
@@ -270,6 +270,21 @@ class Item_func_trim :public Item_str_fu
 protected:
   String tmp_value;
   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:
   Item_func_trim(Item *a,Item *b) :Item_str_func(a,b) {}
   Item_func_trim(Item *a) :Item_str_func(a) {}

=== modified file 'strings/ctype-ucs2.c'
--- strings/ctype-ucs2.c	2014-02-17 10:00:51 +0000
+++ strings/ctype-ucs2.c	2014-07-23 15:18:34 +0000
@@ -1983,10 +1983,10 @@ my_strnxfrmlen_utf32(CHARSET_INFO *cs __
 
 static uint
 my_ismbchar_utf32(CHARSET_INFO *cs __attribute__((unused)),
-                  const char *b __attribute__((unused)),
-                  const char *e __attribute__((unused)))
+                  const char *b,
+                  const char *e)
 {
-  return 4;
+  return b + 4 > e ? 0 : 4;
 }
 
 
@@ -2895,10 +2895,10 @@ static int my_strnncollsp_ucs2(CHARSET_I
 
 
 static uint my_ismbchar_ucs2(CHARSET_INFO *cs __attribute__((unused)),
-                             const char *b __attribute__((unused)),
-                             const char *e __attribute__((unused)))
+                             const char *b,
+                             const char *e)
 {
-  return 2;
+  return b + 2 > e ? 0 : 2;
 }