| Index: impl/memory/datastore_index_selection.go
|
| diff --git a/impl/memory/datastore_index_selection.go b/impl/memory/datastore_index_selection.go
|
| index f0aec8240b7248b7e48c62fd74a54121da034437..2e465692c087a2fdd56114b6272b4fa3707ec06d 100644
|
| --- a/impl/memory/datastore_index_selection.go
|
| +++ b/impl/memory/datastore_index_selection.go
|
| @@ -12,6 +12,7 @@ import (
|
|
|
| ds "github.com/luci/gae/service/datastore"
|
| "github.com/luci/gae/service/datastore/serialize"
|
| + "github.com/luci/luci-go/common/stringset"
|
| )
|
|
|
| // reducedQuery contains only the pieces of the query necessary to iterate for
|
| @@ -25,7 +26,7 @@ type reducedQuery struct {
|
| // eqFilters indicate the set of all prefix constraints which need to be
|
| // fulfilled in the composite query. All of these will translate into prefix
|
| // bytes for SOME index.
|
| - eqFilters map[string]stringSet
|
| + eqFilters map[string]stringset.Set
|
|
|
| // suffixFormat is the PRECISE listing of the suffix columns that ALL indexes
|
| // in the multi query will have.
|
| @@ -113,7 +114,7 @@ func (s IndexDefinitionSortableSlice) Less(i, j int) bool {
|
| // If the proposed index is PERFECT (e.g. contains enough columns to cover all
|
| // equality filters, and also has the correct suffix), idxs will be replaced
|
| // with JUST that index, and this will return true.
|
| -func (idxs *IndexDefinitionSortableSlice) maybeAddDefinition(q *reducedQuery, s *memStore, missingTerms stringSet, id *ds.IndexDefinition) bool {
|
| +func (idxs *IndexDefinitionSortableSlice) maybeAddDefinition(q *reducedQuery, s *memStore, missingTerms stringset.Set, id *ds.IndexDefinition) bool {
|
| // Kindless queries are handled elsewhere.
|
| if id.Kind != q.kind {
|
| impossible(
|
| @@ -185,14 +186,14 @@ func (idxs *IndexDefinitionSortableSlice) maybeAddDefinition(q *reducedQuery, s
|
| toAdd := IndexDefinitionSortable{coll: coll}
|
| toAdd.eqFilts = eqFilts
|
| for _, sb := range toAdd.eqFilts {
|
| - missingTerms.rm(sb.Property)
|
| + missingTerms.Del(sb.Property)
|
| }
|
|
|
| perfect := false
|
| if len(sortBy) == q.numCols {
|
| perfect = true
|
| for k, num := range numByProp {
|
| - if num < len(q.eqFilters[k]) {
|
| + if num < q.eqFilters[k].Len() {
|
| perfect = false
|
| break
|
| }
|
| @@ -203,14 +204,14 @@ func (idxs *IndexDefinitionSortableSlice) maybeAddDefinition(q *reducedQuery, s
|
| } else {
|
| *idxs = append(*idxs, toAdd)
|
| }
|
| - return len(missingTerms) == 0
|
| + return missingTerms.Len() == 0
|
| }
|
|
|
| // getRelevantIndexes retrieves the relevant indexes which could be used to
|
| // service q. It returns nil if it's not possible to service q with the current
|
| // indexes.
|
| func getRelevantIndexes(q *reducedQuery, s *memStore) (IndexDefinitionSortableSlice, error) {
|
| - missingTerms := stringSet{}
|
| + missingTerms := stringset.New(len(q.eqFilters))
|
| for k := range q.eqFilters {
|
| if k == "__ancestor__" {
|
| // ancestor is not a prefix which can be satisfied by a single index. It
|
| @@ -218,7 +219,7 @@ func getRelevantIndexes(q *reducedQuery, s *memStore) (IndexDefinitionSortableSl
|
| // the addDefinition logic)
|
| continue
|
| }
|
| - missingTerms.add(k)
|
| + missingTerms.Add(k)
|
| }
|
| idxs := IndexDefinitionSortableSlice{}
|
|
|
| @@ -234,14 +235,14 @@ func getRelevantIndexes(q *reducedQuery, s *memStore) (IndexDefinitionSortableSl
|
| // add
|
| // idx:KIND:prop
|
| // idx:KIND:-prop
|
| - props := stringSet{}
|
| + props := stringset.New(len(q.eqFilters) + len(q.suffixFormat))
|
| for prop := range q.eqFilters {
|
| - props.add(prop)
|
| + props.Add(prop)
|
| }
|
| for _, col := range q.suffixFormat[:len(q.suffixFormat)-1] {
|
| - props.add(col.Property)
|
| + props.Add(col.Property)
|
| }
|
| - for prop := range props {
|
| + for _, prop := range props.ToSlice() {
|
| if strings.HasPrefix(prop, "__") && strings.HasSuffix(prop, "__") {
|
| continue
|
| }
|
| @@ -276,15 +277,12 @@ func getRelevantIndexes(q *reducedQuery, s *memStore) (IndexDefinitionSortableSl
|
|
|
| // this query is impossible to fulfil with the current indexes. Not all the
|
| // terms (equality + projection) are satisfied.
|
| - if len(missingTerms) < 0 || len(idxs) == 0 {
|
| + if missingTerms.Len() < 0 || len(idxs) == 0 {
|
| remains := &ds.IndexDefinition{
|
| Kind: q.kind,
|
| Ancestor: q.eqFilters["__ancestor__"] != nil,
|
| }
|
| - terms := make([]string, 0, len(missingTerms))
|
| - for mt := range missingTerms {
|
| - terms = append(terms, mt)
|
| - }
|
| + terms := missingTerms.ToSlice()
|
| if serializationDeterministic {
|
| sort.Strings(terms)
|
| }
|
| @@ -344,7 +342,7 @@ func generate(q *reducedQuery, idx *IndexDefinitionSortable, c *constraints) *it
|
| }
|
|
|
| // get the only value out of __ancestor__
|
| - anc := q.eqFilters["__ancestor__"].getOne()
|
| + anc, _ := q.eqFilters["__ancestor__"].Peek()
|
|
|
| // Intentionally do NOT update prefixLen. This allows multiIterator to
|
| // correctly include the entire key in the shared iterator suffix, instead
|
| @@ -438,10 +436,11 @@ func calculateConstraints(q *reducedQuery) *constraints {
|
| residualMapping: make(map[string]int),
|
| }
|
| for prop, vals := range q.eqFilters {
|
| - bvals := make([][]byte, 0, len(vals))
|
| - for val := range vals {
|
| + bvals := make([][]byte, 0, vals.Len())
|
| + vals.Iter(func(val string) bool {
|
| bvals = append(bvals, []byte(val))
|
| - }
|
| + return true
|
| + })
|
| ret.original[prop] = bvals
|
| if prop == "__ancestor__" {
|
| // exclude __ancestor__ from the constraints.
|
|
|