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 datastore | 5 package datastore |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "encoding/base64" | 8 "encoding/base64" |
| 9 "errors" | 9 "errors" |
| 10 "fmt" | 10 "fmt" |
| 11 "math" | 11 "math" |
| 12 "reflect" | 12 "reflect" |
| 13 "time" | 13 "time" |
| 14 | 14 |
| 15 "github.com/luci/gae/service/blobstore" | 15 "github.com/luci/gae/service/blobstore" |
| 16 ) | 16 ) |
| 17 | 17 |
| 18 var ( | 18 var ( |
| 19 minTime = time.Unix(int64(math.MinInt64)/1e6, (int64(math.MinInt64)%1e6) *1e3) | 19 minTime = time.Unix(int64(math.MinInt64)/1e6, (int64(math.MinInt64)%1e6) *1e3) |
| 20 maxTime = time.Unix(int64(math.MaxInt64)/1e6, (int64(math.MaxInt64)%1e6) *1e3) | 20 maxTime = time.Unix(int64(math.MaxInt64)/1e6, (int64(math.MaxInt64)%1e6) *1e3) |
| 21 | 21 |
| 22 » utcTestTime = time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) | 22 » utcTestTime = time.Unix(0, 0) |
| 23 ) | 23 ) |
| 24 | 24 |
| 25 // IndexSetting indicates whether or not a Property should be indexed by the | 25 // IndexSetting indicates whether or not a Property should be indexed by the |
| 26 // datastore. | 26 // datastore. |
| 27 type IndexSetting bool | 27 type IndexSetting bool |
| 28 | 28 |
| 29 // ShouldIndex is the default, which is why it must assume the zero value, | 29 // ShouldIndex is the default, which is why it must assume the zero value, |
| 30 // even though it's werid :(. | 30 // even though it's werid :(. |
| 31 const ( | 31 const ( |
| 32 ShouldIndex IndexSetting = false | 32 ShouldIndex IndexSetting = false |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 // | 87 // |
| 88 // The biggest impact of this is that if you do a Projection query, you'll only | 88 // The biggest impact of this is that if you do a Projection query, you'll only |
| 89 // get back Properties with the above types (e.g. if you store a PTTime value, | 89 // get back Properties with the above types (e.g. if you store a PTTime value, |
| 90 // then Project on it, you'll get back a PTInt value). For convenience, Property | 90 // then Project on it, you'll get back a PTInt value). For convenience, Property |
| 91 // has a Project(PropertyType) method which will side-cast to your intended | 91 // has a Project(PropertyType) method which will side-cast to your intended |
| 92 // type. If you project into a structure with the high-level Interface | 92 // type. If you project into a structure with the high-level Interface |
| 93 // implementation, or use StructPLS, this conversion will be done for you | 93 // implementation, or use StructPLS, this conversion will be done for you |
| 94 // automatically, using the type of the destination field to cast. | 94 // automatically, using the type of the destination field to cast. |
| 95 type PropertyType byte | 95 type PropertyType byte |
| 96 | 96 |
| 97 //go:generate stringer -type=PropertyType | |
|
iannucci
2015/09/19 18:23:26
is stringer automatically included with go, or doe
Vadim Sh.
2015/09/19 20:03:59
Our env includes it:
$ which stringer
/Users/vadim
| |
| 98 | |
| 97 // These constants are in the order described by | 99 // These constants are in the order described by |
| 98 // https://cloud.google.com/appengine/docs/go/datastore/entities#Go_Value_type _ordering | 100 // https://cloud.google.com/appengine/docs/go/datastore/entities#Go_Value_type _ordering |
| 99 // with a slight divergence for the Int/Time split. | 101 // with a slight divergence for the Int/Time split. |
| 100 // | 102 // |
| 101 // NOTE: this enum can only occupy 7 bits, because we use the high bit to encode | 103 // NOTE: this enum can only occupy 7 bits, because we use the high bit to encode |
| 102 // indexed/non-indexed, and we additionally require that all valid values and | 104 // indexed/non-indexed, and we additionally require that all valid values and |
| 103 // all INVERTED valid values must never equal 0xFF or 0x00. The reason for this | 105 // all INVERTED valid values must never equal 0xFF or 0x00. The reason for this |
| 104 // constraint is that we must always be able to create a byte that sorts before | 106 // constraint is that we must always be able to create a byte that sorts before |
| 105 // and after it. | 107 // and after it. |
| 106 // | 108 // |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 func init() { | 164 func init() { |
| 163 if PTUnknown > 0x7e { | 165 if PTUnknown > 0x7e { |
| 164 panic( | 166 panic( |
| 165 "PTUnknown (and therefore PropertyType) exceeds 0x7e. Th is conflicts " + | 167 "PTUnknown (and therefore PropertyType) exceeds 0x7e. Th is conflicts " + |
| 166 "with serialize.WriteProperty's use of the high bit to indicate " + | 168 "with serialize.WriteProperty's use of the high bit to indicate " + |
| 167 "NoIndex and/or \"impl/memory\".increment's abil ity to guarantee " + | 169 "NoIndex and/or \"impl/memory\".increment's abil ity to guarantee " + |
| 168 "incrementability.") | 170 "incrementability.") |
| 169 } | 171 } |
| 170 } | 172 } |
| 171 | 173 |
| 172 func (t PropertyType) String() string { | |
| 173 switch t { | |
| 174 case PTNull: | |
| 175 return "PTNull" | |
| 176 case PTInt: | |
| 177 return "PTInt" | |
| 178 case PTTime: | |
| 179 return "PTTime" | |
| 180 case PTBool: | |
| 181 return "PTBool" | |
| 182 case PTBytes: | |
| 183 return "PTBytes" | |
| 184 case PTString: | |
| 185 return "PTString" | |
| 186 case PTFloat: | |
| 187 return "PTFloat" | |
| 188 case PTGeoPoint: | |
| 189 return "PTGeoPoint" | |
| 190 case PTKey: | |
| 191 return "PTKey" | |
| 192 case PTBlobKey: | |
| 193 return "PTBlobKey" | |
| 194 default: | |
| 195 return fmt.Sprintf("PTUnknown(%02x)", byte(t)) | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 // Property is a value plus an indicator of whether the value should be | 174 // Property is a value plus an indicator of whether the value should be |
| 200 // indexed. Name and Multiple are stored in the PropertyMap object. | 175 // indexed. Name and Multiple are stored in the PropertyMap object. |
| 201 type Property struct { | 176 type Property struct { |
| 202 value interface{} | 177 value interface{} |
| 203 indexSetting IndexSetting | 178 indexSetting IndexSetting |
| 204 propType PropertyType | 179 propType PropertyType |
| 205 } | 180 } |
| 206 | 181 |
| 207 // MkProperty makes a new indexed* Property and returns it. If val is an | 182 // MkProperty makes a new indexed* Property and returns it. If val is an |
| 208 // invalid value, this panics (so don't do it). If you want to handle the error | 183 // invalid value, this panics (so don't do it). If you want to handle the error |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 } | 287 } |
| 313 } | 288 } |
| 314 return o | 289 return o |
| 315 } | 290 } |
| 316 | 291 |
| 317 // Value returns the current value held by this property. It's guaranteed to | 292 // Value returns the current value held by this property. It's guaranteed to |
| 318 // be a valid value type (i.e. `p.SetValue(p.Value(), true)` will never return | 293 // be a valid value type (i.e. `p.SetValue(p.Value(), true)` will never return |
| 319 // an error). | 294 // an error). |
| 320 func (p *Property) Value() interface{} { return p.value } | 295 func (p *Property) Value() interface{} { return p.value } |
| 321 | 296 |
| 322 // IndexSetting says weather or not the datastore should create indicies for | 297 // IndexSetting says whether or not the datastore should create indicies for |
| 323 // this value. | 298 // this value. |
| 324 func (p *Property) IndexSetting() IndexSetting { return p.indexSetting } | 299 func (p *Property) IndexSetting() IndexSetting { return p.indexSetting } |
| 325 | 300 |
| 326 // Type is the PT* type of the data contained in Value(). | 301 // Type is the PT* type of the data contained in Value(). |
| 327 func (p *Property) Type() PropertyType { return p.propType } | 302 func (p *Property) Type() PropertyType { return p.propType } |
| 328 | 303 |
| 329 // SetValue sets the Value field of a Property, and ensures that its value | 304 // SetValue sets the Value field of a Property, and ensures that its value |
| 330 // conforms to the permissible types. That way, you're guaranteed that if you | 305 // conforms to the permissible types. That way, you're guaranteed that if you |
| 331 // have a Property, its value is valid. | 306 // have a Property, its value is valid. |
| 332 // | 307 // |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 781 dflt = UpconvertUnderlyingType(dflt) | 756 dflt = UpconvertUnderlyingType(dflt) |
| 782 cur, err := gm(key) | 757 cur, err := gm(key) |
| 783 if err != nil { | 758 if err != nil { |
| 784 return dflt | 759 return dflt |
| 785 } | 760 } |
| 786 if dflt != nil && reflect.TypeOf(cur) != reflect.TypeOf(dflt) { | 761 if dflt != nil && reflect.TypeOf(cur) != reflect.TypeOf(dflt) { |
| 787 return dflt | 762 return dflt |
| 788 } | 763 } |
| 789 return cur | 764 return cur |
| 790 } | 765 } |
| OLD | NEW |