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

Unified Diff: service/datastore/datastore.go

Issue 1259593005: Add 'user friendly' datastore API. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: more docs Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « service/datastore/context_test.go ('k') | service/datastore/datastore_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/datastore.go
diff --git a/service/datastore/datastore.go b/service/datastore/datastore.go
new file mode 100644
index 0000000000000000000000000000000000000000..b4f1220b0f1311b5753a4c8b511b811415e1883a
--- /dev/null
+++ b/service/datastore/datastore.go
@@ -0,0 +1,199 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package datastore
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/luci/luci-go/common/errors"
+)
+
+type datastoreImpl struct{ RawInterface }
+
+var _ Interface = (*datastoreImpl)(nil)
+
+func (d *datastoreImpl) KeyForObj(src interface{}) Key {
+ ret, err := d.KeyForObjErr(src)
+ if err != nil {
+ panic(err)
+ }
+ return ret
+}
+
+func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) {
+ return newKeyObjErr(d.NewKey, src)
+}
+
+func (d *datastoreImpl) Run(q Query, proto interface{}, cb RunCB) error {
+ if _, ok := proto.(*Key); ok {
+ return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMap, gc func() (Cursor, error)) bool {
+ return cb(k, gc)
+ })
+ }
+
+ mat := parseArg(reflect.TypeOf(proto))
+ if !mat.valid || mat.newElem == nil {
+ return fmt.Errorf("invalid Run proto type: %T", proto)
+ }
+
+ innerErr := error(nil)
+ err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Cursor, error)) bool {
+ itm := mat.newElem()
+ if innerErr = mat.setPM(itm, pm); innerErr != nil {
+ return false
+ }
+ mat.setKey(itm, k)
+ return cb(itm.Interface(), gc)
+ })
+ if err == nil {
+ err = innerErr
+ }
+ return err
+}
+
+func (d *datastoreImpl) GetAll(q Query, dst interface{}) error {
+ v := reflect.ValueOf(dst)
+ if v.Kind() != reflect.Ptr {
+ return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst)
+ }
+ if !v.IsValid() || v.IsNil() {
+ return errors.New("invalid GetAll dst: <nil>")
+ }
+
+ if keys, ok := dst.(*[]Key); ok {
+ return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMap, _ func() (Cursor, error)) bool {
+ *keys = append(*keys, k)
+ return true
+ })
+ }
+
+ slice := v.Elem()
+ mat := parseMultiArg(slice.Type())
+ if !mat.valid || mat.newElem == nil {
+ return fmt.Errorf("invalid GetAll input type: %T", dst)
+ }
+
+ lme := errors.LazyMultiError{Size: slice.Len()}
+ i := 0
+ err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Cursor, error)) bool {
+ slice.Set(reflect.Append(slice, mat.newElem()))
+ itm := slice.Index(i)
+ mat.setKey(itm, k)
+ lme.Assign(i, mat.setPM(itm, pm))
+ i++
+ return true
+ })
+ if err == nil {
+ err = lme.Get()
+ }
+ return err
+}
+
+func isOkType(v reflect.Type) bool {
+ if v.Implements(typeOfPropertyLoadSaver) {
+ return true
+ }
+ if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
+ return true
+ }
+ return false
+}
+
+func (d *datastoreImpl) Get(dst interface{}) (err error) {
+ if !isOkType(reflect.TypeOf(dst)) {
+ return fmt.Errorf("invalid Get input type: %T", dst)
+ }
+ return errors.SingleError(d.GetMulti([]interface{}{dst}))
+}
+
+func (d *datastoreImpl) Put(src interface{}) (err error) {
+ if !isOkType(reflect.TypeOf(src)) {
+ return fmt.Errorf("invalid Put input type: %T", src)
+ }
+ 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())
+ if !mat.valid {
+ return fmt.Errorf("invalid GetMulti input type: %T", dst)
+ }
+
+ keys, err := mat.GetKeys(d.NewKey, slice)
+ if err != nil {
+ return err
+ }
+
+ lme := errors.LazyMultiError{Size: len(keys)}
+ i := 0
+ err = d.RawInterface.GetMulti(keys, func(pm PropertyMap, err error) {
+ if !lme.Assign(i, err) {
+ lme.Assign(i, mat.setPM(slice.Index(i), pm))
+ }
+ i++
+ })
+
+ if err == nil {
+ err = lme.Get()
+ }
+ return err
+}
+
+func (d *datastoreImpl) PutMulti(src interface{}) error {
+ slice := reflect.ValueOf(src)
+ mat := parseMultiArg(slice.Type())
+ if !mat.valid {
+ return fmt.Errorf("invalid PutMulti input type: %T", src)
+ }
+
+ keys, err := mat.GetKeys(d.NewKey, slice)
+ if err != nil {
+ return err
+ }
+
+ vals, err := mat.GetPMs(slice)
+ if err != nil {
+ return err
+ }
+
+ lme := errors.LazyMultiError{Size: len(keys)}
+ i := 0
+ err = d.RawInterface.PutMulti(keys, vals, func(key Key, err error) {
+ if key != keys[i] {
+ mat.setKey(slice.Index(i), key)
+ }
+ lme.Assign(i, err)
+ i++
+ })
+
+ if err == nil {
+ err = lme.Get()
+ }
+ return err
+}
+
+func (d *datastoreImpl) DeleteMulti(keys []Key) (err error) {
+ lme := errors.LazyMultiError{Size: len(keys)}
+ i := 0
+ extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) {
+ lme.Assign(i, internalErr)
+ i++
+ })
+ err = lme.Get()
+ if err == nil {
+ err = extErr
+ }
+ return
+}
+
+func (d *datastoreImpl) Raw() RawInterface {
+ return d.RawInterface
+}
« no previous file with comments | « service/datastore/context_test.go ('k') | service/datastore/datastore_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698