Skip to content

Commit 2258646

Browse files
authored
Merge pull request #3 from longbridgeapp/feat/mysql-supports
Add MySQL supports
2 parents 3033386 + 234a197 commit 2258646

8 files changed

Lines changed: 102 additions & 51 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![Go](https://github.com/longbridgeapp/sqlparser/actions/workflows/go.yml/badge.svg)](https://github.com/longbridgeapp/sqlparser/actions/workflows/go.yml)
44

5-
A SQL parser for PostgreSQL.
5+
A SQL parser.
66

77
## Installation
88

ast.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,20 @@ type Constraint interface {
236236
}
237237

238238
type Ident struct {
239-
Name string // identifier name
240-
Quoted bool // true if double quoted
239+
Name string // identifier name
240+
Quoted bool // true if double quoted
241+
QuoteChar string // " for postgresql, ` for mysql, etc
241242
}
242243

243244
// String returns the string representation of the expression.
244245
func (i *Ident) String() string {
245-
return `"` + strings.Replace(i.Name, `"`, `""`, -1) + `"`
246+
if i.Quoted {
247+
if i.QuoteChar == `"` {
248+
return i.QuoteChar + strings.ReplaceAll(i.Name, `"`, `""`) + i.QuoteChar
249+
}
250+
return i.QuoteChar + i.Name + i.QuoteChar
251+
}
252+
return i.Name
246253
}
247254

248255
// IdentName returns the name of ident. Returns a blank string if ident is nil.

ast_test.go

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,66 +49,78 @@ func TestSplitExprTree(t *testing.T) {
4949

5050
func AssertSplitExprTree(tb testing.TB, s string, want []sqlparser.Expr) {
5151
tb.Helper()
52-
if diff := deep.Equal(sqlparser.SplitExprTree(StripExprPos(sqlparser.MustParseExprString(s))), want); diff != nil {
52+
e := sqlparser.MustParseExprString(s)
53+
if diff := deep.Equal(sqlparser.SplitExprTree(StripExprPos(e)), want); diff != nil {
5354
tb.Fatal("mismatch: \n" + strings.Join(diff, "\n"))
5455
}
5556
}
5657

5758
func TestDeleteStatement_String(t *testing.T) {
5859
AssertStatementStringer(t, &sqlparser.DeleteStatement{
59-
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}, Alias: &sqlparser.Ident{Name: "tbl2"}},
60-
}, `DELETE FROM "tbl" AS "tbl2"`)
60+
TableName: &sqlparser.TableName{
61+
Name: &sqlparser.Ident{Name: "tbl"},
62+
Alias: &sqlparser.Ident{Name: "tbl2"},
63+
},
64+
}, `DELETE FROM tbl AS tbl2`)
6165

6266
AssertStatementStringer(t, &sqlparser.DeleteStatement{
63-
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
67+
TableName: &sqlparser.TableName{
68+
Name: &sqlparser.Ident{Name: "tbl", Quoted: true, QuoteChar: `"`},
69+
},
6470
}, `DELETE FROM "tbl"`)
6571

72+
AssertStatementStringer(t, &sqlparser.DeleteStatement{
73+
TableName: &sqlparser.TableName{
74+
Name: &sqlparser.Ident{Name: "tbl", Quoted: true, QuoteChar: "`"},
75+
},
76+
}, "DELETE FROM `tbl`")
77+
6678
AssertStatementStringer(t, &sqlparser.DeleteStatement{
6779
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
6880
Condition: &sqlparser.BoolLit{Value: true},
69-
}, `DELETE FROM "tbl" WHERE TRUE`)
81+
}, `DELETE FROM tbl WHERE TRUE`)
7082
}
7183

7284
func TestInsertStatement_String(t *testing.T) {
7385
AssertStatementStringer(t, &sqlparser.InsertStatement{
7486
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
7587
DefaultValues: true,
76-
}, `INSERT INTO "tbl" DEFAULT VALUES`)
88+
}, `INSERT INTO tbl DEFAULT VALUES`)
7789

7890
AssertStatementStringer(t, &sqlparser.InsertStatement{
7991
TableName: &sqlparser.TableName{
8092
Name: &sqlparser.Ident{Name: "tbl"},
8193
Alias: &sqlparser.Ident{Name: "x"},
8294
},
8395
DefaultValues: true,
84-
}, `INSERT INTO "tbl" AS "x" DEFAULT VALUES`)
96+
}, `INSERT INTO tbl AS x DEFAULT VALUES`)
8597

8698
AssertStatementStringer(t, &sqlparser.InsertStatement{
8799
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
88100
Query: &sqlparser.SelectStatement{
89101
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
90102
},
91-
}, `INSERT INTO "tbl" SELECT *`)
103+
}, `INSERT INTO tbl SELECT *`)
92104

93105
AssertStatementStringer(t, &sqlparser.InsertStatement{
94106
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
95107
ColumnNames: []*sqlparser.Ident{
96108
{Name: "x"},
97-
{Name: "y"},
109+
{Name: "y", Quoted: true, QuoteChar: `"`},
98110
},
99111
Expressions: []*sqlparser.Exprs{
100112
{Exprs: []sqlparser.Expr{&sqlparser.NullLit{}, &sqlparser.NullLit{}}},
101113
{Exprs: []sqlparser.Expr{&sqlparser.NullLit{}, &sqlparser.NullLit{}}},
102114
},
103-
}, `INSERT INTO "tbl" ("x", "y") VALUES (NULL, NULL), (NULL, NULL)`)
115+
}, `INSERT INTO tbl (x, "y") VALUES (NULL, NULL), (NULL, NULL)`)
104116

105117
AssertStatementStringer(t, &sqlparser.InsertStatement{
106118
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
107119
DefaultValues: true,
108120
UpsertClause: &sqlparser.UpsertClause{
109121
DoNothing: true,
110122
},
111-
}, `INSERT INTO "tbl" DEFAULT VALUES ON CONFLICT DO NOTHING`)
123+
}, `INSERT INTO tbl DEFAULT VALUES ON CONFLICT DO NOTHING`)
112124

113125
AssertStatementStringer(t, &sqlparser.InsertStatement{
114126
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
@@ -125,13 +137,13 @@ func TestInsertStatement_String(t *testing.T) {
125137
},
126138
UpdateWhereExpr: &sqlparser.BoolLit{Value: false},
127139
},
128-
}, `INSERT INTO "tbl" DEFAULT VALUES ON CONFLICT ("x" ASC, "y" DESC) WHERE TRUE DO UPDATE SET "x" = 100, ("y", "z") = 200 WHERE FALSE`)
140+
}, `INSERT INTO tbl DEFAULT VALUES ON CONFLICT (x ASC, y DESC) WHERE TRUE DO UPDATE SET x = 100, (y, z) = 200 WHERE FALSE`)
129141

130142
AssertStatementStringer(t, &sqlparser.InsertStatement{
131143
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
132144
DefaultValues: true,
133145
OutputExpressions: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
134-
}, `INSERT INTO "tbl" DEFAULT VALUES RETURNING *`)
146+
}, `INSERT INTO tbl DEFAULT VALUES RETURNING *`)
135147

136148
AssertStatementStringer(t, &sqlparser.InsertStatement{
137149
TableName: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "tbl"}},
@@ -140,7 +152,7 @@ func TestInsertStatement_String(t *testing.T) {
140152
&sqlparser.ResultColumn{Expr: &sqlparser.Ident{Name: "x"}, Alias: &sqlparser.Ident{Name: "y"}},
141153
&sqlparser.ResultColumn{Expr: &sqlparser.Ident{Name: "z"}},
142154
},
143-
}, `INSERT INTO "tbl" DEFAULT VALUES RETURNING "x" AS "y", "z"`)
155+
}, `INSERT INTO tbl DEFAULT VALUES RETURNING x AS y, z`)
144156
}
145157

146158
func TestSelectStatement_String(t *testing.T) {
@@ -149,23 +161,28 @@ func TestSelectStatement_String(t *testing.T) {
149161
&sqlparser.ResultColumn{Expr: &sqlparser.Ident{Name: "x"}, Alias: &sqlparser.Ident{Name: "y"}},
150162
&sqlparser.ResultColumn{Expr: &sqlparser.Ident{Name: "z"}},
151163
},
152-
}, `SELECT "x" AS "y", "z"`)
164+
}, `SELECT x AS y, z`)
153165

154166
AssertStatementStringer(t, &sqlparser.SelectStatement{
155167
Distinct: true,
156168
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{
157169
Expr: &sqlparser.Ident{Name: "x"},
158170
}},
159-
}, `SELECT DISTINCT "x"`)
171+
}, `SELECT DISTINCT x`)
160172

161173
AssertStatementStringer(t, &sqlparser.SelectStatement{
162174
All: true,
163175
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Expr: &sqlparser.Ident{Name: "x"}}},
164-
}, `SELECT ALL "x"`)
176+
}, `SELECT ALL x`)
165177

166178
AssertStatementStringer(t, &sqlparser.SelectStatement{
167179
Hint: &sqlparser.Hint{Value: "HINT"},
168180
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Expr: &sqlparser.Ident{Name: "x"}}},
181+
}, `SELECT /* HINT */ x`)
182+
183+
AssertStatementStringer(t, &sqlparser.SelectStatement{
184+
Hint: &sqlparser.Hint{Value: "HINT"},
185+
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Expr: &sqlparser.Ident{Name: "x", Quoted: true, QuoteChar: `"`}}},
169186
}, `SELECT /* HINT */ "x"`)
170187

171188
AssertStatementStringer(t, &sqlparser.SelectStatement{
@@ -174,15 +191,15 @@ func TestSelectStatement_String(t *testing.T) {
174191
Condition: &sqlparser.BoolLit{Value: true},
175192
GroupingElements: []sqlparser.Expr{&sqlparser.Ident{Name: "x"}, &sqlparser.Ident{Name: "y"}},
176193
HavingCondition: &sqlparser.Ident{Name: "z"},
177-
}, `SELECT * FROM "tbl" WHERE TRUE GROUP BY "x", "y" HAVING "z"`)
194+
}, `SELECT * FROM tbl WHERE TRUE GROUP BY x, y HAVING z`)
178195

179196
AssertStatementStringer(t, &sqlparser.SelectStatement{
180197
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
181198
FromItems: &sqlparser.ParenSource{
182199
X: &sqlparser.SelectStatement{Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}}},
183200
Alias: &sqlparser.Ident{Name: "tbl"},
184201
},
185-
}, `SELECT * FROM (SELECT *) AS "tbl"`)
202+
}, `SELECT * FROM (SELECT *) AS tbl`)
186203

187204
AssertStatementStringer(t, &sqlparser.SelectStatement{
188205
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
@@ -230,7 +247,7 @@ func TestSelectStatement_String(t *testing.T) {
230247
{X: &sqlparser.Ident{Name: "x"}},
231248
{X: &sqlparser.Ident{Name: "y"}},
232249
},
233-
}, `SELECT * ORDER BY "x", "y"`)
250+
}, `SELECT * ORDER BY x, y`)
234251

235252
AssertStatementStringer(t, &sqlparser.SelectStatement{
236253
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
@@ -245,7 +262,7 @@ func TestSelectStatement_String(t *testing.T) {
245262
Operator: &sqlparser.JoinOperator{Comma: true},
246263
Y: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "y"}},
247264
},
248-
}, `SELECT * FROM "x", "y"`)
265+
}, `SELECT * FROM x, y`)
249266

250267
AssertStatementStringer(t, &sqlparser.SelectStatement{
251268
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
@@ -255,7 +272,7 @@ func TestSelectStatement_String(t *testing.T) {
255272
Y: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "y"}},
256273
Constraint: &sqlparser.OnConstraint{X: &sqlparser.BoolLit{Value: true}},
257274
},
258-
}, `SELECT * FROM "x" JOIN "y" ON TRUE`)
275+
}, `SELECT * FROM x JOIN y ON TRUE`)
259276

260277
AssertStatementStringer(t, &sqlparser.SelectStatement{
261278
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
@@ -267,7 +284,7 @@ func TestSelectStatement_String(t *testing.T) {
267284
Columns: []*sqlparser.Ident{{Name: "a"}, {Name: "b"}},
268285
},
269286
},
270-
}, `SELECT * FROM "x" NATURAL INNER JOIN "y" USING ("a", "b")`)
287+
}, `SELECT * FROM x NATURAL INNER JOIN y USING (a, b)`)
271288

272289
AssertStatementStringer(t, &sqlparser.SelectStatement{
273290
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
@@ -276,7 +293,7 @@ func TestSelectStatement_String(t *testing.T) {
276293
Operator: &sqlparser.JoinOperator{Left: true},
277294
Y: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "y"}},
278295
},
279-
}, `SELECT * FROM "x" LEFT JOIN "y"`)
296+
}, `SELECT * FROM x LEFT JOIN y`)
280297

281298
AssertStatementStringer(t, &sqlparser.SelectStatement{
282299
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
@@ -285,7 +302,7 @@ func TestSelectStatement_String(t *testing.T) {
285302
Operator: &sqlparser.JoinOperator{Left: true, Outer: true},
286303
Y: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "y"}},
287304
},
288-
}, `SELECT * FROM "x" LEFT OUTER JOIN "y"`)
305+
}, `SELECT * FROM x LEFT OUTER JOIN y`)
289306

290307
AssertStatementStringer(t, &sqlparser.SelectStatement{
291308
Columns: &sqlparser.OutputNames{&sqlparser.ResultColumn{Star: true}},
@@ -294,7 +311,7 @@ func TestSelectStatement_String(t *testing.T) {
294311
Operator: &sqlparser.JoinOperator{Cross: true},
295312
Y: &sqlparser.TableName{Name: &sqlparser.Ident{Name: "y"}},
296313
},
297-
}, `SELECT * FROM "x" CROSS JOIN "y"`)
314+
}, `SELECT * FROM x CROSS JOIN y`)
298315
}
299316

300317
func TestUpdateStatement_String(t *testing.T) {
@@ -305,12 +322,13 @@ func TestUpdateStatement_String(t *testing.T) {
305322
{Columns: []*sqlparser.Ident{{Name: "y"}}, Expr: &sqlparser.NumberLit{Value: "200"}},
306323
},
307324
Condition: &sqlparser.BoolLit{Value: true},
308-
}, `UPDATE "tbl" SET "x" = 100, "y" = 200 WHERE TRUE`)
325+
}, `UPDATE tbl SET x = 100, y = 200 WHERE TRUE`)
309326
}
310327

311328
func TestIdent_String(t *testing.T) {
312-
AssertExprStringer(t, &sqlparser.Ident{Name: "foo"}, `"foo"`)
313-
AssertExprStringer(t, &sqlparser.Ident{Name: "foo \" bar"}, `"foo "" bar"`)
329+
AssertExprStringer(t, &sqlparser.Ident{Name: "foo"}, `foo`)
330+
AssertExprStringer(t, &sqlparser.Ident{Name: "foo \" bar", Quoted: true, QuoteChar: `"`}, `"foo "" bar"`)
331+
AssertExprStringer(t, &sqlparser.Ident{Name: `foo " bar`, Quoted: true, QuoteChar: "`"}, "`foo \" bar`")
314332
}
315333

316334
func TestStringLit_String(t *testing.T) {
@@ -394,7 +412,7 @@ func TestCaseExpr_String(t *testing.T) {
394412
{Condition: &sqlparser.NumberLit{Value: "2"}, Body: &sqlparser.BoolLit{Value: false}},
395413
},
396414
ElseExpr: &sqlparser.NullLit{},
397-
}, `CASE "foo" WHEN 1 THEN TRUE WHEN 2 THEN FALSE ELSE NULL END`)
415+
}, `CASE foo WHEN 1 THEN TRUE WHEN 2 THEN FALSE ELSE NULL END`)
398416

399417
AssertExprStringer(t, &sqlparser.CaseExpr{
400418
Blocks: []*sqlparser.CaseBlock{
@@ -409,8 +427,17 @@ func TestExprs_String(t *testing.T) {
409427
}
410428

411429
func TestQualifiedRef_String(t *testing.T) {
412-
AssertExprStringer(t, &sqlparser.QualifiedRef{Table: &sqlparser.Ident{Name: "tbl"}, Column: &sqlparser.Ident{Name: "col"}}, `"tbl"."col"`)
413-
AssertExprStringer(t, &sqlparser.QualifiedRef{Table: &sqlparser.Ident{Name: "tbl"}, Star: true}, `"tbl".*`)
430+
AssertExprStringer(t,
431+
&sqlparser.QualifiedRef{
432+
Table: &sqlparser.Ident{Name: "tbl"},
433+
Column: &sqlparser.Ident{Name: "col"},
434+
},
435+
`tbl.col`,
436+
)
437+
AssertExprStringer(t,
438+
&sqlparser.QualifiedRef{Table: &sqlparser.Ident{Name: "tbl"}, Star: true},
439+
`tbl.*`,
440+
)
414441
}
415442

416443
func TestCall_String(t *testing.T) {

lexer.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ func (l *Lexer) Lex() (pos Pos, token Token, lit string) {
3737
return l.lexBlob()
3838
} else if isAlpha(ch) || ch == '_' {
3939
return l.lexUnquotedIdent(l.pos, "")
40-
} else if ch == '"' {
41-
return l.lexQuotedIdent()
40+
} else if ch == '"' || ch == '`' {
41+
return l.lexQuotedIdent(ch)
4242
} else if ch == '\'' {
4343
return l.lexString()
4444
} else if ch == '?' || ch == ':' || ch == '@' || ch == '$' {
@@ -125,21 +125,23 @@ func (l *Lexer) lexUnquotedIdent(pos Pos, prefix string) (Pos, Token, string) {
125125
return pos, tok, lit
126126
}
127127

128-
func (l *Lexer) lexQuotedIdent() (Pos, Token, string) {
128+
func (l *Lexer) lexQuotedIdent(char rune) (Pos, Token, string) {
129129
ch, pos := l.read()
130-
assert(ch == '"')
130+
assert(ch == char)
131131

132132
l.buf.Reset()
133+
l.buf.WriteRune(char)
133134
for {
134135
ch, _ := l.read()
135136
if ch == -1 {
136-
return pos, ILLEGAL, `"` + l.buf.String()
137-
} else if ch == '"' {
138-
if l.peek() == '"' { // escaped quote
137+
return pos, ILLEGAL, l.buf.String()
138+
} else if ch == char {
139+
if l.peek() == char { // escaped quote
139140
l.read()
140-
l.buf.WriteRune('"')
141+
l.buf.WriteRune(char)
141142
continue
142143
}
144+
l.buf.WriteRune(char)
143145
return pos, QIDENT, l.buf.String()
144146
}
145147
l.buf.WriteRune(ch)

lexer_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ func TestLexer_Lex(t *testing.T) {
1313
AssertLex(t, `foo_BAR123`, sqlparser.IDENT, `foo_BAR123`)
1414
})
1515
t.Run("Quoted", func(t *testing.T) {
16-
AssertLex(t, `"crazy ~!#*&# column name"" foo"`, sqlparser.QIDENT, `crazy ~!#*&# column name" foo`)
16+
AssertLex(t, `"crazy ~!#*&# column name"" foo"`, sqlparser.QIDENT, `"crazy ~!#*&# column name" foo"`)
17+
})
18+
t.Run("BackQuoted", func(t *testing.T) {
19+
AssertLex(t, "`crazy ~!#*&# column name foo`", sqlparser.QIDENT, "`crazy ~!#*&# column name foo`")
1720
})
1821
t.Run("NoEndQuote", func(t *testing.T) {
1922
AssertLex(t, `"unfinished`, sqlparser.ILLEGAL, `"unfinished`)

0 commit comments

Comments
 (0)