Skip to content

Commit cf050bf

Browse files
committed
Add support for LOCK TABLES & UNLOCK TABLES statements
1 parent be86fc0 commit cf050bf

File tree

7 files changed

+5748
-5373
lines changed

7 files changed

+5748
-5373
lines changed

analyzer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func Preview(sql string) int {
9797
return StmtShow
9898
case "use":
9999
return StmtUse
100-
case "analyze", "describe", "desc", "explain", "repair", "optimize":
100+
case "analyze", "describe", "desc", "explain", "repair", "optimize", "lock", "unlock":
101101
return StmtOther
102102
}
103103
if strings.Index(trimmed, "/*!") == 0 {

analyzer_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ func TestPreview(t *testing.T) {
6464
{"describe", StmtOther},
6565
{"desc", StmtOther},
6666
{"explain", StmtOther},
67+
{"lock", StmtOther},
68+
{"unlock", StmtOther},
6769
{"repair", StmtOther},
6870
{"optimize", StmtOther},
6971
{"truncate", StmtDDL},

ast.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ func (*Execute) iStatement() {}
200200
func (*Begin) iStatement() {}
201201
func (*Commit) iStatement() {}
202202
func (*Rollback) iStatement() {}
203+
func (*LockTables) iStatement() {}
204+
func (*UnlockTables) iStatement() {}
203205
func (*DropUser) iStatement() {}
204206
func (*DropRole) iStatement() {}
205207
func (*Grant) iStatement() {}
@@ -1916,6 +1918,79 @@ func (node *Rollback) walkSubtree(visit Visit) error {
19161918
return nil
19171919
}
19181920

1921+
// LockTables represents a LOCK TABLE[S] statement.
1922+
type LockTables struct {
1923+
Tables TableLocks
1924+
}
1925+
1926+
// Format formats the node.
1927+
func (node *LockTables) Format(buf *TrackedBuffer) {
1928+
buf.Myprintf("lock tables %v", node.Tables)
1929+
}
1930+
1931+
func (node *LockTables) walkSubtree(visit Visit) error {
1932+
if node == nil {
1933+
return nil
1934+
}
1935+
return Walk(visit, node.Tables)
1936+
}
1937+
1938+
// TableLocks is a list of table locks in a LOCK TABLES statement.
1939+
type TableLocks []*TableLock
1940+
1941+
// Format formats the node.
1942+
func (node TableLocks) Format(buf *TrackedBuffer) {
1943+
prefix := ""
1944+
for _, lock := range node {
1945+
buf.Myprintf("%s%v", prefix, lock)
1946+
prefix = ", "
1947+
}
1948+
}
1949+
1950+
func (node TableLocks) walkSubtree(visit Visit) error {
1951+
for _, lock := range node {
1952+
if err := Walk(visit, lock); err != nil {
1953+
return err
1954+
}
1955+
}
1956+
return nil
1957+
}
1958+
1959+
// TableLock represents one table lock target and lock mode.
1960+
type TableLock struct {
1961+
Table TableName
1962+
Alias TableIdent
1963+
Lock string
1964+
}
1965+
1966+
// Format formats the node.
1967+
func (node *TableLock) Format(buf *TrackedBuffer) {
1968+
buf.Myprintf("%v", node.Table)
1969+
if !node.Alias.IsEmpty() {
1970+
buf.Myprintf(" as %v", node.Alias)
1971+
}
1972+
buf.Myprintf(" %s", node.Lock)
1973+
}
1974+
1975+
func (node *TableLock) walkSubtree(visit Visit) error {
1976+
if node == nil {
1977+
return nil
1978+
}
1979+
return Walk(visit, node.Table, node.Alias)
1980+
}
1981+
1982+
// UnlockTables represents an UNLOCK TABLE[S] statement.
1983+
type UnlockTables struct{}
1984+
1985+
// Format formats the node.
1986+
func (node *UnlockTables) Format(buf *TrackedBuffer) {
1987+
buf.WriteString("unlock tables")
1988+
}
1989+
1990+
func (node *UnlockTables) walkSubtree(visit Visit) error {
1991+
return nil
1992+
}
1993+
19191994
// DropUser represents a DROP USER statement.
19201995
type DropUser struct {
19211996
IfExists bool

parse_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,27 @@ var (
12801280
}, {
12811281
input: "optimize table foo",
12821282
output: "otheradmin",
1283+
}, {
1284+
input: "lock table tbl_a read",
1285+
output: "lock tables tbl_a read",
1286+
}, {
1287+
input: "lock tables tbl_a read local",
1288+
output: "lock tables tbl_a read local",
1289+
}, {
1290+
input: "lock tables tbl_a t_a write",
1291+
output: "lock tables tbl_a as t_a write",
1292+
}, {
1293+
input: "lock tables tbl_a as `By` read",
1294+
output: "lock tables tbl_a as `By` read",
1295+
}, {
1296+
input: "lock tables db_a.tbl_b as t_b low_priority write, tbl_c read",
1297+
output: "lock tables db_a.tbl_b as t_b low_priority write, tbl_c read",
1298+
}, {
1299+
input: "unlock table",
1300+
output: "unlock tables",
1301+
}, {
1302+
input: "unlock tables",
1303+
output: "unlock tables",
12831304
}, {
12841305
input: "select /* EQ true */ 1 from t where a = true",
12851306
}, {
@@ -1499,6 +1520,24 @@ func TestSelectLockInvalid(t *testing.T) {
14991520
}
15001521
}
15011522

1523+
func TestTableLockInvalid(t *testing.T) {
1524+
invalidSQL := []string{
1525+
"lock table",
1526+
"lock tables",
1527+
"lock tables tbl_a",
1528+
"lock tables tbl_a local",
1529+
"lock tables tbl_a write low_priority",
1530+
"lock tables tbl_a as read read",
1531+
"unlock",
1532+
"unlock tables tbl_a",
1533+
}
1534+
for _, sql := range invalidSQL {
1535+
if _, err := Parse(sql); err == nil {
1536+
t.Errorf("Parse(%q) err: nil, want non-nil", sql)
1537+
}
1538+
}
1539+
}
1540+
15021541
func TestSelectIntoInvalid(t *testing.T) {
15031542
invalidSQL := []string{
15041543
"select col_a into col_b from tbl_a",

0 commit comments

Comments
 (0)