7 "github.com/vapor/errors"
10 // ErrBadFilter is returned from Parse when
11 // it encounters an invalid filter expression.
12 var ErrBadFilter = errors.New("invalid query filter")
14 // Predicate represents a parsed filter predicate.
15 type Predicate struct {
17 selectorTypes map[string]Type
21 // String returns a cleaned, canonical representation of the
23 func (p Predicate) String() string {
27 return p.expr.String()
30 // MarshalText implements the encoding.TextMarshaler interface and
31 // returns a cleaned, canonical representation of the predicate.
32 func (p Predicate) MarshalText() ([]byte, error) {
33 return []byte(p.expr.String()), nil
36 // Parse parses a predicate and returns an internal representation of the
37 // predicate or an error if it fails to parse.
38 func Parse(predicate string, tbl *Table, vals []interface{}) (p Predicate, err error) {
39 expr, parser, err := parse(predicate)
41 return p, errors.WithDetail(ErrBadFilter, err.Error())
43 selectorTypes, err := typeCheck(expr, tbl, vals)
45 return p, errors.WithDetail(ErrBadFilter, err.Error())
50 selectorTypes: selectorTypes,
51 Parameters: parser.maxPlaceholder,
55 // Field is a type for simple expressions that simply access an attribute of
56 // the queried object. They're used for GROUP BYs.
61 func (f Field) String() string {
62 return f.expr.String()
65 // ParseField parses a field expression (either an attrExpr or a selectorExpr).
66 func ParseField(s string) (f Field, err error) {
67 expr, _, err := parse(s)
69 return f, errors.WithDetail(ErrBadFilter, err.Error())
72 return f, errors.WithDetail(ErrBadFilter, "empty field expression")
76 case attrExpr, selectorExpr:
77 return Field{expr: expr}, nil
79 return f, errors.WithDetailf(ErrBadFilter, "%q is not a valid field expression", s)
83 func parse(exprString string) (expr expr, parser *parser, err error) {
86 if perr, ok := r.(parseError); ok {
92 parser = newParser([]byte(exprString))
94 // An empty expression is a valid predicate.
95 if parser.tok == tokEOF {
96 return nil, parser, nil
99 expr = parseExpr(parser)
100 parser.parseTok(tokEOF)
101 return expr, parser, err
104 func newParser(src []byte) *parser {
107 p.next() // advance onto the first input token
111 // The parser structure holds the parser's internal state.
118 pos int // token position
119 tok token // one token look-ahead
120 lit string // token literal
123 func determineBinaryOp(p *parser, minPrecedence int) (op *binaryOp, ok bool) {
124 op, ok = binaryOps[p.lit]
125 return op, ok && op.precedence >= minPrecedence
128 // next advances to the next token.
129 func (p *parser) next() {
130 p.pos, p.tok, p.lit = p.scanner.Scan()
133 func (p *parser) parseLit(lit string) {
135 p.errorf("got %s, expected %s", p.lit, lit)
140 func (p *parser) parseTok(tok token) {
142 p.errorf("got %s, expected %s", p.lit, tok.String())
147 func parseExpr(p *parser) expr {
148 // Uses the precedence-climbing algorithm:
149 // https://en.wikipedia.org/wiki/Operator-precedence_parser#Precedence_climbing_method
150 expr := parsePrimaryExpr(p)
151 return parseExprCont(p, expr, 0)
154 func parseExprCont(p *parser, lhs expr, minPrecedence int) expr {
156 op, ok := determineBinaryOp(p, minPrecedence)
162 rhs := parsePrimaryExpr(p)
165 op2, ok := determineBinaryOp(p, op.precedence+1)
169 rhs = parseExprCont(p, rhs, op2.precedence)
171 lhs = binaryExpr{l: lhs, r: rhs, op: op}
176 func parsePrimaryExpr(p *parser) expr {
179 x = parseSelectorExpr(p, x)
184 func parseOperand(p *parser) expr {
190 return parenExpr{inner: expr}
191 case p.tok == tokString:
192 v := valueExpr{typ: p.tok, value: p.lit}
195 case p.tok == tokInteger:
196 // Parse the literal into an integer so that we store the string
197 // representation of the *decimal* value, never the hex.
198 integer, err := strconv.ParseInt(p.lit, 0, 64)
200 // can't happen; scanner guarantees it
201 p.errorf("invalid integer: %q", p.lit)
203 v := valueExpr{typ: p.tok, value: strconv.Itoa(int(integer))}
206 case p.tok == tokPlaceholder:
207 num, err := strconv.Atoi(p.lit[1:])
208 if err != nil || num <= 0 {
209 p.errorf("invalid placeholder: %q", p.lit)
211 v := placeholderExpr{num: num}
214 if num > p.maxPlaceholder {
215 p.maxPlaceholder = num
219 return parseEnvironmentExpr(p)
223 func parseSelectorExpr(p *parser, objExpr expr) expr {
224 p.next() // move past the '.'
234 func parseEnvironmentExpr(p *parser) expr {
238 return attrExpr{attr: name}
249 type parseError struct {
254 func (err parseError) Error() string {
255 return fmt.Sprintf("col %d: %s", err.pos, err.msg)
258 func (p *parser) errorf(format string, args ...interface{}) {
259 panic(parseError{pos: p.pos, msg: fmt.Sprintf(format, args...)})