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" | |
9 "errors" | 8 "errors" |
10 "fmt" | 9 "fmt" |
11 "math" | 10 "math" |
12 "strings" | 11 "strings" |
13 | 12 |
14 ds "github.com/luci/gae/service/datastore" | 13 ds "github.com/luci/gae/service/datastore" |
| 14 "github.com/luci/gae/service/datastore/serialize" |
15 ) | 15 ) |
16 | 16 |
17 // MaxQueryComponents was lifted from a hard-coded constant in dev_appserver. | 17 // MaxQueryComponents was lifted from a hard-coded constant in dev_appserver. |
18 // No idea if it's a real limit or just a convenience in the current dev | 18 // No idea if it's a real limit or just a convenience in the current dev |
19 // appserver implementation. | 19 // appserver implementation. |
20 const MaxQueryComponents = 100 | 20 const MaxQueryComponents = 100 |
21 | 21 |
22 var errQueryDone = errors.New("query is done") | 22 var errQueryDone = errors.New("query is done") |
23 | 23 |
24 type queryOp int | 24 type queryOp int |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 return &nq | 243 return &nq |
244 } | 244 } |
245 | 245 |
246 func (q *queryImpl) Ancestor(k ds.Key) ds.Query { | 246 func (q *queryImpl) Ancestor(k ds.Key) ds.Query { |
247 return q.checkMutateClone( | 247 return q.checkMutateClone( |
248 func() error { | 248 func() error { |
249 if k == nil { | 249 if k == nil { |
250 // SDK has an explicit nil-check | 250 // SDK has an explicit nil-check |
251 return errors.New("datastore: nil query ancestor
") | 251 return errors.New("datastore: nil query ancestor
") |
252 } | 252 } |
253 » » » if !ds.KeyValid(k, false, globalAppID, q.ns) { | 253 » » » if !k.Valid(false, globalAppID, q.ns) { |
254 // technically the SDK implementation does a Wei
rd Thing (tm) if both the | 254 // technically the SDK implementation does a Wei
rd Thing (tm) if both the |
255 // stringID and intID are set on a key; it only
serializes the stringID in | 255 // stringID and intID are set on a key; it only
serializes the stringID in |
256 // the proto. This means that if you set the Anc
estor to an invalid key, | 256 // the proto. This means that if you set the Anc
estor to an invalid key, |
257 // you'll never actually hear about it. Instead
of doing that insanity, we | 257 // you'll never actually hear about it. Instead
of doing that insanity, we |
258 // just swap to an error here. | 258 // just swap to an error here. |
259 return ds.ErrInvalidKey | 259 return ds.ErrInvalidKey |
260 } | 260 } |
261 if k.Namespace() != q.ns { | 261 if k.Namespace() != q.ns { |
262 return fmt.Errorf("bad namespace: %q (expected %
q)", k.Namespace(), q.ns) | 262 return fmt.Errorf("bad namespace: %q (expected %
q)", k.Namespace(), q.ns) |
263 } | 263 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 "kindless queries can only filter on __k
ey__, got %q", fStr) | 295 "kindless queries can only filter on __k
ey__, got %q", fStr) |
296 } | 296 } |
297 | 297 |
298 p := ds.Property{} | 298 p := ds.Property{} |
299 err = p.SetValue(val, ds.NoIndex) | 299 err = p.SetValue(val, ds.NoIndex) |
300 if err != nil { | 300 if err != nil { |
301 return err | 301 return err |
302 } | 302 } |
303 | 303 |
304 if p.Type() == ds.PTKey { | 304 if p.Type() == ds.PTKey { |
305 » » » » if !ds.KeyValid(p.Value().(ds.Key), false, globa
lAppID, q.ns) { | 305 » » » » if !p.Value().(ds.Key).Valid(false, globalAppID,
q.ns) { |
306 return ds.ErrInvalidKey | 306 return ds.ErrInvalidKey |
307 } | 307 } |
308 } | 308 } |
309 | 309 |
310 if prop == "__key__" { | 310 if prop == "__key__" { |
311 if op == qEqual { | 311 if op == qEqual { |
312 return fmt.Errorf( | 312 return fmt.Errorf( |
313 "query equality filter on __key_
_ is silly: %q", fStr) | 313 "query equality filter on __key_
_ is silly: %q", fStr) |
314 } | 314 } |
315 if p.Type() != ds.PTKey { | 315 if p.Type() != ds.PTKey { |
(...skipping 10 matching lines...) Expand all Loading... |
326 if len(q.order) > 0 && q.order[0].Property != pr
op { | 326 if len(q.order) > 0 && q.order[0].Property != pr
op { |
327 return fmt.Errorf( | 327 return fmt.Errorf( |
328 "first sort order must match ine
quality filter: %q v %q", | 328 "first sort order must match ine
quality filter: %q v %q", |
329 q.order[0].Property, prop) | 329 q.order[0].Property, prop) |
330 } | 330 } |
331 } else if _, ok := q.project[prop]; ok { | 331 } else if _, ok := q.project[prop]; ok { |
332 return fmt.Errorf( | 332 return fmt.Errorf( |
333 "cannot project on field which is used i
n an equality filter: %q", | 333 "cannot project on field which is used i
n an equality filter: %q", |
334 prop) | 334 prop) |
335 } | 335 } |
336 | 336 » » » binVal = string(serialize.ToBytes(p)) |
337 » » » buf := &bytes.Buffer{} | 337 » » » return err |
338 » » » p.Write(buf, ds.WithoutContext) | |
339 » » » binVal = buf.String() | |
340 » » » return nil | |
341 }, | 338 }, |
342 func(q *queryImpl) { | 339 func(q *queryImpl) { |
343 if op == qEqual { | 340 if op == qEqual { |
344 // add it to eq filters | 341 // add it to eq filters |
345 if _, ok := q.eqFilters[prop]; !ok { | 342 if _, ok := q.eqFilters[prop]; !ok { |
346 q.eqFilters[prop] = map[string]struct{}{
binVal: {}} | 343 q.eqFilters[prop] = map[string]struct{}{
binVal: {}} |
347 } else { | 344 } else { |
348 q.eqFilters[prop][binVal] = struct{}{} | 345 q.eqFilters[prop][binVal] = struct{}{} |
349 } | 346 } |
350 | 347 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 q.end = curs | 517 q.end = curs |
521 }) | 518 }) |
522 } | 519 } |
523 | 520 |
524 func (q *queryImpl) EventualConsistency() ds.Query { | 521 func (q *queryImpl) EventualConsistency() ds.Query { |
525 return q.checkMutateClone( | 522 return q.checkMutateClone( |
526 nil, func(q *queryImpl) { | 523 nil, func(q *queryImpl) { |
527 q.eventualConsistency = true | 524 q.eventualConsistency = true |
528 }) | 525 }) |
529 } | 526 } |
OLD | NEW |