diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index 36fb35f05b4..b012fdde54b 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -2594,6 +2594,11 @@ t1 CREATE TABLE `t1` ( `c` float DEFAULT NULL ) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 ALTER TABLE t1 RENAME COLUMN a TO m; +ALTER TABLE t1 RENAME COLUMN a TO m; +ERROR 42S22: Unknown column 'a' in 't1' +ALTER TABLE t1 RENAME COLUMN IF EXISTS a TO m; +Warnings: +Note 1054 Unknown column 'a' in 't1' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -2882,6 +2887,9 @@ t1 CREATE TABLE `t1` ( # exists, dropped or added within the same ALTER TABLE. alter table t1 rename key d to e; ERROR 42000: Key 'd' doesn't exist in table 't1' +alter table t1 rename key if exists d to e; +Warnings: +Note 1176 Key 'd' doesn't exist in table 't1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test index 9ee42a1ca98..01ab0f99d45 100644 --- a/mysql-test/main/alter_table.test +++ b/mysql-test/main/alter_table.test @@ -2110,6 +2110,9 @@ ALTER TABLE t1 RENAME COLUMN a TO a; --replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" "" SHOW CREATE TABLE t1; ALTER TABLE t1 RENAME COLUMN a TO m; +--error ER_BAD_FIELD_ERROR +ALTER TABLE t1 RENAME COLUMN a TO m; +ALTER TABLE t1 RENAME COLUMN IF EXISTS a TO m; --replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" "" SHOW CREATE TABLE t1; SELECT * FROM t1; @@ -2293,6 +2296,7 @@ show create table t1; --echo # exists, dropped or added within the same ALTER TABLE. --error ER_KEY_DOES_NOT_EXISTS alter table t1 rename key d to e; +alter table t1 rename key if exists d to e; show create table t1; --error ER_KEY_DOES_NOT_EXISTS alter table t1 drop key c, rename key c to d; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9c3774c4a91..72a4722afbf 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -341,8 +341,8 @@ public: bool alter_if_exists; Alter_column(LEX_CSTRING par_name, Virtual_column_info *expr, bool par_exists) :name(par_name), new_name{NULL, 0}, default_value(expr), alter_if_exists(par_exists) {} - Alter_column(LEX_CSTRING par_name, LEX_CSTRING _new_name) - :name(par_name), new_name(_new_name), default_value(NULL), alter_if_exists(false) {} + Alter_column(LEX_CSTRING par_name, LEX_CSTRING _new_name, bool exists) + :name(par_name), new_name(_new_name), default_value(NULL), alter_if_exists(exists) {} /** Used to make a clone of this object for ALTER/CREATE TABLE @sa comment for Key_part_spec::clone @@ -362,9 +362,10 @@ class Alter_rename_key : public Sql_alloc public: LEX_CSTRING old_name; LEX_CSTRING new_name; + bool alter_if_exists; - Alter_rename_key(LEX_CSTRING old_name_arg, LEX_CSTRING new_name_arg) - : old_name(old_name_arg), new_name(new_name_arg) {} + Alter_rename_key(LEX_CSTRING old_name_arg, LEX_CSTRING new_name_arg, bool exists) + : old_name(old_name_arg), new_name(new_name_arg), alter_if_exists(exists) {} Alter_rename_key *clone(MEM_ROOT *mem_root) const { return new (mem_root) Alter_rename_key(*this); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ade7434803c..70cefa8e977 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -524,9 +524,9 @@ bool LEX::add_alter_list(LEX_CSTRING name, Virtual_column_info *expr, } -bool LEX::add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name) +bool LEX::add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name, bool exists) { - Alter_column *ac= new (thd->mem_root) Alter_column(name, new_name); + Alter_column *ac= new (thd->mem_root) Alter_column(name, new_name, exists); if (unlikely(ac == NULL)) return true; alter_info.alter_list.push_back(ac, thd->mem_root); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 56142023c82..0a802b9652c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -4323,7 +4323,7 @@ public: } bool add_alter_list(LEX_CSTRING par_name, Virtual_column_info *expr, bool par_exists); - bool add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name); + bool add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name, bool exists); void set_command(enum_sql_command command, DDL_options_st options) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0841b1e52cb..fb459a95e06 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6256,7 +6256,7 @@ drop_create_field: } } - /* Handle ALTER COLUMN IF EXISTS SET/DROP DEFAULT. */ + /* Handle ALTER/RENAME COLUMN IF EXISTS. */ { List_iterator it(alter_info->alter_list); Alter_column *acol; @@ -6424,6 +6424,35 @@ drop_create_field: alter_info->flags|= left_flags; } + /* Handle RENAME KEY IF EXISTS. */ + { + List_iterator rename_key_it(alter_info->alter_rename_key_list); + Alter_rename_key *rename_key; + while ((rename_key= rename_key_it++)) + { + if (!rename_key->alter_if_exists) + continue; + bool exists= false; + for (uint n_key= 0; n_key < table->s->keys; n_key++) + { + if (my_strcasecmp(system_charset_info, + rename_key->old_name.str, + table->key_info[n_key].name.str) == 0) + { + exists= true; + break; + } + } + if (exists) + continue; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_KEY_DOES_NOT_EXISTS, + ER_THD(thd, ER_KEY_DOES_NOT_EXISTS), + rename_key->old_name.str, table->s->table_name.str); + rename_key_it.remove(); + } + } + /* ALTER TABLE ADD KEY IF NOT EXISTS */ /* ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS */ { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c2b843f051b..529e59c4c48 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7757,16 +7757,16 @@ alter_list_item: lex->name= $3->table; lex->alter_info.flags|= ALTER_RENAME; } - | RENAME COLUMN_SYM ident TO_SYM ident + | RENAME COLUMN_SYM opt_if_exists_table_element ident TO_SYM ident { - if (unlikely(Lex->add_alter_list($3, $5))) + if (unlikely(Lex->add_alter_list($4, $6, $3))) MYSQL_YYABORT; } - | RENAME key_or_index field_ident TO_SYM field_ident + | RENAME key_or_index opt_if_exists_table_element field_ident TO_SYM field_ident { LEX *lex=Lex; Alter_rename_key *ak= new (thd->mem_root) - Alter_rename_key($3, $5); + Alter_rename_key($4, $6, $3); if (ak == NULL) MYSQL_YYABORT; lex->alter_info.alter_rename_key_list.push_back(ak);