OLD | NEW |
| (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 gae | |
6 | |
7 import ( | |
8 "fmt" | |
9 | |
10 "golang.org/x/net/context" | |
11 ) | |
12 | |
13 /// Kinds + Keys | |
14 | |
15 // DSKey is the equivalent of *datastore.Key from the original SDK, except that | |
16 // it can have multiple implementations. See helper.DSKey* methods for missing | |
17 // methods like DSKeyIncomplete (and some new ones like DSKeyValid). | |
18 type DSKey interface { | |
19 Kind() string | |
20 StringID() string | |
21 IntID() int64 | |
22 Parent() DSKey | |
23 AppID() string | |
24 Namespace() string | |
25 | |
26 String() string | |
27 } | |
28 | |
29 // DSKeyTok is a single token from a multi-part DSKey. | |
30 type DSKeyTok struct { | |
31 Kind string | |
32 IntID int64 | |
33 StringID string | |
34 } | |
35 | |
36 // DSCursor wraps datastore.Cursor. | |
37 type DSCursor interface { | |
38 fmt.Stringer | |
39 } | |
40 | |
41 // DSQuery wraps datastore.Query. | |
42 type DSQuery interface { | |
43 Ancestor(ancestor DSKey) DSQuery | |
44 Distinct() DSQuery | |
45 End(c DSCursor) DSQuery | |
46 EventualConsistency() DSQuery | |
47 Filter(filterStr string, value interface{}) DSQuery | |
48 KeysOnly() DSQuery | |
49 Limit(limit int) DSQuery | |
50 Offset(offset int) DSQuery | |
51 Order(fieldName string) DSQuery | |
52 Project(fieldNames ...string) DSQuery | |
53 Start(c DSCursor) DSQuery | |
54 } | |
55 | |
56 // CommonDatastore is the interface for the methods which are common between | |
57 // helper.Datastore and RawDatastore. | |
58 type CommonDatastore interface { | |
59 NewKey(kind, stringID string, intID int64, parent DSKey) DSKey | |
60 DecodeKey(encoded string) (DSKey, error) | |
61 | |
62 NewQuery(kind string) DSQuery | |
63 Count(q DSQuery) (int, error) | |
64 | |
65 RunInTransaction(f func(c context.Context) error, opts *DSTransactionOpt
ions) error | |
66 } | |
67 | |
68 // RDSIterator wraps datastore.Iterator. | |
69 type RDSIterator interface { | |
70 Cursor() (DSCursor, error) | |
71 Next(dst DSPropertyLoadSaver) (DSKey, error) | |
72 } | |
73 | |
74 // RawDatastore implements the datastore functionality without any of the fancy | |
75 // reflection stuff. This is so that Filters can avoid doing lots of redundant | |
76 // reflection work. See helper.Datastore for a more user-friendly interface. | |
77 type RawDatastore interface { | |
78 CommonDatastore | |
79 | |
80 Run(q DSQuery) RDSIterator | |
81 GetAll(q DSQuery, dst *[]DSPropertyMap) ([]DSKey, error) | |
82 | |
83 Put(key DSKey, src DSPropertyLoadSaver) (DSKey, error) | |
84 Get(key DSKey, dst DSPropertyLoadSaver) error | |
85 Delete(key DSKey) error | |
86 | |
87 // These allow you to read and write a multiple datastore objects in | |
88 // a non-atomic batch. | |
89 DeleteMulti(keys []DSKey) error | |
90 GetMulti(keys []DSKey, dst []DSPropertyLoadSaver) error | |
91 PutMulti(keys []DSKey, src []DSPropertyLoadSaver) ([]DSKey, error) | |
92 } | |
93 | |
94 // RDSFactory is the function signature for factory methods compatible with | |
95 // SetRDSFactory. | |
96 type RDSFactory func(context.Context) RawDatastore | |
97 | |
98 // RDSFilter is the function signature for a filter RDS implementation. It | |
99 // gets the current RDS implementation, and returns a new RDS implementation | |
100 // backed by the one passed in. | |
101 type RDSFilter func(context.Context, RawDatastore) RawDatastore | |
102 | |
103 // GetRDSUnfiltered gets gets the RawDatastore implementation from context witho
ut | |
104 // any of the filters applied. | |
105 func GetRDSUnfiltered(c context.Context) RawDatastore { | |
106 if f, ok := c.Value(rawDatastoreKey).(RDSFactory); ok && f != nil { | |
107 return f(c) | |
108 } | |
109 return nil | |
110 } | |
111 | |
112 // GetRDS gets the RawDatastore implementation from context. | |
113 func GetRDS(c context.Context) RawDatastore { | |
114 ret := GetRDSUnfiltered(c) | |
115 if ret == nil { | |
116 return nil | |
117 } | |
118 for _, f := range getCurRDSFilters(c) { | |
119 ret = f(c, ret) | |
120 } | |
121 return ret | |
122 } | |
123 | |
124 // SetRDSFactory sets the function to produce Datastore instances, as returned b
y | |
125 // the GetRDS method. | |
126 func SetRDSFactory(c context.Context, rdsf RDSFactory) context.Context { | |
127 return context.WithValue(c, rawDatastoreKey, rdsf) | |
128 } | |
129 | |
130 // SetRDS sets the current Datastore object in the context. Useful for testing | |
131 // with a quick mock. This is just a shorthand SetDSFactory invocation to set | |
132 // a factory which always returns the same object. | |
133 func SetRDS(c context.Context, rds RawDatastore) context.Context { | |
134 return SetRDSFactory(c, func(context.Context) RawDatastore { return rds
}) | |
135 } | |
136 | |
137 func getCurRDSFilters(c context.Context) []RDSFilter { | |
138 curFiltsI := c.Value(rawDatastoreFilterKey) | |
139 if curFiltsI != nil { | |
140 return curFiltsI.([]RDSFilter) | |
141 } | |
142 return nil | |
143 } | |
144 | |
145 // AddRDSFilters adds RawDatastore filters to the context. | |
146 func AddRDSFilters(c context.Context, filts ...RDSFilter) context.Context { | |
147 if len(filts) == 0 { | |
148 return c | |
149 } | |
150 cur := getCurRDSFilters(c) | |
151 newFilts := make([]RDSFilter, 0, len(cur)+len(filts)) | |
152 newFilts = append(newFilts, getCurRDSFilters(c)...) | |
153 newFilts = append(newFilts, filts...) | |
154 return context.WithValue(c, rawDatastoreFilterKey, newFilts) | |
155 } | |
OLD | NEW |