diff --git a/ddl/column.go b/ddl/column.go index 176e2d2519ec8..e500e6dcd0c36 100644 --- a/ddl/column.go +++ b/ddl/column.go @@ -534,6 +534,17 @@ func isColumnWithIndex(colName string, indices []*model.IndexInfo) bool { return false } +func getColumnForeignKeyInfo(colName string, fkInfos []*model.FKInfo) *model.FKInfo { + for _, fkInfo := range fkInfos { + for _, col := range fkInfo.Cols { + if col.L == colName { + return fkInfo + } + } + } + return nil +} + func allocateColumnID(tblInfo *model.TableInfo) int64 { tblInfo.MaxColumnID++ return tblInfo.MaxColumnID diff --git a/ddl/db_test.go b/ddl/db_test.go index ab1e793928b8b..10787935d8f4a 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -2053,7 +2053,20 @@ func (s *testDBSuite2) TestTableForeignKey(c *C) { s.tk.MustExec("create table t3 (a int, b int);") failSQL = "alter table t1 add foreign key (c) REFERENCES t3(a);" s.tk.MustGetErrCode(failSQL, tmysql.ErrKeyColumnDoesNotExits) - s.tk.MustExec("drop table if exists t1,t2,t3;") + // Test drop column with foreign key. + s.tk.MustExec("create table t4 (c int,d int,foreign key (d) references t1 (b));") + failSQL = "alter table t4 drop column d" + s.tk.MustGetErrCode(failSQL, mysql.ErrFkColumnCannotDrop) + // Test change column with foreign key. + failSQL = "alter table t4 change column d e bigint;" + s.tk.MustGetErrCode(failSQL, mysql.ErrFKIncompatibleColumns) + // Test modify column with foreign key. + failSQL = "alter table t4 modify column d bigint;" + s.tk.MustGetErrCode(failSQL, mysql.ErrFKIncompatibleColumns) + s.tk.MustQuery("select count(*) from information_schema.KEY_COLUMN_USAGE;") + s.tk.MustExec("alter table t4 drop foreign key d") + s.tk.MustExec("alter table t4 modify column d bigint;") + s.tk.MustExec("drop table if exists t1,t2,t3,t4;") } func (s *testDBSuite3) TestTruncateTable(c *C) { diff --git a/ddl/ddl.go b/ddl/ddl.go index c40205a1b7e27..65943279665f7 100644 --- a/ddl/ddl.go +++ b/ddl/ddl.go @@ -113,6 +113,8 @@ var ( errTooManyFields = terror.ClassDDL.New(codeTooManyFields, "Too many columns") errInvalidSplitRegionRanges = terror.ClassDDL.New(codeInvalidRanges, "Failed to split region ranges") errReorgPanic = terror.ClassDDL.New(codeReorgWorkerPanic, "reorg worker panic.") + errFkColumnCannotDrop = terror.ClassDDL.New(mysql.ErrFkColumnCannotDrop, mysql.MySQLErrName[mysql.ErrFkColumnCannotDrop]) + errFKIncompatibleColumns = terror.ClassDDL.New(mysql.ErrFKIncompatibleColumns, mysql.MySQLErrName[mysql.ErrFKIncompatibleColumns]) errOnlyOnRangeListPartition = terror.ClassDDL.New(codeOnlyOnRangeListPartition, mysql.MySQLErrName[mysql.ErrOnlyOnRangeListPartition]) // errWrongKeyColumn is for table column cannot be indexed. @@ -827,6 +829,8 @@ func init() { codeSystemVersioningWrongPartitions: mysql.ErrSystemVersioningWrongPartitions, codeWrongPartitionTypeExpectedSystemTime: mysql.ErrWrongPartitionTypeExpectedSystemTime, codeWrongTypeColumnValue: mysql.ErrWrongTypeColumnValue, + mysql.ErrFkColumnCannotDrop: mysql.ErrFkColumnCannotDrop, + mysql.ErrFKIncompatibleColumns: mysql.ErrFKIncompatibleColumns, } terror.ErrClassToMySQLCodes[terror.ClassDDL] = ddlMySQLErrCodes } diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 86a7f1aa364fc..4e2d0d3ff1d9a 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -2571,6 +2571,10 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or return nil, infoschema.ErrColumnExists.GenWithStackByArgs(newColName) } } + // Check the column with foreign key. + if fkInfo := getColumnForeignKeyInfo(originalColName.L, t.Meta().ForeignKeys); fkInfo != nil { + return nil, errFKIncompatibleColumns.GenWithStackByArgs(originalColName, fkInfo.Name) + } // Constraints in the new column means adding new constraints. Errors should thrown, // which will be done by `processColumnOptions` later. @@ -3379,6 +3383,10 @@ func isDroppableColumn(tblInfo *model.TableInfo, colName model.CIStr) error { if isColumnWithIndex(colName.L, tblInfo.Indices) { return errCantDropColWithIndex.GenWithStack("can't drop column %s with index covered now", colName) } + // Check the column with foreign key. + if fkInfo := getColumnForeignKeyInfo(colName.L, tblInfo.ForeignKeys); fkInfo != nil { + return errFkColumnCannotDrop.GenWithStackByArgs(colName, fkInfo.Name) + } return nil } diff --git a/go.mod b/go.mod index f8db4b13ad607..145cbc9930c51 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e github.com/pingcap/kvproto v0.0.0-20191106014506-c5d88d699a8d github.com/pingcap/log v0.0.0-20190715063458-479153f07ebd - github.com/pingcap/parser v0.0.0-20191218055518-56b91dae84dc + github.com/pingcap/parser v0.0.0-20191219054832-7df8c2c0e634 github.com/pingcap/pd v1.1.0-beta.0.20190912093418-dc03c839debd github.com/pingcap/tidb-tools v3.0.6-0.20191119150227-ff0a3c6e5763+incompatible github.com/pingcap/tipb v0.0.0-20191120045257-1b9900292ab6 diff --git a/go.sum b/go.sum index 49d379375f752..e7eed589b6bc3 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,8 @@ github.com/pingcap/kvproto v0.0.0-20191106014506-c5d88d699a8d h1:zTHgLr8+0LTEJmj github.com/pingcap/kvproto v0.0.0-20191106014506-c5d88d699a8d/go.mod h1:QMdbTAXCHzzygQzqcG9uVUgU2fKeSN1GmfMiykdSzzY= github.com/pingcap/log v0.0.0-20190715063458-479153f07ebd h1:hWDol43WY5PGhsh3+8794bFHY1bPrmu6bTalpssCrGg= github.com/pingcap/log v0.0.0-20190715063458-479153f07ebd/go.mod h1:WpHUKhNZ18v116SvGrmjkA9CBhYmuUTKL+p8JC9ANEw= -github.com/pingcap/parser v0.0.0-20191218055518-56b91dae84dc h1:QRKjvChXjiiyQsAIr4jqoK3GBhnG34dXVmdUHaIP56E= -github.com/pingcap/parser v0.0.0-20191218055518-56b91dae84dc/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= +github.com/pingcap/parser v0.0.0-20191219054832-7df8c2c0e634 h1:2gAX2u/8VTLox9qF138DwqkZTJD2oGOwbGhTcZHR8lQ= +github.com/pingcap/parser v0.0.0-20191219054832-7df8c2c0e634/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/pd v1.1.0-beta.0.20190912093418-dc03c839debd h1:bKj6hodu/ro78B0oN2yicdGn0t4yd9XjnyoW95qmWic= github.com/pingcap/pd v1.1.0-beta.0.20190912093418-dc03c839debd/go.mod h1:I7TEby5BHTYIxgHszfsOJSBsk8b2Qt8QrSIgdv5n5QQ= github.com/pingcap/tidb-tools v3.0.6-0.20191119150227-ff0a3c6e5763+incompatible h1:I8HirWsu1MZp6t9G/g8yKCEjJJxtHooKakEgccvdJ4M=