| 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 "encoding/base64" |
| 8 "errors" | 9 "errors" |
| 9 "fmt" | 10 "fmt" |
| 10 "math" | 11 "math" |
| 11 "strings" | 12 "strings" |
| 12 | 13 |
| 13 ds "github.com/luci/gae/service/datastore" | 14 ds "github.com/luci/gae/service/datastore" |
| 14 "github.com/luci/gae/service/datastore/serialize" | 15 "github.com/luci/gae/service/datastore/serialize" |
| 15 ) | 16 ) |
| 16 | 17 |
| 17 // MaxQueryComponents was lifted from a hard-coded constant in dev_appserver. | 18 // MaxQueryComponents was lifted from a hard-coded constant in dev_appserver. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 err = fmt.Errorf("datastore: invalid operator %q in filt
er %q", toks[1], f) | 57 err = fmt.Errorf("datastore: invalid operator %q in filt
er %q", toks[1], f) |
| 57 } else { | 58 } else { |
| 58 prop = toks[0] | 59 prop = toks[0] |
| 59 } | 60 } |
| 60 } | 61 } |
| 61 return | 62 return |
| 62 } | 63 } |
| 63 | 64 |
| 64 type queryCursor string | 65 type queryCursor string |
| 65 | 66 |
| 66 func (q queryCursor) String() string { return string(q) } | 67 func (q queryCursor) String() string { return base64.URLEncoding.EncodeToString(
[]byte(q)) } |
| 67 func (q queryCursor) Valid() bool { return q != "" } | 68 func (q queryCursor) Valid() bool { return q != "" } |
| 68 | 69 |
| 69 type queryIneqFilter struct { | 70 type queryIneqFilter struct { |
| 70 prop string | 71 prop string |
| 71 | 72 |
| 72 low *string | 73 low *string |
| 73 high *string | 74 high *string |
| 74 } | 75 } |
| 75 | 76 |
| 77 func decodeCursor(s string) (ds.Cursor, error) { |
| 78 d, err := base64.URLEncoding.DecodeString(s) |
| 79 if err != nil { |
| 80 return nil, fmt.Errorf("Failed to Base64-decode cursor: %s", err
) |
| 81 } |
| 82 c := queryCursor(string(d)) |
| 83 if !c.Valid() { |
| 84 return nil, errors.New("Decoded cursor is not valid.") |
| 85 } |
| 86 return c, nil |
| 87 } |
| 88 |
| 76 func increment(bstr string, positive bool) string { | 89 func increment(bstr string, positive bool) string { |
| 77 lastIdx := len(bstr) - 1 | 90 lastIdx := len(bstr) - 1 |
| 78 last := bstr[lastIdx] | 91 last := bstr[lastIdx] |
| 79 if positive { | 92 if positive { |
| 80 if last == 0xFF { | 93 if last == 0xFF { |
| 81 return bstr + "\x00" | 94 return bstr + "\x00" |
| 82 } | 95 } |
| 83 return bstr[:lastIdx-1] + string(last+1) | 96 return bstr[:lastIdx-1] + string(last+1) |
| 84 } else { | 97 } else { |
| 85 if last == 0 { | 98 if last == 0 { |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 q.end = curs | 530 q.end = curs |
| 518 }) | 531 }) |
| 519 } | 532 } |
| 520 | 533 |
| 521 func (q *queryImpl) EventualConsistency() ds.Query { | 534 func (q *queryImpl) EventualConsistency() ds.Query { |
| 522 return q.checkMutateClone( | 535 return q.checkMutateClone( |
| 523 nil, func(q *queryImpl) { | 536 nil, func(q *queryImpl) { |
| 524 q.eventualConsistency = true | 537 q.eventualConsistency = true |
| 525 }) | 538 }) |
| 526 } | 539 } |
| OLD | NEW |