| 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 // 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 |
| 19 // results. | 35 // results. |
| 20 // deduplication is applied externally | 36 // deduplication is applied externally |
| 21 // projection / keysonly / entity retrieval is done externally | 37 // projection / keysonly / entity retrieval is done externally |
| 22 type reducedQuery struct { | 38 type reducedQuery struct { |
| 23 ns string | 39 ns string |
| 24 kind string | 40 kind string |
| 25 | 41 |
| 26 // eqFilters indicate the set of all prefix constraints which need to be | 42 // eqFilters indicate the set of all prefix constraints which need to be |
| 27 // fulfilled in the composite query. All of these will translate into pr
efix | 43 // fulfilled in the composite query. All of these will translate into pr
efix |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 remains.SortBy = append(remains.SortBy, q.suffixFormat...) | 308 remains.SortBy = append(remains.SortBy, q.suffixFormat...) |
| 293 last := remains.SortBy[len(remains.SortBy)-1] | 309 last := remains.SortBy[len(remains.SortBy)-1] |
| 294 if !last.Descending { | 310 if !last.Descending { |
| 295 // this removes the __key__ column, since it's implicit. | 311 // this removes the __key__ column, since it's implicit. |
| 296 remains.SortBy = remains.SortBy[:len(remains.SortBy)-1] | 312 remains.SortBy = remains.SortBy[:len(remains.SortBy)-1] |
| 297 } | 313 } |
| 298 if remains.Builtin() { | 314 if remains.Builtin() { |
| 299 impossible( | 315 impossible( |
| 300 fmt.Errorf("recommended missing index would be a
builtin: %s", remains)) | 316 fmt.Errorf("recommended missing index would be a
builtin: %s", remains)) |
| 301 } | 317 } |
| 302 » » return nil, fmt.Errorf( | 318 » » return nil, &ErrMissingIndex{q.ns, remains} |
| 303 » » » "Your indexes are insufficient! Try adding:\n %s", rema
ins) | |
| 304 } | 319 } |
| 305 | 320 |
| 306 return idxs, nil | 321 return idxs, nil |
| 307 } | 322 } |
| 308 | 323 |
| 309 // generate generates a single iterDefinition for the given index. | 324 // generate generates a single iterDefinition for the given index. |
| 310 func generate(q *reducedQuery, idx *indexDefinitionSortable, c *constraints) *it
erDefinition { | 325 func generate(q *reducedQuery, idx *indexDefinitionSortable, c *constraints) *it
erDefinition { |
| 311 def := &iterDefinition{ | 326 def := &iterDefinition{ |
| 312 c: idx.coll, | 327 c: idx.coll, |
| 313 start: q.start, | 328 start: q.start, |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 if bestIdx == nil { | 546 if bestIdx == nil { |
| 532 // something is really wrong here... if relevantIdxs is
!nil, then we | 547 // something is really wrong here... if relevantIdxs is
!nil, then we |
| 533 // should always be able to make progress in this loop. | 548 // should always be able to make progress in this loop. |
| 534 impossible(fmt.Errorf("deadlock: cannot fulfil query?")) | 549 impossible(fmt.Errorf("deadlock: cannot fulfil query?")) |
| 535 } | 550 } |
| 536 ret = append(ret, generate(q, bestIdx, constraints)) | 551 ret = append(ret, generate(q, bestIdx, constraints)) |
| 537 } | 552 } |
| 538 | 553 |
| 539 return ret, nil | 554 return ret, nil |
| 540 } | 555 } |
| OLD | NEW |