| Index: service/datastore/datastore.go
|
| diff --git a/service/datastore/datastore.go b/service/datastore/datastore.go
|
| index 5f9c64c8ce5c7d825bd91da3b03967fdec334ec5..e244c69f536f2ff0a741e1daada888744e88d39a 100644
|
| --- a/service/datastore/datastore.go
|
| +++ b/service/datastore/datastore.go
|
| @@ -48,6 +48,16 @@ func (d *datastoreImpl) NewKey(kind, stringID string, intID int64, parent *Key)
|
| return NewKey(d.aid, d.ns, kind, stringID, intID, parent)
|
| }
|
|
|
| +func (d *datastoreImpl) NewIncompleteKeys(count int, kind string, parent *Key) (keys []*Key) {
|
| + if count > 0 {
|
| + keys = make([]*Key, count)
|
| + for i := range keys {
|
| + keys[i] = d.NewKey(kind, "", 0, parent)
|
| + }
|
| + }
|
| + return
|
| +}
|
| +
|
| func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key {
|
| return NewKeyToks(d.aid, d.ns, toks)
|
| }
|
| @@ -56,20 +66,28 @@ func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key {
|
| //
|
| // obj is any object that Interface.Get is able to accept.
|
| //
|
| -// This method will panic if obj is an invalid datastore model. If the key could
|
| -// not be applied to the object, nothing will happen.
|
| -func PopulateKey(obj interface{}, key *Key) {
|
| +// Upon successful application, this method will return true. If the key could
|
| +// not be applied to the object, this method will return false. It will panic if
|
| +// obj is an invalid datastore model.
|
| +func PopulateKey(obj interface{}, key *Key) bool {
|
| pls := getMGS(obj)
|
| - if !pls.SetMeta("key", key) {
|
| - lst := key.LastTok()
|
| - if lst.StringID != "" {
|
| - pls.SetMeta("id", lst.StringID)
|
| - } else {
|
| - pls.SetMeta("id", lst.IntID)
|
| + if pls.SetMeta("key", key) {
|
| + return true
|
| + }
|
| +
|
| + lst := key.LastTok()
|
| + if lst.StringID != "" {
|
| + if !pls.SetMeta("id", lst.StringID) {
|
| + return false
|
| + }
|
| + } else {
|
| + if !pls.SetMeta("id", lst.IntID) {
|
| + return false
|
| }
|
| - pls.SetMeta("kind", lst.Kind)
|
| - pls.SetMeta("parent", key.Parent())
|
| }
|
| + pls.SetMeta("kind", lst.Kind)
|
| + pls.SetMeta("parent", key.Parent())
|
| + return true
|
| }
|
|
|
| func checkMultiSliceType(v interface{}) error {
|
| @@ -129,6 +147,57 @@ func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat
|
| return
|
| }
|
|
|
| +func (d *datastoreImpl) AllocateIDs(ent ...interface{}) error {
|
| + if len(ent) == 0 {
|
| + return nil
|
| + }
|
| +
|
| + mma, err := makeMetaMultiArg(ent, true)
|
| + if err != nil {
|
| + panic(err)
|
| + }
|
| +
|
| + keys, _, err := mma.getKeysPMs(d.aid, d.ns, false)
|
| + if err != nil {
|
| + return err
|
| + }
|
| + if len(keys) == 0 {
|
| + return nil
|
| + }
|
| +
|
| + // Convert each key to be partial valid, assigning an integer ID of 0. Confirm
|
| + // that each object can be populated with such a key.
|
| + for i, key := range keys {
|
| + keys[i] = key.Partial()
|
| + }
|
| +
|
| + var et errorTracker
|
| + it := mma.iterator(et.init(mma))
|
| + err = filterStop(d.RawInterface.AllocateIDs(keys, func(key *Key, err error) error {
|
| + it.next(func(mat *multiArgType, v reflect.Value) error {
|
| + if err != nil {
|
| + return err
|
| + }
|
| +
|
| + if !mat.setKey(v, key) {
|
| + return ErrInvalidKey
|
| + }
|
| + return nil
|
| + })
|
| +
|
| + return nil
|
| + }))
|
| + if err == nil {
|
| + err = et.error()
|
| +
|
| + if err != nil && len(ent) == 1 {
|
| + // Single-argument Exists will return a single error.
|
| + err = errors.SingleError(err)
|
| + }
|
| + }
|
| + return err
|
| +}
|
| +
|
| func (d *datastoreImpl) Run(q *Query, cbIface interface{}) error {
|
| isKey, hasErr, hasCursorCB, mat := runParseCallback(cbIface)
|
|
|
| @@ -257,6 +326,10 @@ func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error {
|
| }
|
|
|
| func (d *datastoreImpl) Exists(ent ...interface{}) (*ExistsResult, error) {
|
| + if len(ent) == 0 {
|
| + return nil, nil
|
| + }
|
| +
|
| mma, err := makeMetaMultiArg(ent, true)
|
| if err != nil {
|
| panic(err)
|
| @@ -266,15 +339,16 @@ func (d *datastoreImpl) Exists(ent ...interface{}) (*ExistsResult, error) {
|
| if err != nil {
|
| return nil, err
|
| }
|
| + if len(keys) == 0 {
|
| + return nil, nil
|
| + }
|
|
|
| - i := 0
|
| var bt boolTracker
|
| it := mma.iterator(bt.init(mma))
|
| err = filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error {
|
| it.next(func(*multiArgType, reflect.Value) error {
|
| return err
|
| })
|
| - i++
|
| return nil
|
| }))
|
| if err == nil {
|
| @@ -297,6 +371,10 @@ func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) {
|
| }
|
|
|
| func (d *datastoreImpl) Get(dst ...interface{}) (err error) {
|
| + if len(dst) == 0 {
|
| + return nil
|
| + }
|
| +
|
| mma, err := makeMetaMultiArg(dst, false)
|
| if err != nil {
|
| panic(err)
|
| @@ -306,8 +384,10 @@ func (d *datastoreImpl) Get(dst ...interface{}) (err error) {
|
| if err != nil {
|
| return err
|
| }
|
| + if len(keys) == 0 {
|
| + return nil
|
| + }
|
|
|
| - i := 0
|
| var et errorTracker
|
| it := mma.iterator(et.init(mma))
|
| meta := NewMultiMetaGetter(pms)
|
| @@ -318,8 +398,6 @@ func (d *datastoreImpl) Get(dst ...interface{}) (err error) {
|
| }
|
| return mat.setPM(slot, pm)
|
| })
|
| -
|
| - i++
|
| return nil
|
| }))
|
|
|
| @@ -342,6 +420,10 @@ func (d *datastoreImpl) GetMulti(dst interface{}) error {
|
| }
|
|
|
| func (d *datastoreImpl) Put(src ...interface{}) (err error) {
|
| + if len(src) == 0 {
|
| + return nil
|
| + }
|
| +
|
| mma, err := makeMetaMultiArg(src, false)
|
| if err != nil {
|
| panic(err)
|
| @@ -351,6 +433,9 @@ func (d *datastoreImpl) Put(src ...interface{}) (err error) {
|
| if err != nil {
|
| return err
|
| }
|
| + if len(keys) == 0 {
|
| + return nil
|
| + }
|
|
|
| i := 0
|
| var et errorTracker
|
| @@ -389,6 +474,10 @@ func (d *datastoreImpl) PutMulti(src interface{}) error {
|
| }
|
|
|
| func (d *datastoreImpl) Delete(ent ...interface{}) error {
|
| + if len(ent) == 0 {
|
| + return nil
|
| + }
|
| +
|
| mma, err := makeMetaMultiArg(ent, true)
|
| if err != nil {
|
| panic(err)
|
| @@ -398,15 +487,16 @@ func (d *datastoreImpl) Delete(ent ...interface{}) error {
|
| if err != nil {
|
| return err
|
| }
|
| + if len(keys) == 0 {
|
| + return nil
|
| + }
|
|
|
| - i := 0
|
| var et errorTracker
|
| it := mma.iterator(et.init(mma))
|
| err = filterStop(d.RawInterface.DeleteMulti(keys, func(err error) error {
|
| it.next(func(*multiArgType, reflect.Value) error {
|
| return err
|
| })
|
| - i++
|
|
|
| return nil
|
| }))
|
|
|