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

Side by Side Diff: service/datastore/datastore.go

Issue 1525873002: Panic when non-runtime-handleable type errors occur (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: add test Created 5 years 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 | « no previous file | service/datastore/datastore_test.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 package datastore 5 package datastore
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "reflect" 9 "reflect"
10 10
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 fq, err := q.Finalize() 158 fq, err := q.Finalize()
159 if err != nil { 159 if err != nil {
160 return 0, err 160 return 0, err
161 } 161 }
162 return d.RawInterface.Count(fq) 162 return d.RawInterface.Count(fq)
163 } 163 }
164 164
165 func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error { 165 func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error {
166 v := reflect.ValueOf(dst) 166 v := reflect.ValueOf(dst)
167 if v.Kind() != reflect.Ptr { 167 if v.Kind() != reflect.Ptr {
168 » » return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) 168 » » panic(fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst))
169 } 169 }
170 if !v.IsValid() || v.IsNil() { 170 if !v.IsValid() || v.IsNil() {
171 » » return errors.New("invalid GetAll dst: <nil>") 171 » » panic(errors.New("invalid GetAll dst: <nil>"))
172 } 172 }
173 173
174 if keys, ok := dst.(*[]*Key); ok { 174 if keys, ok := dst.(*[]*Key); ok {
175 fq, err := q.KeysOnly(true).Finalize() 175 fq, err := q.KeysOnly(true).Finalize()
176 if err != nil { 176 if err != nil {
177 return err 177 return err
178 } 178 }
179 179
180 return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ Curs orCB) error { 180 return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ Curs orCB) error {
181 *keys = append(*keys, k) 181 *keys = append(*keys, k)
182 return nil 182 return nil
183 }) 183 })
184 } 184 }
185 fq, err := q.Finalize() 185 fq, err := q.Finalize()
186 if err != nil { 186 if err != nil {
187 return err 187 return err
188 } 188 }
189 189
190 slice := v.Elem() 190 slice := v.Elem()
191 mat := parseMultiArg(slice.Type()) 191 mat := parseMultiArg(slice.Type())
192 if mat.newElem == nil { 192 if mat.newElem == nil {
193 » » return fmt.Errorf("invalid GetAll input type: %T", dst) 193 » » panic(fmt.Errorf("invalid GetAll dst (non-concrete element type) : %T", dst))
194 } 194 }
195 195
196 errs := map[int]error{} 196 errs := map[int]error{}
197 i := 0 197 i := 0
198 err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) er ror { 198 err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) er ror {
199 slice.Set(reflect.Append(slice, mat.newElem())) 199 slice.Set(reflect.Append(slice, mat.newElem()))
200 itm := slice.Index(i) 200 itm := slice.Index(i)
201 mat.setKey(itm, k) 201 mat.setKey(itm, k)
202 err := mat.setPM(itm, pm) 202 err := mat.setPM(itm, pm)
203 if err != nil { 203 if err != nil {
204 errs[i] = err 204 errs[i] = err
205 } 205 }
206 i++ 206 i++
207 return nil 207 return nil
208 }) 208 })
209 if err == nil { 209 if err == nil {
210 if len(errs) > 0 { 210 if len(errs) > 0 {
211 me := make(errors.MultiError, slice.Len()) 211 me := make(errors.MultiError, slice.Len())
212 for i, e := range errs { 212 for i, e := range errs {
213 me[i] = e 213 me[i] = e
214 } 214 }
215 err = me 215 err = me
216 } 216 }
217 } 217 }
218 return err 218 return err
219 } 219 }
220 220
221 func isOkType(v reflect.Type) bool { 221 func isOkType(t reflect.Type) error {
222 » if v == typeOfKey { 222 » if t == nil {
223 » » return false 223 » » return errors.New("no type information")
224 } 224 }
225 » if v.Implements(typeOfPropertyLoadSaver) { 225 » if t.Implements(typeOfPropertyLoadSaver) {
226 » » return true 226 » » return nil
227 } 227 }
228 » if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { 228 » if t == typeOfKey {
229 » » return true 229 » » return errors.New("not user datatype")
230 } 230 }
231 » return false 231 » if t.Kind() != reflect.Ptr {
232 » » return errors.New("not a pointer")
233 » }
234 » if t.Elem().Kind() != reflect.Struct {
235 » » return errors.New("does not point to a struct")
236 » }
237 » return nil
232 } 238 }
233 239
234 func (d *datastoreImpl) ExistsMulti(keys []*Key) ([]bool, error) { 240 func (d *datastoreImpl) ExistsMulti(keys []*Key) ([]bool, error) {
235 lme := errors.NewLazyMultiError(len(keys)) 241 lme := errors.NewLazyMultiError(len(keys))
236 ret := make([]bool, len(keys)) 242 ret := make([]bool, len(keys))
237 i := 0 243 i := 0
238 err := d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error { 244 err := d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error {
239 if err == nil { 245 if err == nil {
240 ret[i] = true 246 ret[i] = true
241 } else if err != ErrNoSuchEntity { 247 } else if err != ErrNoSuchEntity {
242 lme.Assign(i, err) 248 lme.Assign(i, err)
243 } 249 }
244 i++ 250 i++
245 return nil 251 return nil
246 }) 252 })
247 if err != nil { 253 if err != nil {
248 return ret, err 254 return ret, err
249 } 255 }
250 return ret, lme.Get() 256 return ret, lme.Get()
251 } 257 }
252 258
253 func (d *datastoreImpl) Exists(k *Key) (bool, error) { 259 func (d *datastoreImpl) Exists(k *Key) (bool, error) {
254 ret, err := d.ExistsMulti([]*Key{k}) 260 ret, err := d.ExistsMulti([]*Key{k})
255 return ret[0], errors.SingleError(err) 261 return ret[0], errors.SingleError(err)
256 } 262 }
257 263
258 func (d *datastoreImpl) Get(dst interface{}) (err error) { 264 func (d *datastoreImpl) Get(dst interface{}) (err error) {
259 » if !isOkType(reflect.TypeOf(dst)) { 265 » if err := isOkType(reflect.TypeOf(dst)); err != nil {
260 » » return fmt.Errorf("invalid Get input type: %T", dst) 266 » » panic(fmt.Errorf("invalid Get input type (%T): %s", dst, err))
261 } 267 }
262 return errors.SingleError(d.GetMulti([]interface{}{dst})) 268 return errors.SingleError(d.GetMulti([]interface{}{dst}))
263 } 269 }
264 270
265 func (d *datastoreImpl) Put(src interface{}) (err error) { 271 func (d *datastoreImpl) Put(src interface{}) (err error) {
266 » if !isOkType(reflect.TypeOf(src)) { 272 » if err := isOkType(reflect.TypeOf(src)); err != nil {
267 » » return fmt.Errorf("invalid Put input type: %T", src) 273 » » panic(fmt.Errorf("invalid Put input type (%T): %s", src, err))
268 } 274 }
269 return errors.SingleError(d.PutMulti([]interface{}{src})) 275 return errors.SingleError(d.PutMulti([]interface{}{src}))
270 } 276 }
271 277
272 func (d *datastoreImpl) Delete(key *Key) (err error) { 278 func (d *datastoreImpl) Delete(key *Key) (err error) {
273 return errors.SingleError(d.DeleteMulti([]*Key{key})) 279 return errors.SingleError(d.DeleteMulti([]*Key{key}))
274 } 280 }
275 281
276 func (d *datastoreImpl) GetMulti(dst interface{}) error { 282 func (d *datastoreImpl) GetMulti(dst interface{}) error {
277 slice := reflect.ValueOf(dst) 283 slice := reflect.ValueOf(dst)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 err = lme.Get() 341 err = lme.Get()
336 if err == nil { 342 if err == nil {
337 err = extErr 343 err = extErr
338 } 344 }
339 return 345 return
340 } 346 }
341 347
342 func (d *datastoreImpl) Raw() RawInterface { 348 func (d *datastoreImpl) Raw() RawInterface {
343 return d.RawInterface 349 return d.RawInterface
344 } 350 }
OLDNEW
« no previous file with comments | « no previous file | service/datastore/datastore_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698