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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
package mapr
import (
"dtail/logger"
"errors"
"fmt"
"strconv"
"strings"
)
// QueryOperation determines the mapreduce operation.
type QueryOperation int
// The possible mapreduce operation.s
const (
UndefQueryOperation QueryOperation = iota
StringEq QueryOperation = iota
StringNe QueryOperation = iota
StringContains QueryOperation = iota
FloatOperation QueryOperation = iota
FloatEq QueryOperation = iota
FloatNe QueryOperation = iota
FloatLt QueryOperation = iota
FloatLe QueryOperation = iota
FloatGt QueryOperation = iota
FloatGe QueryOperation = iota
)
type whereType int
// The possible field types.
const (
UndefWhereType whereType = iota
Field whereType = iota
String whereType = iota
Float whereType = iota
)
func (w whereType) String() string {
switch w {
case Field:
return fmt.Sprintf("Field")
case String:
return fmt.Sprintf("String")
case Float:
return fmt.Sprintf("Float")
default:
return fmt.Sprintf("UndefWhereType")
}
}
// Represent a parsed "where" clause, used by mapr.Query
type whereCondition struct {
lString string
lFloat float64
lType whereType
Operation QueryOperation
rString string
rFloat float64
rType whereType
}
func (wc *whereCondition) String() string {
return fmt.Sprintf("whereCondition(Operation:%v,lString:%s,lFloat:%v,lType:%s,rString:%s,rFloat:%v,rType:%s)",
wc.Operation, wc.lString, wc.lFloat, wc.lType.String(), wc.rString, wc.rFloat, wc.rType.String())
}
func makeWhereConditions(tokens []token) (where []whereCondition, err error) {
parse := func(tokens []token) (whereCondition, []token, error) {
var wc whereCondition
if len(tokens) < 3 {
return wc, nil, errors.New(invalidQuery + "Not enough arguments in 'where' clause")
}
whereOp := strings.ToLower(tokens[1].str)
switch whereOp {
case "==":
wc.Operation = FloatEq
case "!=":
wc.Operation = FloatNe
case "<":
wc.Operation = FloatLt
case "<=":
wc.Operation = FloatLe
case "=<":
wc.Operation = FloatLe
case ">":
wc.Operation = FloatGt
case ">=":
wc.Operation = FloatGe
case "=>":
wc.Operation = FloatGe
case "eq":
wc.Operation = StringEq
case "ne":
wc.Operation = StringNe
case "contains":
wc.Operation = StringContains
default:
return wc, nil, errors.New(invalidQuery + "Unknown operation in 'where' clause: " + whereOp)
}
wc.lString = tokens[0].str
wc.rString = tokens[2].str
if wc.Operation > FloatOperation {
if !tokens[0].isBareword {
return wc, nil, errors.New(invalidQuery + "Expected bareword at 'where' clause's lValue: " + tokens[0].str)
}
if f, err := strconv.ParseFloat(wc.lString, 64); err == nil {
wc.lFloat = f
wc.lType = Float
} else {
wc.lType = Field
}
if !tokens[2].isBareword {
return wc, nil, errors.New(invalidQuery + "Expected bareword at 'where' clause's rValue: " + tokens[2].str)
}
if f, err := strconv.ParseFloat(wc.rString, 64); err == nil {
wc.rFloat = f
wc.rType = Float
} else {
wc.rType = Field
}
return wc, tokens[3:], nil
}
if tokens[0].isBareword {
wc.lType = Field
} else {
wc.lType = String
}
if tokens[2].isBareword {
wc.rType = Field
} else {
wc.rType = String
}
return wc, tokens[3:], nil
}
for len(tokens) > 0 {
var wc whereCondition
var err error
wc, tokens, err = parse(tokens)
if err != nil {
return nil, err
}
where = append(where, wc)
tokens = tokensConsumeOptional(tokens, "and")
}
return
}
func (wc *whereCondition) floatClause(lValue float64, rValue float64) bool {
switch wc.Operation {
case FloatEq:
return lValue == rValue
case FloatNe:
return lValue != rValue
case FloatLt:
return lValue < rValue
case FloatLe:
return lValue <= rValue
case FloatGt:
return lValue > rValue
case FloatGe:
return lValue >= rValue
default:
logger.Error("Unknown float operation", lValue, wc.Operation, rValue)
}
return false
}
func (wc *whereCondition) stringClause(lValue string, rValue string) bool {
switch wc.Operation {
case StringEq:
return lValue == rValue
case StringNe:
return lValue != rValue
case StringContains:
return strings.Contains(lValue, rValue)
default:
logger.Error("Unknown string operation", lValue, wc.Operation, rValue)
}
return false
}
|