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.
This commit is contained in:
parent
0aef90d65e
commit
6b84ecdc37
@ -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;
|
|||||||
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;
|
||||||
|
|
||||||
|
108
sql/sql_table.cc
108
sql/sql_table.cc
@ -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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user