Skip to content

Commit

Permalink
*: make SET TRANSACTION ISOLATION LEVEL READ COMMITTED take effect
Browse files Browse the repository at this point in the history
it is equivalent to setting "tx_isolation" variable.
if the value is READ-COMMITTED, set the transaction isolation level option.
  • Loading branch information
tiancaiamao committed Jul 4, 2017
1 parent 4023bb8 commit e38a2fc
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 4 deletions.
7 changes: 7 additions & 0 deletions ast/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ var (
_ Node = &VariableAssignment{}
)

const (
ReadCommitted = "READ-COMMITTED"
ReadUncommitted = "READ-UNCOMMITTED"
Serializable = "SERIALIZABLE "
RepeatableRead = "REPEATABLE-READ"
)

// TypeOpt is used for parsing data type option from SQL.
type TypeOpt struct {
IsUnsigned bool
Expand Down
10 changes: 10 additions & 0 deletions executor/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ func (s *testSuite) TestSetVar(c *C) {
c.Assert(vars.SkipConstraintCheck, IsTrue)
tk.MustExec("set @@tidb_skip_constraint_check = '0'")
c.Assert(vars.SkipConstraintCheck, IsFalse)

// Test set transaction isolation level, which is equivalent to setting variable "tx_isolation".
tk.MustExec("SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE")
tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("SERIALIZABLE"))

tk.MustExec("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED")
tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-UNCOMMITTED"))

tk.MustExec("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")
tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED"))
}

func (s *testSuite) TestSetCharset(c *C) {
Expand Down
53 changes: 49 additions & 4 deletions parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,8 @@ import (
TableOptionListOpt "create table option list opt"
TableRef "table reference"
TableRefs "table references"
TransactionChar "Transaction characteristic"
TransactionChars "Transaction characteristic list"
TrimDirection "Trim string direction"
TruncateTableStmt "TRANSACTION TABLE statement"
UnionOpt "Union Option(empty/ALL/DISTINCT)"
Expand Down Expand Up @@ -835,8 +837,6 @@ import (
OuterOpt "optional OUTER clause"
CrossOpt "Cross join option"
TablesTerminalSym "{TABLE|TABLES}"
TransactionChar "Transaction characteristic"
TransactionChars "Transaction characteristic list"
IsolationLevel "Isolation level"
ShowIndexKwd "Show index/indexs/key keyword"
FromOrIn "From or In"
Expand Down Expand Up @@ -4836,27 +4836,72 @@ SetStmt:
}
| "SET" "GLOBAL" "TRANSACTION" TransactionChars
{
// Parsed but ignored
vars := $4.([]*ast.VariableAssignment)
for _, v := range vars {
v.IsGlobal = true
}
$$ = &ast.SetStmt{Variables: vars}
}
| "SET" "SESSION" "TRANSACTION" TransactionChars
{
// Parsed but ignored
$$ = &ast.SetStmt{Variables: $4.([]*ast.VariableAssignment)}
}

TransactionChars:
TransactionChar
{
if $1 != nil {
$$ = []*ast.VariableAssignment{$1.(*ast.VariableAssignment)}
} else {
$$ = []*ast.VariableAssignment{}
}
}
| TransactionChars ',' TransactionChar
{
if $3 != nil {
$$ = append($1.([]*ast.VariableAssignment), $3.(*ast.VariableAssignment))
} else {
$$ = $1
}
}

TransactionChar:
"ISOLATION" "LEVEL" IsolationLevel
{
tp := types.NewFieldType(mysql.TypeString)
tp.Charset, tp.Collate = parser.charset, parser.collation
expr := ast.NewValueExpr($3)
expr.SetType(tp)
$$ = &ast.VariableAssignment{Name: "tx_isolation", Value: expr, IsSystem: true}
}
| "READ" "WRITE"
{
// Parsed but ignored
$$ = nil
}
| "READ" "ONLY"
{
// Parsed but ignored
$$ = nil
}

IsolationLevel:
"REPEATABLE" "READ"
{
$$ = ast.RepeatableRead
}
| "READ" "COMMITTED"
{
$$ = ast.ReadCommitted
}
| "READ" "UNCOMMITTED"
{
$$ = ast.ReadUncommitted
}
| "SERIALIZABLE"
{
$$ = ast.Serializable
}

VariableAssignment:
Identifier eq Expression
Expand Down
33 changes: 33 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1761,3 +1761,36 @@ func (s *testParserSuite) TestGeneratedColumn(c *C) {
}

}

func (s *testParserSuite) TestSetTransaction(c *C) {
defer testleak.AfterTest(c)()
// Set transaction is equivalent to setting the global or session value of tx_isolation.
// For example:
// SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
// SET SESSION tx_isolation='READ-COMMITTED'
tests := []struct {
input string
isGlobal bool
value string
}{
{
"SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
false, "READ-COMMITTED",
},
{
"SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ",
true, "REPEATABLE-READ",
},
}
parser := New()
for _, t := range tests {
stmt1, err := parser.ParseOneStmt(t.input, "", "")
c.Assert(err, IsNil)
setStmt := stmt1.(*ast.SetStmt)
vars := setStmt.Variables[0]
c.Assert(vars.Name, Equals, "tx_isolation")
c.Assert(vars.IsGlobal, Equals, t.isGlobal)
c.Assert(vars.IsSystem, Equals, true)
c.Assert(vars.Value.GetValue(), Equals, t.value)
}
}
3 changes: 3 additions & 0 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,9 @@ func (s *session) ActivePendingTxn() error {
if err != nil {
return errors.Trace(err)
}
if s.sessionVars.Systems[variable.TxnIsolation] == ast.ReadCommitted {
txn.SetOption(kv.IsolationLevel, kv.RC)
}
return nil
}

Expand Down
1 change: 1 addition & 0 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ const (
CharacterSetResults = "character_set_results"
MaxAllowedPacket = "max_allowed_packet"
TimeZone = "time_zone"
TxnIsolation = "tx_isolation"
)

// TableDelta stands for the changed count for one table.
Expand Down

0 comments on commit e38a2fc

Please sign in to comment.