diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 73e584186da44..3ce114b2e78a2 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -666,6 +666,20 @@ func checkTooLongIndex(index model.CIStr) error { return nil } +func checkTooLongColumn(col model.CIStr) error { + if utf8.RuneCountInString(col.L) > mysql.MaxColumnNameLength { + return dbterror.ErrTooLongIdent.GenWithStackByArgs(col) + } + return nil +} + +func checkTooLongForeignKey(fk model.CIStr) error { + if utf8.RuneCountInString(fk.L) > mysql.MaxForeignKeyIdentifierLen { + return dbterror.ErrTooLongIdent.GenWithStackByArgs(fk) + } + return nil +} + func setColumnFlagWithConstraint(colMap map[string]*table.Column, v *ast.Constraint) { switch v.Tp { case ast.ConstraintPrimaryKey: @@ -1596,11 +1610,10 @@ func checkGeneratedColumn(ctx sessionctx.Context, colDefs []*ast.ColumnDef) erro return nil } -func checkTooLongColumn(cols []*model.ColumnInfo) error { +func checkTooLongColumns(cols []*model.ColumnInfo) error { for _, col := range cols { - colName := col.Name.O - if utf8.RuneCountInString(colName) > mysql.MaxColumnNameLength { - return dbterror.ErrTooLongIdent.GenWithStackByArgs(colName) + if err := checkTooLongColumn(col.Name); err != nil { + return err } } return nil @@ -2047,7 +2060,7 @@ func checkTableInfoValidExtra(tbInfo *model.TableInfo) error { if err := checkDuplicateColumn(tbInfo.Columns); err != nil { return err } - if err := checkTooLongColumn(tbInfo.Columns); err != nil { + if err := checkTooLongColumns(tbInfo.Columns); err != nil { return err } if err := checkTooManyColumns(tbInfo.Columns); err != nil { @@ -6165,6 +6178,15 @@ func buildFKInfo(ctx sessionctx.Context, fkName model.CIStr, keys []*ast.IndexPa if len(keys) != len(refer.IndexPartSpecifications) { return nil, infoschema.ErrForeignKeyNotMatch.GenWithStackByArgs(fkName, "Key reference and table reference don't match") } + if err := checkTooLongForeignKey(fkName); err != nil { + return nil, err + } + if err := checkTooLongSchema(refer.Table.Schema); err != nil { + return nil, err + } + if err := checkTooLongTable(refer.Table.Name); err != nil { + return nil, err + } // all base columns of stored generated columns baseCols := make(map[string]struct{}) @@ -6236,6 +6258,9 @@ func buildFKInfo(ctx sessionctx.Context, fkName model.CIStr, keys []*ast.IndexPa fkInfo.RefCols = make([]model.CIStr, len(refer.IndexPartSpecifications)) for i, key := range refer.IndexPartSpecifications { + if err := checkTooLongColumn(key.Column.Name); err != nil { + return nil, err + } fkInfo.RefCols[i] = key.Column.Name } diff --git a/ddl/foreign_key_test.go b/ddl/foreign_key_test.go index 2b7c41f620955..a50fd80e03681 100644 --- a/ddl/foreign_key_test.go +++ b/ddl/foreign_key_test.go @@ -792,6 +792,34 @@ func TestCreateTableWithForeignKeyError(t *testing.T) { create: "create table t2 (a int, b int, index fk_1(a), foreign key (b) references t1(b));", err: "[ddl:1061]duplicate key name fk_1", }, + { + refer: "create table t1 (id int key);", + create: "create table t2 (id int key, foreign key name5678901234567890123456789012345678901234567890123456789012345(id) references t1(id));", + err: "[ddl:1059]Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long", + }, + { + refer: "create table t1 (id int key);", + create: "create table t2 (id int key, constraint name5678901234567890123456789012345678901234567890123456789012345 foreign key (id) references t1(id));", + err: "[ddl:1059]Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long", + }, + { + create: "create table t2 (id int key, constraint fk foreign key (id) references name5678901234567890123456789012345678901234567890123456789012345.t1(id));", + err: "[ddl:1059]Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long", + }, + { + prepare: []string{ + "set @@foreign_key_checks=0;", + }, + create: "create table t2 (id int key, constraint fk foreign key (id) references name5678901234567890123456789012345678901234567890123456789012345(id));", + err: "[ddl:1059]Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long", + }, + { + prepare: []string{ + "set @@foreign_key_checks=0;", + }, + create: "create table t2 (id int key, constraint fk foreign key (id) references t1(name5678901234567890123456789012345678901234567890123456789012345));", + err: "[ddl:1059]Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long", + }, } for _, ca := range cases { tk.MustExec("drop table if exists t2") @@ -840,6 +868,10 @@ func TestCreateTableWithForeignKeyError(t *testing.T) { "create table t1 (a int key, b int, index(b))", "create table t2 (a int, b int, foreign key (a) references t1(a), foreign key (b) references t1(b));", }, + { + "create table t1 (id int key);", + "create table t2 (id int key, foreign key name567890123456789012345678901234567890123456789012345678901234(id) references t1(id));", + }, } for _, ca := range passCases { tk.MustExec("drop table if exists t2") @@ -1707,6 +1739,22 @@ func TestAlterTableAddForeignKeyError(t *testing.T) { alter: "alter table t2 add foreign key fk_b(a, b) references t1(a, b)", err: "[ddl:1452]Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk_b` FOREIGN KEY (`a`, `b`) REFERENCES `t1` (`a`, `b`))", }, + { + prepares: []string{ + "create table t1 (id int key);", + "create table t2 (a int, b int unique);", + }, + alter: "alter table t2 add foreign key name5678901234567890123456789012345678901234567890123456789012345(b) references t1(id)", + err: "[ddl:1059]Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long", + }, + { + prepares: []string{ + "create table t1 (id int key);", + "create table t2 (a int, b int unique);", + }, + alter: "alter table t2 add constraint name5678901234567890123456789012345678901234567890123456789012345 foreign key (b) references t1(id)", + err: "[ddl:1059]Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long", + }, } for i, ca := range cases { tk.MustExec("drop table if exists t2") @@ -1770,6 +1818,11 @@ func TestAlterTableAddForeignKeyError(t *testing.T) { "alter table t2 add foreign key fk_b(b) references t_unknown(a)", "set @@foreign_key_checks=1;", }, + { + "create table t1 (id int key);", + "create table t2 (a int, b int unique);", + "alter table t2 add foreign key name567890123456789012345678901234567890123456789012345678901234(b) references t1(id)", + }, } for _, ca := range passCases { tk.MustExec("drop table if exists t2") diff --git a/parser/mysql/const.go b/parser/mysql/const.go index 0cfcacd7b0084..2d8da77f90e64 100644 --- a/parser/mysql/const.go +++ b/parser/mysql/const.go @@ -81,6 +81,8 @@ const ( MaxKeyParts = 16 // MaxIndexIdentifierLen is max length of index identifier. MaxIndexIdentifierLen = 64 + // MaxForeignKeyIdentifierLen is max length of foreign key identifier. + MaxForeignKeyIdentifierLen = 64 // MaxConstraintIdentifierLen is max length of constrain identifier. MaxConstraintIdentifierLen = 64 // MaxViewIdentifierLen is max length of view identifier.