From e3ab386874ae212393ef416ff14efb57eb648585 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Thu, 28 Sep 2017 03:19:53 -0500 Subject: [PATCH] *: revert 4669 "make prepare stmt retriable when schema is out-dated" (#4676) * Revert "executor: analyze use NewSelectResult (#4667)" This reverts commit d1d78b726ba6ba4c79d38ce95252fc41753db02e. * Revert "table: Speed up the add index operation (#4632)" This reverts commit d782ce103eea7680f289f6a35576dc9349bb0bb4. * Revert "*: make prepare stmt retriable when schema is out-dated. (#4669)" This reverts commit 3dfbf52e64cc0af6039758d169bf133b965f5584. --- ast/ast.go | 4 ++-- executor/adapter.go | 17 +++++++++-------- executor/compiler.go | 1 - new_session_test.go | 11 ++++++----- session.go | 29 +++++++++++++++++++---------- 5 files changed, 36 insertions(+), 26 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index a10b7d67d2ef4..f226bcb8f609b 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -174,8 +174,8 @@ type Statement interface { // Exec executes SQL and gets a Recordset. Exec(ctx context.Context) (RecordSet, error) - // AstNode return the ast nodes for retry. - AstNode() StmtNode + // IsPrepared returns whether this statement is prepared statement. + IsPrepared() bool } // Visitor visits a Node. diff --git a/executor/adapter.go b/executor/adapter.go index 9ff9115cb20c5..310a0f713ad86 100644 --- a/executor/adapter.go +++ b/executor/adapter.go @@ -93,20 +93,20 @@ func (a *recordSet) Close() error { type statement struct { is infoschema.InfoSchema // The InfoSchema cannot change during execution, so we hold a reference to it. - ctx context.Context - text string - plan plan.Plan - startTime time.Time - expensive bool - astNode ast.StmtNode + ctx context.Context + text string + plan plan.Plan + startTime time.Time + isPreparedStmt bool + expensive bool } func (a *statement) OriginText() string { return a.text } -func (a *statement) AstNode() ast.StmtNode { - return a.astNode +func (a *statement) IsPrepared() bool { + return a.isPreparedStmt } // Exec implements the ast.Statement Exec interface. @@ -248,6 +248,7 @@ func (a *statement) buildExecutor(ctx context.Context) (Executor, error) { return nil, errors.Trace(err) } a.text = executorExec.Stmt.Text() + a.isPreparedStmt = true a.plan = executorExec.Plan e = executorExec.StmtExec } diff --git a/executor/compiler.go b/executor/compiler.go index 1bb00a9a948e5..39040c6843e0d 100644 --- a/executor/compiler.go +++ b/executor/compiler.go @@ -49,7 +49,6 @@ func (c *Compiler) Compile(ctx context.Context, node ast.StmtNode) (ast.Statemen is: is, plan: p, text: node.Text(), - astNode: node, expensive: isExpensive, } return sa, nil diff --git a/new_session_test.go b/new_session_test.go index 4d8f47a2c49dd..0c242029fd64b 100644 --- a/new_session_test.go +++ b/new_session_test.go @@ -899,11 +899,12 @@ func (s *testSchemaSuite) TestPrepareStmtCommitWhenSchemaChanged(c *C) { tk1.MustExec("execute stmt using @a, @a") tk1.MustExec("commit") - tk1.MustExec("begin") - tk.MustExec("alter table t drop column b") - tk1.MustExec("execute stmt using @a, @a") - _, err := tk1.Exec("commit") - c.Assert(terror.ErrorEqual(err, executor.ErrWrongValueCountOnRow), IsTrue, Commentf("err %v", err)) + // TODO: PrepareStmt should handle this. + //tk1.MustExec("begin") + //tk.MustExec("alter table t drop column b") + //tk1.MustExec("execute stmt using @a, @a") + //_, err := tk1.Exec("commit") + //c.Assert(terror.ErrorEqual(err, executor.ErrWrongValueCountOnRow), IsTrue, Commentf("err %v", err)) } func (s *testSchemaSuite) TestCommitWhenSchemaChanged(c *C) { diff --git a/session.go b/session.go index 82dc98ac38c40..1a71901239ed1 100644 --- a/session.go +++ b/session.go @@ -403,8 +403,9 @@ func (s *session) retry(maxCnt int, infoSchemaChanged bool) error { s.sessionVars.RetryInfo.ResetOffset() for i, sr := range nh.history { st := sr.st + txt := st.OriginText() if infoSchemaChanged { - st, err = updateStatement(st, s) + st, err = updateStatement(st, s, txt) if err != nil { return errors.Trace(err) } @@ -413,7 +414,6 @@ func (s *session) retry(maxCnt int, infoSchemaChanged bool) error { if retryCnt == 0 { // We do not have to log the query every time. // We print the queries at the first try only. - txt := st.OriginText() log.Warnf("[%d] Retry [%d] query [%d] %s", connID, retryCnt, i, sqlForLog(txt)) } else { log.Warnf("[%d] Retry [%d] query [%d]", connID, retryCnt, i) @@ -449,16 +449,25 @@ func (s *session) retry(maxCnt int, infoSchemaChanged bool) error { return err } -func updateStatement(st ast.Statement, s *session) (ast.Statement, error) { +func updateStatement(st ast.Statement, s *session, txt string) (ast.Statement, error) { // statement maybe stale because of infoschema changed, this function will return the updated one. - // Rebuild plan if infoschema changed, reuse the statement otherwise. - resultSt, err := Compile(s, st.AstNode()) - if err != nil { - // If a txn is inserting data when DDL is dropping column, - // it would fail to commit and retry, and run here then. - return resultSt, errors.Trace(err) + if st.IsPrepared() { + // TODO: Rebuild plan if infoschema changed, reuse the statement otherwise. + } else { + // Rebuild plan if infoschema changed, reuse the statement otherwise. + charset, collation := s.sessionVars.GetCharsetInfo() + stmt, err := s.parser.ParseOneStmt(txt, charset, collation) + if err != nil { + return st, errors.Trace(err) + } + st, err = Compile(s, stmt) + if err != nil { + // If a txn is inserting data when DDL is dropping column, + // it would fail to commit and retry, and run here then. + return st, errors.Trace(err) + } } - return resultSt, nil + return st, nil } func sqlForLog(sql string) string {