diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2018-01-30 17:08:36 +0400 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2018-01-30 17:08:36 +0400 |
commit | 926adcfeeaf23f4414822e3da712fb5e2560f5cb (patch) | |
tree | 35b1e6cd48546156c65ef3b816c25d349b1b9108 | |
parent | 5478547c96a33adf7848d9e7f84bc6dcb9dead2f (diff) | |
download | mariadb-git-926adcfeeaf23f4414822e3da712fb5e2560f5cb.tar.gz |
MDEV-14694 ALTER COLUMN IF EXISTS .. causes syntax error.
Implementing the 'IF EXISTS' option for statements
ALTER TABLE ALTER COLUMN SET/DROP DEFAULT.
-rw-r--r-- | mysql-test/r/alter_table.result | 13 | ||||
-rw-r--r-- | mysql-test/t/alter_table.test | 10 | ||||
-rw-r--r-- | sql/sql_class.h | 5 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_table.cc | 38 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 29 | ||||
-rw-r--r-- | sql/sql_yacc_ora.yy | 17 |
7 files changed, 85 insertions, 29 deletions
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index b8f51ee25ad..ad2ec606839 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -2275,6 +2275,19 @@ t1 CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +create table t1 (i int); +alter table t1 alter column if exists a set default 1; +Warnings: +Note 1054 Unknown column 'a' in 't1' +alter table t1 alter column if exists a drop default; +Warnings: +Note 1054 Unknown column 'a' in 't1' +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; # # End of 10.2 tests # diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 79a01d5e0c4..f11e7a2178c 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1882,6 +1882,16 @@ alter table t1 drop column a, drop index a; show create table t1; drop table t1; +# +# MDEV-14694 ALTER COLUMN IF EXISTS .. causes syntax error +# + +create table t1 (i int); +alter table t1 alter column if exists a set default 1; +alter table t1 alter column if exists a drop default; +show create table t1; +drop table t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_class.h b/sql/sql_class.h index f081edaa67a..c9a790b44db 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -284,8 +284,9 @@ class Alter_column :public Sql_alloc { public: const char *name; Virtual_column_info *default_value; - Alter_column(const char *par_name, Virtual_column_info *expr) - :name(par_name), default_value(expr) {} + bool alter_if_exists; + Alter_column(const char *par_name, Virtual_column_info *expr, bool par_exists) + :name(par_name), default_value(expr), alter_if_exists(par_exists) {} /** Used to make a clone of this object for ALTER/CREATE TABLE @sa comment for Key_part_spec::clone diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1465465a56c..2f2418c088d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3645,6 +3645,8 @@ public: alter_info.check_constraint_list.push_back(constr); return false; } + bool add_alter_list(const char *par_name, Virtual_column_info *expr, + bool par_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 d1bb661c3b4..7974718e8dd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6114,6 +6114,40 @@ drop_create_field: } } + /* Handle ALTER COLUMN IF EXISTS SET/DROP DEFAULT. */ + { + List_iterator<Alter_column> it(alter_info->alter_list); + Alter_column *acol; + + while ((acol=it++)) + { + if (!acol->alter_if_exists) + continue; + /* + If there is NO field with the same name in the table already, + remove the acol from the list. + */ + for (f_ptr=table->field; *f_ptr; f_ptr++) + { + if (my_strcasecmp(system_charset_info, + acol->name, (*f_ptr)->field_name.str) == 0) + break; + } + if (*f_ptr == NULL) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_BAD_FIELD_ERROR, + ER_THD(thd, ER_BAD_FIELD_ERROR), + acol->name, table->s->table_name.str); + it.remove(); + if (alter_info->alter_list.is_empty()) + { + alter_info->flags&= ~(Alter_info::ALTER_CHANGE_COLUMN_DEFAULT); + } + } + } + } + /* Handle DROP COLUMN/KEY IF EXISTS. */ { List_iterator<Alter_drop> drop_it(alter_info->drop_list); @@ -6142,7 +6176,9 @@ drop_create_field: } else if (drop->type == Alter_drop::CHECK_CONSTRAINT) { - for (uint i=table->s->field_check_constraints; i < table->s->table_check_constraints; i++) + for (uint i=table->s->field_check_constraints; + i < table->s->table_check_constraints; + i++) { if (my_strcasecmp(system_charset_info, drop->name, table->check_constraints[i]->name.str) == 0) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4d55ebf8bea..889b16c83d9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -699,6 +699,18 @@ void LEX::add_key_to_list(LEX_CSTRING *field_name, alter_info.key_list.push_back(key, mem_root); } +bool LEX::add_alter_list(const char *name, Virtual_column_info *expr, + bool exists) +{ + MEM_ROOT *mem_root= thd->mem_root; + Alter_column *ac= new (mem_root) Alter_column(name, expr, exists); + if (ac == NULL) + return true; + alter_info.alter_list.push_back(ac, mem_root); + alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT; + return false; +} + void LEX::init_last_field(Column_definition *field, const LEX_CSTRING *field_name, const CHARSET_INFO *cs) @@ -8174,24 +8186,15 @@ alter_list_item: lex->alter_info.keys_onoff= Alter_info::ENABLE; lex->alter_info.flags|= Alter_info::ALTER_KEYS_ONOFF; } - | ALTER opt_column field_ident SET DEFAULT column_default_expr + | ALTER opt_column opt_if_exists_table_element field_ident SET DEFAULT column_default_expr { - LEX *lex=Lex; - Alter_column *ac= new (thd->mem_root) Alter_column($3.str,$6); - if (ac == NULL) + if (Lex->add_alter_list($4.str, $7, $3)) MYSQL_YYABORT; - lex->alter_info.alter_list.push_back(ac, thd->mem_root); - lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT; } - | ALTER opt_column field_ident DROP DEFAULT + | ALTER opt_column opt_if_exists_table_element field_ident DROP DEFAULT { - LEX *lex=Lex; - Alter_column *ac= (new (thd->mem_root) - Alter_column($3.str, (Virtual_column_info*) 0)); - if (ac == NULL) + if (Lex->add_alter_list($4.str, (Virtual_column_info*) 0, $3)) MYSQL_YYABORT; - lex->alter_info.alter_list.push_back(ac, thd->mem_root); - lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT; } | RENAME opt_to table_ident { diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index e96e8bdcb9a..da1faf14553 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -7735,24 +7735,15 @@ alter_list_item: lex->alter_info.keys_onoff= Alter_info::ENABLE; lex->alter_info.flags|= Alter_info::ALTER_KEYS_ONOFF; } - | ALTER opt_column field_ident SET DEFAULT column_default_expr + | ALTER opt_column opt_if_exists_table_element field_ident SET DEFAULT column_default_expr { - LEX *lex=Lex; - Alter_column *ac= new (thd->mem_root) Alter_column($3.str,$6); - if (ac == NULL) + if (Lex->add_alter_list($4.str, $7, $3)) MYSQL_YYABORT; - lex->alter_info.alter_list.push_back(ac, thd->mem_root); - lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT; } - | ALTER opt_column field_ident DROP DEFAULT + | ALTER opt_column opt_if_exists_table_element field_ident DROP DEFAULT { - LEX *lex=Lex; - Alter_column *ac= (new (thd->mem_root) - Alter_column($3.str, (Virtual_column_info*) 0)); - if (ac == NULL) + if (Lex->add_alter_list($4.str, (Virtual_column_info*) 0, $3)) MYSQL_YYABORT; - lex->alter_info.alter_list.push_back(ac, thd->mem_root); - lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT; } | RENAME opt_to table_ident { |