summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_charset.result11
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_charset.test14
-rw-r--r--sql/field.cc18
-rw-r--r--sql/field.h38
-rw-r--r--sql/handler.h4
-rw-r--r--sql/sql_partition.cc4
-rw-r--r--sql/sql_table.cc80
-rw-r--r--sql/sql_table.h2
-rw-r--r--sql/sql_type.cc158
-rw-r--r--sql/sql_type.h139
-rw-r--r--sql/table.cc2
-rw-r--r--storage/federatedx/ha_federatedx.cc4
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,