Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ddl: add foreign key compatibility for temporary table #24961

Merged
merged 12 commits into from
Jun 2, 2021
20 changes: 19 additions & 1 deletion ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3012,7 +3012,7 @@ func (s *testDBSuite2) TestTableForeignKey(c *C) {
tk.MustExec("create table t3 (a int, b int);")
failSQL = "alter table t1 add foreign key (c) REFERENCES t3(a);"
tk.MustGetErrCode(failSQL, errno.ErrKeyColumnDoesNotExits)
// test oreign key not match error
// test origin key not match error
failSQL = "alter table t1 add foreign key (a) REFERENCES t3(a, b);"
tk.MustGetErrCode(failSQL, errno.ErrWrongFkDef)
// Test drop column with foreign key.
Expand All @@ -3031,6 +3031,24 @@ func (s *testDBSuite2) TestTableForeignKey(c *C) {
tk.MustExec("drop table if exists t1,t2,t3,t4;")
}

func (s *testDBSuite2) TestTemporaryTableForeignKey(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1 (a int, b int);")
tk.MustExec("drop table if exists t1_tmp;")
tk.MustExec("create global temporary table t1_tmp (a int, b int) on commit delete rows;")
// test add foreign key.
tk.MustExec("drop table if exists t2;")
tk.MustExec("create table t2 (a int, b int);")
failSQL := "alter table t1_tmp add foreign key (c) REFERENCES t2(a);"
tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign)
// Test drop column with foreign key.
failSQL = "create global temporary table t3 (c int,d int,foreign key (d) references t1 (b)) on commit delete rows;"
tk.MustGetErrCode(failSQL, mysql.ErrCannotAddForeign)
tk.MustExec("drop table if exists t1,t2,t3,t1_tmp;")
}

func (s *testDBSuite8) TestFKOnGeneratedColumns(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down
3 changes: 3 additions & 0 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5267,6 +5267,9 @@ func (d *ddl) CreateForeignKey(ctx sessionctx.Context, ti ast.Ident, fkName mode
if err != nil {
return errors.Trace(infoschema.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name))
}
if t.Meta().TempTableType != model.TempTableNone {
return infoschema.ErrCannotAddForeign
}

fkInfo, err := buildFKInfo(fkName, keys, refer, t.Cols(), t.Meta())
if err != nil {
Expand Down
7 changes: 0 additions & 7 deletions ddl/serial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,13 +534,6 @@ func (s *testSerialSuite) TestCreateTableWithLike(c *C) {
_, err = tk.Exec("create table temporary_table_t1 like temporary_table")
c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error())
tk.MustExec("drop table if exists temporary_table;")

tk.MustExec("drop table if exists temporary_table_like;")
tk.MustExec("create table temporary_table (a int, b int,index(a))")
tk.MustExec("drop table if exists temporary_table_like_t1;")
_, err = tk.Exec("create global temporary table temporary_table_like_t1 like temporary_table on commit delete rows;")
c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("create table like").Error())
tk.MustExec("drop table if exists temporary_table_like;")
}

// TestCancelAddIndex1 tests canceling ddl job when the add index worker is not started.
Expand Down
8 changes: 6 additions & 2 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3481,8 +3481,12 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.IndexPriv, v.Table.Schema.L,
v.Table.Name.L, "", authErr)
case *ast.CreateTableStmt:
if v.TemporaryKeyword != ast.TemporaryNone && v.ReferTable != nil {
return nil, ErrOptOnTemporaryTable.GenWithStackByArgs("create table like")
if v.TemporaryKeyword != ast.TemporaryNone {
for _, cons := range v.Constraints {
if cons.Tp == ast.ConstraintForeignKey {
return nil, infoschema.ErrCannotAddForeign
}
}
}
if b.ctx.GetSessionVars().User != nil {
authErr = ErrTableaccessDenied.GenWithStackByArgs("CREATE", b.ctx.GetSessionVars().User.AuthUsername,
Expand Down