diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 34c7752798da2da257c7c4602a28a7bebfeb3c93..2865a019f4bf2f11f2e5822cacbf7e3074591070 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1,4 +1,5 @@
 drop table if exists t1;
+set names latin1;
 select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
 hello	'hello'	""hello""	'h'e'l'l'o'	hel"lo	hel'lo
 hello	'hello'	""hello""	'h'e'l'l'o'	hel"lo	hel'lo
@@ -249,6 +250,34 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf');
 SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password");
 1
 DROP TABLE t1;
+select 1=_latin1'1';
+1=_latin1'1'
+1
+select _latin1'1'=1;
+_latin1'1'=1
+1
+select _latin2'1'=1;
+_latin2'1'=1
+1
+select 1=_latin2'1';
+1=_latin2'1'
+1
+select _latin1'1'=_latin2'1';
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation '='
+select row('a','b','c') = row('a','b','c');
+row('a','b','c') = row('a','b','c')
+1
+select row('A','b','c') = row('a','b','c');
+row('A','b','c') = row('a','b','c')
+1
+select row('A' COLLATE latin1_bin,'b','c') = row('a','b','c');
+row('A' COLLATE latin1_bin,'b','c') = row('a','b','c')
+0
+select row('A','b','c') = row('a' COLLATE latin1_bin,'b','c');
+row('A','b','c') = row('a' COLLATE latin1_bin,'b','c')
+0
+select row('A' COLLATE latin1_general_ci,'b','c') = row('a' COLLATE latin1_bin,'b','c');
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation '='
 select POSITION(_latin1'B' IN _latin1'abcd');
 POSITION(_latin1'B' IN _latin1'abcd')
 2
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index a898d3551d75ca3ecb2808f5e569238223f1a06a..7dc08dece55f3967ddd3eabbd6d2c7e6b8196bbe 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -8,6 +8,8 @@
 drop table if exists t1;
 --enable_warnings
 
+set names latin1;
+
 select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
 select 'hello' 'monty';
 select length('\n\t\r\b\0\_\%\\');
@@ -136,6 +138,21 @@ DROP TABLE t1;
 #
 # Test collation and coercibility
 #
+
+select 1=_latin1'1';
+select _latin1'1'=1;
+select _latin2'1'=1;
+select 1=_latin2'1';
+--error 1265
+select _latin1'1'=_latin2'1';
+select row('a','b','c') = row('a','b','c');
+select row('A','b','c') = row('a','b','c');
+select row('A' COLLATE latin1_bin,'b','c') = row('a','b','c');
+select row('A','b','c') = row('a' COLLATE latin1_bin,'b','c');
+--error 1265
+select row('A' COLLATE latin1_general_ci,'b','c') = row('a' COLLATE latin1_bin,'b','c');
+
+
 select POSITION(_latin1'B' IN _latin1'abcd');
 select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin);
 select POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd');
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index a19311cd2fe3b8c2c8716bd7b48aa7f4386c23d0..11a6e6604bf015ed5c4dbd0fe6c0376982ff1e6d 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -109,15 +109,6 @@ static bool convert_constant_item(Field *field, Item **item)
 }
 
 
-bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables,
-				 Item ** ref)
-{
-  if (Item_int_func::fix_fields(thd, tables, ref))
-    return 1;
-  return 0;
-}
-
-
 void Item_bool_func2::fix_length_and_dec()
 {
   max_length= 1;				     // Function returns 0 or 1
@@ -191,8 +182,6 @@ void Item_bool_func2::fix_length_and_dec()
       {
 	cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
 			 INT_RESULT);		// Works for all types.
-	cmp_collation.set(&my_charset_bin, 
-			  DERIVATION_NONE);	// For test in fix_fields
 	return;
       }
     }
@@ -206,23 +195,11 @@ void Item_bool_func2::fix_length_and_dec()
       {
 	cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
 			 INT_RESULT); // Works for all types.
-	cmp_collation.set(&my_charset_bin,
-			  DERIVATION_NONE);	// For test in fix_fields
 	return;
       }
     }
   }
   set_cmp_func();
-  /*
-    We must set cmp_charset here as we may be called from for an automatic
-    generated item, like in natural join
-  */
-  if (cmp_collation.set(args[0]->collation, args[1]->collation))
-  {
-    /* set_cmp_charset() failed */
-    my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
-    return;
-  }
 }
 
 
@@ -252,6 +229,18 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
       comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
     }
   }
+  else if (type == STRING_RESULT)
+  {
+    /*
+      We must set cmp_charset here as we may be called from for an automatic
+      generated item, like in natural join
+    */
+    if (cmp_collation.set((*a)->collation, (*b)->collation))
+    {
+      my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name());
+      return 1;
+    }
+  }
   return 0;
 }
 
@@ -264,7 +253,7 @@ int Arg_comparator::compare_string()
     if ((res2= (*b)->val_str(&owner->tmp_value2)))
     {
       owner->null_value= 0;
-      return sortcmp(res1,res2,owner->cmp_collation.collation);
+      return sortcmp(res1,res2,cmp_collation.collation);
     }
   }
   owner->null_value= 1;
@@ -278,7 +267,7 @@ int Arg_comparator::compare_e_string()
   res2= (*b)->val_str(&owner->tmp_value2);
   if (!res1 || !res2)
     return test(res1 == res2);
-  return test(sortcmp(res1, res2, owner->cmp_collation.collation) == 0);
+  return test(sortcmp(res1, res2, cmp_collation.collation) == 0);
 }
 
 
@@ -502,7 +491,7 @@ longlong Item_func_strcmp::val_int()
     null_value=1;
     return 0;
   }
-  int value= sortcmp(a,b,cmp_collation.collation);
+  int value= sortcmp(a,b,cmp.cmp_collation.collation);
   null_value=0;
   return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
 }
@@ -1893,7 +1882,7 @@ longlong Item_func_like::val_int()
   null_value=0;
   if (canDoTurboBM)
     return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
-  return my_wildcmp(cmp_collation.collation,
+  return my_wildcmp(cmp.cmp_collation.collation,
 		    res->ptr(),res->ptr()+res->length(),
 		    res2->ptr(),res2->ptr()+res2->length(),
 		    escape,wild_one,wild_many) ? 0 : 1;
@@ -2103,7 +2092,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
 
   *splm1 = pattern_len;
 
-  if (cmp_collation.collation == &my_charset_bin)
+  if (cmp.cmp_collation.collation == &my_charset_bin)
   {
     int i;
     for (i = pattern_len - 2; i >= 0; i--)
@@ -2206,7 +2195,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
   for (i = bmBc; i < end; i++)
     *i = pattern_len;
 
-  if (cmp_collation.collation == &my_charset_bin)
+  if (cmp.cmp_collation.collation == &my_charset_bin)
   {
     for (j = 0; j < plm1; j++)
       bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
@@ -2237,7 +2226,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
   const int tlmpl= text_len - pattern_len;
 
   /* Searching */
-  if (cmp_collation.collation == &my_charset_bin)
+  if (cmp.cmp_collation.collation == &my_charset_bin)
   {
     while (j <= tlmpl)
     {
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 1d93c9b6892e752159909f807903cc6a18b7fa5b..8309cd25a720798aaaf7010797978e0fbdfa9527 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -35,6 +35,8 @@ class Arg_comparator: public Sql_alloc
   Arg_comparator *comparators;   // used only for compare_row()
 
 public:
+  DTCollation cmp_collation;
+
   Arg_comparator() {};
   Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};
 
@@ -112,13 +114,10 @@ class Item_bool_func2 :public Item_int_func
 protected:
   Arg_comparator cmp;
   String tmp_value1,tmp_value2;
-  DTCollation cmp_collation;
 
 public:
   Item_bool_func2(Item *a,Item *b):
-    Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1)
-    { cmp_collation.set(0,DERIVATION_NONE);}
-  bool fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref);
+    Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
   void fix_length_and_dec();
   void set_cmp_func()
   {