Skip to content

Commit

Permalink
Skip fk validation on CREATE TABLE when fks are disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
Hydrocharged committed Oct 12, 2021
1 parent 057afd4 commit ec7fe4e
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
18 changes: 18 additions & 0 deletions enginetest/enginetests.go
Original file line number Diff line number Diff line change
Expand Up @@ -1947,6 +1947,24 @@ func TestCreateForeignKeys(t *testing.T, harness Harness) {
RunQuery(t, e, harness, "CREATE TABLE child3 (pk BIGINT PRIMARY KEY);")
TestQuery(t, harness, e, "ALTER TABLE child3 ADD COLUMN v1 BIGINT NULL, ADD CONSTRAINT fk_child3 FOREIGN KEY (v1) REFERENCES parent3(v1);", []sql.Row(nil), nil, nil)
})

TestScript(t, harness, ScriptTest{
Name: "Do not validate foreign keys if FOREIGN_KEY_CHECKS is set to zero",
Assertions: []ScriptTestAssertion{
{
Query: "SET FOREIGN_KEY_CHECKS=0;",
Expected: []sql.Row{{}},
},
{
Query: "CREATE TABLE child4 (pk BIGINT PRIMARY KEY, CONSTRAINT fk_child4 FOREIGN KEY (pk) REFERENCES delayed_parent4 (pk))",
Expected: nil,
},
{
Query: "CREATE TABLE delayed_parent4 (pk BIGINT PRIMARY KEY)",
Expected: nil,
},
},
})
}

func TestDropForeignKeys(t *testing.T, harness Harness) {
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190830154057-c17b040389b9 h1:5/jaG/gKlo3xxvUn85ReNyTlN7BvlPPsxC6sHZKjGEE=
golang.org/x/tools v0.0.0-20190830154057-c17b040389b9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
Expand Down
3 changes: 3 additions & 0 deletions sql/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ var (
// ErrForeignKeyColumnCountMismatch is called when the declared column and referenced column counts do not match.
ErrForeignKeyColumnCountMismatch = errors.NewKind("the foreign key must reference an equivalent number of columns")

// ErrForeignKeyNotResolved is called when an add or update is attempted on a foreign key that has not been resolved yet.
ErrForeignKeyNotResolved = errors.NewKind("cannot add or update a child row: a foreign key constraint fails (`%s`, CONSTRAINT `%s` FOREIGN KEY (`%s`) REFERENCES `%s` (`%s`))")

// ErrDuplicateEntry is returns when a duplicate entry is placed on an index such as a UNIQUE or a Primary Key.
ErrDuplicateEntry = errors.NewKind("Duplicate entry for key '%s'")

Expand Down
41 changes: 31 additions & 10 deletions sql/plan/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,17 +296,38 @@ func (c *CreateTable) createForeignKeys(ctx *sql.Context, tableNode sql.Table) e
return ErrNoForeignKeySupport.New(c.name)
}

for _, fkDef := range c.fkDefs {
refTbl, ok, err := c.db.GetTableInsensitive(ctx, fkDef.ReferencedTable)
if err != nil {
return err
}
if !ok {
return sql.ErrTableNotFound.New(fkDef.ReferencedTable)
fkChecks, err := ctx.GetSessionVariable(ctx, "foreign_key_checks")
if err != nil {
return err
}
if fkChecks.(int8) == 1 {
for _, fkDef := range c.fkDefs {
refTbl, ok, err := c.db.GetTableInsensitive(ctx, fkDef.ReferencedTable)
if err != nil {
return err
}
if !ok {
return sql.ErrTableNotFound.New(fkDef.ReferencedTable)
}
err = executeCreateForeignKey(ctx, fkAlterable, refTbl, fkDef)
if err != nil {
return err
}
}
err = executeCreateForeignKey(ctx, fkAlterable, refTbl, fkDef)
if err != nil {
return err
} else {
for _, fkDef := range c.fkDefs {
err = fkAlterable.CreateForeignKey(
ctx,
fkDef.Name,
fkDef.Columns,
fkDef.ReferencedTable,
fkDef.ReferencedColumns,
fkDef.OnUpdate,
fkDef.OnDelete,
)
if err != nil {
return err
}
}
}

Expand Down

0 comments on commit ec7fe4e

Please sign in to comment.