| 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 "errors" | 9 "errors" |
| 10 "fmt" | 10 "fmt" |
| 11 "strings" | |
| 12 | 11 |
| 13 ds "github.com/luci/gae/service/datastore" | 12 ds "github.com/luci/gae/service/datastore" |
| 14 "github.com/luci/gae/service/datastore/serialize" | 13 "github.com/luci/gae/service/datastore/serialize" |
| 15 "github.com/luci/luci-go/common/cmpbin" | 14 "github.com/luci/luci-go/common/cmpbin" |
| 16 "github.com/luci/luci-go/common/stringset" | 15 "github.com/luci/luci-go/common/stringset" |
| 17 ) | 16 ) |
| 18 | 17 |
| 19 type queryStrategy interface { | 18 type queryStrategy interface { |
| 20 // handle applies the strategy to the embedded user callback. | 19 // handle applies the strategy to the embedded user callback. |
| 21 // - rawData is the slice of encoded Properties from the index row | 20 // - rawData is the slice of encoded Properties from the index row |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 | 181 |
| 183 func executeNamespaceQuery(fq *ds.FinalizedQuery, aid string, head *memStore, cb
ds.RawRunCB) error { | 182 func executeNamespaceQuery(fq *ds.FinalizedQuery, aid string, head *memStore, cb
ds.RawRunCB) error { |
| 184 // these objects have no properties, so any filters on properties cause
an | 183 // these objects have no properties, so any filters on properties cause
an |
| 185 // empty result. | 184 // empty result. |
| 186 if len(fq.EqFilters()) > 0 || len(fq.Project()) > 0 || len(fq.Orders())
> 1 { | 185 if len(fq.EqFilters()) > 0 || len(fq.Project()) > 0 || len(fq.Orders())
> 1 { |
| 187 return nil | 186 return nil |
| 188 } | 187 } |
| 189 if !(fq.IneqFilterProp() == "" || fq.IneqFilterProp() == "__key__") { | 188 if !(fq.IneqFilterProp() == "" || fq.IneqFilterProp() == "__key__") { |
| 190 return nil | 189 return nil |
| 191 } | 190 } |
| 192 colls := head.GetCollectionNames() | |
| 193 foundEnts := false | |
| 194 limit, hasLimit := fq.Limit() | 191 limit, hasLimit := fq.Limit() |
| 195 offset, hasOffset := fq.Offset() | 192 offset, hasOffset := fq.Offset() |
| 196 start, end := fq.Bounds() | 193 start, end := fq.Bounds() |
| 197 | 194 |
| 198 cursErr := errors.New("cursors not supported for __namespace__ query") | 195 cursErr := errors.New("cursors not supported for __namespace__ query") |
| 199 cursFn := func() (ds.Cursor, error) { return nil, cursErr } | 196 cursFn := func() (ds.Cursor, error) { return nil, cursErr } |
| 200 if !(start == nil && end == nil) { | 197 if !(start == nil && end == nil) { |
| 201 return cursErr | 198 return cursErr |
| 202 } | 199 } |
| 203 » for _, c := range colls { | 200 » for _, ns := range namespaces(head) { |
| 204 » » if !strings.HasPrefix(c, "ents:") { | |
| 205 » » » if foundEnts { | |
| 206 » » » » break | |
| 207 » » » } | |
| 208 » » » continue | |
| 209 » » } | |
| 210 » » foundEnts = true | |
| 211 if hasOffset && offset > 0 { | 201 if hasOffset && offset > 0 { |
| 212 offset-- | 202 offset-- |
| 213 continue | 203 continue |
| 214 } | 204 } |
| 215 if hasLimit { | 205 if hasLimit { |
| 216 if limit <= 0 { | 206 if limit <= 0 { |
| 217 return ds.Stop | 207 return ds.Stop |
| 218 } | 208 } |
| 219 limit-- | 209 limit-- |
| 220 } | 210 } |
| 221 k := (*ds.Key)(nil) | 211 k := (*ds.Key)(nil) |
| 222 ns := c[len("ents:"):] | |
| 223 if ns == "" { | 212 if ns == "" { |
| 224 // Datastore uses an id of 1 to indicate the default nam
espace in its | 213 // Datastore uses an id of 1 to indicate the default nam
espace in its |
| 225 // metadata API. | 214 // metadata API. |
| 226 k = ds.MakeKey(aid, "", "__namespace__", 1) | 215 k = ds.MakeKey(aid, "", "__namespace__", 1) |
| 227 } else { | 216 } else { |
| 228 k = ds.MakeKey(aid, "", "__namespace__", ns) | 217 k = ds.MakeKey(aid, "", "__namespace__", ns) |
| 229 } | 218 } |
| 230 if err := cb(k, nil, cursFn); err != nil { | 219 if err := cb(k, nil, cursFn); err != nil { |
| 231 return err | 220 return err |
| 232 } | 221 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 keyProp := decodedProps[len(decodedProps)-1] | 291 keyProp := decodedProps[len(decodedProps)-1] |
| 303 if keyProp.Type() != ds.PTKey { | 292 if keyProp.Type() != ds.PTKey { |
| 304 impossible(fmt.Errorf("decoded index row doesn't end wit
h a Key: %#v", keyProp)) | 293 impossible(fmt.Errorf("decoded index row doesn't end wit
h a Key: %#v", keyProp)) |
| 305 } | 294 } |
| 306 | 295 |
| 307 return strategy.handle( | 296 return strategy.handle( |
| 308 rawData, decodedProps, keyProp.Value().(*ds.Key), | 297 rawData, decodedProps, keyProp.Value().(*ds.Key), |
| 309 getCursorFn(suffix)) | 298 getCursorFn(suffix)) |
| 310 }) | 299 }) |
| 311 } | 300 } |
| OLD | NEW |