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 |