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

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

Issue 1259593005: Add 'user friendly' datastore API. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: rebase 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package datastore
6
7 import (
8 "fmt"
9 "reflect"
10
11 "github.com/luci/luci-go/common/errors"
12 )
13
14 type datastoreImpl struct{ RawInterface }
15
16 var _ Interface = (*datastoreImpl)(nil)
17
18 func (d *datastoreImpl) KeyForObj(src interface{}) Key {
19 ret, err := d.KeyForObjErr(src)
20 if err != nil {
21 panic(err)
22 }
23 return ret
24 }
25
26 func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) {
27 return newKeyObjErr(d.NewKey, src)
28 }
29
30 func (d *datastoreImpl) Run(q Query, proto interface{}, cb RunCB) error {
31 if _, ok := proto.(*Key); ok {
32 return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc func() (Cursor, error)) bool {
33 return cb(k, gc)
34 })
35 }
36
37 mat := parseArg(reflect.TypeOf(proto))
38 if !mat.valid || mat.newElem == nil {
39 return fmt.Errorf("invalid Run proto type: %T", proto)
40 }
41
42 innerErr := error(nil)
43 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Curs or, error)) bool {
44 itm := mat.newElem()
45 if innerErr = mat.setPM(itm, pm); innerErr != nil {
46 return false
47 }
48 mat.setKey(itm, k)
49 return cb(itm.Interface(), gc)
50 })
51 if err == nil {
52 err = innerErr
53 }
54 return err
55 }
56
57 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error {
58 v := reflect.ValueOf(dst)
59 if v.Kind() != reflect.Ptr {
60 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst)
61 }
62 if !v.IsValid() || v.IsNil() {
63 return errors.New("invalid GetAll dst: <nil>")
64 }
65
66 if keys, ok := dst.(*[]Key); ok {
67 return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ func() (Cursor, error)) bool {
68 *keys = append(*keys, k)
69 return true
70 })
71 }
72
73 slice := v.Elem()
74 mat := parseMultiArg(slice.Type())
75 if !mat.valid || mat.newElem == nil {
76 return fmt.Errorf("invalid GetAll input type: %T", dst)
77 }
78
79 lme := errors.LazyMultiError{Size: slice.Len()}
80 i := 0
81 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Curso r, error)) bool {
82 slice.Set(reflect.Append(slice, mat.newElem()))
83 itm := slice.Index(i)
84 mat.setKey(itm, k)
85 lme.Assign(i, mat.setPM(itm, pm))
86 i++
87 return true
88 })
89 if err == nil {
90 err = lme.Get()
91 }
92 return err
93 }
94
95 func isOkType(v reflect.Type) bool {
96 if v.Implements(typeOfPropertyLoadSaver) {
97 return true
98 }
99 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
100 return true
101 }
102 return false
103 }
104
105 func (d *datastoreImpl) Get(dst interface{}) (err error) {
106 if !isOkType(reflect.TypeOf(dst)) {
107 return fmt.Errorf("invalid Get input type: %T", dst)
108 }
109 return errors.SingleError(d.GetMulti([]interface{}{dst}))
110 }
111
112 func (d *datastoreImpl) Put(src interface{}) (err error) {
113 if !isOkType(reflect.TypeOf(src)) {
Vadim Sh. 2015/08/03 21:25:12 so Put requires passing values by pointer? Does it
iannucci 2015/08/03 21:51:48 Yeah, it requires pass by pointer. It COULD make s
114 return fmt.Errorf("invalid Put input type: %T", src)
115 }
116 return errors.SingleError(d.PutMulti([]interface{}{src}))
117 }
118
119 func (d *datastoreImpl) Delete(key Key) (err error) {
120 return errors.SingleError(d.DeleteMulti([]Key{key}))
121 }
122
123 func (d *datastoreImpl) GetMulti(dst interface{}) error {
124 slice := reflect.ValueOf(dst)
125 mat := parseMultiArg(slice.Type())
126 if !mat.valid {
127 return fmt.Errorf("invalid GetMulti input type: %T", dst)
128 }
129
130 keys, err := mat.GetKeys(d.NewKey, slice)
131 if err != nil {
132 return err
133 }
134
135 lme := errors.LazyMultiError{Size: len(keys)}
136 i := 0
137 err = d.RawInterface.GetMulti(keys, func(pm PropertyMap, err error) {
138 if !lme.Assign(i, err) {
139 lme.Assign(i, mat.setPM(slice.Index(i), pm))
140 }
141 i++
142 })
143
144 if err == nil {
145 err = lme.Get()
146 }
147 return err
148 }
149
150 func (d *datastoreImpl) PutMulti(src interface{}) error {
151 slice := reflect.ValueOf(src)
152 mat := parseMultiArg(slice.Type())
153 if !mat.valid {
154 return fmt.Errorf("invalid PutMulti input type: %T", src)
155 }
156
157 keys, err := mat.GetKeys(d.NewKey, slice)
158 if err != nil {
159 return err
160 }
161
162 vals, err := mat.GetPMs(slice)
163 if err != nil {
164 return err
165 }
166
167 lme := errors.LazyMultiError{Size: len(keys)}
168 i := 0
169 err = d.RawInterface.PutMulti(keys, vals, func(key Key, err error) {
170 if key != keys[i] {
171 mat.setKey(slice.Index(i), key)
172 }
173 lme.Assign(i, err)
174 i++
175 })
176
177 if err == nil {
178 err = lme.Get()
179 }
180 return err
181 }
182
183 func (d *datastoreImpl) DeleteMulti(keys []Key) (err error) {
184 lme := errors.LazyMultiError{Size: len(keys)}
185 i := 0
186 extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) {
187 lme.Assign(i, internalErr)
188 i++
189 })
190 err = lme.Get()
191 if err == nil {
192 err = extErr
193 }
194 return
195 }
196
197 func (d *datastoreImpl) Raw() RawInterface {
198 return d.RawInterface
199 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698