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: DROP GLOBAL TEMPORARY TABLE should fail on normal tables #25639

Merged
merged 13 commits into from
Jun 24, 2021
1 change: 1 addition & 0 deletions errno/errcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ const (
ErrTxnTooLarge = 8004
ErrWriteConflictInTiDB = 8005
ErrOptOnTemporaryTable = 8006
ErrDropTableOnTemporaryTable = 8007
ErrUnsupportedReloadPlugin = 8018
ErrUnsupportedReloadPluginVar = 8019
ErrTableLocked = 8020
Expand Down
1 change: 1 addition & 0 deletions errno/errname.go
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{
ErrForUpdateCantRetry: mysql.Message("[%d] can not retry select for update statement", nil),
ErrAdminCheckTable: mysql.Message("TiDB admin check table failed.", nil),
ErrOptOnTemporaryTable: mysql.Message("`%s` is unsupported on temporary tables.", nil),
ErrDropTableOnTemporaryTable: mysql.Message("`drop global temporary table` can only drop global temporary table", nil),
ErrTxnTooLarge: mysql.Message("Transaction is too large, size: %d", nil),
ErrWriteConflictInTiDB: mysql.Message("Write conflict, txnStartTS %d is stale", nil),
ErrInvalidPluginID: mysql.Message("Wrong plugin id: %s, valid plugin id is [name]-[version], both name and version should not contain '-'", nil),
Expand Down
5 changes: 5 additions & 0 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,11 @@ error = '''
`%s` is unsupported on temporary tables.
'''

["planner:8007"]
error = '''
`drop global temporary table` can only drop global temporary table
'''

["planner:8108"]
error = '''
Unsupported type %T
Expand Down
11 changes: 6 additions & 5 deletions planner/core/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,12 @@ var (
ErrCTERecursiveForbiddenJoinOrder = dbterror.ClassOptimizer.NewStd(mysql.ErrCTERecursiveForbiddenJoinOrder)
ErrInvalidRequiresSingleReference = dbterror.ClassOptimizer.NewStd(mysql.ErrInvalidRequiresSingleReference)
// Since we cannot know if user logged in with a password, use message of ErrAccessDeniedNoPassword instead
ErrAccessDenied = dbterror.ClassOptimizer.NewStdErr(mysql.ErrAccessDenied, mysql.MySQLErrName[mysql.ErrAccessDeniedNoPassword])
ErrBadNull = dbterror.ClassOptimizer.NewStd(mysql.ErrBadNull)
ErrNotSupportedWithSem = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedWithSem)
ErrAsOf = dbterror.ClassOptimizer.NewStd(mysql.ErrAsOf)
ErrOptOnTemporaryTable = dbterror.ClassOptimizer.NewStd(mysql.ErrOptOnTemporaryTable)
ErrAccessDenied = dbterror.ClassOptimizer.NewStdErr(mysql.ErrAccessDenied, mysql.MySQLErrName[mysql.ErrAccessDeniedNoPassword])
ErrBadNull = dbterror.ClassOptimizer.NewStd(mysql.ErrBadNull)
ErrNotSupportedWithSem = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedWithSem)
ErrAsOf = dbterror.ClassOptimizer.NewStd(mysql.ErrAsOf)
ErrOptOnTemporaryTable = dbterror.ClassOptimizer.NewStd(mysql.ErrOptOnTemporaryTable)
ErrDropTableOnTemporaryTable = dbterror.ClassOptimizer.NewStd(mysql.ErrDropTableOnTemporaryTable)
// ErrPartitionNoTemporary returns when partition at temporary mode
ErrPartitionNoTemporary = dbterror.ClassOptimizer.NewStd(mysql.ErrPartitionNoTemporary)
)
27 changes: 25 additions & 2 deletions planner/core/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func InTxnRetry(p *preprocessor) {
p.flag |= inTxnRetry
}

// WithPreprocessorReturn returns a PreprocessOpt to initialize the PreprocesorReturn.
// WithPreprocessorReturn returns a PreprocessOpt to initialize the PreprocessorReturn.
func WithPreprocessorReturn(ret *PreprocessorReturn) PreprocessOpt {
return func(p *preprocessor) {
p.PreprocessorReturn = ret
Expand Down Expand Up @@ -93,7 +93,7 @@ func TryAddExtraLimit(ctx sessionctx.Context, node ast.StmtNode) ast.StmtNode {
}

// Preprocess resolves table names of the node, and checks some statements validation.
// prepreocssReturn used to extract the infoschema for the tableName and the timestamp from the asof clause.
// preprocessReturn used to extract the infoschema for the tableName and the timestamp from the asof clause.
func Preprocess(ctx sessionctx.Context, node ast.Node, preprocessOpt ...PreprocessOpt) error {
v := preprocessor{ctx: ctx, tableAliasInJoin: make([]map[string]interface{}, 0), withName: make(map[string]interface{})}
for _, optFn := range preprocessOpt {
Expand Down Expand Up @@ -842,6 +842,29 @@ func (p *preprocessor) checkDropTableGrammar(stmt *ast.DropTableStmt) {
p.err = expression.ErrFunctionsNoopImpl.GenWithStackByArgs("DROP TEMPORARY TABLE")
return
}
if stmt.TemporaryKeyword == ast.TemporaryNone {
return
}
currentDB := model.NewCIStr(p.ctx.GetSessionVars().CurrentDB)
for _, t := range stmt.Tables {
djshow832 marked this conversation as resolved.
Show resolved Hide resolved
if isIncorrectName(t.Name.String()) {
p.err = ddl.ErrWrongTableName.GenWithStackByArgs(t.Name.String())
return
}
if t.Schema.String() != "" {
currentDB = t.Schema
}
Howie59 marked this conversation as resolved.
Show resolved Hide resolved
tableInfo, err := p.ensureInfoSchema().TableByName(currentDB, t.Name)
if err != nil {
p.err = err
return
}
if tableInfo.Meta().TempTableType != model.TempTableGlobal {
p.err = ErrDropTableOnTemporaryTable
return
}
}

}

func (p *preprocessor) checkDropTableNames(tables []*ast.TableName) {
Expand Down
26 changes: 26 additions & 0 deletions planner/core/preprocess_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,29 @@ func (s *testValidatorSuite) TestForeignKey(c *C) {

s.runSQL(c, "ALTER TABLE test.t1 ADD CONSTRAINT fk FOREIGN KEY (c) REFERENCES test2.t (e)", false, nil)
}

func (s *testValidatorSuite) TestDropGlobalTempTable(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",
"create table tb(id int);",
"create global temporary table temp(id int) on commit delete rows;",
"create global temporary table temp1(id int) on commit delete rows;",
}
for _, execSQL := range execSQLList {
_, err := s.se.Execute(ctx, execSQL)
c.Assert(err, IsNil)
}
s.is = s.dom.InfoSchema()
s.runSQL(c, "drop global temporary table tb;", false, core.ErrDropTableOnTemporaryTable)
s.runSQL(c, "drop global temporary table temp", false, nil)
s.runSQL(c, "drop global temporary table test.tb;", false, core.ErrDropTableOnTemporaryTable)
s.runSQL(c, "drop global temporary table test.temp1", false, nil)
}