Skip to content

Commit ec1c75a

Browse files
committed
sql/parse: parse USING and config key-value in CREATE INDEX
Signed-off-by: Miguel Molina <miguel@erizocosmi.co>
1 parent 880fccd commit ec1c75a

File tree

7 files changed

+300
-15
lines changed

7 files changed

+300
-15
lines changed

sql/analyzer/validation_rules_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ func TestValidateIndexCreation(t *testing.T) {
276276
expression.NewGetFieldWithTable(0, sql.Int64, "bar", "b", false),
277277
)},
278278
"",
279+
make(map[string]string),
279280
),
280281
false,
281282
},
@@ -288,6 +289,7 @@ func TestValidateIndexCreation(t *testing.T) {
288289
expression.NewGetFieldWithTable(0, sql.Int64, "foo", "c", false),
289290
)},
290291
"",
292+
make(map[string]string),
291293
),
292294
false,
293295
},
@@ -300,6 +302,7 @@ func TestValidateIndexCreation(t *testing.T) {
300302
expression.NewGetFieldWithTable(0, sql.Int64, "foo", "b", false),
301303
)},
302304
"",
305+
make(map[string]string),
303306
),
304307
true,
305308
},

sql/index.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ type IndexDriver interface {
109109
// Create a new index. If exprs is more than one expression, it means the
110110
// index has multiple columns indexed. If it's just one, it means it may
111111
// be an expression or a column.
112-
Create(path, table, db, id string, exprs []Expression) (Index, error)
112+
Create(path, table, db, id string, exprs []Expression, config map[string]string) (Index, error)
113113
// Load the index at the given path.
114114
Load(path string) (Index, error)
115115
// Save the given index at the given path.

sql/parse/create_index.go

Lines changed: 173 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ type parseFunc func(*bufio.Reader) error
2424
func parseCreateIndex(s string) (sql.Node, error) {
2525
r := bufio.NewReader(strings.NewReader(s))
2626

27-
var name, table string
27+
var name, table, driver string
2828
var exprs []string
29+
var config = make(map[string]string)
2930
steps := []parseFunc{
3031
expect("create"),
3132
skipSpaces,
@@ -37,8 +38,20 @@ func parseCreateIndex(s string) (sql.Node, error) {
3738
skipSpaces,
3839
readIdent(&table),
3940
skipSpaces,
41+
optional(
42+
expect("using"),
43+
skipSpaces,
44+
readIdent(&driver),
45+
skipSpaces,
46+
),
4047
readExprs(&exprs),
4148
skipSpaces,
49+
optional(
50+
expect("with"),
51+
skipSpaces,
52+
readKeyValue(config),
53+
skipSpaces,
54+
),
4255
}
4356

4457
for _, step := range steps {
@@ -47,9 +60,6 @@ func parseCreateIndex(s string) (sql.Node, error) {
4760
}
4861
}
4962

50-
// TODO: parse using
51-
// TODO: parse config
52-
5363
var indexExprs = make([]sql.Expression, len(exprs))
5464
for i, e := range exprs {
5565
var err error
@@ -63,10 +73,128 @@ func parseCreateIndex(s string) (sql.Node, error) {
6373
name,
6474
plan.NewUnresolvedTable(table),
6575
indexExprs,
66-
"",
76+
driver,
77+
config,
6778
), nil
6879
}
6980

81+
func optional(steps ...parseFunc) parseFunc {
82+
return func(rd *bufio.Reader) error {
83+
for _, step := range steps {
84+
err := step(rd)
85+
if err == io.EOF || errUnexpectedSyntax.Is(err) {
86+
return nil
87+
}
88+
89+
if err != nil {
90+
return err
91+
}
92+
}
93+
94+
return nil
95+
}
96+
}
97+
98+
func readKeyValue(kv map[string]string) parseFunc {
99+
return func(rd *bufio.Reader) error {
100+
r, _, err := rd.ReadRune()
101+
if err != nil {
102+
return err
103+
}
104+
105+
if r != '(' {
106+
return errUnexpectedSyntax.New("(", string(r))
107+
}
108+
109+
for {
110+
var key, value string
111+
steps := []parseFunc{
112+
skipSpaces,
113+
readIdent(&key),
114+
skipSpaces,
115+
expectRune('='),
116+
skipSpaces,
117+
readValue(&value),
118+
skipSpaces,
119+
}
120+
121+
for _, step := range steps {
122+
if err := step(rd); err != nil {
123+
return err
124+
}
125+
}
126+
127+
r, _, err := rd.ReadRune()
128+
if err != nil {
129+
return err
130+
}
131+
132+
switch r {
133+
case ')':
134+
kv[key] = value
135+
return nil
136+
case ',':
137+
kv[key] = value
138+
continue
139+
default:
140+
return errUnexpectedSyntax.New(", or )", string(r))
141+
}
142+
}
143+
}
144+
}
145+
146+
func readValue(val *string) parseFunc {
147+
return func(rd *bufio.Reader) error {
148+
var buf bytes.Buffer
149+
var singleQuote, doubleQuote, ignoreNext bool
150+
var first = true
151+
for {
152+
r, _, err := rd.ReadRune()
153+
if err == io.EOF {
154+
break
155+
}
156+
157+
if err != nil {
158+
return err
159+
}
160+
161+
if singleQuote || doubleQuote {
162+
switch true {
163+
case ignoreNext:
164+
ignoreNext = false
165+
case r == '\\':
166+
ignoreNext = true
167+
continue
168+
case r == '\'' && singleQuote:
169+
singleQuote = false
170+
continue
171+
case r == '"' && doubleQuote:
172+
doubleQuote = false
173+
continue
174+
}
175+
} else if first && (r == '\'' || r == '"') {
176+
if r == '\'' {
177+
singleQuote = true
178+
} else {
179+
doubleQuote = true
180+
}
181+
first = false
182+
continue
183+
} else if !unicode.IsLetter(r) && !unicode.IsNumber(r) && r != '_' {
184+
if err := rd.UnreadRune(); err != nil {
185+
return err
186+
}
187+
break
188+
}
189+
190+
buf.WriteRune(r)
191+
}
192+
193+
*val = strings.ToLower(buf.String())
194+
return nil
195+
}
196+
}
197+
70198
func parseIndexExpr(str string) (sql.Expression, error) {
71199
stmt, err := sqlparser.Parse("SELECT " + str)
72200
if err != nil {
@@ -123,22 +251,38 @@ func readExprs(exprs *[]string) parseFunc {
123251
var buf bytes.Buffer
124252
r, _, err := rd.ReadRune()
125253
if err != nil {
254+
if err == io.EOF {
255+
return errUnexpectedSyntax.New("(", "EOF")
256+
}
126257
return err
127258
}
128259

129260
if r != '(' {
130-
return errUnexpectedSyntax.New("(", r)
261+
return errUnexpectedSyntax.New("(", string(r))
131262
}
132263

133264
var level int
134265
var hasNonIdentChars bool
266+
var singleQuote, doubleQuote bool
267+
var ignoreNext bool
135268
for {
136269
r, _, err := rd.ReadRune()
137270
if err != nil {
138271
return err
139272
}
140273

141274
switch true {
275+
case singleQuote || doubleQuote:
276+
switch true {
277+
case ignoreNext:
278+
ignoreNext = false
279+
case r == '\\':
280+
ignoreNext = true
281+
case r == '"' && doubleQuote:
282+
doubleQuote = false
283+
case r == '\'' && singleQuote:
284+
singleQuote = false
285+
}
142286
case unicode.IsLetter(r) || r == '_':
143287
case r == '(':
144288
level++
@@ -154,6 +298,12 @@ func readExprs(exprs *[]string) parseFunc {
154298
buf.Reset()
155299
return nil
156300
}
301+
case r == '"':
302+
hasNonIdentChars = true
303+
doubleQuote = true
304+
case r == '\'':
305+
hasNonIdentChars = true
306+
singleQuote = true
157307
case r == ',' && level == 0:
158308
if hasNonIdentChars {
159309
return errUnexpectedSyntax.New(",", ")")
@@ -171,9 +321,25 @@ func readExprs(exprs *[]string) parseFunc {
171321
}
172322
}
173323

324+
func expectRune(expected rune) parseFunc {
325+
return func(rd *bufio.Reader) error {
326+
r, _, err := rd.ReadRune()
327+
if err != nil {
328+
return err
329+
}
330+
331+
if r != expected {
332+
return errUnexpectedSyntax.New(expected, string(r))
333+
}
334+
335+
return nil
336+
}
337+
}
338+
174339
func expect(expected string) parseFunc {
175340
return func(r *bufio.Reader) error {
176341
var ident string
342+
177343
if err := readIdent(&ident)(r); err != nil {
178344
return err
179345
}
@@ -198,10 +364,7 @@ func skipSpaces(r *bufio.Reader) error {
198364
}
199365

200366
if !unicode.IsSpace(ru) {
201-
if err := r.UnreadRune(); err != nil {
202-
return err
203-
}
204-
return nil
367+
return r.UnreadRune()
205368
}
206369
}
207370
}

0 commit comments

Comments
 (0)