List:Commits« Previous MessageNext Message »
From:Sergey Glukhov Date:February 17 2009 12:39pm
Subject:bzr commit into mysql-5.0-bugteam branch (Sergey.Glukhov:2733)
Bug#37601
View as plain text  
#At file:///home/gluh/MySQL/mysql-5.0-bug-37601/ based on revid:gshchepa@stripped

 2733 Sergey Glukhov	2009-02-17
      Bug#37601 Cast Is Not Done On Row Comparison
      In case of ROW item each compared pair does not
      check if argumet collations can be aggregated and
      thus appropiriate item conversion does not happen.
      The fix is to add the check and convertion for ROW
      pairs.
modified:
  mysql-test/r/row.result
  mysql-test/t/row.test
  sql/item.cc
  sql/item.h
  sql/item_cmpfunc.cc

per-file messages:
  mysql-test/r/row.result
    test result
  mysql-test/t/row.test
    test case
  sql/item.cc
    added agg_item_set_converter() function which was a part of
    agg_item_charsets() func. The only difference is that
    agg_item_set_converter() checks and converts items 
    using already known collation.
  sql/item.h
    added agg_item_set_converter() function
  sql/item_cmpfunc.cc
    In case of ROW item each compared pair does not
    check if argumet collations can be aggregated and
    thus appropiriate item conversion does not happen.
    The fix is to add the check and convertion for ROW
    pairs.
=== modified file 'mysql-test/r/row.result'
--- a/mysql-test/r/row.result	2008-02-28 18:53:31 +0000
+++ b/mysql-test/r/row.result	2009-02-17 13:40:55 +0000
@@ -443,3 +443,17 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 3) F
 ROW(a, 1) IN (SELECT SUM(b), 3)
 0
 DROP TABLE t1;
+create table t1 (a varchar(200),
+b int unsigned not null primary key auto_increment)
+default character set 'utf8';
+create table t2 (c varchar(200),
+d int unsigned not null primary key auto_increment)
+default character set 'latin1';
+insert into t1 (a) values('abc');
+insert into t2 (c) values('abc');
+select * from t1,t2 where (a,b) = (c,d);
+a	b	c	d
+abc	1	abc	1
+select host,user from mysql.user where (host,user) = ('localhost','test');
+host	user
+drop table t1,t2;

=== modified file 'mysql-test/t/row.test'
--- a/mysql-test/t/row.test	2008-02-28 18:53:31 +0000
+++ b/mysql-test/t/row.test	2009-02-17 13:40:55 +0000
@@ -237,3 +237,21 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 1) F
 SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a;
 
 DROP TABLE t1;
+
+#
+# Bug#37601 Cast Is Not Done On Row Comparison
+#
+create table t1 (a varchar(200),
+                 b int unsigned not null primary key auto_increment)
+default character set 'utf8';
+
+create table t2 (c varchar(200),
+                 d int unsigned not null primary key auto_increment)
+default character set 'latin1';
+
+insert into t1 (a) values('abc');
+insert into t2 (c) values('abc');
+select * from t1,t2 where (a,b) = (c,d);
+
+select host,user from mysql.user where (host,user) = ('localhost','test');
+drop table t1,t2;

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2009-01-16 14:48:41 +0000
+++ b/sql/item.cc	2009-02-17 13:40:55 +0000
@@ -1595,42 +1595,11 @@ bool agg_item_collations_for_comparison(
 }
 
 
-/* 
-  Collect arguments' character sets together.
-  We allow to apply automatic character set conversion in some cases.
-  The conditions when conversion is possible are:
-  - arguments A and B have different charsets
-  - A wins according to coercibility rules
-    (i.e. a column is stronger than a string constant,
-     an explicit COLLATE clause is stronger than a column)
-  - character set of A is either superset for character set of B,
-    or B is a string constant which can be converted into the
-    character set of A without data loss.
-    
-  If all of the above is true, then it's possible to convert
-  B into the character set of A, and then compare according
-  to the collation of A.
-  
-  For functions with more than two arguments:
-
-    collect(A,B,C) ::= collect(collect(A,B),C)
 
-  Since this function calls THD::change_item_tree() on the passed Item **
-  pointers, it is necessary to pass the original Item **'s, not copies.
-  Otherwise their values will not be properly restored (see BUG#20769).
-  If the items are not consecutive (eg. args[2] and args[5]), use the
-  item_sep argument, ie.
-
-    agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
-
-*/
-
-bool agg_item_charsets(DTCollation &coll, const char *fname,
-                       Item **args, uint nargs, uint flags, int item_sep)
+bool agg_item_set_converter(DTCollation &coll, const char *fname,
+                            Item **args, uint nargs, uint flags, int item_sep)
 {
   Item **arg, *safe_args[2];
-  if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
-    return TRUE;
 
   /*
     For better error reporting: save the first and the second argument.
@@ -1711,6 +1680,47 @@ bool agg_item_charsets(DTCollation &coll
 }
 
 
+/* 
+  Collect arguments' character sets together.
+  We allow to apply automatic character set conversion in some cases.
+  The conditions when conversion is possible are:
+  - arguments A and B have different charsets
+  - A wins according to coercibility rules
+    (i.e. a column is stronger than a string constant,
+     an explicit COLLATE clause is stronger than a column)
+  - character set of A is either superset for character set of B,
+    or B is a string constant which can be converted into the
+    character set of A without data loss.
+    
+  If all of the above is true, then it's possible to convert
+  B into the character set of A, and then compare according
+  to the collation of A.
+  
+  For functions with more than two arguments:
+
+    collect(A,B,C) ::= collect(collect(A,B),C)
+
+  Since this function calls THD::change_item_tree() on the passed Item **
+  pointers, it is necessary to pass the original Item **'s, not copies.
+  Otherwise their values will not be properly restored (see BUG#20769).
+  If the items are not consecutive (eg. args[2] and args[5]), use the
+  item_sep argument, ie.
+
+    agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
+
+*/
+
+bool agg_item_charsets(DTCollation &coll, const char *fname,
+                       Item **args, uint nargs, uint flags, int item_sep)
+{
+  Item **arg, *safe_args[2];
+  if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
+    return TRUE;
+
+  return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep);
+}
+
+
 void Item_ident_for_show::make_field(Send_field *tmp_field)
 {
   tmp_field->table_name= tmp_field->org_table_name= table_name;

=== modified file 'sql/item.h'
--- a/sql/item.h	2009-01-16 14:48:41 +0000
+++ b/sql/item.h	2009-02-17 13:40:55 +0000
@@ -1169,6 +1169,8 @@ bool agg_item_collations(DTCollation &c,
                          Item **items, uint nitems, uint flags, int item_sep);
 bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
                                         Item **items, uint nitems, uint flags);
+bool agg_item_set_converter(DTCollation &coll, const char *fname,
+                            Item **args, uint nargs, uint flags, int item_sep);
 bool agg_item_charsets(DTCollation &c, const char *name,
                        Item **items, uint nitems, uint flags, int item_sep);
 

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2009-01-15 11:08:09 +0000
+++ b/sql/item_cmpfunc.cc	2009-02-17 13:40:55 +0000
@@ -490,7 +490,8 @@ int Arg_comparator::set_compare_func(Ite
 	my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
 	return 1;
       }
-      comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
+      if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)))
+        return 1;
     }
     break;
   }
@@ -835,6 +836,16 @@ int Arg_comparator::set_cmp_func(Item_bo
     get_value_func= &get_time_value;
     return 0;
   }
+  else if (type == STRING_RESULT &&
+           (*a)->result_type() == STRING_RESULT &&
+           (*b)->result_type() == STRING_RESULT)
+  {
+    DTCollation coll;
+    coll.set((*a)->collation.collation);
+    if (agg_item_set_converter(coll, owner_arg->func_name(),
+                               b, 1, MY_COLL_CMP_CONV, 1))
+      return 1;
+  }
 
   return set_compare_func(owner_arg, type);
 }

Thread
bzr commit into mysql-5.0-bugteam branch (Sergey.Glukhov:2733)Bug#37601Sergey Glukhov17 Feb