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 const MaxQueryComponents = 100 | 17 const MaxQueryComponents = 100 |
18 | 18 |
19 var errQueryDone = errors.New("query is done") | 19 var errQueryDone = errors.New("query is done") |
20 | 20 |
21 type queryOp int | 21 type queryOp int |
22 | 22 |
23 const ( | 23 const ( |
24 qInvalid queryOp = iota | 24 qInvalid queryOp = iota |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 return &nq | 239 return &nq |
240 } | 240 } |
241 | 241 |
242 func (q *queryImpl) Ancestor(k ds.Key) ds.Query { | 242 func (q *queryImpl) Ancestor(k ds.Key) ds.Query { |
243 return q.checkMutateClone( | 243 return q.checkMutateClone( |
244 func() error { | 244 func() error { |
245 if k == nil { | 245 if k == nil { |
246 // SDK has an explicit nil-check | 246 // SDK has an explicit nil-check |
247 return errors.New("datastore: nil query ancestor
") | 247 return errors.New("datastore: nil query ancestor
") |
248 } | 248 } |
249 » » » if !ds.KeyValid(k, false, globalAppID, q.ns) { | 249 » » » if !k.Valid(false, globalAppID, q.ns) { |
250 // technically the SDK implementation does a Wei
rd Thing (tm) if both the | 250 // technically the SDK implementation does a Wei
rd Thing (tm) if both the |
251 // stringID and intID are set on a key; it only
serializes the stringID in | 251 // stringID and intID are set on a key; it only
serializes the stringID in |
252 // the proto. This means that if you set the Anc
estor to an invalid key, | 252 // the proto. This means that if you set the Anc
estor to an invalid key, |
253 // you'll never actually hear about it. Instead
of doing that insanity, we | 253 // you'll never actually hear about it. Instead
of doing that insanity, we |
254 // just swap to an error here. | 254 // just swap to an error here. |
255 return ds.ErrInvalidKey | 255 return ds.ErrInvalidKey |
256 } | 256 } |
257 if k.Namespace() != q.ns { | 257 if k.Namespace() != q.ns { |
258 return fmt.Errorf("bad namespace: %q (expected %
q)", k.Namespace(), q.ns) | 258 return fmt.Errorf("bad namespace: %q (expected %
q)", k.Namespace(), q.ns) |
259 } | 259 } |
(...skipping 30 matching lines...) Expand all Loading... |
290 "kindless queries can only filter on __k
ey__, got %q", fStr) | 290 "kindless queries can only filter on __k
ey__, got %q", fStr) |
291 } | 291 } |
292 | 292 |
293 p := ds.Property{} | 293 p := ds.Property{} |
294 err = p.SetValue(val, ds.NoIndex) | 294 err = p.SetValue(val, ds.NoIndex) |
295 if err != nil { | 295 if err != nil { |
296 return err | 296 return err |
297 } | 297 } |
298 | 298 |
299 if p.Type() == ds.PTKey { | 299 if p.Type() == ds.PTKey { |
300 » » » » if !ds.KeyValid(p.Value().(ds.Key), false, globa
lAppID, q.ns) { | 300 » » » » if !p.Value().(ds.Key).Valid(false, globalAppID,
q.ns) { |
301 return ds.ErrInvalidKey | 301 return ds.ErrInvalidKey |
302 } | 302 } |
303 } | 303 } |
304 | 304 |
305 » » » buf := &bytes.Buffer{} | 305 » » » binVal = string(serialize.ToBytes(p)) |
306 » » » p.Write(buf, ds.WithoutContext) | |
307 | 306 |
308 if prop == "__key__" { | 307 if prop == "__key__" { |
309 if op == qEqual { | 308 if op == qEqual { |
310 return fmt.Errorf( | 309 return fmt.Errorf( |
311 "query equality filter on __key_
_ is silly: %q", fStr) | 310 "query equality filter on __key_
_ is silly: %q", fStr) |
312 } | 311 } |
313 if p.Type() != ds.PTKey { | 312 if p.Type() != ds.PTKey { |
314 return fmt.Errorf("__key__ filter value
is not a key: %T", val) | 313 return fmt.Errorf("__key__ filter value
is not a key: %T", val) |
315 } | 314 } |
316 } | 315 } |
317 | 316 |
318 if op != qEqual { | 317 if op != qEqual { |
319 if q.ineqFilter.prop != "" && q.ineqFilter.prop
!= prop { | 318 if q.ineqFilter.prop != "" && q.ineqFilter.prop
!= prop { |
320 return fmt.Errorf( | 319 return fmt.Errorf( |
321 "inequality filters on multiple
properties: %q and %q", | 320 "inequality filters on multiple
properties: %q and %q", |
322 q.ineqFilter.prop, prop) | 321 q.ineqFilter.prop, prop) |
323 } | 322 } |
324 if len(q.order) > 0 && q.order[0].Property != pr
op { | 323 if len(q.order) > 0 && q.order[0].Property != pr
op { |
325 return fmt.Errorf( | 324 return fmt.Errorf( |
326 "first sort order must match ine
quality filter: %q v %q", | 325 "first sort order must match ine
quality filter: %q v %q", |
327 q.order[0].Property, prop) | 326 q.order[0].Property, prop) |
328 } | 327 } |
329 } else if _, ok := q.project[prop]; ok { | 328 } else if _, ok := q.project[prop]; ok { |
330 return fmt.Errorf( | 329 return fmt.Errorf( |
331 "cannot project on field which is used i
n an equality filter: %q", | 330 "cannot project on field which is used i
n an equality filter: %q", |
332 prop) | 331 prop) |
333 } | 332 } |
334 binVal = buf.String() | |
335 return | 333 return |
336 }, | 334 }, |
337 func(q *queryImpl) { | 335 func(q *queryImpl) { |
338 if op == qEqual { | 336 if op == qEqual { |
339 // add it to eq filters | 337 // add it to eq filters |
340 if _, ok := q.eqFilters[prop]; !ok { | 338 if _, ok := q.eqFilters[prop]; !ok { |
341 q.eqFilters[prop] = map[string]struct{}{
binVal: {}} | 339 q.eqFilters[prop] = map[string]struct{}{
binVal: {}} |
342 } else { | 340 } else { |
343 q.eqFilters[prop][binVal] = struct{}{} | 341 q.eqFilters[prop][binVal] = struct{}{} |
344 } | 342 } |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 q.end = curs | 513 q.end = curs |
516 }) | 514 }) |
517 } | 515 } |
518 | 516 |
519 func (q *queryImpl) EventualConsistency() ds.Query { | 517 func (q *queryImpl) EventualConsistency() ds.Query { |
520 return q.checkMutateClone( | 518 return q.checkMutateClone( |
521 nil, func(q *queryImpl) { | 519 nil, func(q *queryImpl) { |
522 q.eventualConsistency = true | 520 q.eventualConsistency = true |
523 }) | 521 }) |
524 } | 522 } |
OLD | NEW |