Commit 6b84ecdc authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-4440 IF NOT EXISTS in multi-action ALTER does not work when the problem...

MDEV-4440 IF NOT EXISTS in multi-action ALTER does not work when the problem is created by a previous part of the ALTER.
        Loops added to the handle_if_exists_option() to check the
        CREATE/DROP lists for duplicates.
parent 0aef90d6
...@@ -1460,6 +1460,33 @@ t2 CREATE TABLE `t2` ( ...@@ -1460,6 +1460,33 @@ t2 CREATE TABLE `t2` (
KEY `id` (`id`) KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2; DROP TABLE t2;
CREATE TABLE t2 (
id INT(11) NOT NULL);
ALTER TABLE t2 ADD COLUMN a INT, ADD COLUMN IF NOT EXISTS a INT;
Warnings:
Note 1060 Duplicate column name 'a'
ALTER TABLE t2 ADD KEY k_id(id), ADD KEY IF NOT EXISTS k_id(id);
Warnings:
Note 1061 Duplicate key name 'k_id'
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,
KEY `k_id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
ALTER TABLE t2 DROP KEY k_id, DROP KEY IF EXISTS k_id;
Warnings:
Note 1091 Can't DROP 'k_id'; check that column/key exists
ALTER TABLE t2 DROP COLUMN a, DROP COLUMN IF EXISTS a;
Warnings:
Note 1091 Can't DROP 'a'; check that column/key exists
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
# Bug#11748057 (formerly known as 34972): ALTER TABLE statement doesn't # Bug#11748057 (formerly known as 34972): ALTER TABLE statement doesn't
# identify correct column name. # identify correct column name.
......
...@@ -1313,6 +1313,16 @@ ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1; ...@@ -1313,6 +1313,16 @@ ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1; ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
SHOW CREATE TABLE t2; SHOW CREATE TABLE t2;
DROP TABLE t2;
CREATE TABLE t2 (
id INT(11) NOT NULL);
ALTER TABLE t2 ADD COLUMN a INT, ADD COLUMN IF NOT EXISTS a INT;
ALTER TABLE t2 ADD KEY k_id(id), ADD KEY IF NOT EXISTS k_id(id);
SHOW CREATE TABLE t2;
ALTER TABLE t2 DROP KEY k_id, DROP KEY IF EXISTS k_id;
ALTER TABLE t2 DROP COLUMN a, DROP COLUMN IF EXISTS a;
SHOW CREATE TABLE t2;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
......
...@@ -5666,21 +5666,35 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) ...@@ -5666,21 +5666,35 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
{ {
if (my_strcasecmp(system_charset_info, if (my_strcasecmp(system_charset_info,
sql_field->field_name, (*f_ptr)->field_name) == 0) sql_field->field_name, (*f_ptr)->field_name) == 0)
goto drop_create_field;
}
{
/*
If in the ADD list there is a field with the same name,
remove the sql_field from the list.
*/
List_iterator<Create_field> chk_it(alter_info->create_list);
Create_field *chk_field;
while ((chk_field= chk_it++) && chk_field != sql_field)
{ {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, if (my_strcasecmp(system_charset_info,
ER_DUP_FIELDNAME, ER(ER_DUP_FIELDNAME), sql_field->field_name, chk_field->field_name) == 0)
sql_field->field_name); goto drop_create_field;
it.remove();
if (alter_info->create_list.is_empty())
{
alter_info->flags&= ~Alter_info::ALTER_ADD_COLUMN;
if (alter_info->key_list.is_empty())
alter_info->flags&= ~(Alter_info::ALTER_ADD_INDEX |
Alter_info::ADD_FOREIGN_KEY);
}
break;
} }
} }
continue;
drop_create_field:
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DUP_FIELDNAME, ER(ER_DUP_FIELDNAME),
sql_field->field_name);
it.remove();
if (alter_info->create_list.is_empty())
{
alter_info->flags&= ~Alter_info::ALTER_ADD_COLUMN;
if (alter_info->key_list.is_empty())
alter_info->flags&= ~(Alter_info::ALTER_ADD_INDEX |
Alter_info::ADD_FOREIGN_KEY);
}
} }
} }
...@@ -5780,6 +5794,26 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) ...@@ -5780,6 +5794,26 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
} }
} }
} }
if (!remove_drop)
{
/*
Check if the name appears twice in the DROP list.
*/
List_iterator<Alter_drop> chk_it(alter_info->drop_list);
Alter_drop *chk_drop;
while ((chk_drop= chk_it++) && chk_drop != drop)
{
if (drop->type == chk_drop->type &&
my_strcasecmp(system_charset_info,
drop->name, chk_drop->name) == 0)
{
remove_drop= TRUE;
break;
}
}
}
if (remove_drop) if (remove_drop)
{ {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
...@@ -5800,7 +5834,6 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) ...@@ -5800,7 +5834,6 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
Key *key; Key *key;
List_iterator<Key> key_it(alter_info->key_list); List_iterator<Key> key_it(alter_info->key_list);
uint n_key; uint n_key;
bool remove_key;
const char *keyname; const char *keyname;
while ((key=key_it++)) while ((key=key_it++))
{ {
...@@ -5817,7 +5850,6 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) ...@@ -5817,7 +5850,6 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
if (keyname == NULL) if (keyname == NULL)
continue; continue;
} }
remove_key= FALSE;
if (key->type != Key::FOREIGN_KEY) if (key->type != Key::FOREIGN_KEY)
{ {
for (n_key=0; n_key < table->s->keys; n_key++) for (n_key=0; n_key < table->s->keys; n_key++)
...@@ -5825,8 +5857,7 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) ...@@ -5825,8 +5857,7 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
if (my_strcasecmp(system_charset_info, if (my_strcasecmp(system_charset_info,
keyname, table->key_info[n_key].name) == 0) keyname, table->key_info[n_key].name) == 0)
{ {
remove_key= TRUE; goto remove_key;
break;
} }
} }
} }
...@@ -5840,25 +5871,44 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) ...@@ -5840,25 +5871,44 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
{ {
if (my_strcasecmp(system_charset_info, f_key->foreign_id->str, if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
key->name.str) == 0) key->name.str) == 0)
remove_key= TRUE; goto remove_key;
break;
} }
} }
if (remove_key)
{ {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, Key *chk_key;
ER_DUP_KEYNAME, ER(ER_DUP_KEYNAME), keyname); List_iterator<Key> chk_it(alter_info->key_list);
key_it.remove(); const char *chkname;
if (key->type == Key::FOREIGN_KEY) while ((chk_key=chk_it++) && chk_key != key)
{ {
/* ADD FOREIGN KEY appends two items. */ if ((chkname= chk_key->name.str) == NULL)
key_it.remove(); {
List_iterator<Key_part_spec> part_it(chk_key->columns);
Key_part_spec *kp;
if ((kp= part_it++))
chkname= kp->field_name.str;
if (keyname == NULL)
continue;
}
if (key->type == chk_key->type &&
my_strcasecmp(system_charset_info, keyname, chkname) == 0)
goto remove_key;
} }
if (alter_info->key_list.is_empty())
alter_info->flags&= ~(Alter_info::ALTER_ADD_INDEX |
Alter_info::ADD_FOREIGN_KEY);
break;
} }
continue;
remove_key:
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DUP_KEYNAME, ER(ER_DUP_KEYNAME), keyname);
key_it.remove();
if (key->type == Key::FOREIGN_KEY)
{
/* ADD FOREIGN KEY appends two items. */
key_it.remove();
}
if (alter_info->key_list.is_empty())
alter_info->flags&= ~(Alter_info::ALTER_ADD_INDEX |
Alter_info::ADD_FOREIGN_KEY);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment