Skip to content

Commit

Permalink
ddl: check foreign key constraint when drop,modify,change column (pin…
Browse files Browse the repository at this point in the history
  • Loading branch information
crazycs520 committed Dec 18, 2019
1 parent d0502a6 commit 3202706
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 1 deletion.
11 changes: 11 additions & 0 deletions ddl/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 15 additions & 1 deletion ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2067,7 +2067,21 @@ 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);"
assertErrorCode(c, s.tk, 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) {
Expand Down
4 changes: 4 additions & 0 deletions ddl/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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])
errReferencedForeignKey = 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.
Expand Down Expand Up @@ -826,6 +828,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
}
8 changes: 8 additions & 0 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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, errReferencedForeignKey.GenWithStackByArgs(originalColName, fkInfo.Name)
}

// Constraints in the new column means adding new constraints. Errors should thrown,
// which will be done by `processColumnOptions` later.
Expand Down Expand Up @@ -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
}

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,5 @@ require (
)

go 1.13

replace github.com/pingcap/parser => github.com/crazycs520/parser v0.0.0-20191218032222-cb5d742ae9e0
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142/go.mod h1:F5haX7
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/crazycs520/parser v0.0.0-20191218032222-cb5d742ae9e0 h1:3Z4NvkQhzgJsMhY1x7EVwh167Rk49Fwc1/8RoDQ8Yhc=
github.com/crazycs520/parser v0.0.0-20191218032222-cb5d742ae9e0/go.mod h1:xLjI+gnWYexq011WPMEvCNS8rFM9qe1vdojIEzSKPuc=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 h1:hxuZop6tSoOi0sxFzoGGYdRqNrPubyaIf9KoBG9tPiE=
Expand Down

0 comments on commit 3202706

Please sign in to comment.