diff options
-rw-r--r-- | mysql-test/suite/innodb/r/instant_alter_charset.result | 11 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/instant_alter_charset.test | 14 | ||||
-rw-r--r-- | sql/field.cc | 18 | ||||
-rw-r--r-- | sql/field.h | 38 | ||||
-rw-r--r-- | sql/handler.h | 4 | ||||
-rw-r--r-- | sql/sql_partition.cc | 4 | ||||
-rw-r--r-- | sql/sql_table.cc | 80 | ||||
-rw-r--r-- | sql/sql_table.h | 2 | ||||
-rw-r--r-- | sql/sql_type.cc | 158 | ||||
-rw-r--r-- | sql/sql_type.h | 139 | ||||
-rw-r--r-- | sql/table.cc | 2 | ||||
-rw-r--r-- | storage/federatedx/ha_federatedx.cc | 4 |
12 files changed, 356 insertions, 118 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter_charset.result b/mysql-test/suite/innodb/r/instant_alter_charset.result index 6b60c79b558..8b1171191fa 100644 --- a/mysql-test/suite/innodb/r/instant_alter_charset.result +++ b/mysql-test/suite/innodb/r/instant_alter_charset.result @@ -2032,3 +2032,14 @@ ALTER TABLE t1 MODIFY a VARCHAR(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; INSERT INTO t1 VALUES ('a'); DROP TABLE t1; +# +# MDEV-22775 [HY000][1553] Changing name of primary key column with foreign key constraint fails. +# +create table t1 (id int primary key) engine=innodb default charset=utf8; +create table t2 (input_id int primary key, id int not null, +key a (id), +constraint a foreign key (id) references t1 (id) +)engine=innodb default charset=utf8; +alter table t1 change id id2 int; +drop table t2; +drop table t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_charset.test b/mysql-test/suite/innodb/t/instant_alter_charset.test index a5ddd49830c..1d444b88a7f 100644 --- a/mysql-test/suite/innodb/t/instant_alter_charset.test +++ b/mysql-test/suite/innodb/t/instant_alter_charset.test @@ -843,3 +843,17 @@ ALTER TABLE t1 MODIFY a VARCHAR(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; INSERT INTO t1 VALUES ('a'); DROP TABLE t1; + + +--echo # +--echo # MDEV-22775 [HY000][1553] Changing name of primary key column with foreign key constraint fails. +--echo # + +create table t1 (id int primary key) engine=innodb default charset=utf8; +create table t2 (input_id int primary key, id int not null, + key a (id), + constraint a foreign key (id) references t1 (id) +)engine=innodb default charset=utf8; +alter table t1 change id id2 int; +drop table t2; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 7aea222ca07..89c51288de8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -11076,16 +11076,26 @@ Column_definition::Column_definition(THD *thd, Field *old_field, CREATE TABLE t1 (a INT) AS SELECT a FROM t2; See Type_handler::Column_definition_redefine_stage1() for data type specific code. + + @param this - The field definition corresponding to the expression + in the "AS SELECT.." part. + + @param dup_field - The field definition from the "CREATE TABLE (...)" part. + It has already underwent prepare_stage1(), so + must be fully initialized: + -- dup_field->charset is set and BINARY + sorting style is applied, see find_bin_collation(). + + @param file - The table handler */ void Column_definition::redefine_stage1_common(const Column_definition *dup_field, - const handler *file, - const Schema_specification_st *schema) + const handler *file) { set_handler(dup_field->type_handler()); default_value= dup_field->default_value; - charset= dup_field->charset ? dup_field->charset : - schema->default_table_charset; + DBUG_ASSERT(dup_field->charset); // Set by prepare_stage1() + charset= dup_field->charset; length= dup_field->char_length; pack_length= dup_field->pack_length; key_length= dup_field->key_length; diff --git a/sql/field.h b/sql/field.h index b04e29ac6fb..6cb19d1e238 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4631,6 +4631,11 @@ public: void frm_pack_charset(uchar *buff) const; void frm_unpack_basic(const uchar *buff); bool frm_unpack_charset(TABLE_SHARE *share, const uchar *buff); + CHARSET_INFO *explicit_or_derived_charset(const Column_derived_attributes + *derived_attr) const + { + return charset ? charset : derived_attr->charset(); + } }; @@ -4765,6 +4770,15 @@ public: void create_length_to_internal_length_bit(); void create_length_to_internal_length_newdecimal(); + /* + Prepare the "charset" member for string data types, + such as CHAR, VARCHAR, TEXT, ENUM, SET: + - derive the charset if not specified explicitly + - find a _bin collation if the BINARY comparison style was specified, e.g.: + CREATE TABLE t1 (a VARCHAR(10) BINARY) CHARSET utf8; + */ + bool prepare_charset_for_string(const Column_derived_attributes *dattr); + /** Prepare a SET/ENUM field. Create "interval" from "interval_list" if needed, and adjust "length". @@ -4800,7 +4814,13 @@ public: bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root); bool prepare_stage1(THD *thd, MEM_ROOT *mem_root, - handler *file, ulonglong table_flags); + handler *file, ulonglong table_flags, + const Column_derived_attributes *derived_attr); + void prepare_stage1_simple(CHARSET_INFO *cs) + { + charset= cs; + create_length_to_internal_length_simple(); + } bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root, handler *file, ulonglong table_flags); bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root, @@ -4808,15 +4828,19 @@ public: bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root, handler *file, ulonglong table_flags); + bool bulk_alter(const Column_derived_attributes *derived_attr, + const Column_bulk_alter_attributes *bulk_attr) + { + return type_handler()->Column_definition_bulk_alter(this, + derived_attr, + bulk_attr); + } void redefine_stage1_common(const Column_definition *dup_field, - const handler *file, - const Schema_specification_st *schema); - bool redefine_stage1(const Column_definition *dup_field, const handler *file, - const Schema_specification_st *schema) + const handler *file); + bool redefine_stage1(const Column_definition *dup_field, const handler *file) { const Type_handler *handler= dup_field->type_handler(); - return handler->Column_definition_redefine_stage1(this, dup_field, - file, schema); + return handler->Column_definition_redefine_stage1(this, dup_field, file); } bool prepare_stage2(handler *handler, ulonglong table_flags); bool prepare_stage2_blob(handler *handler, diff --git a/sql/handler.h b/sql/handler.h index 81a18137955..891187db171 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2092,7 +2092,7 @@ public: struct Table_scope_and_contents_source_pod_st // For trivial members { - CHARSET_INFO *table_charset; + CHARSET_INFO *alter_table_convert_to_charset; LEX_CUSTRING tabledef_version; LEX_CSTRING connect_string; LEX_CSTRING comment; @@ -2237,7 +2237,7 @@ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st, DBUG_ASSERT(cs); if (check_conflicting_charset_declarations(cs)) return true; - table_charset= default_table_charset= cs; + alter_table_convert_to_charset= default_table_charset= cs; used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET); return false; } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 7ed1eb7aa52..373326c75c6 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2388,6 +2388,8 @@ static int add_column_list_values(String *str, partition_info *part_info, */ if (create_info) { + const Column_derived_attributes + derived_attr(create_info->default_table_charset); Create_field *sql_field; if (!(sql_field= get_sql_field(field_name, @@ -2402,7 +2404,7 @@ static int add_column_list_values(String *str, partition_info *part_info, &need_cs_check)) return 1; if (need_cs_check) - field_cs= get_sql_field_charset(sql_field, create_info); + field_cs= sql_field->explicit_or_derived_charset(&derived_attr); else field_cs= NULL; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ac1984a074c..ea1a35a9ddd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2926,6 +2926,15 @@ bool check_duplicates_in_interval(const char *set_or_name, } +bool Column_definition:: + prepare_charset_for_string(const Column_derived_attributes *dattr) +{ + if (!charset) + charset= dattr->charset(); + return (flags & BINCMP_FLAG) && !(charset= find_bin_collation(charset)); +} + + bool Column_definition::prepare_stage2_blob(handler *file, ulonglong table_flags, uint field_flags) @@ -3007,38 +3016,6 @@ bool Column_definition::prepare_stage2(handler *file, } -/* - Get character set from field object generated by parser using - default values when not set. - - SYNOPSIS - get_sql_field_charset() - sql_field The sql_field object - create_info Info generated by parser - - RETURN VALUES - cs Character set -*/ - -CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field, - HA_CREATE_INFO *create_info) -{ - CHARSET_INFO *cs= sql_field->charset; - - if (!cs) - cs= create_info->default_table_charset; - /* - table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname - if we want change character set for all varchar/char columns. - But the table charset must not affect the BLOB fields, so don't - allow to change my_charset_bin to somethig else. - */ - if (create_info->table_charset && cs != &my_charset_bin) - cs= create_info->table_charset; - return cs; -} - - /** Modifies the first column definition whose SQL type is TIMESTAMP by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. @@ -3211,11 +3188,14 @@ bool Column_definition::prepare_stage1_bit(THD *thd, bool Column_definition::prepare_stage1(THD *thd, MEM_ROOT *mem_root, handler *file, - ulonglong table_flags) + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) { return type_handler()->Column_definition_prepare_stage1(thd, mem_root, this, file, - table_flags); + table_flags, + derived_attr); } @@ -3428,6 +3408,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, int select_field_count= C_CREATE_SELECT(create_table_mode); bool tmp_table= create_table_mode == C_ALTER_TABLE; bool is_hash_field_needed= false; + const Column_derived_attributes dattr(create_info->default_table_charset); + const Column_bulk_alter_attributes + battr(create_info->alter_table_convert_to_charset); DBUG_ENTER("mysql_prepare_create_table"); DBUG_EXECUTE_IF("test_pseudo_invisible",{ @@ -3484,26 +3467,27 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, for (field_no=0; (sql_field=it++) ; field_no++) { + /* Virtual fields are always NULL */ + if (sql_field->vcol_info) + sql_field->flags&= ~NOT_NULL_FLAG; + /* Initialize length from its original value (number of characters), which was set in the parser. This is necessary if we're executing a prepared statement for the second time. */ sql_field->length= sql_field->char_length; - /* Set field charset. */ - sql_field->charset= get_sql_field_charset(sql_field, create_info); - if ((sql_field->flags & BINCMP_FLAG) && - !(sql_field->charset= find_bin_collation(sql_field->charset))) - DBUG_RETURN(true); - /* Virtual fields are always NULL */ - if (sql_field->vcol_info) - sql_field->flags&= ~NOT_NULL_FLAG; + if (sql_field->bulk_alter(&dattr, &battr)) + DBUG_RETURN(true); if (sql_field->prepare_stage1(thd, thd->mem_root, - file, file->ha_table_flags())) + file, file->ha_table_flags(), + &dattr)) DBUG_RETURN(true); + DBUG_ASSERT(sql_field->charset); + if (sql_field->real_field_type() == MYSQL_TYPE_BIT && file->ha_table_flags() & HA_CAN_BIT_FIELD) total_uneven_bit_length+= sql_field->length & 7; @@ -3554,7 +3538,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (!(sql_field->flags & NOT_NULL_FLAG)) null_fields--; - if (sql_field->redefine_stage1(dup_field, file, create_info)) + if (sql_field->redefine_stage1(dup_field, file)) DBUG_RETURN(true); it2.remove(); // Remove first (create) definition @@ -4569,7 +4553,9 @@ bool Column_definition::prepare_blob_field(THD *thd) bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root) { - return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY) || + DBUG_ASSERT(charset); + const Column_derived_attributes dattr(&my_charset_bin); + return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY, &dattr) || prepare_stage2(NULL, HA_CAN_GEOMETRY); } @@ -11331,8 +11317,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd) { create_info.used_fields&= ~HA_CREATE_USED_CHARSET; create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; - create_info.default_table_charset= create_info.table_charset; - create_info.table_charset= 0; + create_info.default_table_charset= create_info.alter_table_convert_to_charset; + create_info.alter_table_convert_to_charset= 0; } /* diff --git a/sql/sql_table.h b/sql/sql_table.h index 35bff0873ea..62b61684286 100644 --- a/sql/sql_table.h +++ b/sql/sql_table.h @@ -252,8 +252,6 @@ bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db, const char *table_path=0); void close_cached_table(THD *thd, TABLE *table); void sp_prepare_create_field(THD *thd, Column_definition *sql_field); -CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field, - HA_CREATE_INFO *create_info); bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags); int write_bin_log(THD *thd, bool clear_error, char const *query, ulong query_length, diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 7dea9cdea4a..2abd724e153 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2671,9 +2671,12 @@ bool Type_handler:: MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { - def->create_length_to_internal_length_simple(); + def->prepare_stage1_simple(&my_charset_bin); return false; } @@ -2682,8 +2685,12 @@ bool Type_handler_null:: MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { + def->prepare_charset_for_string(derived_attr); def->create_length_to_internal_length_null(); return false; } @@ -2693,19 +2700,56 @@ bool Type_handler_row:: MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { + def->charset= &my_charset_bin; def->create_length_to_internal_length_null(); return false; } +bool Type_handler_temporal_result:: + Column_definition_prepare_stage1(THD *thd, + MEM_ROOT *mem_root, + Column_definition *def, + handler *file, + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const +{ + def->prepare_stage1_simple(&my_charset_numeric); + return false; +} + + +bool Type_handler_numeric:: + Column_definition_prepare_stage1(THD *thd, + MEM_ROOT *mem_root, + Column_definition *def, + handler *file, + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const +{ + def->prepare_stage1_simple(&my_charset_numeric); + return false; +} + bool Type_handler_newdecimal:: Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { + def->charset= &my_charset_numeric; def->create_length_to_internal_length_newdecimal(); return false; } @@ -2715,8 +2759,12 @@ bool Type_handler_bit:: MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { + def->charset= &my_charset_numeric; return def->prepare_stage1_bit(thd, mem_root, file, table_flags); } @@ -2725,9 +2773,13 @@ bool Type_handler_typelib:: MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { - return def->prepare_stage1_typelib(thd, mem_root, file, table_flags); + return def->prepare_charset_for_string(derived_attr) || + def->prepare_stage1_typelib(thd, mem_root, file, table_flags); } @@ -2736,9 +2788,13 @@ bool Type_handler_string_result:: MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { - return def->prepare_stage1_string(thd, mem_root, file, table_flags); + return def->prepare_charset_for_string(derived_attr) || + def->prepare_stage1_string(thd, mem_root, file, table_flags); } @@ -2748,8 +2804,12 @@ bool Type_handler_geometry:: MEM_ROOT *mem_root, Column_definition *def, handler *file, - ulonglong table_flags) const + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const { + def->charset= &my_charset_bin; def->create_length_to_internal_length_string(); return def->prepare_blob_field(thd); } @@ -2758,14 +2818,38 @@ bool Type_handler_geometry:: /*************************************************************************/ +bool Type_handler_general_purpose_string:: + Column_definition_bulk_alter(Column_definition *def, + const Column_derived_attributes + *derived_attr, + const Column_bulk_alter_attributes + *bulk_alter_attr) + const +{ + if (!bulk_alter_attr->alter_table_convert_to_charset()) + return false; // No "CONVERT TO" clause. + CHARSET_INFO *defcs= def->explicit_or_derived_charset(derived_attr); + DBUG_ASSERT(defcs); + /* + Handle 'ALTER TABLE t1 CONVERT TO CHARACTER SET csname'. + Change character sets for all varchar/char/text columns, + but do not touch varbinary/binary/blob columns. + */ + if (defcs != &my_charset_bin) + def->charset= bulk_alter_attr->alter_table_convert_to_charset(); + return false; +}; + + +/*************************************************************************/ + bool Type_handler:: Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const { - def->redefine_stage1_common(dup, file, schema); + def->redefine_stage1_common(dup, file); def->create_length_to_internal_length_simple(); return false; } @@ -2774,11 +2858,10 @@ bool Type_handler:: bool Type_handler_null:: Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const { - def->redefine_stage1_common(dup, file, schema); + def->redefine_stage1_common(dup, file); def->create_length_to_internal_length_null(); return false; } @@ -2787,11 +2870,10 @@ bool Type_handler_null:: bool Type_handler_newdecimal:: Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const { - def->redefine_stage1_common(dup, file, schema); + def->redefine_stage1_common(dup, file); def->create_length_to_internal_length_newdecimal(); return false; } @@ -2800,11 +2882,10 @@ bool Type_handler_newdecimal:: bool Type_handler_string_result:: Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const { - def->redefine_stage1_common(dup, file, schema); + def->redefine_stage1_common(dup, file); def->set_compression_method(dup->compression_method()); def->create_length_to_internal_length_string(); return false; @@ -2814,11 +2895,10 @@ bool Type_handler_string_result:: bool Type_handler_typelib:: Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const { - def->redefine_stage1_common(dup, file, schema); + def->redefine_stage1_common(dup, file); def->create_length_to_internal_length_typelib(); return false; } @@ -2827,11 +2907,10 @@ bool Type_handler_typelib:: bool Type_handler_bit:: Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const { - def->redefine_stage1_common(dup, file, schema); + def->redefine_stage1_common(dup, file); /* If we are replacing a field with a BIT field, we need to initialize pack_flag. @@ -7541,6 +7620,7 @@ Field *Type_handler_row:: uint32 flags) const { DBUG_ASSERT(attr->length == 0); +//DBUG_ASSERT(attr->charset == &my_charset_bin); DBUG_ASSERT(f_maybe_null(attr->pack_flag)); return new (mem_root) Field_row(rec.ptr(), name); } @@ -7553,6 +7633,7 @@ Field *Type_handler_olddecimal:: const Column_definition_attributes *attr, uint32 flags) const { +//DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_decimal(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), @@ -7570,6 +7651,7 @@ Field *Type_handler_newdecimal:: const Column_definition_attributes *attr, uint32 flags) const { +// DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_new_decimal(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), @@ -7587,6 +7669,7 @@ Field *Type_handler_float:: const Column_definition_attributes *attr, uint32 flags) const { +// DBUG_ASSERT(attr->charset == &my_charset_numeric); int decimals= f_decimals(attr->pack_flag); if (decimals == FLOATING_POINT_DECIMALS) decimals= NOT_FIXED_DEC; @@ -7606,6 +7689,7 @@ Field *Type_handler_double:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); int decimals= f_decimals(attr->pack_flag); if (decimals == FLOATING_POINT_DECIMALS) decimals= NOT_FIXED_DEC; @@ -7625,6 +7709,7 @@ Field *Type_handler_tiny:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_tiny(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, @@ -7640,6 +7725,7 @@ Field *Type_handler_short:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_short(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), @@ -7656,6 +7742,7 @@ Field *Type_handler_int24:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_medium(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), @@ -7672,6 +7759,7 @@ Field *Type_handler_long:: const Column_definition_attributes *attr, uint32 flags) const { +// DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_long(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, @@ -7687,6 +7775,7 @@ Field *Type_handler_longlong:: const Column_definition_attributes *attr, uint32 flags) const { +// DBUG_ASSERT(attr->charset == &my_charset_numeric); if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG)) return new (mem_root) Field_vers_trx_id(rec.ptr(), (uint32) attr->length, @@ -7710,6 +7799,7 @@ Field *Type_handler_timestamp:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new_Field_timestamp(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, share, @@ -7724,6 +7814,7 @@ Field *Type_handler_timestamp2:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_timestampf(rec.ptr(), rec.null_ptr(), rec.null_bit(), attr->unireg_check, @@ -7738,6 +7829,7 @@ Field *Type_handler_year:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_year(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), attr->unireg_check, name); @@ -7751,6 +7843,7 @@ Field *Type_handler_date:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_date(rec.ptr(),rec.null_ptr(),rec.null_bit(), attr->unireg_check, name); @@ -7764,6 +7857,7 @@ Field *Type_handler_newdate:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_newdate(rec.ptr(), rec.null_ptr(), rec.null_bit(), attr->unireg_check, name); @@ -7777,6 +7871,7 @@ Field *Type_handler_time:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new_Field_time(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, attr->temporal_dec(MIN_TIME_WIDTH)); @@ -7790,6 +7885,7 @@ Field *Type_handler_time2:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_timef(rec.ptr(), rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, @@ -7804,6 +7900,7 @@ Field *Type_handler_datetime:: const Column_definition_attributes *attr, uint32 flags) const { +// DBUG_ASSERT(attr->charset == &my_charset_numeric); return new_Field_datetime(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, attr->temporal_dec(MAX_DATETIME_WIDTH)); @@ -7817,6 +7914,7 @@ Field *Type_handler_datetime2:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return new (mem_root) Field_datetimef(rec.ptr(), rec.null_ptr(), rec.null_bit(), attr->unireg_check, name, @@ -7844,6 +7942,7 @@ Field *Type_handler_bit:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_numeric); return f_bit_as_char(attr->pack_flag) ? new (mem_root) Field_bit_as_char(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), @@ -7862,6 +7961,7 @@ Field *Type_handler_geometry:: const Column_definition_attributes *attr, uint32 flags) const { + // DBUG_ASSERT(attr->charset == &my_charset_bin); status_var_increment(current_thd->status_var.feature_gis); return new (mem_root) Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(), diff --git a/sql/sql_type.h b/sql/sql_type.h index 6958d4f970f..7a514643bf6 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -76,7 +76,6 @@ class Spvar_definition; struct st_value; class Protocol; class handler; -struct Schema_specification_st; struct TABLE; struct SORT_FIELD_ATTR; class Vers_history_point; @@ -110,6 +109,53 @@ enum scalar_comparison_op }; +/* + A helper class to store column attributes that are inherited + by columns (from the table level) when not specified explicitly. +*/ +class Column_derived_attributes +{ + /* + Table level CHARACTER SET and COLLATE value: + + CREATE TABLE t1 (a VARCHAR(1), b CHAR(2)) CHARACTER SET latin1; + + All character string columns (CHAR, VARCHAR, TEXT) + inherit CHARACTER SET from the table level. + */ + CHARSET_INFO *m_charset; +public: + explicit Column_derived_attributes(CHARSET_INFO *cs) + :m_charset(cs) + { } + CHARSET_INFO *charset() const { return m_charset; } +}; + + +/* + A helper class to store requests for changes + in multiple column data types during ALTER. +*/ +class Column_bulk_alter_attributes +{ + /* + Target CHARACTER SET specification in ALTER .. CONVERT, e.g. + + ALTER TABLE t1 CONVERT TO CHARACTER SET utf8; + + All character string columns (CHAR, VARCHAR, TEXT) + get converted to the "CONVERT TO CHARACTER SET". + */ + CHARSET_INFO *m_alter_table_convert_to_charset; +public: + explicit Column_bulk_alter_attributes(CHARSET_INFO *convert) + :m_alter_table_convert_to_charset(convert) + { } + CHARSET_INFO *alter_table_convert_to_charset() const + { return m_alter_table_convert_to_charset; } +}; + + class Native: public Binary_string { public: @@ -3597,7 +3643,17 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; + virtual bool Column_definition_bulk_alter(Column_definition *c, + const Column_derived_attributes + *derived_attr, + const Column_bulk_alter_attributes + *bulk_alter_attr) + const + { return false; } /* This method is called on queries like: CREATE TABLE t2 (a INT) AS SELECT a FROM t1; @@ -3616,9 +3672,7 @@ public: */ virtual bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st * - schema) + const handler *file) const; virtual bool Column_definition_prepare_stage2(Column_definition *c, handler *file, @@ -4008,11 +4062,13 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const { DBUG_ASSERT(0); @@ -4294,6 +4350,14 @@ class Type_handler_numeric: public Type_handler { public: String *print_item_value(THD *thd, Item *item, String *str) const; + bool Column_definition_prepare_stage1(THD *thd, + MEM_ROOT *mem_root, + Column_definition *c, + handler *file, + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; double Item_func_min_max_val_real(Item_func_min_max *) const; longlong Item_func_min_max_val_int(Item_func_min_max *) const; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, @@ -4734,6 +4798,14 @@ public: void sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const; + bool Column_definition_prepare_stage1(THD *thd, + MEM_ROOT *mem_root, + Column_definition *c, + handler *file, + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const; bool Item_param_set_from_value(THD *thd, @@ -4820,11 +4892,13 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const; uint32 max_display_length(const Item *item) const; /* @@ -4935,6 +5009,12 @@ class Type_handler_general_purpose_string: public Type_handler_string_result public: bool is_general_purpose_string_type() const { return true; } bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *p) const; + bool Column_definition_bulk_alter(Column_definition *c, + const Column_derived_attributes + *derived_attr, + const Column_bulk_alter_attributes + *bulk_alter_attr) + const; }; @@ -5291,11 +5371,13 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, @@ -5975,11 +6057,13 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, @@ -6021,11 +6105,13 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, @@ -6348,7 +6434,10 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const; @@ -6424,11 +6513,13 @@ public: MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const; + ulonglong table_flags, + const Column_derived_attributes + *derived_attr) + const; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, - const handler *file, - const Schema_specification_st *schema) + const handler *file) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; diff --git a/sql/table.cc b/sql/table.cc index b7c3a33aa40..12299271ab3 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4479,7 +4479,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) create_info->row_type= share->row_type; create_info->key_block_size= share->key_block_size; create_info->default_table_charset= share->table_charset; - create_info->table_charset= 0; + create_info->alter_table_convert_to_charset= 0; create_info->comment= share->comment; create_info->transactional= share->transactional; create_info->page_checksum= share->page_checksum; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index de4e20ee112..19b56980714 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -3419,7 +3419,9 @@ int ha_federatedx::create(const char *name, TABLE *table_arg, { FEDERATEDX_SERVER server; - fill_server(thd->mem_root, &server, &tmp_share, create_info->table_charset); + // It's possibly wrong to use alter_table_convert_to_charset here. + fill_server(thd->mem_root, &server, &tmp_share, + create_info->alter_table_convert_to_charset); #ifndef DBUG_OFF mysql_mutex_init(fe_key_mutex_FEDERATEDX_SERVER_mutex, |