diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index d1dc3de437..e2e0e3dfeb 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -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()) } diff --git a/executor/ddl.go b/executor/ddl.go index e5172fedd2..3c220d5ae3 100644 --- a/executor/ddl.go +++ b/executor/ddl.go @@ -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) diff --git a/planner/core/preprocess.go b/planner/core/preprocess.go index 4d1909ac80..ec4eb6103d 100644 --- a/planner/core/preprocess.go +++ b/planner/core/preprocess.go @@ -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, ",")) } } diff --git a/planner/core/preprocess_test.go b/planner/core/preprocess_test.go index 4f4ad089a7..f5057d8895 100644 --- a/planner/core/preprocess_test.go +++ b/planner/core/preprocess_test.go @@ -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) -}