Skip to content

Commit

Permalink
ddl: fix issue of foreign key name too long (pingcap#38855)
Browse files Browse the repository at this point in the history
  • Loading branch information
crazycs520 authored Nov 3, 2022
1 parent c799b0f commit 09f6295
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 5 deletions.
35 changes: 30 additions & 5 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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{})
Expand Down Expand Up @@ -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
}

Expand Down
53 changes: 53 additions & 0 deletions ddl/foreign_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
2 changes: 2 additions & 0 deletions parser/mysql/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 09f6295

Please sign in to comment.