/
insert.go
135 lines (111 loc) · 3.1 KB
/
insert.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package parser
import (
"github.com/asdine/genji/sql/query"
"github.com/asdine/genji/sql/scanner"
)
// parseInsertStatement parses an insert string and returns a Statement AST object.
// This function assumes the INSERT token has already been consumed.
func (p *Parser) parseInsertStatement() (query.InsertStmt, error) {
var stmt query.InsertStmt
var err error
// Parse "INTO".
if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != scanner.INTO {
return stmt, newParseError(scanner.Tokstr(tok, lit), []string{"INTO"}, pos)
}
// Parse table name
stmt.TableName, err = p.parseIdent()
if err != nil {
return stmt, err
}
// Parse field list: (a, b, c)
fields, ok, err := p.parseFieldList()
if err != nil {
return stmt, err
}
if ok {
stmt.FieldNames = fields
}
// Parse VALUES (v1, v2, v3)
stmt.Values, err = p.parseValues()
if err != nil {
return stmt, err
}
return stmt, nil
}
// parseFieldList parses a list of fields in the form: (field, field, ...), if exists
func (p *Parser) parseFieldList() ([]string, bool, error) {
// Parse ( token.
if tok, _, _ := p.ScanIgnoreWhitespace(); tok != scanner.LPAREN {
p.Unscan()
return nil, false, nil
}
// Parse field list.
var fields []string
var err error
if fields, err = p.parseIdentList(); err != nil {
return nil, false, err
}
// Parse required ) token.
if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != scanner.RPAREN {
return nil, false, newParseError(scanner.Tokstr(tok, lit), []string{")"}, pos)
}
return fields, true, nil
}
// parseValues parses the "VALUES" clause of the query, if it exists.
func (p *Parser) parseValues() (query.LiteralExprList, error) {
// Check if the VALUES token exists.
if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != scanner.VALUES {
return nil, newParseError(scanner.Tokstr(tok, lit), []string{"VALUES"}, pos)
}
var valuesList query.LiteralExprList
// Parse first (required) value list.
d, err := p.parseValue()
if err != nil {
return nil, err
}
valuesList = append(valuesList, d)
// Parse remaining (optional) values.
for {
if tok, _, _ := p.ScanIgnoreWhitespace(); tok != scanner.COMMA {
p.Unscan()
break
}
d, err := p.parseValue()
if err != nil {
return nil, err
}
valuesList = append(valuesList, d)
}
return valuesList, nil
}
// parseValue parses either a parameter, a JSON document or a list of expressions.
func (p *Parser) parseValue() (query.Expr, error) {
// Parse a param first
prm, err := p.parseParam()
if err != nil {
return nil, err
}
if prm != nil {
return prm, nil
}
// If not a param, start over
p.Unscan()
// check if it's a json document
expr, ok, err := p.parseDocument()
if err != nil || ok {
return expr, err
}
// if not a document, start over
p.Unscan()
// check if it's an expression list
if tok, _, _ := p.ScanIgnoreWhitespace(); tok != scanner.LPAREN {
tok, pos, lit := p.ScanIgnoreWhitespace()
return nil, newParseError(scanner.Tokstr(tok, lit), []string{"expression list or JSON"}, pos)
}
p.Unscan()
expr, err = p.parseExprList(scanner.LPAREN, scanner.RPAREN)
if err != nil {
return nil, err
}
return expr, nil
}