Chromium Code Reviews| 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 "encoding/base64" | 9 "encoding/base64" |
| 10 "errors" | 10 "errors" |
| 11 "fmt" | 11 "fmt" |
| 12 "time" | |
| 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 "github.com/luci/luci-go/common/cmpbin" | 16 "github.com/luci/luci-go/common/cmpbin" |
| 16 "github.com/luci/luci-go/common/stringset" | 17 "github.com/luci/luci-go/common/stringset" |
| 17 ) | 18 ) |
| 18 | 19 |
| 19 // MaxQueryComponents was lifted from a hard-coded constant in dev_appserver. | 20 // MaxQueryComponents was lifted from a hard-coded constant in dev_appserver. |
| 20 // No idea if it's a real limit or just a convenience in the current dev | 21 // No idea if it's a real limit or just a convenience in the current dev |
| 21 // appserver implementation. | 22 // appserver implementation. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 } | 96 } |
| 96 if p, _, _ := fq.IneqFilterHigh(); p != "" { | 97 if p, _, _ := fq.IneqFilterHigh(); p != "" { |
| 97 numComponents++ | 98 numComponents++ |
| 98 } | 99 } |
| 99 for _, v := range fq.EqFilters() { | 100 for _, v := range fq.EqFilters() { |
| 100 numComponents += v.Len() | 101 numComponents += v.Len() |
| 101 } | 102 } |
| 102 return numComponents | 103 return numComponents |
| 103 } | 104 } |
| 104 | 105 |
| 106 // convertQueryProperty converts a ds.Property into a suitable property for | |
| 107 // query serialization. | |
| 108 // | |
| 109 // PTTime fields are serialized into indexes as PTInt, so we need to represent | |
| 110 // them as PTInt in the serialized query. | |
|
iannucci
2015/12/29 19:53:46
could you add another case for all the various byt
dnj
2015/12/29 21:40:47
Sure. AFAICT this only additionally affected blobs
| |
| 111 func convertQueryProperty(p ds.Property) ds.Property { | |
| 112 switch p.Type() { | |
| 113 case ds.PTTime: | |
| 114 return ds.MkProperty(serialize.TimeToInt(p.Value().(time.Time))) | |
| 115 default: | |
| 116 return p | |
| 117 } | |
| 118 } | |
| 119 | |
| 105 // GetBinaryBounds gets the binary encoding of the upper and lower bounds of | 120 // GetBinaryBounds gets the binary encoding of the upper and lower bounds of |
|
iannucci
2015/12/29 19:53:46
this bug probably also affects equality comparison
dnj
2015/12/29 21:40:47
yarp, nice catch. Added test case and fix.
| |
| 106 // the inequality filter on fq, if any is defined. If a bound does not exist, | 121 // the inequality filter on fq, if any is defined. If a bound does not exist, |
| 107 // it is nil. | 122 // it is nil. |
| 108 // | 123 // |
| 109 // NOTE: if fq specifies a descending sort order for the inequality, the bounds | 124 // NOTE: if fq specifies a descending sort order for the inequality, the bounds |
| 110 // will be inverted, incremented, and fliped. | 125 // will be inverted, incremented, and flipped. |
| 111 func GetBinaryBounds(fq *ds.FinalizedQuery) (lower, upper []byte) { | 126 func GetBinaryBounds(fq *ds.FinalizedQuery) (lower, upper []byte) { |
| 112 // Pick up the start/end range from the inequalities, if any. | 127 // Pick up the start/end range from the inequalities, if any. |
| 113 // | 128 // |
| 114 // start and end in the reducedQuery are normalized so that `start >= | 129 // start and end in the reducedQuery are normalized so that `start >= |
| 115 // X < end`. Because of that, we need to tweak the inequality filters | 130 // X < end`. Because of that, we need to tweak the inequality filters |
| 116 // contained in the query if they use the > or <= operators. | 131 // contained in the query if they use the > or <= operators. |
| 117 if ineqProp := fq.IneqFilterProp(); ineqProp != "" { | 132 if ineqProp := fq.IneqFilterProp(); ineqProp != "" { |
| 118 _, startOp, startV := fq.IneqFilterLow() | 133 _, startOp, startV := fq.IneqFilterLow() |
| 119 if startOp != "" { | 134 if startOp != "" { |
| 120 » » » lower = serialize.ToBytes(startV) | 135 » » » lower = serialize.ToBytes(convertQueryProperty(startV)) |
| 121 if startOp == ">" { | 136 if startOp == ">" { |
| 122 lower = increment(lower) | 137 lower = increment(lower) |
| 123 } | 138 } |
| 124 } | 139 } |
| 125 | 140 |
| 126 _, endOp, endV := fq.IneqFilterHigh() | 141 _, endOp, endV := fq.IneqFilterHigh() |
| 127 if endOp != "" { | 142 if endOp != "" { |
| 128 » » » upper = serialize.ToBytes(endV) | 143 » » » upper = serialize.ToBytes(convertQueryProperty(endV)) |
| 129 if endOp == "<=" { | 144 if endOp == "<=" { |
| 130 upper = increment(upper) | 145 upper = increment(upper) |
| 131 } | 146 } |
| 132 } | 147 } |
| 133 | 148 |
| 134 // The inequality is specified in natural (ascending) order in t he query's | 149 // The inequality is specified in natural (ascending) order in t he query's |
| 135 // Filter syntax, but the order information may indicate to use a descending | 150 // Filter syntax, but the order information may indicate to use a descending |
| 136 // index column for it. If that's the case, then we must invert, swap and | 151 // index column for it. If that's the case, then we must invert, swap and |
| 137 // increment the inequality endpoints. | 152 // increment the inequality endpoints. |
| 138 // | 153 // |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 // and the new value has overflowed this representation. | 285 // and the new value has overflowed this representation. |
| 271 // | 286 // |
| 272 // Fortunately, the first byte of a serialized index column entr y is a | 287 // Fortunately, the first byte of a serialized index column entr y is a |
| 273 // PropertyType byte, and the only valid values that we'll be in crementing | 288 // PropertyType byte, and the only valid values that we'll be in crementing |
| 274 // are never equal to 0xFF, since they have the high bit set (so either they're | 289 // are never equal to 0xFF, since they have the high bit set (so either they're |
| 275 // 0x8*, or 0x7*, depending on if it's inverted). | 290 // 0x8*, or 0x7*, depending on if it's inverted). |
| 276 impossible(fmt.Errorf("incrementing %v would require more sigfig s", bstr)) | 291 impossible(fmt.Errorf("incrementing %v would require more sigfig s", bstr)) |
| 277 } | 292 } |
| 278 return ret | 293 return ret |
| 279 } | 294 } |
| OLD | NEW |