Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: service/rawdatastore/datastore_impl.go

Issue 1243323002: Refactor a bit. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix golint Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « service/rawdatastore/datastore.go ('k') | service/rawdatastore/datastore_key.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // HEAVILY adapted from github.com/golang/appengine/datastore 5 // HEAVILY adapted from github.com/golang/appengine/datastore
6 6
7 package helper 7 package rawdatastore
8 8
9 import ( 9 import (
10 "errors" 10 "errors"
11 "fmt" 11 "fmt"
12 "reflect" 12 "reflect"
13 "strconv" 13 "strconv"
14 "strings" 14 "strings"
15 "sync" 15 "sync"
16 "time" 16 "time"
17 "unicode" 17 "unicode"
18 18
19 "github.com/luci/gae" 19 "github.com/luci/gae"
20 "github.com/luci/gae/service/blobstore"
20 ) 21 )
21 22
22 // Entities with more than this many indexed properties will not be saved. 23 // Entities with more than this many indexed properties will not be saved.
23 const maxIndexedProperties = 20000 24 const maxIndexedProperties = 20000
24 25
25 var (
26 typeOfDSKey = reflect.TypeOf((*gae.DSKey)(nil)).Elem()
27 typeOfDSPropertyConverter = reflect.TypeOf((*gae.DSPropertyConverter)(ni l)).Elem()
28 typeOfGeoPoint = reflect.TypeOf(gae.DSGeoPoint{})
29 typeOfTime = reflect.TypeOf(time.Time{})
30 typeOfString = reflect.TypeOf("")
31 typeOfInt64 = reflect.TypeOf(int64(0))
32 typeOfBool = reflect.TypeOf(true)
33
34 valueOfnilDSKey = reflect.Zero(typeOfDSKey)
35 )
36
37 type structTag struct { 26 type structTag struct {
38 name string 27 name string
39 » idxSetting gae.IndexSetting 28 » idxSetting IndexSetting
40 isSlice bool 29 isSlice bool
41 substructCodec *structCodec 30 substructCodec *structCodec
42 convert bool 31 convert bool
43 metaVal interface{} 32 metaVal interface{}
44 canSet bool 33 canSet bool
45 } 34 }
46 35
47 type structCodec struct { 36 type structCodec struct {
48 byMeta map[string]int 37 byMeta map[string]int
49 byName map[string]int 38 byName map[string]int
50 byIndex []structTag 39 byIndex []structTag
51 hasSlice bool 40 hasSlice bool
52 problem error 41 problem error
53 } 42 }
54 43
55 type structPLS struct { 44 type structPLS struct {
56 o reflect.Value 45 o reflect.Value
57 c *structCodec 46 c *structCodec
58 } 47 }
59 48
60 var _ gae.DSPropertyLoadSaver = (*structPLS)(nil) 49 var _ PropertyLoadSaver = (*structPLS)(nil)
61 50
62 // typeMismatchReason returns a string explaining why the property p could not 51 // typeMismatchReason returns a string explaining why the property p could not
63 // be stored in an entity field of type v.Type(). 52 // be stored in an entity field of type v.Type().
64 func typeMismatchReason(val interface{}, v reflect.Value) string { 53 func typeMismatchReason(val interface{}, v reflect.Value) string {
65 entityType := reflect.TypeOf(val) 54 entityType := reflect.TypeOf(val)
66 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) 55 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type())
67 } 56 }
68 57
69 func (p *structPLS) Load(propMap gae.DSPropertyMap) error { 58 func (p *structPLS) Load(propMap PropertyMap) error {
70 if err := p.Problem(); err != nil { 59 if err := p.Problem(); err != nil {
71 return err 60 return err
72 } 61 }
73 62
74 convFailures := gae.MultiError(nil) 63 convFailures := gae.MultiError(nil)
75 64
76 t := reflect.Type(nil) 65 t := reflect.Type(nil)
77 for name, props := range propMap { 66 for name, props := range propMap {
78 multiple := len(props) > 1 67 multiple := len(props) > 1
79 for i, prop := range props { 68 for i, prop := range props {
80 if reason := loadInner(p.c, p.o, i, name, prop, multiple ); reason != "" { 69 if reason := loadInner(p.c, p.o, i, name, prop, multiple ); reason != "" {
81 if t == nil { 70 if t == nil {
82 t = p.o.Type() 71 t = p.o.Type()
83 } 72 }
84 » » » » convFailures = append(convFailures, &gae.ErrDSFi eldMismatch{ 73 » » » » convFailures = append(convFailures, &ErrFieldMis match{
85 StructType: t, 74 StructType: t,
86 FieldName: name, 75 FieldName: name,
87 Reason: reason, 76 Reason: reason,
88 }) 77 })
89 } 78 }
90 } 79 }
91 } 80 }
92 81
93 if len(convFailures) > 0 { 82 if len(convFailures) > 0 {
94 return convFailures 83 return convFailures
95 } 84 }
96 85
97 return nil 86 return nil
98 } 87 }
99 88
100 func loadInner(codec *structCodec, structValue reflect.Value, index int, name st ring, p gae.DSProperty, requireSlice bool) string { 89 func loadInner(codec *structCodec, structValue reflect.Value, index int, name st ring, p Property, requireSlice bool) string {
101 var v reflect.Value 90 var v reflect.Value
102 // Traverse a struct's struct-typed fields. 91 // Traverse a struct's struct-typed fields.
103 for { 92 for {
104 fieldIndex, ok := codec.byName[name] 93 fieldIndex, ok := codec.byName[name]
105 if !ok { 94 if !ok {
106 return "no such struct field" 95 return "no such struct field"
107 } 96 }
108 v = structValue.Field(fieldIndex) 97 v = structValue.Field(fieldIndex)
109 98
110 st := codec.byIndex[fieldIndex] 99 st := codec.byIndex[fieldIndex]
(...skipping 10 matching lines...) Expand all
121 } else { 110 } else {
122 structValue = v 111 structValue = v
123 } 112 }
124 // Strip the "I." from "I.X". 113 // Strip the "I." from "I.X".
125 name = name[len(st.name):] 114 name = name[len(st.name):]
126 codec = st.substructCodec 115 codec = st.substructCodec
127 } 116 }
128 117
129 doConversion := func(v reflect.Value) (string, bool) { 118 doConversion := func(v reflect.Value) (string, bool) {
130 a := v.Addr() 119 a := v.Addr()
131 » » if conv, ok := a.Interface().(gae.DSPropertyConverter); ok { 120 » » if conv, ok := a.Interface().(PropertyConverter); ok {
132 » » » err := conv.FromDSProperty(p) 121 » » » err := conv.FromProperty(p)
133 if err != nil { 122 if err != nil {
134 return err.Error(), true 123 return err.Error(), true
135 } 124 }
136 return "", true 125 return "", true
137 } 126 }
138 return "", false 127 return "", false
139 } 128 }
140 129
141 if ret, ok := doConversion(v); ok { 130 if ret, ok := doConversion(v); ok {
142 return ret 131 return ret
143 } 132 }
144 133
145 var slice reflect.Value 134 var slice reflect.Value
146 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { 135 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
147 slice = v 136 slice = v
148 v = reflect.New(v.Type().Elem()).Elem() 137 v = reflect.New(v.Type().Elem()).Elem()
149 } else if requireSlice { 138 } else if requireSlice {
150 return "multiple-valued property requires a slice field type" 139 return "multiple-valued property requires a slice field type"
151 } 140 }
152 141
153 pVal := p.Value() 142 pVal := p.Value()
154 143
155 if ret, ok := doConversion(v); ok { 144 if ret, ok := doConversion(v); ok {
156 if ret != "" { 145 if ret != "" {
157 return ret 146 return ret
158 } 147 }
159 } else { 148 } else {
160 knd := v.Kind() 149 knd := v.Kind()
161 » » if v.Type().Implements(typeOfDSKey) { 150 » » if v.Type().Implements(typeOfKey) {
162 knd = reflect.Interface 151 knd = reflect.Interface
163 } 152 }
164 switch knd { 153 switch knd {
165 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, re flect.Int64: 154 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, re flect.Int64:
166 x, ok := pVal.(int64) 155 x, ok := pVal.(int64)
167 if !ok && pVal != nil { 156 if !ok && pVal != nil {
168 return typeMismatchReason(pVal, v) 157 return typeMismatchReason(pVal, v)
169 } 158 }
170 if v.OverflowInt(x) { 159 if v.OverflowInt(x) {
171 return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type()) 160 return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type())
172 } 161 }
173 v.SetInt(x) 162 v.SetInt(x)
174 case reflect.Bool: 163 case reflect.Bool:
175 x, ok := pVal.(bool) 164 x, ok := pVal.(bool)
176 if !ok && pVal != nil { 165 if !ok && pVal != nil {
177 return typeMismatchReason(pVal, v) 166 return typeMismatchReason(pVal, v)
178 } 167 }
179 v.SetBool(x) 168 v.SetBool(x)
180 case reflect.String: 169 case reflect.String:
181 switch x := pVal.(type) { 170 switch x := pVal.(type) {
182 » » » case gae.BSKey: 171 » » » case blobstore.Key:
183 v.SetString(string(x)) 172 v.SetString(string(x))
184 case string: 173 case string:
185 v.SetString(x) 174 v.SetString(x)
186 default: 175 default:
187 if pVal != nil { 176 if pVal != nil {
188 return typeMismatchReason(pVal, v) 177 return typeMismatchReason(pVal, v)
189 } 178 }
190 } 179 }
191 case reflect.Float32, reflect.Float64: 180 case reflect.Float32, reflect.Float64:
192 x, ok := pVal.(float64) 181 x, ok := pVal.(float64)
193 if !ok && pVal != nil { 182 if !ok && pVal != nil {
194 return typeMismatchReason(pVal, v) 183 return typeMismatchReason(pVal, v)
195 } 184 }
196 if v.OverflowFloat(x) { 185 if v.OverflowFloat(x) {
197 return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type()) 186 return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type())
198 } 187 }
199 v.SetFloat(x) 188 v.SetFloat(x)
200 case reflect.Interface: 189 case reflect.Interface:
201 » » » x, ok := pVal.(gae.DSKey) 190 » » » x, ok := pVal.(Key)
202 if !ok && pVal != nil { 191 if !ok && pVal != nil {
203 return typeMismatchReason(pVal, v) 192 return typeMismatchReason(pVal, v)
204 } 193 }
205 if x != nil { 194 if x != nil {
206 v.Set(reflect.ValueOf(x)) 195 v.Set(reflect.ValueOf(x))
207 } 196 }
208 case reflect.Struct: 197 case reflect.Struct:
209 switch v.Type() { 198 switch v.Type() {
210 case typeOfTime: 199 case typeOfTime:
211 x, ok := pVal.(time.Time) 200 x, ok := pVal.(time.Time)
212 if !ok && pVal != nil { 201 if !ok && pVal != nil {
213 return typeMismatchReason(pVal, v) 202 return typeMismatchReason(pVal, v)
214 } 203 }
215 v.Set(reflect.ValueOf(x)) 204 v.Set(reflect.ValueOf(x))
216 case typeOfGeoPoint: 205 case typeOfGeoPoint:
217 » » » » x, ok := pVal.(gae.DSGeoPoint) 206 » » » » x, ok := pVal.(GeoPoint)
218 if !ok && pVal != nil { 207 if !ok && pVal != nil {
219 return typeMismatchReason(pVal, v) 208 return typeMismatchReason(pVal, v)
220 } 209 }
221 v.Set(reflect.ValueOf(x)) 210 v.Set(reflect.ValueOf(x))
222 default: 211 default:
223 panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v))) 212 panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v)))
224 } 213 }
225 case reflect.Slice: 214 case reflect.Slice:
226 switch x := pVal.(type) { 215 switch x := pVal.(type) {
227 case []byte: 216 case []byte:
228 v.SetBytes(x) 217 v.SetBytes(x)
229 » » » case gae.DSByteString: 218 » » » case ByteString:
230 v.SetBytes([]byte(x)) 219 v.SetBytes([]byte(x))
231 default: 220 default:
232 panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v))) 221 panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v)))
233 } 222 }
234 default: 223 default:
235 panic(fmt.Errorf("helper: impossible: %s", typeMismatchR eason(pVal, v))) 224 panic(fmt.Errorf("helper: impossible: %s", typeMismatchR eason(pVal, v)))
236 } 225 }
237 } 226 }
238 if slice.IsValid() { 227 if slice.IsValid() {
239 slice.Set(reflect.Append(slice, v)) 228 slice.Set(reflect.Append(slice, v))
240 } 229 }
241 return "" 230 return ""
242 } 231 }
243 232
244 func (p *structPLS) Save(withMeta bool) (gae.DSPropertyMap, error) { 233 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) {
245 size := len(p.c.byName) 234 size := len(p.c.byName)
246 if withMeta { 235 if withMeta {
247 size += len(p.c.byMeta) 236 size += len(p.c.byMeta)
248 } 237 }
249 » ret := make(gae.DSPropertyMap, size) 238 » ret := make(PropertyMap, size)
250 » if _, err := p.save(ret, "", gae.ShouldIndex); err != nil { 239 » if _, err := p.save(ret, "", ShouldIndex); err != nil {
251 return nil, err 240 return nil, err
252 } 241 }
253 if withMeta { 242 if withMeta {
254 for k := range p.c.byMeta { 243 for k := range p.c.byMeta {
255 val, err := p.GetMeta(k) 244 val, err := p.GetMeta(k)
256 if err != nil { 245 if err != nil {
257 return nil, err // TODO(riannucci): should these be ignored? 246 return nil, err // TODO(riannucci): should these be ignored?
258 } 247 }
259 » » » p := gae.DSProperty{} 248 » » » p := Property{}
260 » » » if err = p.SetValue(val, gae.NoIndex); err != nil { 249 » » » if err = p.SetValue(val, NoIndex); err != nil {
261 return nil, err 250 return nil, err
262 } 251 }
263 » » » ret["$"+k] = []gae.DSProperty{p} 252 » » » ret["$"+k] = []Property{p}
264 } 253 }
265 } 254 }
266 return ret, nil 255 return ret, nil
267 } 256 }
268 257
269 func (p *structPLS) save(propMap gae.DSPropertyMap, prefix string, is gae.IndexS etting) (idxCount int, err error) { 258 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) {
270 if err = p.Problem(); err != nil { 259 if err = p.Problem(); err != nil {
271 return 260 return
272 } 261 }
273 262
274 » saveProp := func(name string, si gae.IndexSetting, v reflect.Value, st * structTag) (err error) { 263 » saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) {
275 if st.substructCodec != nil { 264 if st.substructCodec != nil {
276 count, err := (&structPLS{v, st.substructCodec}).save(pr opMap, name, si) 265 count, err := (&structPLS{v, st.substructCodec}).save(pr opMap, name, si)
277 if err == nil { 266 if err == nil {
278 idxCount += count 267 idxCount += count
279 if idxCount > maxIndexedProperties { 268 if idxCount > maxIndexedProperties {
280 err = errors.New("gae: too many indexed properties") 269 err = errors.New("gae: too many indexed properties")
281 } 270 }
282 } 271 }
283 return err 272 return err
284 } 273 }
285 274
286 » » prop := gae.DSProperty{} 275 » » prop := Property{}
287 if st.convert { 276 if st.convert {
288 » » » prop, err = v.Addr().Interface().(gae.DSPropertyConverte r).ToDSProperty() 277 » » » prop, err = v.Addr().Interface().(PropertyConverter).ToP roperty()
289 } else { 278 } else {
290 err = prop.SetValue(v.Interface(), si) 279 err = prop.SetValue(v.Interface(), si)
291 } 280 }
292 if err != nil { 281 if err != nil {
293 return err 282 return err
294 } 283 }
295 propMap[name] = append(propMap[name], prop) 284 propMap[name] = append(propMap[name], prop)
296 » » if prop.IndexSetting() == gae.ShouldIndex { 285 » » if prop.IndexSetting() == ShouldIndex {
297 idxCount++ 286 idxCount++
298 if idxCount > maxIndexedProperties { 287 if idxCount > maxIndexedProperties {
299 return errors.New("gae: too many indexed propert ies") 288 return errors.New("gae: too many indexed propert ies")
300 } 289 }
301 } 290 }
302 return nil 291 return nil
303 } 292 }
304 293
305 for i, st := range p.c.byIndex { 294 for i, st := range p.c.byIndex {
306 if st.name == "-" { 295 if st.name == "-" {
307 continue 296 continue
308 } 297 }
309 name := st.name 298 name := st.name
310 if prefix != "" { 299 if prefix != "" {
311 name = prefix + name 300 name = prefix + name
312 } 301 }
313 v := p.o.Field(i) 302 v := p.o.Field(i)
314 is1 := is 303 is1 := is
315 » » if st.idxSetting == gae.NoIndex { 304 » » if st.idxSetting == NoIndex {
316 » » » is1 = gae.NoIndex 305 » » » is1 = NoIndex
317 } 306 }
318 if st.isSlice { 307 if st.isSlice {
319 for j := 0; j < v.Len(); j++ { 308 for j := 0; j < v.Len(); j++ {
320 if err = saveProp(name, is1, v.Index(j), &st); e rr != nil { 309 if err = saveProp(name, is1, v.Index(j), &st); e rr != nil {
321 return 310 return
322 } 311 }
323 } 312 }
324 } else { 313 } else {
325 if err = saveProp(name, is1, v, &st); err != nil { 314 if err = saveProp(name, is1, v, &st); err != nil {
326 return 315 return
327 } 316 }
328 } 317 }
329 } 318 }
330 return 319 return
331 } 320 }
332 321
333 func (p *structPLS) GetMeta(key string) (interface{}, error) { 322 func (p *structPLS) GetMeta(key string) (interface{}, error) {
334 if err := p.Problem(); err != nil { 323 if err := p.Problem(); err != nil {
335 return nil, err 324 return nil, err
336 } 325 }
337 idx, ok := p.c.byMeta[key] 326 idx, ok := p.c.byMeta[key]
338 if !ok { 327 if !ok {
339 » » return nil, gae.ErrDSMetaFieldUnset 328 » » return nil, ErrMetaFieldUnset
340 } 329 }
341 st := p.c.byIndex[idx] 330 st := p.c.byIndex[idx]
342 val := st.metaVal 331 val := st.metaVal
343 f := p.o.Field(idx) 332 f := p.o.Field(idx)
344 if st.canSet { 333 if st.canSet {
345 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) { 334 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) {
346 val = f.Interface() 335 val = f.Interface()
347 } 336 }
348 } 337 }
349 return val, nil 338 return val, nil
350 } 339 }
351 340
352 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { 341 func (p *structPLS) SetMeta(key string, val interface{}) (err error) {
353 if err = p.Problem(); err != nil { 342 if err = p.Problem(); err != nil {
354 return 343 return
355 } 344 }
356 idx, ok := p.c.byMeta[key] 345 idx, ok := p.c.byMeta[key]
357 if !ok { 346 if !ok {
358 » » return gae.ErrDSMetaFieldUnset 347 » » return ErrMetaFieldUnset
359 } 348 }
360 if !p.c.byIndex[idx].canSet { 349 if !p.c.byIndex[idx].canSet {
361 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key) 350 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key)
362 } 351 }
363 p.o.Field(idx).Set(reflect.ValueOf(val)) 352 p.o.Field(idx).Set(reflect.ValueOf(val))
364 return nil 353 return nil
365 } 354 }
366 355
367 func (p *structPLS) Problem() error { return p.c.problem } 356 func (p *structPLS) Problem() error { return p.c.problem }
368 357
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 return 457 return
469 } 458 }
470 } 459 }
471 if !st.canSet { 460 if !st.canSet {
472 st.name = "-" 461 st.name = "-"
473 continue 462 continue
474 } 463 }
475 464
476 substructType := reflect.Type(nil) 465 substructType := reflect.Type(nil)
477 ft := f.Type 466 ft := f.Type
478 » » if reflect.PtrTo(ft).Implements(typeOfDSPropertyConverter) { 467 » » if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) {
479 st.convert = true 468 st.convert = true
480 } else { 469 } else {
481 switch f.Type.Kind() { 470 switch f.Type.Kind() {
482 case reflect.Struct: 471 case reflect.Struct:
483 if ft != typeOfTime && ft != typeOfGeoPoint { 472 if ft != typeOfTime && ft != typeOfGeoPoint {
484 substructType = ft 473 substructType = ft
485 } 474 }
486 case reflect.Slice: 475 case reflect.Slice:
487 » » » » if reflect.PtrTo(ft.Elem()).Implements(typeOfDSP ropertyConverter) { 476 » » » » if reflect.PtrTo(ft.Elem()).Implements(typeOfPro pertyConverter) {
488 st.convert = true 477 st.convert = true
489 } else if ft.Elem().Kind() == reflect.Struct { 478 } else if ft.Elem().Kind() == reflect.Struct {
490 substructType = ft.Elem() 479 substructType = ft.Elem()
491 } 480 }
492 st.isSlice = ft.Elem().Kind() != reflect.Uint8 481 st.isSlice = ft.Elem().Kind() != reflect.Uint8
493 c.hasSlice = c.hasSlice || st.isSlice 482 c.hasSlice = c.hasSlice || st.isSlice
494 case reflect.Interface: 483 case reflect.Interface:
495 » » » » if ft != typeOfDSKey { 484 » » » » if ft != typeOfKey {
496 c.problem = me("field %q has non-concret e interface type %s", 485 c.problem = me("field %q has non-concret e interface type %s",
497 f.Name, f.Type) 486 f.Name, f.Type)
498 return 487 return
499 } 488 }
500 } 489 }
501 } 490 }
502 491
503 if substructType != nil { 492 if substructType != nil {
504 sub := getStructCodecLocked(substructType) 493 sub := getStructCodecLocked(substructType)
505 if sub.problem != nil { 494 if sub.problem != nil {
(...skipping 23 matching lines...) Expand all
529 } 518 }
530 c.byName[absName] = i 519 c.byName[absName] = i
531 } 520 }
532 } else { 521 } else {
533 if !st.convert { // check the underlying static type of the field 522 if !st.convert { // check the underlying static type of the field
534 t := ft 523 t := ft
535 if st.isSlice { 524 if st.isSlice {
536 t = t.Elem() 525 t = t.Elem()
537 } 526 }
538 v := reflect.New(t).Elem().Interface() 527 v := reflect.New(t).Elem().Interface()
539 » » » » v, _ = gae.DSUpconvertUnderlyingType(v, t) 528 » » » » v, _ = UpconvertUnderlyingType(v, t)
540 » » » » if _, err := gae.DSPropertyTypeOf(v, false); err != nil { 529 » » » » if _, err := PropertyTypeOf(v, false); err != ni l {
541 c.problem = me("field %q has invalid typ e: %s", name, ft) 530 c.problem = me("field %q has invalid typ e: %s", name, ft)
542 return 531 return
543 } 532 }
544 } 533 }
545 534
546 if _, ok := c.byName[name]; ok { 535 if _, ok := c.byName[name]; ok {
547 c.problem = me("struct tag has repeated property name: %q", name) 536 c.problem = me("struct tag has repeated property name: %q", name)
548 return 537 return
549 } 538 }
550 c.byName[name] = i 539 c.byName[name] = i
551 } 540 }
552 st.name = name 541 st.name = name
553 if opts == "noindex" { 542 if opts == "noindex" {
554 » » » st.idxSetting = gae.NoIndex 543 » » » st.idxSetting = NoIndex
555 } 544 }
556 } 545 }
557 if c.problem == errRecursiveStruct { 546 if c.problem == errRecursiveStruct {
558 c.problem = nil 547 c.problem = nil
559 } 548 }
560 return 549 return
561 } 550 }
562 551
563 func convertMeta(val string, t reflect.Type) (interface{}, error) { 552 func convertMeta(val string, t reflect.Type) (interface{}, error) {
564 switch t { 553 switch t {
565 case typeOfString: 554 case typeOfString:
566 return val, nil 555 return val, nil
567 case typeOfInt64: 556 case typeOfInt64:
568 if val == "" { 557 if val == "" {
569 return int64(0), nil 558 return int64(0), nil
570 } 559 }
571 return strconv.ParseInt(val, 10, 64) 560 return strconv.ParseInt(val, 10, 64)
572 } 561 }
573 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%s", t , val) 562 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%s", t , val)
574 } 563 }
OLDNEW
« no previous file with comments | « service/rawdatastore/datastore.go ('k') | service/rawdatastore/datastore_key.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698