Skip to content

Commit

Permalink
ddl: check foreign key constraint when drop,modify,change column (#14043
Browse files Browse the repository at this point in the history
) (#14162)
  • Loading branch information
crazycs520 authored and zimulala committed Dec 20, 2019
1 parent 98a0ce6 commit fcbcc45
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 4 deletions.
10 changes: 10 additions & 0 deletions ddl/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,16 @@ 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++
Expand Down
15 changes: 14 additions & 1 deletion ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2173,7 +2173,20 @@ func (s *testDBSuite) 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.testErrorCode(c, 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.testErrorCode(c, failSQL, mysql.ErrFkColumnCannotDrop)
// Test change column with foreign key.
failSQL = "alter table t4 change column d e bigint;"
s.testErrorCode(c, failSQL, mysql.ErrFKIncompatibleColumns)
// Test modify column with foreign key.
failSQL = "alter table t4 modify column d bigint;"
s.testErrorCode(c, 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 *testDBSuite) TestBitDefaultValue(c *C) {
Expand Down
6 changes: 6 additions & 0 deletions ddl/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,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(codeFkColumnCannotDrop, mysql.MySQLErrName[mysql.ErrFkColumnCannotDrop])
errReferencedForeignKey = terror.ClassDDL.New(codeFKIncompatibleColumns, mysql.MySQLErrName[mysql.ErrFKIncompatibleColumns])

// errWrongKeyColumn is for table column cannot be indexed.
errWrongKeyColumn = terror.ClassDDL.New(codeWrongKeyColumn, mysql.MySQLErrName[mysql.ErrWrongKeyColumn])
Expand Down Expand Up @@ -662,6 +664,8 @@ const (
codePrimaryCantHaveNull = terror.ErrCode(mysql.ErrPrimaryCantHaveNull)
codeWrongExprInPartitionFunc = terror.ErrCode(mysql.ErrWrongExprInPartitionFunc)
codeUnknownPartition = terror.ErrCode(mysql.ErrUnknownPartition)
codeFkColumnCannotDrop = terror.ErrCode(mysql.ErrFkColumnCannotDrop)
codeFKIncompatibleColumns = terror.ErrCode(mysql.ErrFKIncompatibleColumns)
)

func init() {
Expand Down Expand Up @@ -715,6 +719,8 @@ func init() {
codeUnknownCollation: mysql.ErrUnknownCollation,
codeCollationCharsetMismatch: mysql.ErrCollationCharsetMismatch,
codeConflictingDeclarations: mysql.ErrConflictingDeclarations,
codeFkColumnCannotDrop: mysql.ErrFkColumnCannotDrop,
codeFKIncompatibleColumns: mysql.ErrFKIncompatibleColumns,
}
terror.ErrClassToMySQLCodes[terror.ClassDDL] = ddlMySQLErrCodes
}
9 changes: 9 additions & 0 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,11 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or
}
}

// Check the column with foreign key.
if fkInfo := getColumnForeignKeyInfo(originalColName.L, t.Meta().ForeignKeys); fkInfo != nil {
return nil, errReferencedForeignKey.GenWithStackByArgs(originalColName, fkInfo.Name)
}

// Constraints in the new column means adding new constraints. Errors should thrown,
// which will be done by `setDefaultAndComment` later.
if specNewColumn.Tp == nil {
Expand Down Expand Up @@ -2729,6 +2734,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
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ require (
github.com/pingcap/goleveldb v0.0.0-20171020084629-8d44bfdf1030
github.com/pingcap/kvproto v0.0.0-20190826051950-fc8799546726
github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596
github.com/pingcap/parser v0.0.0-20191118062231-d32e257db9f2
github.com/pingcap/parser v0.0.0-20191220111854-63cc130be9fa
github.com/pingcap/pd v2.1.12+incompatible
github.com/pingcap/tidb-tools v2.1.3-0.20190116051332-34c808eef588+incompatible
github.com/pingcap/tipb v0.0.0-20191120045257-1b9900292ab6
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ github.com/pingcap/kvproto v0.0.0-20190826051950-fc8799546726 h1:AzGIEmaYVYMtmki
github.com/pingcap/kvproto v0.0.0-20190826051950-fc8799546726/go.mod h1:0gwbe1F2iBIjuQ9AH0DbQhL+Dpr5GofU8fgYyXk+ykk=
github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596 h1:t2OQTpPJnrPDGlvA+3FwJptMTt6MEPdzK1Wt99oaefQ=
github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596/go.mod h1:WpHUKhNZ18v116SvGrmjkA9CBhYmuUTKL+p8JC9ANEw=
github.com/pingcap/parser v0.0.0-20191118062231-d32e257db9f2 h1:aPvPSsdQe2pLd4fTky0zQKjLXqj6jYvE6R4DEavod3Y=
github.com/pingcap/parser v0.0.0-20191118062231-d32e257db9f2/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/parser v0.0.0-20191220111854-63cc130be9fa h1:cDcoEb9rNlWifDVHGcBTFecK3MU4/Q2+LdJa6X6iK8Q=
github.com/pingcap/parser v0.0.0-20191220111854-63cc130be9fa/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/pd v2.1.12+incompatible h1:6N3LBxx2aSZqT+IWEG730EDNDttP7dXO8J6yvBh+HXw=
github.com/pingcap/pd v2.1.12+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E=
github.com/pingcap/tidb-tools v2.1.3-0.20190116051332-34c808eef588+incompatible h1:e9Gi/LP9181HT3gBfSOeSBA+5JfemuE4aEAhqNgoE4k=
Expand Down

0 comments on commit fcbcc45

Please sign in to comment.