← Back to team overview

maria-developers team mailing list archive

Please review MDEV-10181 Illegal mix of collation for a field and an ASCII string as a view field

 

Hi Sergei,

Please review a patch for MDEV-10181.

Thanks!
diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result
index c84da0d..2555749 100644
--- a/mysql-test/r/ctype_recoding.result
+++ b/mysql-test/r/ctype_recoding.result
@@ -277,9 +277,40 @@ CREATE TABLE t1 ( a VARCHAR(1) );
 INSERT INTO t1 VALUES ('m'),('n');
 CREATE VIEW v1 AS SELECT 'w' ;
 SELECT * FROM t1 WHERE a < ALL ( SELECT * FROM v1 );
-ERROR HY000: Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation '<='
+a
+m
+n
 drop view v1;
 drop table t1;
 SET character_set_connection = default;
 SET optimizer_switch= default;
 #End of 5.3 tests
+#
+# Start of 5.5 tests
+#
+#
+# MDEV-10181 Illegal mix of collation for a field and an ASCII string as a view field
+#
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES ('A'),('a'),('B'),('b');
+CREATE VIEW v1 AS SELECT 'a';
+SELECT * FROM v1,t1 where t1.a=v1.a;
+a	a
+a	A
+a	a
+DROP VIEW v1;
+DROP TABLE t1;
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES ('a'),('b'),('c');
+CREATE VIEW v1 AS SELECT 'a' AS a UNION SELECT 'b';
+SELECT * FROM v1,t1 WHERE t1.a=v1.a;
+a	a
+a	a
+b	b
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# End of 5.5 tests
+#
diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test
index ee07ef2..81c04fc 100644
--- a/mysql-test/t/ctype_recoding.test
+++ b/mysql-test/t/ctype_recoding.test
@@ -220,7 +220,6 @@ SET character_set_connection = utf8;
 CREATE TABLE t1 ( a VARCHAR(1) );
 INSERT INTO t1 VALUES ('m'),('n');
 CREATE VIEW v1 AS SELECT 'w' ;
---error ER_CANT_AGGREGATE_2COLLATIONS
 SELECT * FROM t1 WHERE a < ALL ( SELECT * FROM v1 );
 drop view v1;
 drop table t1;
@@ -228,3 +227,30 @@ SET character_set_connection = default;
 SET optimizer_switch= default;
 
 --echo #End of 5.3 tests
+
+--echo #
+--echo # Start of 5.5 tests
+--echo #
+
+--echo #
+--echo # MDEV-10181 Illegal mix of collation for a field and an ASCII string as a view field
+--echo #
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES ('A'),('a'),('B'),('b');
+CREATE VIEW v1 AS SELECT 'a';
+SELECT * FROM v1,t1 where t1.a=v1.a;
+DROP VIEW v1;
+DROP TABLE t1;
+
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES ('a'),('b'),('c');
+CREATE VIEW v1 AS SELECT 'a' AS a UNION SELECT 'b';
+SELECT * FROM v1,t1 WHERE t1.a=v1.a;
+DROP VIEW v1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 5.5 tests
+--echo #
diff --git a/sql/field.cc b/sql/field.cc
index ceea089..a0686fb 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1701,6 +1701,7 @@ Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
   if (charset_arg->state & MY_CS_BINSORT)
     flags|=BINARY_FLAG;
   field_derivation= DERIVATION_IMPLICIT;
+  field_repertoire= my_charset_repertoire(charset_arg);
 }
 
 
diff --git a/sql/field.h b/sql/field.h
index f761aa8..fdf229e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -580,11 +580,12 @@ class Field
   { return binary() ? &my_charset_bin : charset(); }
   virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
   virtual bool has_charset(void) const { return FALSE; }
-  virtual void set_charset(CHARSET_INFO *charset_arg) { }
   virtual enum Derivation derivation(void) const
   { return DERIVATION_IMPLICIT; }
   virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
-  virtual void set_derivation(enum Derivation derivation_arg) { }
+  virtual void set_derivation(enum Derivation derivation_arg,
+                              uint repertoire_arg)
+  { }
   virtual int set_time() { return 1; }
   void set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code,
                    int cuted_increment);
@@ -775,8 +776,10 @@ class Field_num :public Field {
 
 class Field_str :public Field {
 protected:
+  // TODO-10.2: Reuse DTCollation instead of these three members
   CHARSET_INFO *field_charset;
   enum Derivation field_derivation;
+  uint field_repertoire;
 public:
   Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
 	    uchar null_bit_arg, utype unireg_check_arg,
@@ -799,15 +802,15 @@ class Field_str :public Field {
   int  store_decimal(const my_decimal *);
   int  store(const char *to,uint length,CHARSET_INFO *cs)=0;
   uint size_of() const { return sizeof(*this); }
-  uint repertoire(void) const
-  {
-    return my_charset_repertoire(field_charset);
-  }
+  uint repertoire(void) const { return field_repertoire; }
   CHARSET_INFO *charset(void) const { return field_charset; }
-  void set_charset(CHARSET_INFO *charset_arg) { field_charset= charset_arg; }
   enum Derivation derivation(void) const { return field_derivation; }
-  virtual void set_derivation(enum Derivation derivation_arg)
-  { field_derivation= derivation_arg; }
+  void set_derivation(enum Derivation derivation_arg,
+                      uint repertoire_arg)
+  {
+    field_derivation= derivation_arg;
+    field_repertoire= repertoire_arg;
+  }
   bool binary() const { return field_charset == &my_charset_bin; }
   uint32 max_display_length() { return field_length; }
   friend class Create_field;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 91aecad..613cbb2 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -14586,7 +14586,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
                                      item->collation.collation);
     else
       new_field= item->make_string_field(table);
-    new_field->set_derivation(item->collation.derivation);
+    new_field->set_derivation(item->collation.derivation,
+                              item->collation.repertoire);
     break;
   case DECIMAL_RESULT:
     new_field= Field_new_decimal::create_from_item(item);
@@ -14825,7 +14826,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
                                        modify_item, convert_blob_length);
   case Item::TYPE_HOLDER:  
     result= ((Item_type_holder *)item)->make_field_by_type(table);
-    result->set_derivation(item->collation.derivation);
+    result->set_derivation(item->collation.derivation,
+                           item->collation.repertoire);
     return result;
   default:					// Dosen't have to be stored
     return 0;

Follow ups