diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index de2fbb3c295..bbeaf3519c2 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -3133,9 +3133,7 @@ SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL, - 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`) + KEY `t2_ibfk_0` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t2,t1; 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'; 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 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; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 27d9814404d..0a8e46d694c 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2113,3 +2113,28 @@ UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; DROP TABLE t2; 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; + diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1fea4971c4d..f5141806b38 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -706,6 +706,7 @@ typedef class st_select_lex SELECT_LEX; #define ALTER_CHECK_PARTITION (1L << 23) #define ALTER_REPAIR_PARTITION (1L << 24) #define ALTER_REMOVE_PARTITIONING (1L << 25) +#define ALTER_FOREIGN_KEY (1L << 26) typedef struct st_alter_info { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ed875d321bc..2687b64841f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3796,7 +3796,7 @@ static uint compare_tables(TABLE *table, List *create_list, create_info->used_fields & HA_CREATE_USED_ENGINE || create_info->used_fields & HA_CREATE_USED_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) DBUG_RETURN(ALTER_TABLE_DATA_CHANGED); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e9379ab2f18..28592541c98 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4167,6 +4167,9 @@ key_def: HA_KEY_ALG_UNDEF, 1, lex->col_list)); 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 { @@ -5137,7 +5140,7 @@ alter_list_item: } | 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 {