Commit 7614eb0d authored by unknown's avatar unknown

Bug#21505 Create view - illegal mix of collation for operation 'UNION'

  
  The problem was that any VIEW columns had always implicit derivation.
  Fix: derivation is now copied from the original expression
  given in VIEW definition.
  For example:
  - a VIEW column which comes from a string constant
    in CREATE VIEW definition have now coercible derivation.
  - a VIEW column having COLLATE clause
    in CREATE VIEW definition have now explicit derivation.


mysql-test/r/ctype_utf8.result:
  Adding test case
mysql-test/t/ctype_utf8.test:
  Adding test case
sql/field.cc:
  Copying derivation from item to field.
sql/field.h:
  Adding derivation and methods to get/set it into Field.
sql/item.cc:
  Copying derivation from field to item.
sql/item.h:
  Moving "enum Derivation" declaration from item.h to mysql_priv.h
sql/mysql_priv.h:
  Moving "enum Derivation" declaration from item.h to mysql_priv.h
sql/sql_select.cc:
  Copying derivation from item to field in
  create_tmp_field_from_item() and create_tmp_field().
parent a39b8a06
...@@ -1536,6 +1536,32 @@ set @a:=null; ...@@ -1536,6 +1536,32 @@ set @a:=null;
execute my_stmt using @a; execute my_stmt using @a;
a b a b
drop table if exists t1; drop table if exists t1;
drop table if exists t1;
drop view if exists v1, v2;
set names utf8;
create table t1(col1 varchar(12) character set utf8 collate utf8_unicode_ci);
insert into t1 values('t1_val');
create view v1 as select 'v1_val' as col1;
select coercibility(col1), collation(col1) from v1;
coercibility(col1) collation(col1)
4 utf8_general_ci
create view v2 as select col1 from v1 union select col1 from t1;
select coercibility(col1), collation(col1)from v2;
coercibility(col1) collation(col1)
2 utf8_unicode_ci
2 utf8_unicode_ci
drop view v1, v2;
create view v1 as select 'v1_val' collate utf8_swedish_ci as col1;
select coercibility(col1), collation(col1) from v1;
coercibility(col1) collation(col1)
0 utf8_swedish_ci
create view v2 as select col1 from v1 union select col1 from t1;
select coercibility(col1), collation(col1) from v2;
coercibility(col1) collation(col1)
0 utf8_swedish_ci
0 utf8_swedish_ci
drop view v1, v2;
drop table t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
colA int(11) NOT NULL, colA int(11) NOT NULL,
colB varchar(255) character set utf8 NOT NULL, colB varchar(255) character set utf8 NOT NULL,
......
...@@ -1228,6 +1228,30 @@ set @a:=null; ...@@ -1228,6 +1228,30 @@ set @a:=null;
execute my_stmt using @a; execute my_stmt using @a;
drop table if exists t1; drop table if exists t1;
#
# Bug#21505 Create view - illegal mix of collation for operation 'UNION'
#
--disable_warnings
drop table if exists t1;
drop view if exists v1, v2;
--enable_warnings
set names utf8;
create table t1(col1 varchar(12) character set utf8 collate utf8_unicode_ci);
insert into t1 values('t1_val');
create view v1 as select 'v1_val' as col1;
select coercibility(col1), collation(col1) from v1;
create view v2 as select col1 from v1 union select col1 from t1;
select coercibility(col1), collation(col1)from v2;
drop view v1, v2;
create view v1 as select 'v1_val' collate utf8_swedish_ci as col1;
select coercibility(col1), collation(col1) from v1;
create view v2 as select col1 from v1 union select col1 from t1;
select coercibility(col1), collation(col1) from v2;
drop view v1, v2;
drop table t1;
# #
# Bug#19960: Inconsistent results when joining # Bug#19960: Inconsistent results when joining
# InnoDB tables using partial UTF8 indexes # InnoDB tables using partial UTF8 indexes
......
...@@ -1399,6 +1399,7 @@ Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, ...@@ -1399,6 +1399,7 @@ Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
field_charset=charset; field_charset=charset;
if (charset->state & MY_CS_BINSORT) if (charset->state & MY_CS_BINSORT)
flags|=BINARY_FLAG; flags|=BINARY_FLAG;
field_derivation= DERIVATION_IMPLICIT;
} }
......
...@@ -302,6 +302,9 @@ public: ...@@ -302,6 +302,9 @@ public:
virtual CHARSET_INFO *sort_charset(void) const { return charset(); } virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
virtual bool has_charset(void) const { return FALSE; } virtual bool has_charset(void) const { return FALSE; }
virtual void set_charset(CHARSET_INFO *charset) { } virtual void set_charset(CHARSET_INFO *charset) { }
virtual enum Derivation derivation(void) const
{ return DERIVATION_IMPLICIT; }
virtual void set_derivation(enum Derivation derivation) { }
bool set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code, bool set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code,
int cuted_increment); int cuted_increment);
bool check_int(const char *str, int length, const char *int_end, bool check_int(const char *str, int length, const char *int_end,
...@@ -373,6 +376,7 @@ public: ...@@ -373,6 +376,7 @@ public:
class Field_str :public Field { class Field_str :public Field {
protected: protected:
CHARSET_INFO *field_charset; CHARSET_INFO *field_charset;
enum Derivation field_derivation;
public: public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
...@@ -387,6 +391,9 @@ public: ...@@ -387,6 +391,9 @@ public:
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
CHARSET_INFO *charset(void) const { return field_charset; } CHARSET_INFO *charset(void) const { return field_charset; }
void set_charset(CHARSET_INFO *charset) { field_charset=charset; } void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
enum Derivation derivation(void) const { return field_derivation; }
virtual void set_derivation(enum Derivation derivation_arg)
{ field_derivation= derivation_arg; }
bool binary() const { return field_charset == &my_charset_bin; } bool binary() const { return field_charset == &my_charset_bin; }
uint32 max_length() { return field_length; } uint32 max_length() { return field_length; }
friend class create_field; friend class create_field;
......
...@@ -1622,7 +1622,7 @@ void Item_field::set_field(Field *field_par) ...@@ -1622,7 +1622,7 @@ void Item_field::set_field(Field *field_par)
db_name= field_par->table->s->db; db_name= field_par->table->s->db;
alias_name_used= field_par->table->alias_name_used; alias_name_used= field_par->table->alias_name_used;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
collation.set(field_par->charset(), DERIVATION_IMPLICIT); collation.set(field_par->charset(), field_par->derivation());
fixed= 1; fixed= 1;
} }
......
...@@ -27,19 +27,7 @@ class Item_field; ...@@ -27,19 +27,7 @@ class Item_field;
/* /*
"Declared Type Collation" "Declared Type Collation"
A combination of collation and its derivation. A combination of collation and its derivation.
*/
enum Derivation
{
DERIVATION_IGNORABLE= 5,
DERIVATION_COERCIBLE= 4,
DERIVATION_SYSCONST= 3,
DERIVATION_IMPLICIT= 2,
DERIVATION_NONE= 1,
DERIVATION_EXPLICIT= 0
};
/*
Flags for collation aggregation modes: Flags for collation aggregation modes:
MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
......
...@@ -96,6 +96,17 @@ extern CHARSET_INFO *system_charset_info, *files_charset_info ; ...@@ -96,6 +96,17 @@ extern CHARSET_INFO *system_charset_info, *files_charset_info ;
extern CHARSET_INFO *national_charset_info, *table_alias_charset; extern CHARSET_INFO *national_charset_info, *table_alias_charset;
enum Derivation
{
DERIVATION_IGNORABLE= 5,
DERIVATION_COERCIBLE= 4,
DERIVATION_SYSCONST= 3,
DERIVATION_IMPLICIT= 2,
DERIVATION_NONE= 1,
DERIVATION_EXPLICIT= 0
};
typedef struct my_locale_st typedef struct my_locale_st
{ {
const char *name; const char *name;
......
...@@ -8560,6 +8560,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, ...@@ -8560,6 +8560,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
item->collation.collation); item->collation.collation);
else else
new_field= item->make_string_field(table); new_field= item->make_string_field(table);
new_field->set_derivation(item->collation.derivation);
break; break;
case DECIMAL_RESULT: case DECIMAL_RESULT:
new_field= new Field_new_decimal(item->max_length, maybe_null, item->name, new_field= new Field_new_decimal(item->max_length, maybe_null, item->name,
...@@ -8735,7 +8736,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -8735,7 +8736,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
(make_copy_field ? 0 : copy_func), (make_copy_field ? 0 : copy_func),
modify_item, convert_blob_length); modify_item, convert_blob_length);
case Item::TYPE_HOLDER: case Item::TYPE_HOLDER:
return ((Item_type_holder *)item)->make_field_by_type(table); result= ((Item_type_holder *)item)->make_field_by_type(table);
result->set_derivation(item->collation.derivation);
return result;
default: // Dosen't have to be stored default: // Dosen't have to be stored
return 0; return 0;
} }
......
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