Chromium Code Reviews| Index: service/datastore/datastore.go |
| diff --git a/service/datastore/datastore.go b/service/datastore/datastore.go |
| index 752c99c55779e02a2f97cced14b351645f18a6af..cb0a0bb77f9baa39f647725c92685b27f0e42492 100644 |
| --- a/service/datastore/datastore.go |
| +++ b/service/datastore/datastore.go |
| @@ -37,7 +37,7 @@ func (d *datastoreImpl) KeyForObj(src interface{}) *Key { |
| } |
| func (d *datastoreImpl) KeyForObjErr(src interface{}) (*Key, error) { |
| - return newKeyObjErr(d.aid, d.ns, src) |
| + return newKeyObjErr(d.aid, d.ns, getMGS(src)) |
| } |
| func (d *datastoreImpl) MakeKey(elems ...interface{}) *Key { |
| @@ -72,7 +72,15 @@ func PopulateKey(obj interface{}, key *Key) { |
| } |
| } |
| -func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat multiArgType) { |
| +func checkMultiSliceType(v interface{}) error { |
| + if reflect.TypeOf(v).Kind() == reflect.Slice { |
| + return nil |
| + } |
| + return fmt.Errorf("argument must be a slice, not %T", v) |
| + |
| +} |
| + |
| +func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat *multiArgType) { |
| badSig := func() { |
| panic(fmt.Errorf( |
| "cb does not match the required callback signature: `%T` != `func(TYPE, [CursorCB]) [error]`", |
| @@ -100,7 +108,7 @@ func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat |
| if firstArg == typeOfKey { |
| isKey = true |
| } else { |
| - mat = parseArg(firstArg, false) |
| + mat = mustParseArg(firstArg) |
| if mat.newElem == nil { |
| badSig() |
| } |
| @@ -218,7 +226,7 @@ func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error { |
| } |
| slice := v.Elem() |
| - mat := parseMultiArg(slice.Type()) |
| + mat := mustParseMultiArg(slice.Type()) |
| if mat.newElem == nil { |
| panic(fmt.Errorf("invalid GetAll dst (non-concrete element type): %T", dst)) |
| } |
| @@ -248,26 +256,7 @@ func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error { |
| return err |
| } |
| -func isOkType(t reflect.Type) error { |
|
dnj
2016/05/25 05:27:15
This check is moved into "multiarg.go".
|
| - if t == nil { |
| - return errors.New("no type information") |
| - } |
| - if t.Implements(typeOfPropertyLoadSaver) { |
| - return nil |
| - } |
| - if t == typeOfKey { |
| - return errors.New("not user datatype") |
| - } |
| - if t.Kind() != reflect.Ptr { |
| - return errors.New("not a pointer") |
| - } |
| - if t.Elem().Kind() != reflect.Struct { |
| - return errors.New("does not point to a struct") |
| - } |
| - return nil |
| -} |
| - |
| -func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) { |
| +func (d *datastoreImpl) ExistsMulti(keys ...*Key) (BoolList, error) { |
| lme := errors.NewLazyMultiError(len(keys)) |
| ret := make(BoolList, len(keys)) |
| i := 0 |
| @@ -287,80 +276,105 @@ func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) { |
| } |
| func (d *datastoreImpl) Exists(k *Key) (bool, error) { |
| - ret, err := d.ExistsMulti([]*Key{k}) |
| + ret, err := d.ExistsMulti(k) |
| return ret[0], errors.SingleError(err) |
| } |
| -func (d *datastoreImpl) Get(dst interface{}) (err error) { |
| - if err := isOkType(reflect.TypeOf(dst)); err != nil { |
| - panic(fmt.Errorf("invalid Get input type (%T): %s", dst, err)) |
| - } |
| - return errors.SingleError(d.GetMulti([]interface{}{dst})) |
| -} |
| - |
| -func (d *datastoreImpl) Put(src interface{}) (err error) { |
| - if err := isOkType(reflect.TypeOf(src)); err != nil { |
| - panic(fmt.Errorf("invalid Put input type (%T): %s", src, err)) |
| +func (d *datastoreImpl) Get(dst ...interface{}) (err error) { |
| + mma, err := makeMetaMultiArg(dst) |
| + if err != nil { |
| + panic(err) |
| } |
| - return errors.SingleError(d.PutMulti([]interface{}{src})) |
| -} |
| - |
| -func (d *datastoreImpl) Delete(key *Key) (err error) { |
| - return errors.SingleError(d.DeleteMulti([]*Key{key})) |
| -} |
| - |
| -func (d *datastoreImpl) GetMulti(dst interface{}) error { |
| - slice := reflect.ValueOf(dst) |
| - mat := parseMultiArg(slice.Type()) |
| - keys, pms, err := mat.GetKeysPMs(d.aid, d.ns, slice, true) |
| + keys, pms, err := mma.getKeysPMs(d.aid, d.ns, true) |
| if err != nil { |
| return err |
| } |
| - lme := errors.NewLazyMultiError(len(keys)) |
| i := 0 |
| + it := mma.iterator() |
| meta := NewMultiMetaGetter(pms) |
| err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error) error { |
| - if !lme.Assign(i, err) { |
| - lme.Assign(i, mat.setPM(slice.Index(i), pm)) |
| - } |
| + it.next(func(mat *multiArgType, slot reflect.Value) error { |
|
dnj
2016/05/25 05:27:15
Just a quick explanation, since Rietveld sorted th
|
| + if err != nil { |
| + return err |
| + } |
| + return mat.setPM(slot, pm) |
| + }) |
| + |
| i++ |
| return nil |
| })) |
| if err == nil { |
| - err = lme.Get() |
| + err = it.error() |
|
dnj
2016/05/25 05:27:15
(This returns the MultiError accumulated by "it").
|
| + |
| + if err != nil && len(dst) == 1 { |
| + // Single-argument Get will return a single error. |
| + err = errors.SingleError(err) |
| + } |
| } |
| return err |
| } |
| -func (d *datastoreImpl) PutMulti(src interface{}) error { |
| - slice := reflect.ValueOf(src) |
| - mat := parseMultiArg(slice.Type()) |
| +func (d *datastoreImpl) GetMulti(dst interface{}) error { |
| + if err := checkMultiSliceType(dst); err != nil { |
| + panic(err) |
| + } |
| + return d.Get(dst) |
| +} |
| - keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice, false) |
| +func (d *datastoreImpl) Put(src ...interface{}) (err error) { |
| + mma, err := makeMetaMultiArg(src) |
| + if err != nil { |
| + panic(err) |
| + } |
| + |
| + keys, vals, err := mma.getKeysPMs(d.aid, d.ns, false) |
| if err != nil { |
| return err |
| } |
| - lme := errors.NewLazyMultiError(len(keys)) |
| i := 0 |
| + it := mma.iterator() |
| err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) error { |
| - if !lme.Assign(i, err) && key != keys[i] { |
| - mat.setKey(slice.Index(i), key) |
| - } |
| + it.next(func(mat *multiArgType, slot reflect.Value) error { |
| + if err != nil { |
| + return err |
| + } |
| + if key != keys[i] { |
| + mat.setKey(slot, key) |
| + } |
| + return nil |
| + }) |
| + |
| i++ |
| return nil |
| })) |
| if err == nil { |
| - err = lme.Get() |
| + err = it.error() |
| + |
| + if err != nil && len(src) == 1 { |
| + // Single-argument Get will return a single error. |
| + err = errors.SingleError(err) |
| + } |
| } |
| return err |
| } |
| -func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) { |
| +func (d *datastoreImpl) PutMulti(src interface{}) error { |
| + if err := checkMultiSliceType(src); err != nil { |
| + panic(err) |
| + } |
| + return d.Put(src) |
| +} |
| + |
| +func (d *datastoreImpl) Delete(key *Key) (err error) { |
| + return errors.SingleError(d.DeleteMulti(key)) |
| +} |
| + |
| +func (d *datastoreImpl) DeleteMulti(keys ...*Key) (err error) { |
| lme := errors.NewLazyMultiError(len(keys)) |
| i := 0 |
| extErr := filterStop(d.RawInterface.DeleteMulti(keys, func(internalErr error) error { |