summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bar@mysql.com/bar.intranet.mysql.r18.ru>2006-11-09 14:41:34 +0400
committerunknown <bar@mysql.com/bar.intranet.mysql.r18.ru>2006-11-09 14:41:34 +0400
commit7614eb0d1db4819ec6f1c3c59196d1dcb0d0c8d5 (patch)
tree4128d47fe2a8d79671addfc8d18cbde6885ce7cd
parenta39b8a064ed1cd200e34be4ee0af078da7b2412c (diff)
downloadmariadb-git-7614eb0d1db4819ec6f1c3c59196d1dcb0d0c8d5.tar.gz
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().
-rw-r--r--mysql-test/r/ctype_utf8.result26
-rw-r--r--mysql-test/t/ctype_utf8.test24
-rw-r--r--sql/field.cc1
-rw-r--r--sql/field.h7
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h12
-rw-r--r--sql/mysql_priv.h11
-rw-r--r--sql/sql_select.cc5
8 files changed, 74 insertions, 14 deletions
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index d1a3839d6e9..4eb74510c93 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -1536,6 +1536,32 @@ set @a:=null;
execute my_stmt using @a;
a b
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 (
colA int(11) NOT NULL,
colB varchar(255) character set utf8 NOT NULL,
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 812965d648a..71259dab0c9 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1228,6 +1228,30 @@ set @a:=null;
execute my_stmt using @a;
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
# InnoDB tables using partial UTF8 indexes
diff --git a/sql/field.cc b/sql/field.cc
index 745e48460b5..f04efc66dfd 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1399,6 +1399,7 @@ Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
field_charset=charset;
if (charset->state & MY_CS_BINSORT)
flags|=BINARY_FLAG;
+ field_derivation= DERIVATION_IMPLICIT;
}
diff --git a/sql/field.h b/sql/field.h
index b79c2bf77a8..0f845f6c2f9 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -302,6 +302,9 @@ public:
virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
virtual bool has_charset(void) const { return FALSE; }
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,
int cuted_increment);
bool check_int(const char *str, int length, const char *int_end,
@@ -373,6 +376,7 @@ public:
class Field_str :public Field {
protected:
CHARSET_INFO *field_charset;
+ enum Derivation field_derivation;
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
@@ -387,6 +391,9 @@ public:
uint size_of() const { return sizeof(*this); }
CHARSET_INFO *charset(void) const { return field_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; }
uint32 max_length() { return field_length; }
friend class create_field;
diff --git a/sql/item.cc b/sql/item.cc
index d56ca95093b..f3081551299 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1622,7 +1622,7 @@ void Item_field::set_field(Field *field_par)
db_name= field_par->table->s->db;
alias_name_used= field_par->table->alias_name_used;
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;
}
diff --git a/sql/item.h b/sql/item.h
index 0cfb0b01fd8..b5490f9e814 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -27,19 +27,7 @@ class Item_field;
/*
"Declared Type Collation"
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:
MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 165bedb3659..683f111e4f3 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -96,6 +96,17 @@ extern CHARSET_INFO *system_charset_info, *files_charset_info ;
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
{
const char *name;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 75cfff4cbb6..abadd0697ac 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8560,6 +8560,7 @@ 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);
break;
case DECIMAL_RESULT:
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),
modify_item, convert_blob_length);
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
return 0;
}