mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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.
This commit is contained in:

parent
9870d87f25
commit
aa1c8a5826
@ -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;
|
|||||||
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,
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
sql/item.h
12
sql/item.h
@ -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 ;
|
|||||||
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,
|
|||||||
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,
|
|||||||
(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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user