ddl: check foreign key constraint when drop,modify,change column (#14043)
This commit is contained in:
committed by
pingcap-github-bot
parent
438d39ebcd
commit
5940bb2ceb
@ -535,6 +535,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
|
||||
|
||||
@ -2306,7 +2306,20 @@ func (s *testDBSuite2) TestTableForeignKey(c *C) {
|
||||
// test oreign key not match error
|
||||
failSQL = "alter table t1 add foreign key (a) REFERENCES t3(a, b);"
|
||||
s.tk.MustGetErrCode(failSQL, mysql.ErrWrongFkDef)
|
||||
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) TestFKOnGeneratedColumns(c *C) {
|
||||
|
||||
@ -107,6 +107,8 @@ var (
|
||||
errTooManyFields = terror.ClassDDL.New(mysql.ErrTooManyFields, mysql.MySQLErrName[mysql.ErrTooManyFields])
|
||||
errInvalidSplitRegionRanges = terror.ClassDDL.New(mysql.ErrInvalidSplitRegionRanges, mysql.MySQLErrName[mysql.ErrInvalidSplitRegionRanges])
|
||||
errReorgPanic = terror.ClassDDL.New(mysql.ErrReorgPanic, mysql.MySQLErrName[mysql.ErrReorgPanic])
|
||||
errFkColumnCannotDrop = terror.ClassDDL.New(mysql.ErrFkColumnCannotDrop, mysql.MySQLErrName[mysql.ErrFkColumnCannotDrop])
|
||||
errReferencedForeignKey = terror.ClassDDL.New(mysql.ErrFKIncompatibleColumns, mysql.MySQLErrName[mysql.ErrFKIncompatibleColumns])
|
||||
|
||||
errOnlyOnRangeListPartition = terror.ClassDDL.New(mysql.ErrOnlyOnRangeListPartition, mysql.MySQLErrName[mysql.ErrOnlyOnRangeListPartition])
|
||||
// errWrongKeyColumn is for table column cannot be indexed.
|
||||
@ -728,6 +730,8 @@ func init() {
|
||||
mysql.ErrWrongTableName: mysql.ErrWrongTableName,
|
||||
mysql.ErrWrongTypeColumnValue: mysql.ErrWrongTypeColumnValue,
|
||||
mysql.WarnDataTruncated: mysql.WarnDataTruncated,
|
||||
mysql.ErrFkColumnCannotDrop: mysql.ErrFkColumnCannotDrop,
|
||||
mysql.ErrFKIncompatibleColumns: mysql.ErrFKIncompatibleColumns,
|
||||
}
|
||||
terror.ErrClassToMySQLCodes[terror.ClassDDL] = ddlMySQLErrCodes
|
||||
}
|
||||
|
||||
@ -2638,6 +2638,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.
|
||||
@ -3654,6 +3658,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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user