Commit 7253099c authored by ingo@mysql.com's avatar ingo@mysql.com

Bug#18477 - MySQL/InnoDB Ignoring Foreign Keys in ALTER TABLE

InnoDB requires a full table rebuild for foreign key changes.
It was not possible in compare_tables() to detect such changes.

On Heikkis proposal I added a new flag to the syntax parser
where foreign key definition changes are done. I test for
this flag in compare_tables() now.
parent da000b2d
...@@ -3133,9 +3133,7 @@ SHOW CREATE TABLE t2; ...@@ -3133,9 +3133,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL, `a` int(11) DEFAULT NULL,
KEY `t2_ibfk_0` (`a`), KEY `t2_ibfk_0` (`a`)
CONSTRAINT `t2_ibfk_0` FOREIGN KEY (`a`) REFERENCES `t1` (`a`),
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2,t1; DROP TABLE t2,t1;
create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb; create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
...@@ -3214,3 +3212,34 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; ...@@ -3214,3 +3212,34 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
create table t1 (
c1 bigint not null,
c2 bigint not null,
primary key (c1),
unique key (c2)
) engine=innodb;
create table t2 (
c1 bigint not null,
primary key (c1)
) engine=innodb;
alter table t1 add constraint c2_fk foreign key (c2)
references t2(c1) on delete cascade;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` bigint(20) NOT NULL,
`c2` bigint(20) NOT NULL,
PRIMARY KEY (`c1`),
UNIQUE KEY `c2` (`c2`),
CONSTRAINT `c2_fk` FOREIGN KEY (`c2`) REFERENCES `t2` (`c1`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
alter table t1 drop foreign key c2_fk;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` bigint(20) NOT NULL,
`c2` bigint(20) NOT NULL,
PRIMARY KEY (`c1`),
UNIQUE KEY `c2` (`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1, t2;
...@@ -2113,3 +2113,28 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; ...@@ -2113,3 +2113,28 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu';
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#18477 - MySQL/InnoDB Ignoring Foreign Keys in ALTER TABLE
#
create table t1 (
c1 bigint not null,
c2 bigint not null,
primary key (c1),
unique key (c2)
) engine=innodb;
#
create table t2 (
c1 bigint not null,
primary key (c1)
) engine=innodb;
#
alter table t1 add constraint c2_fk foreign key (c2)
references t2(c1) on delete cascade;
show create table t1;
#
alter table t1 drop foreign key c2_fk;
show create table t1;
#
drop table t1, t2;
...@@ -706,6 +706,7 @@ typedef class st_select_lex SELECT_LEX; ...@@ -706,6 +706,7 @@ typedef class st_select_lex SELECT_LEX;
#define ALTER_CHECK_PARTITION (1L << 23) #define ALTER_CHECK_PARTITION (1L << 23)
#define ALTER_REPAIR_PARTITION (1L << 24) #define ALTER_REPAIR_PARTITION (1L << 24)
#define ALTER_REMOVE_PARTITIONING (1L << 25) #define ALTER_REMOVE_PARTITIONING (1L << 25)
#define ALTER_FOREIGN_KEY (1L << 26)
typedef struct st_alter_info typedef struct st_alter_info
{ {
......
...@@ -3781,7 +3781,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, ...@@ -3781,7 +3781,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list,
create_info->used_fields & HA_CREATE_USED_ENGINE || create_info->used_fields & HA_CREATE_USED_ENGINE ||
create_info->used_fields & HA_CREATE_USED_CHARSET || create_info->used_fields & HA_CREATE_USED_CHARSET ||
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET || create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
(alter_info->flags & ALTER_RECREATE) || (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
order_num) order_num)
DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); DBUG_RETURN(ALTER_TABLE_DATA_CHANGED);
......
...@@ -4167,6 +4167,9 @@ key_def: ...@@ -4167,6 +4167,9 @@ key_def:
HA_KEY_ALG_UNDEF, 1, HA_KEY_ALG_UNDEF, 1,
lex->col_list)); lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */ lex->col_list.empty(); /* Alloced by sql_alloc */
/* Only used for ALTER TABLE. Ignored otherwise. */
lex->alter_info.flags|= ALTER_FOREIGN_KEY;
} }
| constraint opt_check_constraint | constraint opt_check_constraint
{ {
...@@ -5137,7 +5140,7 @@ alter_list_item: ...@@ -5137,7 +5140,7 @@ alter_list_item:
} }
| DROP FOREIGN KEY_SYM opt_ident | DROP FOREIGN KEY_SYM opt_ident
{ {
Lex->alter_info.flags|= ALTER_DROP_INDEX; Lex->alter_info.flags|= ALTER_DROP_INDEX | ALTER_FOREIGN_KEY;
} }
| DROP PRIMARY_SYM KEY_SYM | DROP PRIMARY_SYM KEY_SYM
{ {
......
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