mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 19:04:35 +00:00
102 lines
2.3 KiB
Go
102 lines
2.3 KiB
Go
package handler
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/bitly/go-simplejson"
|
|
)
|
|
|
|
func parseQueryString(query string) (*simplejson.Json, error) {
|
|
_, items := lex("foo", query)
|
|
res, err := parseQueryStringRec(items)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
js := simplejson.New()
|
|
js.Set("query", res)
|
|
return js, nil
|
|
}
|
|
|
|
const (
|
|
matchTypeRange = "range"
|
|
matchTypeMatch = "match"
|
|
matchTypeWildcard = "wildcard"
|
|
)
|
|
|
|
func parseQueryStringRec(items chan item) (*simplejson.Json, error) {
|
|
retTerm := simplejson.New()
|
|
currFieldName := ""
|
|
currBool := ""
|
|
currMatchType := matchTypeMatch
|
|
currPathAddition := ""
|
|
terms := []*simplejson.Json{}
|
|
itemLoop:
|
|
for it := range items {
|
|
if it.typ == itemError {
|
|
return nil, fmt.Errorf(it.val)
|
|
}
|
|
|
|
switch it.typ {
|
|
case itemIdentifier:
|
|
currFieldName = it.val
|
|
case itemString, itemBoolean, itemNumber:
|
|
currTerm := simplejson.New()
|
|
if strings.ContainsRune(it.val, '*') {
|
|
currMatchType = matchTypeWildcard
|
|
currPathAddition = "value"
|
|
}
|
|
path := []string{currMatchType, currFieldName}
|
|
if len(currPathAddition) > 0 {
|
|
path = append(path, currPathAddition)
|
|
}
|
|
currTerm.SetPath(path, it.val)
|
|
terms = append(terms, currTerm)
|
|
|
|
// reset
|
|
currFieldName = ""
|
|
currMatchType = matchTypeMatch
|
|
|
|
case itemBooleanOp:
|
|
thisBool := "must"
|
|
if strings.ToLower(it.val) == "or" {
|
|
thisBool = "should"
|
|
}
|
|
if len(currBool) == 0 {
|
|
currBool = thisBool
|
|
} else {
|
|
if thisBool != currBool {
|
|
// undefined behaviour order of precedence needs to be explicitly defined using parentheses
|
|
return nil, fmt.Errorf("error parsing query. Cannot mix boolean operators without explicitly defining precedence with parentheses")
|
|
}
|
|
}
|
|
case itemLeftParen:
|
|
currTerm, err := parseQueryStringRec(items)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
terms = append(terms, currTerm)
|
|
case itemRightParen:
|
|
break itemLoop
|
|
case itemOperator:
|
|
switch it.val {
|
|
case "==":
|
|
currMatchType = matchTypeMatch
|
|
currPathAddition = ""
|
|
case ">=":
|
|
currMatchType = matchTypeRange
|
|
currPathAddition = "gte"
|
|
case "<=":
|
|
currMatchType = matchTypeRange
|
|
currPathAddition = "lte"
|
|
}
|
|
|
|
}
|
|
}
|
|
if len(currBool) == 0 {
|
|
currBool = "must"
|
|
}
|
|
retTerm.SetPath([]string{"bool", currBool}, terms)
|
|
return retTerm, nil
|
|
}
|