summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2018-01-30 17:08:36 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2018-01-30 17:08:36 +0400
commit926adcfeeaf23f4414822e3da712fb5e2560f5cb (patch)
tree35b1e6cd48546156c65ef3b816c25d349b1b9108
parent5478547c96a33adf7848d9e7f84bc6dcb9dead2f (diff)
downloadmariadb-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.result13
-rw-r--r--mysql-test/t/alter_table.test10
-rw-r--r--sql/sql_class.h5
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_table.cc38
-rw-r--r--sql/sql_yacc.yy29
-rw-r--r--sql/sql_yacc_ora.yy17
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
{