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" |
11 "strings" | 11 "strings" |
12 | 12 |
13 ds "github.com/luci/gae/service/datastore" | 13 ds "github.com/luci/gae/service/datastore" |
14 "github.com/luci/gae/service/datastore/serialize" | 14 "github.com/luci/gae/service/datastore/serialize" |
15 "github.com/luci/luci-go/common/stringset" | 15 "github.com/luci/luci-go/common/stringset" |
16 ) | 16 ) |
17 | 17 |
| 18 // ErrMissingIndex is returned when the current indexes are not sufficient |
| 19 // for the current query. |
| 20 type ErrMissingIndex struct { |
| 21 ns string |
| 22 Missing *ds.IndexDefinition |
| 23 } |
| 24 |
| 25 func (e *ErrMissingIndex) Error() string { |
| 26 yaml, err := e.Missing.YAMLString() |
| 27 if err != nil { |
| 28 panic(err) |
| 29 } |
| 30 return fmt.Sprintf( |
| 31 "Insufficient indexes. Consider adding:\n%s", yaml) |
| 32 } |
| 33 |
18 var bjoin = serialize.Join | 34 var bjoin = serialize.Join |
19 | 35 |
20 // reducedQuery contains only the pieces of the query necessary to iterate for | 36 // reducedQuery contains only the pieces of the query necessary to iterate for |
21 // results. | 37 // results. |
22 // deduplication is applied externally | 38 // deduplication is applied externally |
23 // projection / keysonly / entity retrieval is done externally | 39 // projection / keysonly / entity retrieval is done externally |
24 type reducedQuery struct { | 40 type reducedQuery struct { |
25 ns string | 41 ns string |
26 kind string | 42 kind string |
27 | 43 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 remains.SortBy = append(remains.SortBy, q.suffixFormat...) | 310 remains.SortBy = append(remains.SortBy, q.suffixFormat...) |
295 last := remains.SortBy[len(remains.SortBy)-1] | 311 last := remains.SortBy[len(remains.SortBy)-1] |
296 if !last.Descending { | 312 if !last.Descending { |
297 // this removes the __key__ column, since it's implicit. | 313 // this removes the __key__ column, since it's implicit. |
298 remains.SortBy = remains.SortBy[:len(remains.SortBy)-1] | 314 remains.SortBy = remains.SortBy[:len(remains.SortBy)-1] |
299 } | 315 } |
300 if remains.Builtin() { | 316 if remains.Builtin() { |
301 impossible( | 317 impossible( |
302 fmt.Errorf("recommended missing index would be a
builtin: %s", remains)) | 318 fmt.Errorf("recommended missing index would be a
builtin: %s", remains)) |
303 } | 319 } |
304 » » return nil, fmt.Errorf( | 320 » » return nil, &ErrMissingIndex{q.ns, remains} |
305 » » » "Your indexes are insufficient! Try adding:\n %s", rema
ins) | |
306 } | 321 } |
307 | 322 |
308 return idxs, nil | 323 return idxs, nil |
309 } | 324 } |
310 | 325 |
311 // generate generates a single iterDefinition for the given index. | 326 // generate generates a single iterDefinition for the given index. |
312 func generate(q *reducedQuery, idx *indexDefinitionSortable, c *constraints) *it
erDefinition { | 327 func generate(q *reducedQuery, idx *indexDefinitionSortable, c *constraints) *it
erDefinition { |
313 def := &iterDefinition{ | 328 def := &iterDefinition{ |
314 c: idx.coll, | 329 c: idx.coll, |
315 start: q.start, | 330 start: q.start, |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 if bestIdx == nil { | 548 if bestIdx == nil { |
534 // something is really wrong here... if relevantIdxs is
!nil, then we | 549 // something is really wrong here... if relevantIdxs is
!nil, then we |
535 // should always be able to make progress in this loop. | 550 // should always be able to make progress in this loop. |
536 impossible(fmt.Errorf("deadlock: cannot fulfil query?")) | 551 impossible(fmt.Errorf("deadlock: cannot fulfil query?")) |
537 } | 552 } |
538 ret = append(ret, generate(q, bestIdx, constraints)) | 553 ret = append(ret, generate(q, bestIdx, constraints)) |
539 } | 554 } |
540 | 555 |
541 return ret, nil | 556 return ret, nil |
542 } | 557 } |
OLD | NEW |