OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package memory | 5 package memory |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "sort" | 10 "sort" |
(...skipping 18 matching lines...) Expand all Loading... |
29 } | 29 } |
30 return fmt.Sprintf( | 30 return fmt.Sprintf( |
31 "Insufficient indexes. Consider adding:\n%s", yaml) | 31 "Insufficient indexes. Consider adding:\n%s", yaml) |
32 } | 32 } |
33 | 33 |
34 // reducedQuery contains only the pieces of the query necessary to iterate for | 34 // reducedQuery contains only the pieces of the query necessary to iterate for |
35 // results. | 35 // results. |
36 // deduplication is applied externally | 36 // deduplication is applied externally |
37 // projection / keysonly / entity retrieval is done externally | 37 // projection / keysonly / entity retrieval is done externally |
38 type reducedQuery struct { | 38 type reducedQuery struct { |
| 39 aid string |
39 ns string | 40 ns string |
40 kind string | 41 kind string |
41 | 42 |
42 // eqFilters indicate the set of all prefix constraints which need to be | 43 // eqFilters indicate the set of all prefix constraints which need to be |
43 // fulfilled in the composite query. All of these will translate into pr
efix | 44 // fulfilled in the composite query. All of these will translate into pr
efix |
44 // bytes for SOME index. | 45 // bytes for SOME index. |
45 eqFilters map[string]stringset.Set | 46 eqFilters map[string]stringset.Set |
46 | 47 |
47 // suffixFormat is the PRECISE listing of the suffix columns that ALL in
dexes | 48 // suffixFormat is the PRECISE listing of the suffix columns that ALL in
dexes |
48 // in the multi query will have. | 49 // in the multi query will have. |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 if q.suffixFormat[0].Descending { | 372 if q.suffixFormat[0].Descending { |
372 chopped = serialize.Invert(chopped) | 373 chopped = serialize.Invert(chopped) |
373 } | 374 } |
374 def.prefix = serialize.Join(def.prefix, chopped) | 375 def.prefix = serialize.Join(def.prefix, chopped) |
375 | 376 |
376 // Update start and end, since we know that if they contain anyt
hing, they | 377 // Update start and end, since we know that if they contain anyt
hing, they |
377 // contain values for the __key__ field. | 378 // contain values for the __key__ field. |
378 if def.start != nil { | 379 if def.start != nil { |
379 offset := 0 | 380 offset := 0 |
380 if len(q.suffixFormat) > 1 { | 381 if len(q.suffixFormat) > 1 { |
381 » » » » chunks, _ := parseSuffix(q.ns, q.suffixFormat, d
ef.start, 1) | 382 » » » » chunks, _ := parseSuffix(q.aid, q.ns, q.suffixFo
rmat, def.start, 1) |
382 offset = len(chunks[0]) | 383 offset = len(chunks[0]) |
383 } | 384 } |
384 if !bytes.HasPrefix(def.start[offset:], chopped) { | 385 if !bytes.HasPrefix(def.start[offset:], chopped) { |
385 // again, shouldn't happen, but if it does, we w
ant to know about it. | 386 // again, shouldn't happen, but if it does, we w
ant to know about it. |
386 impossible(fmt.Errorf( | 387 impossible(fmt.Errorf( |
387 "start suffix for implied ancestor doesn
't start with ancestor! start:%v ancestor:%v", | 388 "start suffix for implied ancestor doesn
't start with ancestor! start:%v ancestor:%v", |
388 def.start, chopped)) | 389 def.start, chopped)) |
389 } | 390 } |
390 def.start = def.start[:offset+len(chopped)] | 391 def.start = def.start[:offset+len(chopped)] |
391 } | 392 } |
392 if def.end != nil { | 393 if def.end != nil { |
393 offset := 0 | 394 offset := 0 |
394 if len(q.suffixFormat) > 1 { | 395 if len(q.suffixFormat) > 1 { |
395 » » » » chunks, _ := parseSuffix(q.ns, q.suffixFormat, d
ef.end, 1) | 396 » » » » chunks, _ := parseSuffix(q.aid, q.ns, q.suffixFo
rmat, def.end, 1) |
396 offset = len(chunks[0]) | 397 offset = len(chunks[0]) |
397 } | 398 } |
398 if !bytes.HasPrefix(def.end[offset:], chopped) { | 399 if !bytes.HasPrefix(def.end[offset:], chopped) { |
399 impossible(fmt.Errorf( | 400 impossible(fmt.Errorf( |
400 "end suffix for implied ancestor doesn't
start with ancestor! end:%v ancestor:%v", | 401 "end suffix for implied ancestor doesn't
start with ancestor! end:%v ancestor:%v", |
401 def.end, chopped)) | 402 def.end, chopped)) |
402 } | 403 } |
403 def.end = def.end[:offset+len(chopped)] | 404 def.end = def.end[:offset+len(chopped)] |
404 } | 405 } |
405 } | 406 } |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 if bestIdx == nil { | 547 if bestIdx == nil { |
547 // something is really wrong here... if relevantIdxs is
!nil, then we | 548 // something is really wrong here... if relevantIdxs is
!nil, then we |
548 // should always be able to make progress in this loop. | 549 // should always be able to make progress in this loop. |
549 impossible(fmt.Errorf("deadlock: cannot fulfil query?")) | 550 impossible(fmt.Errorf("deadlock: cannot fulfil query?")) |
550 } | 551 } |
551 ret = append(ret, generate(q, bestIdx, constraints)) | 552 ret = append(ret, generate(q, bestIdx, constraints)) |
552 } | 553 } |
553 | 554 |
554 return ret, nil | 555 return ret, nil |
555 } | 556 } |
OLD | NEW |