Skip to content

Commit

Permalink
MDEV-22775: Merge 10.4 into 10.5
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-m committed Apr 8, 2021
2 parents 7b48da4 + 58780b5 commit 2a78107
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 123 deletions.
11 changes: 11 additions & 0 deletions mysql-test/suite/innodb/r/instant_alter_charset.result
Original file line number Diff line number Diff line change
Expand Up @@ -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;
14 changes: 14 additions & 0 deletions mysql-test/suite/innodb/t/instant_alter_charset.test
Original file line number Diff line number Diff line change
Expand Up @@ -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;
12 changes: 7 additions & 5 deletions plugin/type_inet/sql_type_inet.h
Original file line number Diff line number Diff line change
Expand Up @@ -458,19 +458,21 @@ class Type_handler_inet6: public Type_handler
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const override
ulonglong table_flags,
const Column_derived_attributes
*derived_attr)
const override
{
def->create_length_to_internal_length_simple();
def->prepare_stage1_simple(&my_charset_numeric);
return false;
}

bool Column_definition_redefine_stage1(Column_definition *def,
const Column_definition *dup,
const handler *file,
const Schema_specification_st *schema)
const handler *file)
const override
{
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;
Expand Down
18 changes: 14 additions & 4 deletions sql/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10828,16 +10828,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;
decimals= dup_field->decimals;
Expand Down
38 changes: 31 additions & 7 deletions sql/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -5131,6 +5131,11 @@ class Column_definition_attributes
bool frm_unpack_temporal_with_dec(TABLE_SHARE *share, uint intlen,
const uchar *buff);
void set_length_and_dec(const Lex_length_and_dec_st &attr);
CHARSET_INFO *explicit_or_derived_charset(const Column_derived_attributes
*derived_attr) const
{
return charset ? charset : derived_attr->charset();
}
};


Expand Down Expand Up @@ -5266,6 +5271,15 @@ class Column_definition: public Sql_alloc,
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".
Expand Down Expand Up @@ -5301,23 +5315,33 @@ class Column_definition: public Sql_alloc,
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,
handler *file, ulonglong table_flags);
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,
Expand Down
4 changes: 2 additions & 2 deletions sql/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2167,7 +2167,7 @@ struct Vers_parse_info: public Table_period_info

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;
Expand Down Expand Up @@ -2316,7 +2316,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;
}
Expand Down
4 changes: 3 additions & 1 deletion sql/sql_partition.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2313,6 +2313,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,
Expand All @@ -2324,7 +2326,7 @@ static int add_column_list_values(String *str, partition_info *part_info,
th= sql_field->type_handler();
if (th->partition_field_check(sql_field->field_name, item_expr))
return 1;
field_cs= get_sql_field_charset(sql_field, create_info);
field_cs= sql_field->explicit_or_derived_charset(&derived_attr);
}
else
{
Expand Down
80 changes: 33 additions & 47 deletions sql/sql_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3043,6 +3043,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)
Expand Down Expand Up @@ -3123,38 +3132,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.
Expand Down Expand Up @@ -3327,11 +3304,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);
}


Expand Down Expand Up @@ -3598,6 +3578,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",{
Expand Down Expand Up @@ -3653,26 +3636,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;
Expand Down Expand Up @@ -3723,7 +3707,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
Expand Down Expand Up @@ -4764,7 +4748,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);
}

Expand Down Expand Up @@ -11946,8 +11932,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;
}

/*
Expand Down
2 changes: 0 additions & 2 deletions sql/sql_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,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,
Expand Down
Loading

0 comments on commit 2a78107

Please sign in to comment.