Skip to content

Commit

Permalink
ddl: add create table like check for temporary table (pingcap#25082)
Browse files Browse the repository at this point in the history
  • Loading branch information
Howie59 authored and tiancaiamao committed Jun 23, 2021
1 parent 4920411 commit c60c954
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 2 deletions.
80 changes: 79 additions & 1 deletion ddl/serial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,16 +525,94 @@ func (s *testSerialSuite) TestCreateTableWithLike(c *C) {

tk.MustExec("drop database ctwl_db")
tk.MustExec("drop database ctwl_db1")
}

func (s *testSerialSuite) TestCreateTableWithLikeAtTemporaryMode(c *C) {
tk := testkit.NewTestKit(c, s.store)

// Test create table like at temporary mode.
tk.MustExec("set tidb_enable_global_temporary_table=true")
tk.MustExec("use test")
tk.MustExec("drop table if exists temporary_table;")
tk.MustExec("create global temporary table temporary_table (a int, b int,index(a)) on commit delete rows")
tk.MustExec("drop table if exists temporary_table_t1;")
_, err = tk.Exec("create table temporary_table_t1 like temporary_table")
_, 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;")

// Test create temporary table like.
// Test auto_random.
tk.MustExec("drop table if exists auto_random_table")
_, err = tk.Exec("create table auto_random_table (a bigint primary key auto_random(3), b varchar(255));")
defer tk.MustExec("drop table if exists auto_random_table")
tk.MustExec("drop table if exists auto_random_temporary_global")
_, err = tk.Exec("create global temporary table auto_random_temporary_global like auto_random_table on commit delete rows;")
c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random").Error())

// Test pre split regions.
tk.MustExec("drop table if exists table_pre_split")
_, err = tk.Exec("create table table_pre_split(id int) shard_row_id_bits = 2 pre_split_regions=2;")
defer tk.MustExec("drop table if exists table_pre_split")
tk.MustExec("drop table if exists temporary_table_pre_split")
_, err = tk.Exec("create global temporary table temporary_table_pre_split like table_pre_split ON COMMIT DELETE ROWS;")
c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions").Error())

// Test shard_row_id_bits.
tk.MustExec("drop table if exists shard_row_id_table, shard_row_id_temporary_table, shard_row_id_table_plus, shard_row_id_temporary_table_plus")
_, err = tk.Exec("create table shard_row_id_table (a int) shard_row_id_bits = 5;")
_, err = tk.Exec("create global temporary table shard_row_id_temporary_table like shard_row_id_table on commit delete rows;")
c.Assert(err.Error(), Equals, core.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error())
tk.MustExec("create table shard_row_id_table_plus (a int);")
tk.MustExec("create global temporary table shard_row_id_temporary_table_plus (a int) on commit delete rows;")
defer tk.MustExec("drop table if exists shard_row_id_table, shard_row_id_temporary_table, shard_row_id_table_plus, shard_row_id_temporary_table_plus")
_, err = tk.Exec("alter table shard_row_id_temporary_table_plus shard_row_id_bits = 4;")
c.Assert(err.Error(), Equals, ddl.ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits").Error())

// Test partition.
tk.MustExec("drop table if exists global_partition_table;")
tk.MustExec("create table global_partition_table (a int, b int) partition by hash(a) partitions 3;")
defer tk.MustExec("drop table if exists global_partition_table;")
tk.MustGetErrCode("create global temporary table global_partition_temp_table like global_partition_table ON COMMIT DELETE ROWS;",
errno.ErrPartitionNoTemporary)
// Test virtual columns.
tk.MustExec("drop table if exists test_gv_ddl, test_gv_ddl_temp")
tk.MustExec(`create table test_gv_ddl(a int, b int as (a+8) virtual, c int as (b + 2) stored)`)
tk.MustExec(`create global temporary table test_gv_ddl_temp like test_gv_ddl on commit delete rows;`)
defer tk.MustExec("drop table if exists test_gv_ddl_temp, test_gv_ddl")
is := tk.Se.(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema)
table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_gv_ddl"))
c.Assert(err, IsNil)
testCases := []struct {
generatedExprString string
generatedStored bool
}{
{"", false},
{"`a` + 8", false},
{"`b` + 2", true},
}
for i, column := range table.Meta().Columns {
c.Assert(column.GeneratedExprString, Equals, testCases[i].generatedExprString)
c.Assert(column.GeneratedStored, Equals, testCases[i].generatedStored)
}
result := tk.MustQuery(`DESC test_gv_ddl_temp`)
result.Check(testkit.Rows(`a int(11) YES <nil> `, `b int(11) YES <nil> VIRTUAL GENERATED`, `c int(11) YES <nil> STORED GENERATED`))
tk.MustExec("begin;")
tk.MustExec("insert into test_gv_ddl_temp values (1, default, default)")
tk.MustQuery("select * from test_gv_ddl_temp").Check(testkit.Rows("1 9 11"))
_, err = tk.Exec("commit")
c.Assert(err, IsNil)

// Test foreign key.
tk.MustExec("drop table if exists test_foreign_key, t1")
tk.MustExec("create table t1 (a int, b int);")
tk.MustExec("create table test_foreign_key (c int,d int,foreign key (d) references t1 (b));")
defer tk.MustExec("drop table if exists test_foreign_key, t1;")
tk.MustExec("create global temporary table test_foreign_key_temp like test_foreign_key on commit delete rows;")
is = tk.Se.(sessionctx.Context).GetInfoSchema().(infoschema.InfoSchema)
table, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("test_foreign_key_temp"))
c.Assert(err, IsNil)
tableInfo := table.Meta()
c.Assert(len(tableInfo.ForeignKeys), Equals, 0)
}

// TestCancelAddIndex1 tests canceling ddl job when the add index worker is not started.
Expand Down
5 changes: 5 additions & 0 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,11 @@ error = '''
`%-.192s`.`%-.192s` contains view recursion
'''

["planner:1562"]
error = '''
Cannot create temporary table with partitions
'''

["planner:1706"]
error = '''
Primary key/partition key update is not allowed since the table is updated both as '%-.192s' and '%-.192s'.
Expand Down
2 changes: 2 additions & 0 deletions planner/core/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,6 @@ var (
ErrNotSupportedWithSem = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedWithSem)
ErrAsOf = dbterror.ClassOptimizer.NewStd(mysql.ErrAsOf)
ErrOptOnTemporaryTable = dbterror.ClassOptimizer.NewStd(mysql.ErrOptOnTemporaryTable)
// ErrPartitionNoTemporary returns when partition at temporary mode
ErrPartitionNoTemporary = dbterror.ClassOptimizer.NewStd(mysql.ErrPartitionNoTemporary)
)
28 changes: 27 additions & 1 deletion planner/core/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -639,10 +639,19 @@ func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) {
p.err = err
return
}
if tableInfo.Meta().TempTableType != model.TempTableNone {
tableMetaInfo := tableInfo.Meta()
if tableMetaInfo.TempTableType != model.TempTableNone {
p.err = ErrOptOnTemporaryTable.GenWithStackByArgs("create table like")
return
}
if stmt.TemporaryKeyword != ast.TemporaryNone {
err := checkReferInfoForTemporaryTable(tableMetaInfo)
if err != nil {
p.err = err
return
}

}
}
if stmt.TemporaryKeyword != ast.TemporaryNone {
for _, opt := range stmt.Options {
Expand Down Expand Up @@ -1023,6 +1032,23 @@ func checkTableEngine(engineName string) error {
return nil
}

func checkReferInfoForTemporaryTable(tableMetaInfo *model.TableInfo) error {
if tableMetaInfo.AutoRandomBits != 0 {
return ErrOptOnTemporaryTable.GenWithStackByArgs("auto_random")
}
if tableMetaInfo.PreSplitRegions != 0 {
return ErrOptOnTemporaryTable.GenWithStackByArgs("pre split regions")
}
if tableMetaInfo.Partition != nil {
return ErrPartitionNoTemporary
}
if tableMetaInfo.ShardRowIDBits != 0 {
return ErrOptOnTemporaryTable.GenWithStackByArgs("shard_row_id_bits")
}

return nil
}

// checkColumn checks if the column definition is valid.
// See https://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html
func checkColumn(colDef *ast.ColumnDef) error {
Expand Down

0 comments on commit c60c954

Please sign in to comment.