1
2
3
4
5
6
7
8
9
10
11
12
13
14 package mango
15
16 import (
17 "fmt"
18 "regexp"
19 "strings"
20
21 "github.com/go-kivik/kivik/v4/x/collate"
22 )
23
24
25 type Node interface {
26 Op() Operator
27 Value() interface{}
28 String() string
29 Match(interface{}) bool
30 }
31
32 type notNode struct {
33 sel Node
34 }
35
36 var _ Node = (*notNode)(nil)
37
38 func (*notNode) Op() Operator {
39 return OpNot
40 }
41
42 func (n *notNode) Value() interface{} {
43 return n.sel
44 }
45
46 func (n *notNode) String() string {
47 return fmt.Sprintf("%s %s", OpNot, n.sel)
48 }
49
50 func (n *notNode) Match(doc interface{}) bool {
51 return !n.sel.Match(doc)
52 }
53
54 type combinationNode struct {
55 op Operator
56 sel []Node
57 }
58
59 var _ Node = (*combinationNode)(nil)
60
61 func (c *combinationNode) Op() Operator {
62 return c.op
63 }
64
65 func (c *combinationNode) Value() interface{} {
66 return c.sel
67 }
68
69 func (c *combinationNode) String() string {
70 var sb strings.Builder
71 sb.WriteString(string(c.op))
72 sb.WriteString(" [")
73 for i, sel := range c.sel {
74 if i > 0 {
75 sb.WriteString(", ")
76 }
77 sb.WriteString(fmt.Sprintf("%v", sel))
78 }
79 sb.WriteString("]")
80 return sb.String()
81 }
82
83 func (c *combinationNode) Match(doc interface{}) bool {
84 switch c.op {
85 case OpAnd:
86 for _, sel := range c.sel {
87 if !sel.Match(doc) {
88 return false
89 }
90 }
91 return true
92 case OpOr:
93 for _, sel := range c.sel {
94 if sel.Match(doc) {
95 return true
96 }
97 }
98 return false
99 case OpNor:
100 for _, sel := range c.sel {
101 if sel.Match(doc) {
102 return false
103 }
104 }
105 return true
106 }
107 panic("not implemented")
108 }
109
110 type fieldNode struct {
111 field string
112 cond Node
113 }
114
115 var _ Node = (*fieldNode)(nil)
116
117 func (f *fieldNode) Op() Operator {
118 return f.cond.Op()
119 }
120
121 func (f *fieldNode) Value() interface{} {
122 return f.cond.Value()
123 }
124
125 func (f *fieldNode) String() string {
126 return fmt.Sprintf("%s %s", f.field, f.cond.String())
127 }
128
129 func (f *fieldNode) Match(doc interface{}) bool {
130 val := doc
131
132
133 segments := SplitKeys(f.field)
134 for _, segment := range segments {
135 m, ok := val.(map[string]interface{})
136 if !ok {
137 return false
138 }
139
140 val = m[segment]
141 }
142
143
144 return f.cond.Match(val)
145 }
146
147 type conditionNode struct {
148 op Operator
149 cond interface{}
150 }
151
152 var _ Node = (*conditionNode)(nil)
153
154 func (e *conditionNode) Op() Operator {
155 return e.op
156 }
157
158 func (e *conditionNode) Value() interface{} {
159 return e.cond
160 }
161
162 func (e *conditionNode) String() string {
163 return fmt.Sprintf("%s %v", e.op, e.cond)
164 }
165
166 func (e *conditionNode) Match(doc interface{}) bool {
167 switch e.op {
168 case OpEqual:
169 return collate.CompareObject(doc, e.cond) == 0
170 case OpNotEqual:
171 return collate.CompareObject(doc, e.cond) != 0
172 case OpLessThan:
173 return collate.CompareObject(doc, e.cond) < 0
174 case OpLessThanOrEqual:
175 return collate.CompareObject(doc, e.cond) <= 0
176 case OpGreaterThan:
177 return collate.CompareObject(doc, e.cond) > 0
178 case OpGreaterThanOrEqual:
179 return collate.CompareObject(doc, e.cond) >= 0
180 case OpExists:
181 return (doc != nil) == e.cond.(bool)
182 case OpType:
183 switch tp := e.cond.(string); tp {
184 case "null":
185 return doc == nil
186 case "boolean":
187 _, ok := doc.(bool)
188 return ok
189 case "number":
190 _, ok := doc.(float64)
191 return ok
192 case "string":
193 _, ok := doc.(string)
194 return ok
195 case "array":
196 _, ok := doc.([]interface{})
197 return ok
198 case "object":
199 _, ok := doc.(map[string]interface{})
200 return ok
201 default:
202 panic("unexpected $type value: " + tp)
203 }
204 case OpIn:
205 for _, v := range e.cond.([]interface{}) {
206 if collate.CompareObject(doc, v) == 0 {
207 return true
208 }
209 }
210 return false
211 case OpNotIn:
212 for _, v := range e.cond.([]interface{}) {
213 if collate.CompareObject(doc, v) == 0 {
214 return false
215 }
216 }
217 return true
218 case OpSize:
219 array, ok := doc.([]interface{})
220 if !ok {
221 return false
222 }
223 return float64(len(array)) == e.cond.(float64)
224 case OpMod:
225 num, ok := doc.(float64)
226 if !ok {
227 return false
228 }
229 if num != float64(int(num)) {
230 return false
231 }
232 mod := e.cond.([2]int64)
233 return int64(num)%mod[0] == mod[1]
234 case OpRegex:
235 str, ok := doc.(string)
236 if !ok {
237 return false
238 }
239 return e.cond.(*regexp.Regexp).MatchString(str)
240 case OpAll:
241 array, ok := doc.([]interface{})
242 if !ok {
243 return false
244 }
245 for _, v := range e.cond.([]interface{}) {
246 if !contains(array, v) {
247 return false
248 }
249 }
250 return true
251 }
252 return false
253 }
254
255 func contains(haystack []interface{}, needle interface{}) bool {
256 for _, v := range haystack {
257 if collate.CompareObject(v, needle) == 0 {
258 return true
259 }
260 }
261 return false
262 }
263
264 type elementNode struct {
265 op Operator
266 cond *conditionNode
267 }
268
269 var _ Node = (*elementNode)(nil)
270
271 func (e *elementNode) Op() Operator {
272 return e.op
273 }
274
275 func (e *elementNode) Value() interface{} {
276 return e.cond
277 }
278
279 func (e *elementNode) String() string {
280 return fmt.Sprintf("%s {%s}", e.op, e.cond)
281 }
282
283 func (e *elementNode) Match(doc interface{}) bool {
284 switch e.op {
285 case OpElemMatch:
286 array, ok := doc.([]interface{})
287 if !ok {
288 return false
289 }
290 for _, v := range array {
291 if e.cond.Match(v) {
292 return true
293 }
294 }
295 return false
296 case OpAllMatch:
297 array, ok := doc.([]interface{})
298 if !ok {
299 return false
300 }
301 for _, v := range array {
302 if !e.cond.Match(v) {
303 return false
304 }
305 }
306 return true
307 case OpKeyMapMatch:
308 object, ok := doc.(map[string]interface{})
309 if !ok {
310 return false
311 }
312 for k := range object {
313 if k == e.cond.cond.(string) {
314 return e.cond.Match(k)
315 }
316 }
317 return false
318 }
319 panic("unready")
320 }
321
322
323 func cmpValues(a, b interface{}) int {
324 return strings.Compare(fmt.Sprintf("%v", a), fmt.Sprintf("%v", b))
325 }
326
327
328 func cmpSelectors(a, b Node) int {
329
330 if c := strings.Compare(string(a.Op()), string(b.Op())); c != 0 {
331 return c
332 }
333 switch t := a.(type) {
334 case *notNode:
335 u := b.(*notNode)
336 return cmpSelectors(t.sel, u.sel)
337 case *combinationNode:
338 u := b.(*combinationNode)
339 for i := 0; i < len(t.sel) && i < len(u.sel); i++ {
340 if c := cmpSelectors(t.sel[i], u.sel[i]); c != 0 {
341 return c
342 }
343 }
344 return len(t.sel) - len(u.sel)
345 case *fieldNode:
346 u := b.(*fieldNode)
347 if c := strings.Compare(t.field, u.field); c != 0 {
348 return c
349 }
350 return cmpSelectors(t.cond, u.cond)
351 case *conditionNode:
352 u := b.(*conditionNode)
353 switch t.op {
354 case OpIn, OpNotIn:
355 for i := 0; i < len(t.cond.([]interface{})) && i < len(u.cond.([]interface{})); i++ {
356 if c := cmpValues(t.cond.([]interface{})[i], u.cond.([]interface{})[i]); c != 0 {
357 return c
358 }
359 }
360 return len(t.cond.([]interface{})) - len(u.cond.([]interface{}))
361 case OpMod:
362 tm := t.cond.([2]int)
363 um := u.cond.([2]int)
364 if tm[0] != um[0] {
365 return tm[0] - um[0]
366 }
367 return tm[1] - um[1]
368 default:
369 return cmpValues(t.cond, u.cond)
370 }
371 }
372 return 0
373 }
374
375
376
377
378 func SplitKeys(field string) []string {
379 var escaped bool
380 result := []string{}
381 word := make([]byte, 0, len(field))
382 for _, ch := range field {
383 if escaped {
384 word = append(word, byte(ch))
385 escaped = false
386 continue
387 }
388 if ch == '\\' {
389 escaped = true
390 continue
391 }
392 if ch == '.' {
393 result = append(result, string(word))
394 word = word[:0]
395 continue
396 }
397 word = append(word, byte(ch))
398 }
399 if escaped {
400 word = append(word, '\\')
401 }
402 return append(result, string(word))
403 }
404
View as plain text