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
|
package mapr
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/mimecast/dtail/internal/mapr/funcs"
)
// Represent a parsed "set" clause, used by mapr.Query
type setCondition struct {
lString string
rType fieldType
rString string
rFloat float64
// For now only text functions are supported.
// Maybe in the future we can have typed functions too
// so that a float input/output is possible.
functionStack funcs.FunctionStack
}
func (sc *setCondition) String() string {
return fmt.Sprintf("setCondition(lString:%s,rString:%s,rType:%s,functionStack:%v)",
sc.lString, sc.rString, sc.rType.String(), sc.functionStack)
}
func makeSetConditions(tokens []token) (set []setCondition, err error) {
parse := func(tokens []token) (setCondition, []token, error) {
var sc setCondition
if len(tokens) < 3 {
return sc, nil, errors.New(invalidQuery + "Not enough arguments in 'set' clause")
}
setOp := strings.ToLower(tokens[1].str)
switch setOp {
case "=":
default:
return sc, nil, errors.New(invalidQuery + "Unknown operation in 'set' clause: " + setOp)
}
if !tokens[0].isBareword {
return sc, nil, errors.New(invalidQuery + "Expected bareword at 'set' clause's lValue: " + tokens[0].str)
}
sc.lString = tokens[0].str
if !strings.HasPrefix(sc.lString, "$") {
return sc, nil, errors.New(invalidQuery + "Expected field variable name (starting with $) at 'set' clause's lValue: " + tokens[0].str)
}
sc.rType = Field
rString := tokens[2].str
// Seems like a function call?
if strings.HasSuffix(rString, ")") {
functionStack, functionArg, err := funcs.NewFunctionStack(tokens[2].str)
if err != nil {
return sc, nil, err
}
sc.functionStack = functionStack
sc.rType = FunctionStack
sc.rString = functionArg
return sc, tokens[3:], nil
}
sc.rString = rString
if f, err := strconv.ParseFloat(sc.rString, 64); err == nil {
sc.rFloat = f
sc.rType = Float
} else {
sc.rType = Field
}
return sc, tokens[3:], nil
}
for len(tokens) > 0 {
var sc setCondition
var err error
sc, tokens, err = parse(tokens)
if err != nil {
return nil, err
}
set = append(set, sc)
tokens = tokensConsumeOptional(tokens, ",")
}
return
}
|