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

Side by Side Diff: impl/prod/raw_datastore.go

Issue 1355783002: Refactor keys and queries in datastore service and implementation. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: Created 5 years, 3 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
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 prod 5 package prod
6 6
7 import ( 7 import (
8 ds "github.com/luci/gae/service/datastore" 8 ds "github.com/luci/gae/service/datastore"
9 "github.com/luci/gae/service/info" 9 "github.com/luci/gae/service/info"
10 "golang.org/x/net/context" 10 "golang.org/x/net/context"
11 "google.golang.org/appengine" 11 "google.golang.org/appengine"
12 "google.golang.org/appengine/datastore" 12 "google.golang.org/appengine/datastore"
13 ) 13 )
14 14
15 // useRDS adds a gae.RawDatastore implementation to context, accessible 15 // useRDS adds a gae.RawDatastore implementation to context, accessible
16 // by gae.GetDS(c) 16 // by gae.GetDS(c)
17 func useRDS(c context.Context) context.Context { 17 func useRDS(c context.Context) context.Context {
18 return ds.SetRawFactory(c, func(ci context.Context) ds.RawInterface { 18 return ds.SetRawFactory(c, func(ci context.Context) ds.RawInterface {
19 return rdsImpl{ci, info.Get(ci).GetNamespace()} 19 return rdsImpl{ci, info.Get(ci).GetNamespace()}
20 }) 20 })
21 } 21 }
22 22
23 ////////// Query
24
25 type queryImpl struct{ *datastore.Query }
26
27 func (q queryImpl) Distinct() ds.Query {
28 return queryImpl{q.Query.Distinct()}
29 }
30 func (q queryImpl) End(c ds.Cursor) ds.Query {
31 return queryImpl{q.Query.End(c.(datastore.Cursor))}
32 }
33 func (q queryImpl) EventualConsistency() ds.Query {
34 return queryImpl{q.Query.EventualConsistency()}
35 }
36 func (q queryImpl) KeysOnly() ds.Query {
37 return queryImpl{q.Query.KeysOnly()}
38 }
39 func (q queryImpl) Limit(limit int) ds.Query {
40 return queryImpl{q.Query.Limit(limit)}
41 }
42 func (q queryImpl) Offset(offset int) ds.Query {
43 return queryImpl{q.Query.Offset(offset)}
44 }
45 func (q queryImpl) Order(fieldName string) ds.Query {
46 return queryImpl{q.Query.Order(fieldName)}
47 }
48 func (q queryImpl) Start(c ds.Cursor) ds.Query {
49 return queryImpl{q.Query.Start(c.(datastore.Cursor))}
50 }
51 func (q queryImpl) Ancestor(ancestor ds.Key) ds.Query {
52 return queryImpl{q.Query.Ancestor(dsF2R(ancestor))}
53 }
54 func (q queryImpl) Project(fieldNames ...string) ds.Query {
55 return queryImpl{q.Query.Project(fieldNames...)}
56 }
57 func (q queryImpl) Filter(filterStr string, value interface{}) ds.Query {
58 return queryImpl{q.Query.Filter(filterStr, value)}
59 }
60
61 ////////// Datastore 23 ////////// Datastore
62 24
63 type rdsImpl struct { 25 type rdsImpl struct {
64 context.Context 26 context.Context
65 27
66 ns string 28 ns string
67 } 29 }
68 30
69 func (d rdsImpl) NewKey(kind, stringID string, intID int64, parent ds.Key) ds.Ke y {
70 return dsR2F(datastore.NewKey(d, kind, stringID, intID, dsF2R(parent)))
71 }
72
73 func (rdsImpl) DecodeKey(encoded string) (ds.Key, error) {
74 k, err := datastore.DecodeKey(encoded)
75 return dsR2F(k), err
76 }
77
78 func idxCallbacker(err error, amt int, cb func(idx int, err error)) error { 31 func idxCallbacker(err error, amt int, cb func(idx int, err error)) error {
79 if err == nil { 32 if err == nil {
80 for i := 0; i < amt; i++ { 33 for i := 0; i < amt; i++ {
81 cb(i, nil) 34 cb(i, nil)
82 } 35 }
83 return nil 36 return nil
84 } 37 }
85 me, ok := err.(appengine.MultiError) 38 me, ok := err.(appengine.MultiError)
86 if ok { 39 if ok {
87 for i, err := range me { 40 for i, err := range me {
88 cb(i, err) 41 cb(i, err)
89 } 42 }
90 return nil 43 return nil
91 } 44 }
92 return err 45 return err
93 } 46 }
94 47
95 func (d rdsImpl) DeleteMulti(ks []ds.Key, cb ds.DeleteMultiCB) error { 48 func (d rdsImpl) DeleteMulti(ks []*ds.Key, cb ds.DeleteMultiCB) error {
96 » err := datastore.DeleteMulti(d, dsMF2R(ks)) 49 » keys, err := dsMF2R(d, ks)
50 » if err != nil {
51 » » return err
52 » }
53 » err = datastore.DeleteMulti(d, keys)
97 return idxCallbacker(err, len(ks), func(_ int, err error) { 54 return idxCallbacker(err, len(ks), func(_ int, err error) {
98 cb(err) 55 cb(err)
99 }) 56 })
100 } 57 }
101 58
102 func (d rdsImpl) GetMulti(keys []ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMult iCB) error { 59 func (d rdsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMul tiCB) error {
103 » rkeys := dsMF2R(keys) 60 » rkeys, err := dsMF2R(d, keys)
61 » if err != nil {
62 » » return err
63 » }
64
104 vals := make([]datastore.PropertyLoadSaver, len(keys)) 65 vals := make([]datastore.PropertyLoadSaver, len(keys))
105 for i := range keys { 66 for i := range keys {
106 » » vals[i] = &typeFilter{ds.PropertyMap{}} 67 » » vals[i] = &typeFilter{d, ds.PropertyMap{}}
107 } 68 }
108 » err := datastore.GetMulti(d, rkeys, vals) 69 » err = datastore.GetMulti(d, rkeys, vals)
109 return idxCallbacker(err, len(keys), func(idx int, err error) { 70 return idxCallbacker(err, len(keys), func(idx int, err error) {
110 cb(vals[idx].(*typeFilter).pm, err) 71 cb(vals[idx].(*typeFilter).pm, err)
111 }) 72 })
112 } 73 }
113 74
114 func (d rdsImpl) PutMulti(keys []ds.Key, vals []ds.PropertyMap, cb ds.PutMultiCB ) error { 75 func (d rdsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMultiC B) error {
115 » rkeys := dsMF2R(keys) 76 » rkeys, err := dsMF2R(d, keys)
77 » if err != nil {
78 » » return err
79 » }
80
116 rvals := make([]datastore.PropertyLoadSaver, len(vals)) 81 rvals := make([]datastore.PropertyLoadSaver, len(vals))
117 for i, val := range vals { 82 for i, val := range vals {
118 » » rvals[i] = &typeFilter{val} 83 » » rvals[i] = &typeFilter{d, val}
119 } 84 }
120 » rkeys, err := datastore.PutMulti(d, rkeys, rvals) 85 » rkeys, err = datastore.PutMulti(d, rkeys, rvals)
121 return idxCallbacker(err, len(keys), func(idx int, err error) { 86 return idxCallbacker(err, len(keys), func(idx int, err error) {
122 » » k := ds.Key(nil) 87 » » k := (*ds.Key)(nil)
dnj 2015/09/18 16:47:57 As an aside, I really hate this notation for nil-v
iannucci 2015/09/18 22:25:48 I actually really hate the other one because it's
123 if err == nil { 88 if err == nil {
124 k = dsR2F(rkeys[idx]) 89 k = dsR2F(rkeys[idx])
125 } 90 }
126 cb(k, err) 91 cb(k, err)
127 }) 92 })
128 } 93 }
129 94
130 func (d rdsImpl) NewQuery(kind string) ds.Query { 95 func (d rdsImpl) fixQuery(fq *ds.FinalizedQuery) (*datastore.Query, error) {
iannucci 2015/09/18 04:31:53 Now that we don't have the thin wrapper query thin
dnj 2015/09/18 16:47:57 Maybe call it "breakQuery" then. "lameify"? :)
131 » return queryImpl{datastore.NewQuery(kind)} 96 » ret := datastore.NewQuery(fq.Kind())
97
98 » start, end := fq.Bounds()
99 » if start != nil {
100 » » ret = ret.Start(start.(datastore.Cursor))
101 » }
102 » if end != nil {
103 » » ret = ret.End(end.(datastore.Cursor))
104 » }
105
106 » for prop, vals := range fq.EqFilters() {
107 » » if prop == "__ancestor__" {
108 » » » p, err := dsF2RProp(d, vals[0])
109 » » » if err != nil {
110 » » » » return nil, err
111 » » » }
112 » » » ret = ret.Ancestor(p.Value.(*datastore.Key))
113 » » } else {
114 » » » filt := prop + "="
115 » » » for _, v := range vals {
116 » » » » p, err := dsF2RProp(d, v)
117 » » » » if err != nil {
118 » » » » » return nil, err
119 » » » » }
120
121 » » » » ret = ret.Filter(filt, p.Value)
122 » » » }
123 » » }
124 » }
125
126 » if lnam, lop, lprop := fq.IneqFilterLow(); lnam != "" {
127 » » p, err := dsF2RProp(d, lprop)
128 » » if err != nil {
129 » » » return nil, err
130 » » }
131 » » ret = ret.Filter(lnam+" "+lop, p.Value)
132 » }
133
134 » if hnam, hop, hprop := fq.IneqFilterHigh(); hnam != "" {
135 » » p, err := dsF2RProp(d, hprop)
136 » » if err != nil {
137 » » » return nil, err
138 » » }
139 » » ret = ret.Filter(hnam+" "+hop, p.Value)
140 » }
141
142 » if fq.EventuallyConsistent() {
143 » » ret = ret.EventualConsistency()
144 » }
145
146 » if fq.KeysOnly() {
147 » » ret = ret.KeysOnly()
148 » }
149
150 » if lim, ok := fq.Limit(); ok {
151 » » ret = ret.Limit(int(lim))
152 » }
153
154 » if off, ok := fq.Offset(); ok {
155 » » ret = ret.Offset(int(off))
156 » }
157
158 » for _, o := range fq.Orders() {
159 » » ret = ret.Order(o.String())
160 » }
161
162 » ret = ret.Project(fq.Project()...)
163 » if fq.Distinct() {
164 » » ret = ret.Distinct()
165 » }
166
167 » return ret, nil
132 } 168 }
133 169
134 func (d rdsImpl) DecodeCursor(s string) (ds.Cursor, error) { 170 func (d rdsImpl) DecodeCursor(s string) (ds.Cursor, error) {
135 return datastore.DecodeCursor(s) 171 return datastore.DecodeCursor(s)
136 } 172 }
137 173
138 func (d rdsImpl) Run(q ds.Query, cb ds.RawRunCB) error { 174 func (d rdsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error {
139 tf := typeFilter{} 175 tf := typeFilter{}
140 » t := q.(queryImpl).Query.Run(d) 176 » q, err := d.fixQuery(fq)
177 » if err != nil {
178 » » return err
179 » }
180
181 » t := q.Run(d)
182
141 cfunc := func() (ds.Cursor, error) { 183 cfunc := func() (ds.Cursor, error) {
142 return t.Cursor() 184 return t.Cursor()
143 } 185 }
144 for { 186 for {
145 k, err := t.Next(&tf) 187 k, err := t.Next(&tf)
146 if err == datastore.Done { 188 if err == datastore.Done {
147 return nil 189 return nil
148 } 190 }
149 if err != nil { 191 if err != nil {
150 return err 192 return err
151 } 193 }
152 if !cb(dsR2F(k), tf.pm, cfunc) { 194 if !cb(dsR2F(k), tf.pm, cfunc) {
153 return nil 195 return nil
154 } 196 }
155 } 197 }
156 } 198 }
157 199
158 func (d rdsImpl) RunInTransaction(f func(c context.Context) error, opts *ds.Tran sactionOptions) error { 200 func (d rdsImpl) RunInTransaction(f func(c context.Context) error, opts *ds.Tran sactionOptions) error {
159 ropts := (*datastore.TransactionOptions)(opts) 201 ropts := (*datastore.TransactionOptions)(opts)
160 return datastore.RunInTransaction(d, f, ropts) 202 return datastore.RunInTransaction(d, f, ropts)
161 } 203 }
162 204
163 func (d rdsImpl) Testable() ds.Testable { 205 func (d rdsImpl) Testable() ds.Testable {
164 return nil 206 return nil
165 } 207 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698