From f0fd7957f219fa7e7e3008029fa935989e9dee04 Mon Sep 17 00:00:00 2001 From: ti-srebot <66930949+ti-srebot@users.noreply.github.com> Date: Tue, 15 Jun 2021 15:20:37 +0800 Subject: [PATCH] planner: forbid prepared stale select in txn (#25375) (#25413) --- errno/errcode.go | 1 + errno/errname.go | 1 + errors.toml | 5 +++++ executor/stale_txn_test.go | 4 ++-- planner/core/common_plans.go | 3 +++ planner/core/errors.go | 3 +-- planner/core/preprocess.go | 2 +- 7 files changed, 14 insertions(+), 5 deletions(-) diff --git a/errno/errcode.go b/errno/errcode.go index 2a3fe2733b5bf..d6b7c912a15d9 100644 --- a/errno/errcode.go +++ b/errno/errcode.go @@ -1005,6 +1005,7 @@ const ( ErrNotSupportedWithSem = 8132 ErrDataInConsistentExtraIndex = 8133 ErrDataInConsistentMisMatchIndex = 8134 + ErrAsOf = 8135 // Error codes used by TiDB ddl package ErrUnsupportedDDLOperation = 8200 diff --git a/errno/errname.go b/errno/errname.go index 05a8f476f835b..6ab983acc3f29 100644 --- a/errno/errname.go +++ b/errno/errname.go @@ -1051,6 +1051,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrInvalidPlacementSpec: mysql.Message("Invalid placement policy '%s': %s", nil), ErrPlacementPolicyCheck: mysql.Message("Placement policy didn't meet the constraint, reason: %s", nil), ErrMultiStatementDisabled: mysql.Message("client has multi-statement capability disabled. Run SET GLOBAL tidb_multi_statement_mode='ON' after you understand the security risk", nil), + ErrAsOf: mysql.Message("invalid as of timestamp: %s", nil), // TiKV/PD errors. ErrPDServerTimeout: mysql.Message("PD server timeout", nil), diff --git a/errors.toml b/errors.toml index ce6ce2e58206c..3ef2ba977a86e 100644 --- a/errors.toml +++ b/errors.toml @@ -1206,6 +1206,11 @@ error = ''' Feature '%s' is not supported when security enhanced mode is enabled ''' +["planner:8135"] +error = ''' +invalid as of timestamp: %s +''' + ["privilege:1141"] error = ''' There is no such grant defined for user '%-.48s' on host '%-.64s' diff --git a/executor/stale_txn_test.go b/executor/stale_txn_test.go index cd4741fe98db1..ea6982f8aec31 100644 --- a/executor/stale_txn_test.go +++ b/executor/stale_txn_test.go @@ -815,7 +815,7 @@ func (s *testStaleTxnSuite) TestStaleSelect(c *C) { // test prepared stale select in txn tk.MustExec("begin") - tk.MustQuery("execute s").Check(staleRows) + c.Assert(tk.ExecToErr(staleSQL), NotNil) tk.MustExec("commit") // test stale select in stale txn @@ -825,7 +825,7 @@ func (s *testStaleTxnSuite) TestStaleSelect(c *C) { // test prepared stale select in stale txn tk.MustExec(fmt.Sprintf(`start transaction read only as of timestamp '%s'`, time2.Format("2006-1-2 15:04:05.000"))) - tk.MustQuery("execute s").Check(staleRows) + c.Assert(tk.ExecToErr(staleSQL), NotNil) tk.MustExec("commit") // test prepared stale select with schema change diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index 0fdb48169fd4e..ec5833be9973c 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -260,6 +260,9 @@ func (e *Execute) OptimizePreparedPlan(ctx context.Context, sctx sessionctx.Cont var snapshotTS uint64 if preparedObj.SnapshotTSEvaluator != nil { + if vars.InTxn() { + return ErrAsOf.FastGenWithCause("as of timestamp can't be set in transaction.") + } // if preparedObj.SnapshotTSEvaluator != nil, it is a stale read SQL: // which means its infoschema is specified by the SQL, not the current/latest infoschema var err error diff --git a/planner/core/errors.go b/planner/core/errors.go index dd457e0ca4efe..04fa1797d95bd 100644 --- a/planner/core/errors.go +++ b/planner/core/errors.go @@ -97,7 +97,6 @@ var ( ErrAccessDenied = dbterror.ClassOptimizer.NewStdErr(mysql.ErrAccessDenied, mysql.MySQLErrName[mysql.ErrAccessDeniedNoPassword]) ErrBadNull = dbterror.ClassOptimizer.NewStd(mysql.ErrBadNull) ErrNotSupportedWithSem = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedWithSem) - ErrDifferentAsOf = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknown) - ErrAsOf = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknown) + ErrAsOf = dbterror.ClassOptimizer.NewStd(mysql.ErrAsOf) ErrOptOnTemporaryTable = dbterror.ClassOptimizer.NewStd(mysql.ErrOptOnTemporaryTable) ) diff --git a/planner/core/preprocess.go b/planner/core/preprocess.go index e8cab1bf1551f..e1d0012323f7e 100644 --- a/planner/core/preprocess.go +++ b/planner/core/preprocess.go @@ -1425,7 +1425,7 @@ func (p *preprocessor) handleAsOfAndReadTS(node *ast.AsOfClause) { } } if p.LastSnapshotTS != ts { - p.err = ErrDifferentAsOf.GenWithStack("can not set different time in the as of") + p.err = ErrAsOf.GenWithStack("can not set different time in the as of") return } if p.LastSnapshotTS != 0 {