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

Set ServerStatusInTrans flag #159

Merged
merged 11 commits into from
Sep 16, 2015
2 changes: 2 additions & 0 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func (s *session) FinishTxn(rollback bool) error {
}
defer func() {
s.txn = nil
variable.GetSessionVars(s).SetStatusInTrans(false)
}()

if rollback {
Expand Down Expand Up @@ -345,6 +346,7 @@ func (s *session) GetTxn(forceNew bool) (kv.Transaction, error) {
}
if forceNew {
err = s.txn.Commit()
variable.GetSessionVars(s).SetStatusInTrans(false)
if err != nil {
return nil, err
}
Expand Down
19 changes: 13 additions & 6 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ type SessionVars struct {
// Client Capability
ClientCapability uint32 // Client capability

// Disable autocommit
DisableAutocommit bool

// Found rows
FoundRows uint64
}
Expand Down Expand Up @@ -102,19 +99,29 @@ func (s *SessionVars) SetStatus(status uint16) {
s.Status = status
}

// SetStatusInTrans sets the status flags about ServerStatusInTrans.
func (s *SessionVars) SetStatusInTrans(isInTrans bool) {
if isInTrans {
s.Status |= mysql.ServerStatusInTrans
return
}
s.Status &= (^mysql.ServerStatusInTrans)
}

// GetNextPreparedStmtID generates and return the next session scope prepared statement id
func (s *SessionVars) GetNextPreparedStmtID() uint32 {
s.preparedStmtID++
return s.preparedStmtID
}

// IsAutocommit checks if it is in autocommit enviroment
func IsAutocommit(ctx context.Context) bool {
// ShouldAutocommit checks if it is in autocommit enviroment
func ShouldAutocommit(ctx context.Context) bool {
// With START TRANSACTION, autocommit remains disabled until you end
// the transaction with COMMIT or ROLLBACK.
if GetSessionVars(ctx).Status&mysql.ServerStatusAutocommit > 0 &&
!GetSessionVars(ctx).DisableAutocommit {
GetSessionVars(ctx).Status&mysql.ServerStatusInTrans == 0 {
return true
}

return false
}
2 changes: 1 addition & 1 deletion stmt/stmts/select.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func (s *SelectStmt) Plan(ctx context.Context) (plan.Plan, error) {
}
}
lock := s.Lock
if variable.IsAutocommit(ctx) {
if variable.ShouldAutocommit(ctx) {
// Locking of rows for update using SELECT FOR UPDATE only applies when autocommit
// is disabled (either by beginning transaction with START TRANSACTION or by setting
// autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked.
Expand Down
6 changes: 3 additions & 3 deletions stmt/stmts/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (s *BeginStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) {
// With START TRANSACTION, autocommit remains disabled until you end
// the transaction with COMMIT or ROLLBACK. The autocommit mode then
// reverts to its previous state.
variable.GetSessionVars(ctx).DisableAutocommit = true
variable.GetSessionVars(ctx).SetStatusInTrans(true)
return
}

Expand Down Expand Up @@ -96,7 +96,7 @@ func (s *CommitStmt) SetText(text string) {
// Exec implements the stmt.Statement Exec interface.
func (s *CommitStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) {
err = ctx.FinishTxn(false)
variable.GetSessionVars(ctx).DisableAutocommit = false
variable.GetSessionVars(ctx).SetStatusInTrans(false)
return
}

Expand Down Expand Up @@ -129,6 +129,6 @@ func (s *RollbackStmt) SetText(text string) {
// Exec implements the stmt.Statement Exec interface.
func (s *RollbackStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) {
err = ctx.FinishTxn(true)
variable.GetSessionVars(ctx).DisableAutocommit = false
variable.GetSessionVars(ctx).SetStatusInTrans(false)
return
}
2 changes: 1 addition & 1 deletion tidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func runStmt(ctx context.Context, s stmt.Statement, args ...interface{}) (rset.R
stmt.ClearExecArgs(ctx)
}
// MySQL DDL should be auto-commit
if err == nil && (s.IsDDL() || variable.IsAutocommit(ctx)) {
if err == nil && (s.IsDDL() || variable.ShouldAutocommit(ctx)) {
err = ctx.FinishTxn(false)
}
return rs, errors.Trace(err)
Expand Down
36 changes: 36 additions & 0 deletions tidb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/pingcap/tidb/kv"
mysql "github.com/pingcap/tidb/mysqldef"
"github.com/pingcap/tidb/rset"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/util/errors2"
)

Expand Down Expand Up @@ -462,6 +463,41 @@ func (s *testSessionSuite) TestAutoincrementID(c *C) {
mustExecSQL(c, se, s.dropDBSQL)
}

func checkInTrans(c *C, se Session, stmt string, expect uint16) {
mustExecSQL(c, se, stmt)
if expect == 0 {
c.Assert(se.(*session).txn, IsNil)
} else {
c.Assert(se.(*session).txn, NotNil)
}
ret := variable.GetSessionVars(se.(*session)).Status & mysql.ServerStatusInTrans
c.Assert(ret, Equals, expect)
}

// See: https://dev.mysql.com/doc/internals/en/status-flags.html
func (s *testSessionSuite) TestInTrans(c *C) {
store := newStore(c, s.dbName)
se := newSession(c, store, s.dbName)
checkInTrans(c, se, "drop table if exists t;", 0)
checkInTrans(c, se, "create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)", 0)
checkInTrans(c, se, "insert t values ()", 0)
checkInTrans(c, se, "begin", 1)
checkInTrans(c, se, "insert t values ()", 1)
checkInTrans(c, se, "drop table if exists t;", 0)
checkInTrans(c, se, "create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)", 0)
checkInTrans(c, se, "insert t values ()", 0)
checkInTrans(c, se, "commit", 0)
checkInTrans(c, se, "insert t values ()", 0)

checkInTrans(c, se, "drop table if exists t;", 0)
checkInTrans(c, se, "create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)", 0)
checkInTrans(c, se, "begin", 1)
checkInTrans(c, se, "insert t values ()", 1)
checkInTrans(c, se, "rollback", 0)

mustExecSQL(c, se, s.dropDBSQL)
}

// See: http://dev.mysql.com/doc/refman/5.7/en/commit.html
func (s *testSessionSuite) TestRowLock(c *C) {
store := newStore(c, s.dbName)
Expand Down