ddl: fix DROP [GLOBAL] TEMPORARY TABLE IF EXISTS returns error when table not exist (#27287)

This commit is contained in:
王超
2021-08-17 21:53:59 +08:00
committed by GitHub
parent 045c280c61
commit d4ec0233c8
4 changed files with 187 additions and 64 deletions

View File

@ -3162,6 +3162,165 @@ func (s *testIntegrationSuite3) TestDropTemporaryTable(c *C) {
tk.MustQuery("select * from a_local_temp_table_8").Check(testkit.Rows())
}
func (s *testIntegrationSuite3) TestDropWithGlobalTemporaryTableKeyWord(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_noop_functions=true")
tk.MustExec("set tidb_enable_global_temporary_table=true")
clearSQL := "drop table if exists tb, tb2, temp, temp1, ltemp1, ltemp2"
tk.MustExec(clearSQL)
defer tk.MustExec(clearSQL)
// two normal table test.tb, test.tb2
tk.MustExec("create table tb(id int)")
tk.MustExec("create table tb2(id int)")
// two global temporary table test.temp, test.temp1
tk.MustExec("create global temporary table temp(id int) on commit delete rows")
tk.MustExec("create global temporary table temp1(id int) on commit delete rows")
// two local temporary table test.ltemp1, test.ltemp2
tk.MustExec("create temporary table ltemp1(id int)")
tk.MustExec("create temporary table ltemp2(id int)")
// testing for drop table which is not global temporary
err := tk.ExecToErr("drop global temporary table tb")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table test.tb")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table ltemp1")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table test.ltemp1")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table ltemp1, temp")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table temp, ltemp1")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table xxx, ltemp1")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table xxx")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
// testing for drop table if exists which is not global temporary
err = tk.ExecToErr("drop global temporary table if exists tb")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table if exists ltemp1")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
tk.MustExec("drop global temporary table if exists xxx")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.xxx'"))
err = tk.ExecToErr("drop global temporary table if exists xxx,tb")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
err = tk.ExecToErr("drop global temporary table if exists test.tb")
c.Assert(core.ErrDropTableOnTemporaryTable.Equal(err), IsTrue)
// testing for drop global temporary table successfully
tk.MustExec("drop global temporary table temp")
err = tk.ExecToErr("select * from temp")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
tk.MustExec("drop global temporary table test.temp1")
err = tk.ExecToErr("select * from temp2")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
tk.MustExec("create global temporary table temp (id int) on commit delete rows")
tk.MustExec("create global temporary table temp1 (id int) on commit delete rows")
tk.MustExec("drop global temporary table temp, temp1")
err = tk.ExecToErr("select * from temp")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
err = tk.ExecToErr("select * from temp1")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
tk.MustExec("create global temporary table temp (id int) on commit delete rows")
tk.MustExec("create global temporary table temp1 (id int) on commit delete rows")
tk.MustExec("drop global temporary table if exists temp")
tk.MustQuery("show warnings").Check(testkit.Rows())
err = tk.ExecToErr("select * from temp")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
}
func (s *testIntegrationSuite3) TestDropWithLocalTemporaryTableKeyWord(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_noop_functions=true")
tk.MustExec("set tidb_enable_global_temporary_table=true")
clearSQL := "drop table if exists tb, tb2, temp, temp1, ltemp1, ltemp2, testt.ltemp3"
tk.MustExec(clearSQL)
defer tk.MustExec(clearSQL)
// two normal table test.tb, test.tb2, a temporary table with name test.tb2
tk.MustExec("create table tb(id int)")
tk.MustExec("create table tb2(id int)")
tk.MustExec("insert into tb2 values(1)")
tk.MustExec("create temporary table tb2(id int)")
// two global temporary table test.temp, test.temp1
tk.MustExec("create global temporary table temp(id int) on commit delete rows")
tk.MustExec("create global temporary table temp1(id int) on commit delete rows")
// two local temporary table test.ltemp1, test.ltemp2
tk.MustExec("create temporary table ltemp1(id int)")
tk.MustExec("create temporary table ltemp2(id int)")
// a local temporary table test.ltemp3
tk.MustExec("create database if not exists testt")
tk.MustExec("create temporary table testt.ltemp3(id int)")
// testing for drop table which is not local temporary
err := tk.ExecToErr("drop temporary table tb")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
err = tk.ExecToErr("drop temporary table test.tb")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
err = tk.ExecToErr("drop temporary table temp1")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
err = tk.ExecToErr("drop temporary table test.temp1")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
err = tk.ExecToErr("drop temporary table ltemp1, tb")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
err = tk.ExecToErr("drop temporary table temp, ltemp1")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
err = tk.ExecToErr("drop temporary table xxx, ltemp1")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
err = tk.ExecToErr("drop temporary table xxx")
c.Assert(infoschema.ErrTableDropExists.Equal(err), IsTrue)
// testing for drop table if exists which is not local temporary
tk.MustExec("drop temporary table if exists xxx")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.xxx'"))
tk.MustExec("drop temporary table if exists ltemp1, xxx")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.xxx'"))
tk.MustExec("drop temporary table if exists tb1, xxx")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.tb1,test.xxx'"))
tk.MustExec("drop temporary table if exists temp1")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.temp1'"))
tk.MustExec("drop temporary table if exists temp1, xxx")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.temp1,test.xxx'"))
tk.MustExec("drop temporary table if exists testt.ltemp4")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'testt.ltemp4'"))
tk.MustExec("drop temporary table if exists testt.ltemp3, tb1")
tk.MustQuery("show warnings").Check(testkit.Rows("Note 1051 Unknown table 'test.tb1'"))
// testing for drop temporary table successfully
tk.MustExec("drop temporary table ltemp1")
err = tk.ExecToErr("select * from ltemp1")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
tk.MustExec("drop temporary table test.ltemp2")
err = tk.ExecToErr("select * from ltemp2")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
tk.MustExec("drop temporary table tb2")
tk.MustQuery("select * from tb2").Check(testkit.Rows("1"))
tk.MustExec("create temporary table ltemp1 (id int)")
tk.MustExec("create temporary table ltemp2 (id int)")
tk.MustExec("drop temporary table testt.ltemp3, ltemp1")
err = tk.ExecToErr("select * from testt.ltemp3")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
err = tk.ExecToErr("select * from ltemp1")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
tk.MustExec("drop temporary table if exists ltemp2")
tk.MustQuery("show warnings").Check(testkit.Rows())
err = tk.ExecToErr("select * from ltemp2")
c.Assert(infoschema.ErrTableNotExists.Equal(err), IsTrue)
}
func (s *testIntegrationSuite3) TestTruncateLocalTemporaryTable(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
@ -3173,13 +3332,13 @@ func (s *testIntegrationSuite3) TestTruncateLocalTemporaryTable(c *C) {
tk.MustExec("insert into t1 values(10), (11), (12)")
tk.MustExec("create temporary table t1 (id int primary key auto_increment)")
tk.MustExec("create temporary table t2 (id int primary key)")
tk.MustExec("create database test2")
tk.MustExec("create temporary table test2.t2 (id int)")
tk.MustExec("create database if not exists testt")
tk.MustExec("create temporary table testt.t2 (id int)")
// truncate table out of txn
tk.MustExec("insert into t1 values(1), (2), (3)")
tk.MustExec("insert into t2 values(4), (5), (6)")
tk.MustExec("insert into test2.t2 values(7), (8), (9)")
tk.MustExec("insert into testt.t2 values(7), (8), (9)")
tk.MustExec("truncate table t1")
tk.MustQuery("select * from t1").Check(testkit.Rows())
tk.MustExec("insert into t1 values()")
@ -3188,16 +3347,16 @@ func (s *testIntegrationSuite3) TestTruncateLocalTemporaryTable(c *C) {
tk.MustQuery("select * from t2").Check(testkit.Rows("4", "5", "6"))
tk.MustExec("truncate table t2")
tk.MustQuery("select * from t2").Check(testkit.Rows())
tk.MustQuery("select * from test2.t2").Check(testkit.Rows("7", "8", "9"))
tk.MustQuery("select * from testt.t2").Check(testkit.Rows("7", "8", "9"))
tk.MustExec("drop table t1")
tk.MustQuery("select * from t1").Check(testkit.Rows("10", "11", "12"))
tk.MustExec("create temporary table t1 (id int primary key auto_increment)")
// truncate table with format dbName.tableName
tk.MustExec("insert into t2 values(4), (5), (6)")
tk.MustExec("insert into test2.t2 values(7), (8), (9)")
tk.MustExec("truncate table test2.t2")
tk.MustQuery("select * from test2.t2").Check(testkit.Rows())
tk.MustExec("insert into testt.t2 values(7), (8), (9)")
tk.MustExec("truncate table testt.t2")
tk.MustQuery("select * from testt.t2").Check(testkit.Rows())
tk.MustQuery("select * from t2").Check(testkit.Rows("4", "5", "6"))
tk.MustExec("truncate table test.t2")
tk.MustQuery("select * from t2").Check(testkit.Rows())
@ -3252,9 +3411,9 @@ func (s *testIntegrationSuite3) TestTruncateLocalTemporaryTable(c *C) {
c.Assert(iter.Valid(), IsFalse)
// truncate after drop database should be successful
tk.MustExec("create temporary table test2.t3 (id int)")
tk.MustExec("insert into test2.t3 values(1)")
tk.MustExec("drop database test2")
tk.MustExec("truncate table test2.t3")
tk.MustQuery("select * from test2.t3").Check(testkit.Rows())
tk.MustExec("create temporary table testt.t3 (id int)")
tk.MustExec("insert into testt.t3 values(1)")
tk.MustExec("drop database testt")
tk.MustExec("truncate table testt.t3")
tk.MustQuery("select * from testt.t3").Check(testkit.Rows())
}

View File

@ -158,6 +158,21 @@ func (e *DDLExec) Next(ctx context.Context, req *chunk.Chunk) (err error) {
s.Tables = append(s.Tables[:tbIdx], s.Tables[tbIdx+1:]...)
}
}
// Statement `DROP TEMPORARY TABLE ...` should not have non-local temporary tables
if s.TemporaryKeyword == ast.TemporaryLocal && len(s.Tables) > 0 {
nonExistsTables := make([]string, 0, len(s.Tables))
for _, tn := range s.Tables {
nonExistsTables = append(nonExistsTables, ast.Ident{Schema: tn.Schema, Name: tn.Name}.String())
}
err = infoschema.ErrTableDropExists.GenWithStackByArgs(strings.Join(nonExistsTables, ","))
if s.IfExists {
e.ctx.GetSessionVars().StmtCtx.AppendNote(err)
return nil
}
return err
}
// if all tables are local temporary, directly drop those tables.
if len(s.Tables) == 0 {
return e.dropLocalTemporaryTables(localTempTablesToDrop)

View File

@ -871,7 +871,6 @@ func (p *preprocessor) checkDropTemporaryTableGrammar(stmt *ast.DropTableStmt) {
}
currentDB := model.NewCIStr(p.ctx.GetSessionVars().CurrentDB)
nonExistsTables := make([]string, 0)
for _, t := range stmt.Tables {
if isIncorrectName(t.Name.String()) {
p.err = ddl.ErrWrongTableName.GenWithStackByArgs(t.Name.String())
@ -885,7 +884,7 @@ func (p *preprocessor) checkDropTemporaryTableGrammar(stmt *ast.DropTableStmt) {
tbl, err := p.ensureInfoSchema().TableByName(schema, t.Name)
if infoschema.ErrTableNotExists.Equal(err) {
nonExistsTables = append(nonExistsTables, ast.Ident{Schema: schema, Name: t.Name}.String())
// Non-exist table will be checked in ddl executor
continue
}
@ -899,14 +898,6 @@ func (p *preprocessor) checkDropTemporaryTableGrammar(stmt *ast.DropTableStmt) {
p.err = ErrDropTableOnTemporaryTable
return
}
if stmt.TemporaryKeyword == ast.TemporaryLocal && tblInfo.TempTableType != model.TempTableLocal {
nonExistsTables = append(nonExistsTables, ast.Ident{Schema: schema, Name: t.Name}.String())
}
}
if len(nonExistsTables) > 0 {
p.err = infoschema.ErrTableDropExists.GenWithStackByArgs(strings.Join(nonExistsTables, ","))
}
}

View File

@ -378,47 +378,5 @@ func (s *testValidatorSuite) TestDropGlobalTempTable(c *C) {
s.runSQL(c, "drop global temporary table temp, temp1", false, nil)
s.runSQL(c, "drop global temporary table temp, tb", false, core.ErrDropTableOnTemporaryTable)
s.runSQL(c, "drop global temporary table temp, ltemp1", false, core.ErrDropTableOnTemporaryTable)
s.runSQL(c, "drop temporary table xxxx, ltemp1", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop global temporary table test2.temp2, temp1", false, nil)
}
func (s *testValidatorSuite) TestDropLocalTempTable(c *C) {
defer testleak.AfterTest(c)()
defer func() {
s.dom.Close()
s.store.Close()
}()
ctx := context.Background()
execSQLList := []string{
"use test",
"set tidb_enable_global_temporary_table=true",
"set tidb_enable_noop_functions=true",
"create table tb(id int);",
"create table tb2(id int);",
"create global temporary table temp(id int) on commit delete rows;",
"create global temporary table temp1(id int) on commit delete rows;",
"create temporary table ltemp1(id int);",
"create temporary table ltemp2(id int);",
"create temporary table tb2(id int);",
"create database test2",
"create temporary table test2.ltemp3(id int);",
}
for _, execSQL := range execSQLList {
_, err := s.se.Execute(ctx, execSQL)
c.Assert(err, IsNil)
}
s.is = s.se.GetInfoSchema().(infoschema.InfoSchema)
s.runSQL(c, "drop temporary table tb;", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop temporary table ltemp1", false, nil)
s.runSQL(c, "drop temporary table test.tb;", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop temporary table test.ltemp1", false, nil)
s.runSQL(c, "drop temporary table temp1", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop temporary table test.temp1", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop temporary table ltemp1, ltemp2", false, nil)
s.runSQL(c, "drop temporary table ltemp1, tb", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop temporary table temp, ltemp1", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop temporary table xxxx, ltemp1", false, infoschema.ErrTableDropExists)
s.runSQL(c, "drop temporary table test2.ltemp3, ltemp1", false, nil)
s.runSQL(c, "drop temporary table tb2", false, nil)
}