From 89c0e6c91a780b894648e042147aafa0b0c1a5e5 Mon Sep 17 00:00:00 2001 From: Howie Date: Wed, 12 May 2021 21:49:40 +0800 Subject: [PATCH 1/2] ddl: add check table compatibility for temporary table (#24501) --- errors.toml | 5 +++++ executor/admin_test.go | 16 ++++++++++++++++ executor/ddl.go | 8 ++++++-- expression/integration_test.go | 2 ++ infoschema/error.go | 2 ++ planner/core/preprocess.go | 27 +++++++++++++++++++++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/errors.toml b/errors.toml index 0ce61654373fb..a54913fa1bd2c 100644 --- a/errors.toml +++ b/errors.toml @@ -1281,6 +1281,11 @@ error = ''' Unknown SEQUENCE: '%-.300s' ''' +["schema:8003"] +error = ''' +TiDB admin check table failed. +''' + ["schema:8020"] error = ''' Table '%s' was locked in %s by %v diff --git a/executor/admin_test.go b/executor/admin_test.go index c9cda897a4745..20095eb59a0ba 100644 --- a/executor/admin_test.go +++ b/executor/admin_test.go @@ -76,6 +76,22 @@ func (s *testSuite5) TestAdminCheckIndex(c *C) { check() } +func (s *testSuite5) TestAdminCheckIndexInTemporaryMode(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists temporary_admin_test;") + tk.MustExec("create global temporary table temporary_admin_test (c1 int, c2 int, c3 int default 1, primary key (c1), index (c1), unique key(c2)) ON COMMIT DELETE ROWS;") + tk.MustExec("insert temporary_admin_test (c1, c2) values (1, 1), (2, 2), (3, 3);") + tk.MustGetErrCode("admin check table temporary_admin_test;", mysql.ErrAdminCheckTable) + tk.MustExec("drop table if exists temporary_admin_test;") + + tk.MustExec("drop table if exists non_temporary_admin_test;") + tk.MustExec("create table non_temporary_admin_test (c1 int, c2 int, c3 int default 1, primary key (c1), index (c1), unique key(c2));") + tk.MustExec("insert non_temporary_admin_test (c1, c2) values (1, 1), (2, 2), (3, 3);") + tk.MustExec("admin check table non_temporary_admin_test;") + tk.MustExec("drop table if exists non_temporary_admin_test;") +} + func (s *testSuite5) TestAdminRecoverIndex(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") diff --git a/executor/ddl.go b/executor/ddl.go index 81f7221d1e60e..2f10555d21e1e 100644 --- a/executor/ddl.go +++ b/executor/ddl.go @@ -311,8 +311,12 @@ func (e *DDLExec) dropTableObject(objects []*ast.TableName, obt objectType, ifEx if isSystemTable(tn.Schema.L, tn.Name.L) { return errors.Errorf("Drop tidb system table '%s.%s' is forbidden", tn.Schema.L, tn.Name.L) } - - if obt == tableObject && config.CheckTableBeforeDrop { + tableInfo, err := e.is.TableByName(tn.Schema, tn.Name) + if err != nil { + return err + } + tempTableType := tableInfo.Meta().TempTableType + if obt == tableObject && config.CheckTableBeforeDrop && tempTableType == model.TempTableNone { logutil.BgLogger().Warn("admin check table before drop", zap.String("database", fullti.Schema.O), zap.String("table", fullti.Name.O), diff --git a/expression/integration_test.go b/expression/integration_test.go index f15dc5822be15..a3d983069cce9 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -9161,8 +9161,10 @@ func (s *testIntegrationSuite) TestIssue24429(c *C) { tk.MustExec("set @@sql_mode = ANSI_QUOTES;") tk.MustExec("use test") + tk.MustExec("drop table if exists t;") tk.MustExec("create table t (a int);") tk.MustQuery(`select t."a"=10 from t;`).Check(testkit.Rows()) + tk.MustExec("drop table if exists t;") } func (s *testIntegrationSuite) TestVitessHash(c *C) { diff --git a/infoschema/error.go b/infoschema/error.go index a0ef7ab9c8760..cb49e48419dec 100644 --- a/infoschema/error.go +++ b/infoschema/error.go @@ -69,4 +69,6 @@ var ( ErrTableLocked = dbterror.ClassSchema.NewStd(mysql.ErrTableLocked) // ErrWrongObject returns when the table/view/sequence is not the expected object. ErrWrongObject = dbterror.ClassSchema.NewStd(mysql.ErrWrongObject) + // ErrAdminCheckTable returns when the check table in temporary mode. + ErrAdminCheckTable = dbterror.ClassSchema.NewStd(mysql.ErrAdminCheckTable) ) diff --git a/planner/core/preprocess.go b/planner/core/preprocess.go index a3719fe4c4b0b..b5caf55e8de03 100644 --- a/planner/core/preprocess.go +++ b/planner/core/preprocess.go @@ -125,6 +125,8 @@ type preprocessor struct { func (p *preprocessor) Enter(in ast.Node) (out ast.Node, skipChildren bool) { switch node := in.(type) { + case *ast.AdminStmt: + p.checkAdminCheckTableGrammar(node) case *ast.DeleteStmt: p.stmtTp = TypeDelete case *ast.SelectStmt: @@ -557,6 +559,31 @@ func (p *preprocessor) checkDropDatabaseGrammar(stmt *ast.DropDatabaseStmt) { } } +func (p *preprocessor) checkAdminCheckTableGrammar(stmt *ast.AdminStmt) { + for _, table := range stmt.Tables { + currentDB := p.ctx.GetSessionVars().CurrentDB + if table.Schema.String() != "" { + currentDB = table.Schema.L + } + if currentDB == "" { + p.err = errors.Trace(ErrNoDB) + return + } + sName := model.NewCIStr(currentDB) + tName := table.Name + tableInfo, err := p.is.TableByName(sName, tName) + if err != nil { + p.err = err + return + } + tempTableType := tableInfo.Meta().TempTableType + if stmt.Tp == ast.AdminCheckTable && tempTableType != model.TempTableNone { + p.err = infoschema.ErrAdminCheckTable + return + } + } +} + func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) { tName := stmt.Table.Name.String() if isIncorrectName(tName) { From 6228e22467d3233f14e490a890c427db1759d683 Mon Sep 17 00:00:00 2001 From: disksing Date: Wed, 12 May 2021 22:13:40 +0800 Subject: [PATCH 2/2] store/tikv: remove use of IsStatenessReadOnly option in store/tikv (#24464) --- store/driver/txn/snapshot.go | 2 ++ store/driver/txn/txn_driver.go | 2 ++ store/tikv/snapshot.go | 11 +++++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/store/driver/txn/snapshot.go b/store/driver/txn/snapshot.go index fde6e93662fa8..95029978ed11e 100644 --- a/store/driver/txn/snapshot.go +++ b/store/driver/txn/snapshot.go @@ -78,6 +78,8 @@ func (s *tikvSnapshot) SetOption(opt int, val interface{}) { s.KVSnapshot.SetReplicaRead(val.(tikvstore.ReplicaReadType)) case tikvstore.TaskID: s.KVSnapshot.SetTaskID(val.(uint64)) + case tikvstore.IsStalenessReadOnly: + s.KVSnapshot.SetIsStatenessReadOnly(val.(bool)) default: s.KVSnapshot.SetOption(opt, val) } diff --git a/store/driver/txn/txn_driver.go b/store/driver/txn/txn_driver.go index 10186d45756bb..200f9e4e18a58 100644 --- a/store/driver/txn/txn_driver.go +++ b/store/driver/txn/txn_driver.go @@ -161,6 +161,8 @@ func (txn *tikvTxn) SetOption(opt int, val interface{}) { txn.SetEnable1PC(val.(bool)) case tikvstore.TxnScope: txn.SetScope(val.(string)) + case tikvstore.IsStalenessReadOnly: + txn.KVTxn.GetSnapshot().SetIsStatenessReadOnly(val.(bool)) default: txn.KVTxn.SetOption(opt, val) } diff --git a/store/tikv/snapshot.go b/store/tikv/snapshot.go index d77be2c21ff35..4e41aa609aad8 100644 --- a/store/tikv/snapshot.go +++ b/store/tikv/snapshot.go @@ -571,10 +571,6 @@ func (s *KVSnapshot) SetOption(opt int, val interface{}) { s.mu.Unlock() case kv.SampleStep: s.sampleStep = val.(uint32) - case kv.IsStalenessReadOnly: - s.mu.Lock() - s.mu.isStaleness = val.(bool) - s.mu.Unlock() case kv.MatchStoreLabels: s.mu.Lock() s.mu.matchStoreLabels = val.([]*metapb.StoreLabel) @@ -628,6 +624,13 @@ func (s *KVSnapshot) SetTaskID(id uint64) { s.mu.taskID = id } +// SetIsStatenessReadOnly indicates whether the transaction is staleness read only transaction +func (s *KVSnapshot) SetIsStatenessReadOnly(b bool) { + s.mu.Lock() + defer s.mu.Unlock() + s.mu.isStaleness = b +} + // SnapCacheHitCount gets the snapshot cache hit count. Only for test. func (s *KVSnapshot) SnapCacheHitCount() int { return int(atomic.LoadInt64(&s.mu.hitCnt))