Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion go/vt/sqlparser/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,14 @@ func ExtractSetValues(sql string) (keyValues map[SetKey]interface{}, scope strin
}
result := make(map[SetKey]interface{})
for _, expr := range setStmt.Exprs {
scope := SessionStr
scope := ImplicitStr
key := expr.Name.Lowered()
switch {
case strings.HasPrefix(key, "@@global."):
scope = GlobalStr
key = strings.TrimPrefix(key, "@@global.")
case strings.HasPrefix(key, "@@session."):
scope = SessionStr
key = strings.TrimPrefix(key, "@@session.")
case strings.HasPrefix(key, "@@"):
key = strings.TrimPrefix(key, "@@")
Expand Down
93 changes: 53 additions & 40 deletions go/vt/sqlparser/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,107 +356,120 @@ func TestExtractSetValues(t *testing.T) {
err: "invalid syntax: 1 + 1",
}, {
sql: "set transaction_mode='single'",
out: map[SetKey]interface{}{{Key: "transaction_mode", Scope: "session"}: "single"},
out: map[SetKey]interface{}{{Key: "transaction_mode", Scope: ImplicitStr}: "single"},
}, {
sql: "set autocommit=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: ImplicitStr}: int64(1)},
}, {
sql: "set autocommit=true",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: ImplicitStr}: int64(1)},
}, {
sql: "set autocommit=false",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(0)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: ImplicitStr}: int64(0)},
}, {
sql: "set autocommit=on",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: "on"},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: ImplicitStr}: "on"},
}, {
sql: "set autocommit=off",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: "off"},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: ImplicitStr}: "off"},
}, {
sql: "set @@global.autocommit=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "global"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: GlobalStr}: int64(1)},
}, {
sql: "set @@global.autocommit=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "global"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: GlobalStr}: int64(1)},
}, {
sql: "set @@session.autocommit=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: SessionStr}: int64(1)},
}, {
sql: "set @@session.`autocommit`=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: SessionStr}: int64(1)},
}, {
sql: "set @@session.'autocommit'=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: SessionStr}: int64(1)},
}, {
sql: "set @@session.\"autocommit\"=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: SessionStr}: int64(1)},
}, {
sql: "set @@session.'\"autocommit'=1",
out: map[SetKey]interface{}{{Key: "\"autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "\"autocommit", Scope: SessionStr}: int64(1)},
}, {
sql: "set @@session.`autocommit'`=1",
out: map[SetKey]interface{}{{Key: "autocommit'", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit'", Scope: SessionStr}: int64(1)},
}, {
sql: "set AUTOCOMMIT=1",
out: map[SetKey]interface{}{{Key: "autocommit", Scope: "session"}: int64(1)},
out: map[SetKey]interface{}{{Key: "autocommit", Scope: ImplicitStr}: int64(1)},
}, {
sql: "SET character_set_results = NULL",
out: map[SetKey]interface{}{{Key: "character_set_results", Scope: "session"}: nil},
out: map[SetKey]interface{}{{Key: "character_set_results", Scope: ImplicitStr}: nil},
}, {
sql: "SET foo = 0x1234",
err: "invalid value type: 0x1234",
}, {
sql: "SET names utf8",
out: map[SetKey]interface{}{{Key: "names", Scope: "session"}: "utf8"},
out: map[SetKey]interface{}{{Key: "names", Scope: ImplicitStr}: "utf8"},
}, {
sql: "SET names ascii collate ascii_bin",
out: map[SetKey]interface{}{{Key: "names", Scope: "session"}: "ascii"},
out: map[SetKey]interface{}{{Key: "names", Scope: ImplicitStr}: "ascii"},
}, {
sql: "SET charset default",
out: map[SetKey]interface{}{{Key: "charset", Scope: "session"}: "default"},
out: map[SetKey]interface{}{{Key: "charset", Scope: ImplicitStr}: "default"},
}, {
sql: "SET character set ascii",
out: map[SetKey]interface{}{{Key: "charset", Scope: "session"}: "ascii"},
out: map[SetKey]interface{}{{Key: "charset", Scope: ImplicitStr}: "ascii"},
}, {
sql: "SET SESSION wait_timeout = 3600",
out: map[SetKey]interface{}{{Key: "wait_timeout", Scope: "session"}: int64(3600)},
scope: "session",
out: map[SetKey]interface{}{{Key: "wait_timeout", Scope: ImplicitStr}: int64(3600)},
scope: SessionStr,
}, {
sql: "SET GLOBAL wait_timeout = 3600",
out: map[SetKey]interface{}{{Key: "wait_timeout", Scope: "session"}: int64(3600)},
scope: "global",
out: map[SetKey]interface{}{{Key: "wait_timeout", Scope: ImplicitStr}: int64(3600)},
scope: GlobalStr,
}, {
sql: "set session transaction isolation level repeatable read",
out: map[SetKey]interface{}{{Key: "tx_isolation", Scope: "session"}: "repeatable read"},
scope: "session",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: IsolationLevelRepeatableRead},
scope: SessionStr,
}, {
sql: "set session transaction isolation level read committed",
out: map[SetKey]interface{}{{Key: "tx_isolation", Scope: "session"}: "read committed"},
scope: "session",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: IsolationLevelReadCommitted},
scope: SessionStr,
}, {
sql: "set session transaction isolation level read uncommitted",
out: map[SetKey]interface{}{{Key: "tx_isolation", Scope: "session"}: "read uncommitted"},
scope: "session",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: IsolationLevelReadUncommitted},
scope: SessionStr,
}, {
sql: "set session transaction isolation level serializable",
out: map[SetKey]interface{}{{Key: "tx_isolation", Scope: "session"}: "serializable"},
scope: "session",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: IsolationLevelSerializable},
scope: SessionStr,
}, {
sql: "set transaction isolation level serializable",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: IsolationLevelSerializable},
}, {
sql: "set transaction read only",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: TxReadOnly},
}, {
sql: "set transaction read write",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: TxReadWrite},
}, {
sql: "set session transaction read write",
out: map[SetKey]interface{}{{Key: TransactionStr, Scope: ImplicitStr}: TxReadWrite},
scope: SessionStr,
}, {
sql: "set session tx_read_only = 0",
out: map[SetKey]interface{}{{Key: "tx_read_only", Scope: "session"}: int64(0)},
scope: "session",
out: map[SetKey]interface{}{{Key: "tx_read_only", Scope: ImplicitStr}: int64(0)},
scope: SessionStr,
}, {
sql: "set session tx_read_only = 1",
out: map[SetKey]interface{}{{Key: "tx_read_only", Scope: "session"}: int64(1)},
scope: "session",
out: map[SetKey]interface{}{{Key: "tx_read_only", Scope: ImplicitStr}: int64(1)},
scope: SessionStr,
}, {
sql: "set session sql_safe_updates = 0",
out: map[SetKey]interface{}{{Key: "sql_safe_updates", Scope: "session"}: int64(0)},
scope: "session",
out: map[SetKey]interface{}{{Key: "sql_safe_updates", Scope: ImplicitStr}: int64(0)},
scope: SessionStr,
}, {
sql: "set session sql_safe_updates = 1",
out: map[SetKey]interface{}{{Key: "sql_safe_updates", Scope: "session"}: int64(1)},
scope: "session",
out: map[SetKey]interface{}{{Key: "sql_safe_updates", Scope: ImplicitStr}: int64(1)},
scope: SessionStr,
}}
for _, tcase := range testcases {
out, _, err := ExtractSetValues(tcase.sql)
Expand Down
22 changes: 20 additions & 2 deletions go/vt/sqlparser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,9 @@ type Set struct {

// Set.Scope or Show.Scope
const (
SessionStr = "session"
GlobalStr = "global"
SessionStr = "session"
GlobalStr = "global"
ImplicitStr = ""
)

// Format formats the node.
Expand Down Expand Up @@ -3329,11 +3330,28 @@ type SetExpr struct {
Expr Expr
}

// SetExpr.Expr, for SET TRANSACTION ... or START TRANSACTION
const (
// TransactionStr is the Name for a SET TRANSACTION statement
TransactionStr = "transaction"

IsolationLevelReadUncommitted = "isolation level read uncommitted"
IsolationLevelReadCommitted = "isolation level read committed"
IsolationLevelRepeatableRead = "isolation level repeatable read"
IsolationLevelSerializable = "isolation level serializable"

TxReadOnly = "read only"
TxReadWrite = "read write"
)

// Format formats the node.
func (node *SetExpr) Format(buf *TrackedBuffer) {
// We don't have to backtick set variable names.
if node.Name.EqualString("charset") || node.Name.EqualString("names") {
buf.Myprintf("%s %v", node.Name.String(), node.Expr)
} else if node.Name.EqualString(TransactionStr) {
sqlVal := node.Expr.(*SQLVal)
buf.Myprintf("%s %s", node.Name.String(), strings.ToLower(string(sqlVal.Val)))
} else {
buf.Myprintf("%s = %v", node.Name.String(), node.Expr)
}
Expand Down
29 changes: 13 additions & 16 deletions go/vt/sqlparser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,29 +715,23 @@ var (
}, {
input: "set /* mixed list */ a = 3, names 'utf8', charset 'ascii', b = 4",
}, {
input: "set session transaction isolation level repeatable read",
output: "set session tx_isolation = 'repeatable read'",
input: "set session transaction isolation level repeatable read",
}, {
input: "set global transaction isolation level repeatable read",
output: "set global tx_isolation = 'repeatable read'",
input: "set transaction isolation level repeatable read",
}, {
input: "set transaction isolation level repeatable read",
output: "set tx_isolation = 'repeatable read'",
input: "set global transaction isolation level repeatable read",
}, {
input: "set transaction isolation level read committed",
output: "set tx_isolation = 'read committed'",
input: "set transaction isolation level repeatable read",
}, {
input: "set transaction isolation level read uncommitted",
output: "set tx_isolation = 'read uncommitted'",
input: "set transaction isolation level read committed",
}, {
input: "set transaction isolation level serializable",
output: "set tx_isolation = 'serializable'",
input: "set transaction isolation level read uncommitted",
}, {
input: "set transaction read write",
output: "set tx_read_only = 0",
input: "set transaction isolation level serializable",
}, {
input: "set transaction read only",
output: "set tx_read_only = 1",
input: "set transaction read write",
}, {
input: "set transaction read only",
}, {
input: "set tx_read_only = 1",
}, {
Expand Down Expand Up @@ -1639,6 +1633,9 @@ func TestConvert(t *testing.T) {
}, {
input: "/* a comment */",
output: "empty statement",
}, {
input: "set transaction isolation level 12345",
output: "syntax error at position 38 near '12345'",
}}

for _, tcase := range invalidSQL {
Expand Down
Loading