aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/google.golang.org/appengine/datastore
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/google.golang.org/appengine/datastore')
-rw-r--r--vendor/google.golang.org/appengine/datastore/datastore.go407
-rw-r--r--vendor/google.golang.org/appengine/datastore/doc.go361
-rw-r--r--vendor/google.golang.org/appengine/datastore/key.go396
-rw-r--r--vendor/google.golang.org/appengine/datastore/load.go429
-rw-r--r--vendor/google.golang.org/appengine/datastore/metadata.go78
-rw-r--r--vendor/google.golang.org/appengine/datastore/prop.go330
-rw-r--r--vendor/google.golang.org/appengine/datastore/query.go757
-rw-r--r--vendor/google.golang.org/appengine/datastore/save.go333
-rw-r--r--vendor/google.golang.org/appengine/datastore/transaction.go96
9 files changed, 3187 insertions, 0 deletions
diff --git a/vendor/google.golang.org/appengine/datastore/datastore.go b/vendor/google.golang.org/appengine/datastore/datastore.go
new file mode 100644
index 0000000..576bc50
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/datastore.go
@@ -0,0 +1,407 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import (
8 "errors"
9 "fmt"
10 "reflect"
11
12 "github.com/golang/protobuf/proto"
13 "golang.org/x/net/context"
14
15 "google.golang.org/appengine"
16 "google.golang.org/appengine/internal"
17 pb "google.golang.org/appengine/internal/datastore"
18)
19
20var (
21 // ErrInvalidEntityType is returned when functions like Get or Next are
22 // passed a dst or src argument of invalid type.
23 ErrInvalidEntityType = errors.New("datastore: invalid entity type")
24 // ErrInvalidKey is returned when an invalid key is presented.
25 ErrInvalidKey = errors.New("datastore: invalid key")
26 // ErrNoSuchEntity is returned when no entity was found for a given key.
27 ErrNoSuchEntity = errors.New("datastore: no such entity")
28)
29
30// ErrFieldMismatch is returned when a field is to be loaded into a different
31// type than the one it was stored from, or when a field is missing or
32// unexported in the destination struct.
33// StructType is the type of the struct pointed to by the destination argument
34// passed to Get or to Iterator.Next.
35type ErrFieldMismatch struct {
36 StructType reflect.Type
37 FieldName string
38 Reason string
39}
40
41func (e *ErrFieldMismatch) Error() string {
42 return fmt.Sprintf("datastore: cannot load field %q into a %q: %s",
43 e.FieldName, e.StructType, e.Reason)
44}
45
46// protoToKey converts a Reference proto to a *Key. If the key is invalid,
47// protoToKey will return the invalid key along with ErrInvalidKey.
48func protoToKey(r *pb.Reference) (k *Key, err error) {
49 appID := r.GetApp()
50 namespace := r.GetNameSpace()
51 for _, e := range r.Path.Element {
52 k = &Key{
53 kind: e.GetType(),
54 stringID: e.GetName(),
55 intID: e.GetId(),
56 parent: k,
57 appID: appID,
58 namespace: namespace,
59 }
60 if !k.valid() {
61 return k, ErrInvalidKey
62 }
63 }
64 return
65}
66
67// keyToProto converts a *Key to a Reference proto.
68func keyToProto(defaultAppID string, k *Key) *pb.Reference {
69 appID := k.appID
70 if appID == "" {
71 appID = defaultAppID
72 }
73 n := 0
74 for i := k; i != nil; i = i.parent {
75 n++
76 }
77 e := make([]*pb.Path_Element, n)
78 for i := k; i != nil; i = i.parent {
79 n--
80 e[n] = &pb.Path_Element{
81 Type: &i.kind,
82 }
83 // At most one of {Name,Id} should be set.
84 // Neither will be set for incomplete keys.
85 if i.stringID != "" {
86 e[n].Name = &i.stringID
87 } else if i.intID != 0 {
88 e[n].Id = &i.intID
89 }
90 }
91 var namespace *string
92 if k.namespace != "" {
93 namespace = proto.String(k.namespace)
94 }
95 return &pb.Reference{
96 App: proto.String(appID),
97 NameSpace: namespace,
98 Path: &pb.Path{
99 Element: e,
100 },
101 }
102}
103
104// multiKeyToProto is a batch version of keyToProto.
105func multiKeyToProto(appID string, key []*Key) []*pb.Reference {
106 ret := make([]*pb.Reference, len(key))
107 for i, k := range key {
108 ret[i] = keyToProto(appID, k)
109 }
110 return ret
111}
112
113// multiValid is a batch version of Key.valid. It returns an error, not a
114// []bool.
115func multiValid(key []*Key) error {
116 invalid := false
117 for _, k := range key {
118 if !k.valid() {
119 invalid = true
120 break
121 }
122 }
123 if !invalid {
124 return nil
125 }
126 err := make(appengine.MultiError, len(key))
127 for i, k := range key {
128 if !k.valid() {
129 err[i] = ErrInvalidKey
130 }
131 }
132 return err
133}
134
135// It's unfortunate that the two semantically equivalent concepts pb.Reference
136// and pb.PropertyValue_ReferenceValue aren't the same type. For example, the
137// two have different protobuf field numbers.
138
139// referenceValueToKey is the same as protoToKey except the input is a
140// PropertyValue_ReferenceValue instead of a Reference.
141func referenceValueToKey(r *pb.PropertyValue_ReferenceValue) (k *Key, err error) {
142 appID := r.GetApp()
143 namespace := r.GetNameSpace()
144 for _, e := range r.Pathelement {
145 k = &Key{
146 kind: e.GetType(),
147 stringID: e.GetName(),
148 intID: e.GetId(),
149 parent: k,
150 appID: appID,
151 namespace: namespace,
152 }
153 if !k.valid() {
154 return nil, ErrInvalidKey
155 }
156 }
157 return
158}
159
160// keyToReferenceValue is the same as keyToProto except the output is a
161// PropertyValue_ReferenceValue instead of a Reference.
162func keyToReferenceValue(defaultAppID string, k *Key) *pb.PropertyValue_ReferenceValue {
163 ref := keyToProto(defaultAppID, k)
164 pe := make([]*pb.PropertyValue_ReferenceValue_PathElement, len(ref.Path.Element))
165 for i, e := range ref.Path.Element {
166 pe[i] = &pb.PropertyValue_ReferenceValue_PathElement{
167 Type: e.Type,
168 Id: e.Id,
169 Name: e.Name,
170 }
171 }
172 return &pb.PropertyValue_ReferenceValue{
173 App: ref.App,
174 NameSpace: ref.NameSpace,
175 Pathelement: pe,
176 }
177}
178
179type multiArgType int
180
181const (
182 multiArgTypeInvalid multiArgType = iota
183 multiArgTypePropertyLoadSaver
184 multiArgTypeStruct
185 multiArgTypeStructPtr
186 multiArgTypeInterface
187)
188
189// checkMultiArg checks that v has type []S, []*S, []I, or []P, for some struct
190// type S, for some interface type I, or some non-interface non-pointer type P
191// such that P or *P implements PropertyLoadSaver.
192//
193// It returns what category the slice's elements are, and the reflect.Type
194// that represents S, I or P.
195//
196// As a special case, PropertyList is an invalid type for v.
197func checkMultiArg(v reflect.Value) (m multiArgType, elemType reflect.Type) {
198 if v.Kind() != reflect.Slice {
199 return multiArgTypeInvalid, nil
200 }
201 if v.Type() == typeOfPropertyList {
202 return multiArgTypeInvalid, nil
203 }
204 elemType = v.Type().Elem()
205 if reflect.PtrTo(elemType).Implements(typeOfPropertyLoadSaver) {
206 return multiArgTypePropertyLoadSaver, elemType
207 }
208 switch elemType.Kind() {
209 case reflect.Struct:
210 return multiArgTypeStruct, elemType
211 case reflect.Interface:
212 return multiArgTypeInterface, elemType
213 case reflect.Ptr:
214 elemType = elemType.Elem()
215 if elemType.Kind() == reflect.Struct {
216 return multiArgTypeStructPtr, elemType
217 }
218 }
219 return multiArgTypeInvalid, nil
220}
221
222// Get loads the entity stored for k into dst, which must be a struct pointer
223// or implement PropertyLoadSaver. If there is no such entity for the key, Get
224// returns ErrNoSuchEntity.
225//
226// The values of dst's unmatched struct fields are not modified, and matching
227// slice-typed fields are not reset before appending to them. In particular, it
228// is recommended to pass a pointer to a zero valued struct on each Get call.
229//
230// ErrFieldMismatch is returned when a field is to be loaded into a different
231// type than the one it was stored from, or when a field is missing or
232// unexported in the destination struct. ErrFieldMismatch is only returned if
233// dst is a struct pointer.
234func Get(c context.Context, key *Key, dst interface{}) error {
235 if dst == nil { // GetMulti catches nil interface; we need to catch nil ptr here
236 return ErrInvalidEntityType
237 }
238 err := GetMulti(c, []*Key{key}, []interface{}{dst})
239 if me, ok := err.(appengine.MultiError); ok {
240 return me[0]
241 }
242 return err
243}
244
245// GetMulti is a batch version of Get.
246//
247// dst must be a []S, []*S, []I or []P, for some struct type S, some interface
248// type I, or some non-interface non-pointer type P such that P or *P
249// implements PropertyLoadSaver. If an []I, each element must be a valid dst
250// for Get: it must be a struct pointer or implement PropertyLoadSaver.
251//
252// As a special case, PropertyList is an invalid type for dst, even though a
253// PropertyList is a slice of structs. It is treated as invalid to avoid being
254// mistakenly passed when []PropertyList was intended.
255func GetMulti(c context.Context, key []*Key, dst interface{}) error {
256 v := reflect.ValueOf(dst)
257 multiArgType, _ := checkMultiArg(v)
258 if multiArgType == multiArgTypeInvalid {
259 return errors.New("datastore: dst has invalid type")
260 }
261 if len(key) != v.Len() {
262 return errors.New("datastore: key and dst slices have different length")
263 }
264 if len(key) == 0 {
265 return nil
266 }
267 if err := multiValid(key); err != nil {
268 return err
269 }
270 req := &pb.GetRequest{
271 Key: multiKeyToProto(internal.FullyQualifiedAppID(c), key),
272 }
273 res := &pb.GetResponse{}
274 if err := internal.Call(c, "datastore_v3", "Get", req, res); err != nil {
275 return err
276 }
277 if len(key) != len(res.Entity) {
278 return errors.New("datastore: internal error: server returned the wrong number of entities")
279 }
280 multiErr, any := make(appengine.MultiError, len(key)), false
281 for i, e := range res.Entity {
282 if e.Entity == nil {
283 multiErr[i] = ErrNoSuchEntity
284 } else {
285 elem := v.Index(i)
286 if multiArgType == multiArgTypePropertyLoadSaver || multiArgType == multiArgTypeStruct {
287 elem = elem.Addr()
288 }
289 if multiArgType == multiArgTypeStructPtr && elem.IsNil() {
290 elem.Set(reflect.New(elem.Type().Elem()))
291 }
292 multiErr[i] = loadEntity(elem.Interface(), e.Entity)
293 }
294 if multiErr[i] != nil {
295 any = true
296 }
297 }
298 if any {
299 return multiErr
300 }
301 return nil
302}
303
304// Put saves the entity src into the datastore with key k. src must be a struct
305// pointer or implement PropertyLoadSaver; if a struct pointer then any
306// unexported fields of that struct will be skipped. If k is an incomplete key,
307// the returned key will be a unique key generated by the datastore.
308func Put(c context.Context, key *Key, src interface{}) (*Key, error) {
309 k, err := PutMulti(c, []*Key{key}, []interface{}{src})
310 if err != nil {
311 if me, ok := err.(appengine.MultiError); ok {
312 return nil, me[0]
313 }
314 return nil, err
315 }
316 return k[0], nil
317}
318
319// PutMulti is a batch version of Put.
320//
321// src must satisfy the same conditions as the dst argument to GetMulti.
322func PutMulti(c context.Context, key []*Key, src interface{}) ([]*Key, error) {
323 v := reflect.ValueOf(src)
324 multiArgType, _ := checkMultiArg(v)
325 if multiArgType == multiArgTypeInvalid {
326 return nil, errors.New("datastore: src has invalid type")
327 }
328 if len(key) != v.Len() {
329 return nil, errors.New("datastore: key and src slices have different length")
330 }
331 if len(key) == 0 {
332 return nil, nil
333 }
334 appID := internal.FullyQualifiedAppID(c)
335 if err := multiValid(key); err != nil {
336 return nil, err
337 }
338 req := &pb.PutRequest{}
339 for i := range key {
340 elem := v.Index(i)
341 if multiArgType == multiArgTypePropertyLoadSaver || multiArgType == multiArgTypeStruct {
342 elem = elem.Addr()
343 }
344 sProto, err := saveEntity(appID, key[i], elem.Interface())
345 if err != nil {
346 return nil, err
347 }
348 req.Entity = append(req.Entity, sProto)
349 }
350 res := &pb.PutResponse{}
351 if err := internal.Call(c, "datastore_v3", "Put", req, res); err != nil {
352 return nil, err
353 }
354 if len(key) != len(res.Key) {
355 return nil, errors.New("datastore: internal error: server returned the wrong number of keys")
356 }
357 ret := make([]*Key, len(key))
358 for i := range ret {
359 var err error
360 ret[i], err = protoToKey(res.Key[i])
361 if err != nil || ret[i].Incomplete() {
362 return nil, errors.New("datastore: internal error: server returned an invalid key")
363 }
364 }
365 return ret, nil
366}
367
368// Delete deletes the entity for the given key.
369func Delete(c context.Context, key *Key) error {
370 err := DeleteMulti(c, []*Key{key})
371 if me, ok := err.(appengine.MultiError); ok {
372 return me[0]
373 }
374 return err
375}
376
377// DeleteMulti is a batch version of Delete.
378func DeleteMulti(c context.Context, key []*Key) error {
379 if len(key) == 0 {
380 return nil
381 }
382 if err := multiValid(key); err != nil {
383 return err
384 }
385 req := &pb.DeleteRequest{
386 Key: multiKeyToProto(internal.FullyQualifiedAppID(c), key),
387 }
388 res := &pb.DeleteResponse{}
389 return internal.Call(c, "datastore_v3", "Delete", req, res)
390}
391
392func namespaceMod(m proto.Message, namespace string) {
393 // pb.Query is the only type that has a name_space field.
394 // All other namespace support in datastore is in the keys.
395 switch m := m.(type) {
396 case *pb.Query:
397 if m.NameSpace == nil {
398 m.NameSpace = &namespace
399 }
400 }
401}
402
403func init() {
404 internal.NamespaceMods["datastore_v3"] = namespaceMod
405 internal.RegisterErrorCodeMap("datastore_v3", pb.Error_ErrorCode_name)
406 internal.RegisterTimeoutErrorCode("datastore_v3", int32(pb.Error_TIMEOUT))
407}
diff --git a/vendor/google.golang.org/appengine/datastore/doc.go b/vendor/google.golang.org/appengine/datastore/doc.go
new file mode 100644
index 0000000..85616cf
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/doc.go
@@ -0,0 +1,361 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5/*
6Package datastore provides a client for App Engine's datastore service.
7
8
9Basic Operations
10
11Entities are the unit of storage and are associated with a key. A key
12consists of an optional parent key, a string application ID, a string kind
13(also known as an entity type), and either a StringID or an IntID. A
14StringID is also known as an entity name or key name.
15
16It is valid to create a key with a zero StringID and a zero IntID; this is
17called an incomplete key, and does not refer to any saved entity. Putting an
18entity into the datastore under an incomplete key will cause a unique key
19to be generated for that entity, with a non-zero IntID.
20
21An entity's contents are a mapping from case-sensitive field names to values.
22Valid value types are:
23 - signed integers (int, int8, int16, int32 and int64),
24 - bool,
25 - string,
26 - float32 and float64,
27 - []byte (up to 1 megabyte in length),
28 - any type whose underlying type is one of the above predeclared types,
29 - ByteString,
30 - *Key,
31 - time.Time (stored with microsecond precision),
32 - appengine.BlobKey,
33 - appengine.GeoPoint,
34 - structs whose fields are all valid value types,
35 - slices of any of the above.
36
37Slices of structs are valid, as are structs that contain slices. However, if
38one struct contains another, then at most one of those can be repeated. This
39disqualifies recursively defined struct types: any struct T that (directly or
40indirectly) contains a []T.
41
42The Get and Put functions load and save an entity's contents. An entity's
43contents are typically represented by a struct pointer.
44
45Example code:
46
47 type Entity struct {
48 Value string
49 }
50
51 func handle(w http.ResponseWriter, r *http.Request) {
52 ctx := appengine.NewContext(r)
53
54 k := datastore.NewKey(ctx, "Entity", "stringID", 0, nil)
55 e := new(Entity)
56 if err := datastore.Get(ctx, k, e); err != nil {
57 http.Error(w, err.Error(), 500)
58 return
59 }
60
61 old := e.Value
62 e.Value = r.URL.Path
63
64 if _, err := datastore.Put(ctx, k, e); err != nil {
65 http.Error(w, err.Error(), 500)
66 return
67 }
68
69 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
70 fmt.Fprintf(w, "old=%q\nnew=%q\n", old, e.Value)
71 }
72
73GetMulti, PutMulti and DeleteMulti are batch versions of the Get, Put and
74Delete functions. They take a []*Key instead of a *Key, and may return an
75appengine.MultiError when encountering partial failure.
76
77
78Properties
79
80An entity's contents can be represented by a variety of types. These are
81typically struct pointers, but can also be any type that implements the
82PropertyLoadSaver interface. If using a struct pointer, you do not have to
83explicitly implement the PropertyLoadSaver interface; the datastore will
84automatically convert via reflection. If a struct pointer does implement that
85interface then those methods will be used in preference to the default
86behavior for struct pointers. Struct pointers are more strongly typed and are
87easier to use; PropertyLoadSavers are more flexible.
88
89The actual types passed do not have to match between Get and Put calls or even
90across different calls to datastore. It is valid to put a *PropertyList and
91get that same entity as a *myStruct, or put a *myStruct0 and get a *myStruct1.
92Conceptually, any entity is saved as a sequence of properties, and is loaded
93into the destination value on a property-by-property basis. When loading into
94a struct pointer, an entity that cannot be completely represented (such as a
95missing field) will result in an ErrFieldMismatch error but it is up to the
96caller whether this error is fatal, recoverable or ignorable.
97
98By default, for struct pointers, all properties are potentially indexed, and
99the property name is the same as the field name (and hence must start with an
100upper case letter).
101
102Fields may have a `datastore:"name,options"` tag. The tag name is the
103property name, which must be one or more valid Go identifiers joined by ".",
104but may start with a lower case letter. An empty tag name means to just use the
105field name. A "-" tag name means that the datastore will ignore that field.
106
107The only valid options are "omitempty" and "noindex".
108
109If the options include "omitempty" and the value of the field is empty, then the field will be omitted on Save.
110The empty values are false, 0, any nil interface value, and any array, slice, map, or string of length zero.
111Struct field values will never be empty.
112
113If options include "noindex" then the field will not be indexed. All fields are indexed
114by default. Strings or byte slices longer than 1500 bytes cannot be indexed;
115fields used to store long strings and byte slices must be tagged with "noindex"
116or they will cause Put operations to fail.
117
118To use multiple options together, separate them by a comma.
119The order does not matter.
120
121If the options is "" then the comma may be omitted.
122
123Example code:
124
125 // A and B are renamed to a and b.
126 // A, C and J are not indexed.
127 // D's tag is equivalent to having no tag at all (E).
128 // I is ignored entirely by the datastore.
129 // J has tag information for both the datastore and json packages.
130 type TaggedStruct struct {
131 A int `datastore:"a,noindex"`
132 B int `datastore:"b"`
133 C int `datastore:",noindex"`
134 D int `datastore:""`
135 E int
136 I int `datastore:"-"`
137 J int `datastore:",noindex" json:"j"`
138 }
139
140
141Structured Properties
142
143If the struct pointed to contains other structs, then the nested or embedded
144structs are flattened. For example, given these definitions:
145
146 type Inner1 struct {
147 W int32
148 X string
149 }
150
151 type Inner2 struct {
152 Y float64
153 }
154
155 type Inner3 struct {
156 Z bool
157 }
158
159 type Outer struct {
160 A int16
161 I []Inner1
162 J Inner2
163 Inner3
164 }
165
166then an Outer's properties would be equivalent to those of:
167
168 type OuterEquivalent struct {
169 A int16
170 IDotW []int32 `datastore:"I.W"`
171 IDotX []string `datastore:"I.X"`
172 JDotY float64 `datastore:"J.Y"`
173 Z bool
174 }
175
176If Outer's embedded Inner3 field was tagged as `datastore:"Foo"` then the
177equivalent field would instead be: FooDotZ bool `datastore:"Foo.Z"`.
178
179If an outer struct is tagged "noindex" then all of its implicit flattened
180fields are effectively "noindex".
181
182
183The PropertyLoadSaver Interface
184
185An entity's contents can also be represented by any type that implements the
186PropertyLoadSaver interface. This type may be a struct pointer, but it does
187not have to be. The datastore package will call Load when getting the entity's
188contents, and Save when putting the entity's contents.
189Possible uses include deriving non-stored fields, verifying fields, or indexing
190a field only if its value is positive.
191
192Example code:
193
194 type CustomPropsExample struct {
195 I, J int
196 // Sum is not stored, but should always be equal to I + J.
197 Sum int `datastore:"-"`
198 }
199
200 func (x *CustomPropsExample) Load(ps []datastore.Property) error {
201 // Load I and J as usual.
202 if err := datastore.LoadStruct(x, ps); err != nil {
203 return err
204 }
205 // Derive the Sum field.
206 x.Sum = x.I + x.J
207 return nil
208 }
209
210 func (x *CustomPropsExample) Save() ([]datastore.Property, error) {
211 // Validate the Sum field.
212 if x.Sum != x.I + x.J {
213 return nil, errors.New("CustomPropsExample has inconsistent sum")
214 }
215 // Save I and J as usual. The code below is equivalent to calling
216 // "return datastore.SaveStruct(x)", but is done manually for
217 // demonstration purposes.
218 return []datastore.Property{
219 {
220 Name: "I",
221 Value: int64(x.I),
222 },
223 {
224 Name: "J",
225 Value: int64(x.J),
226 },
227 }, nil
228 }
229
230The *PropertyList type implements PropertyLoadSaver, and can therefore hold an
231arbitrary entity's contents.
232
233
234Queries
235
236Queries retrieve entities based on their properties or key's ancestry. Running
237a query yields an iterator of results: either keys or (key, entity) pairs.
238Queries are re-usable and it is safe to call Query.Run from concurrent
239goroutines. Iterators are not safe for concurrent use.
240
241Queries are immutable, and are either created by calling NewQuery, or derived
242from an existing query by calling a method like Filter or Order that returns a
243new query value. A query is typically constructed by calling NewQuery followed
244by a chain of zero or more such methods. These methods are:
245 - Ancestor and Filter constrain the entities returned by running a query.
246 - Order affects the order in which they are returned.
247 - Project constrains the fields returned.
248 - Distinct de-duplicates projected entities.
249 - KeysOnly makes the iterator return only keys, not (key, entity) pairs.
250 - Start, End, Offset and Limit define which sub-sequence of matching entities
251 to return. Start and End take cursors, Offset and Limit take integers. Start
252 and Offset affect the first result, End and Limit affect the last result.
253 If both Start and Offset are set, then the offset is relative to Start.
254 If both End and Limit are set, then the earliest constraint wins. Limit is
255 relative to Start+Offset, not relative to End. As a special case, a
256 negative limit means unlimited.
257
258Example code:
259
260 type Widget struct {
261 Description string
262 Price int
263 }
264
265 func handle(w http.ResponseWriter, r *http.Request) {
266 ctx := appengine.NewContext(r)
267 q := datastore.NewQuery("Widget").
268 Filter("Price <", 1000).
269 Order("-Price")
270 b := new(bytes.Buffer)
271 for t := q.Run(ctx); ; {
272 var x Widget
273 key, err := t.Next(&x)
274 if err == datastore.Done {
275 break
276 }
277 if err != nil {
278 serveError(ctx, w, err)
279 return
280 }
281 fmt.Fprintf(b, "Key=%v\nWidget=%#v\n\n", key, x)
282 }
283 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
284 io.Copy(w, b)
285 }
286
287
288Transactions
289
290RunInTransaction runs a function in a transaction.
291
292Example code:
293
294 type Counter struct {
295 Count int
296 }
297
298 func inc(ctx context.Context, key *datastore.Key) (int, error) {
299 var x Counter
300 if err := datastore.Get(ctx, key, &x); err != nil && err != datastore.ErrNoSuchEntity {
301 return 0, err
302 }
303 x.Count++
304 if _, err := datastore.Put(ctx, key, &x); err != nil {
305 return 0, err
306 }
307 return x.Count, nil
308 }
309
310 func handle(w http.ResponseWriter, r *http.Request) {
311 ctx := appengine.NewContext(r)
312 var count int
313 err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
314 var err1 error
315 count, err1 = inc(ctx, datastore.NewKey(ctx, "Counter", "singleton", 0, nil))
316 return err1
317 }, nil)
318 if err != nil {
319 serveError(ctx, w, err)
320 return
321 }
322 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
323 fmt.Fprintf(w, "Count=%d", count)
324 }
325
326
327Metadata
328
329The datastore package provides access to some of App Engine's datastore
330metadata. This metadata includes information about the entity groups,
331namespaces, entity kinds, and properties in the datastore, as well as the
332property representations for each property.
333
334Example code:
335
336 func handle(w http.ResponseWriter, r *http.Request) {
337 // Print all the kinds in the datastore, with all the indexed
338 // properties (and their representations) for each.
339 ctx := appengine.NewContext(r)
340
341 kinds, err := datastore.Kinds(ctx)
342 if err != nil {
343 serveError(ctx, w, err)
344 return
345 }
346
347 w.Header().Set("Content-Type", "text/plain; charset=utf-8")
348 for _, kind := range kinds {
349 fmt.Fprintf(w, "%s:\n", kind)
350 props, err := datastore.KindProperties(ctx, kind)
351 if err != nil {
352 fmt.Fprintln(w, "\t(unable to retrieve properties)")
353 continue
354 }
355 for p, rep := range props {
356 fmt.Fprintf(w, "\t-%s (%s)\n", p, strings.Join(rep, ", "))
357 }
358 }
359 }
360*/
361package datastore // import "google.golang.org/appengine/datastore"
diff --git a/vendor/google.golang.org/appengine/datastore/key.go b/vendor/google.golang.org/appengine/datastore/key.go
new file mode 100644
index 0000000..6ab83ea
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/key.go
@@ -0,0 +1,396 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import (
8 "bytes"
9 "encoding/base64"
10 "encoding/gob"
11 "errors"
12 "fmt"
13 "strconv"
14 "strings"
15
16 "github.com/golang/protobuf/proto"
17 "golang.org/x/net/context"
18
19 "google.golang.org/appengine/internal"
20 pb "google.golang.org/appengine/internal/datastore"
21)
22
23type KeyRangeCollisionError struct {
24 start int64
25 end int64
26}
27
28func (e *KeyRangeCollisionError) Error() string {
29 return fmt.Sprintf("datastore: Collision when attempting to allocate range [%d, %d]",
30 e.start, e.end)
31}
32
33type KeyRangeContentionError struct {
34 start int64
35 end int64
36}
37
38func (e *KeyRangeContentionError) Error() string {
39 return fmt.Sprintf("datastore: Contention when attempting to allocate range [%d, %d]",
40 e.start, e.end)
41}
42
43// Key represents the datastore key for a stored entity, and is immutable.
44type Key struct {
45 kind string
46 stringID string
47 intID int64
48 parent *Key
49 appID string
50 namespace string
51}
52
53// Kind returns the key's kind (also known as entity type).
54func (k *Key) Kind() string {
55 return k.kind
56}
57
58// StringID returns the key's string ID (also known as an entity name or key
59// name), which may be "".
60func (k *Key) StringID() string {
61 return k.stringID
62}
63
64// IntID returns the key's integer ID, which may be 0.
65func (k *Key) IntID() int64 {
66 return k.intID
67}
68
69// Parent returns the key's parent key, which may be nil.
70func (k *Key) Parent() *Key {
71 return k.parent
72}
73
74// AppID returns the key's application ID.
75func (k *Key) AppID() string {
76 return k.appID
77}
78
79// Namespace returns the key's namespace.
80func (k *Key) Namespace() string {
81 return k.namespace
82}
83
84// Incomplete returns whether the key does not refer to a stored entity.
85// In particular, whether the key has a zero StringID and a zero IntID.
86func (k *Key) Incomplete() bool {
87 return k.stringID == "" && k.intID == 0
88}
89
90// valid returns whether the key is valid.
91func (k *Key) valid() bool {
92 if k == nil {
93 return false
94 }
95 for ; k != nil; k = k.parent {
96 if k.kind == "" || k.appID == "" {
97 return false
98 }
99 if k.stringID != "" && k.intID != 0 {
100 return false
101 }
102 if k.parent != nil {
103 if k.parent.Incomplete() {
104 return false
105 }
106 if k.parent.appID != k.appID || k.parent.namespace != k.namespace {
107 return false
108 }
109 }
110 }
111 return true
112}
113
114// Equal returns whether two keys are equal.
115func (k *Key) Equal(o *Key) bool {
116 for k != nil && o != nil {
117 if k.kind != o.kind || k.stringID != o.stringID || k.intID != o.intID || k.appID != o.appID || k.namespace != o.namespace {
118 return false
119 }
120 k, o = k.parent, o.parent
121 }
122 return k == o
123}
124
125// root returns the furthest ancestor of a key, which may be itself.
126func (k *Key) root() *Key {
127 for k.parent != nil {
128 k = k.parent
129 }
130 return k
131}
132
133// marshal marshals the key's string representation to the buffer.
134func (k *Key) marshal(b *bytes.Buffer) {
135 if k.parent != nil {
136 k.parent.marshal(b)
137 }
138 b.WriteByte('/')
139 b.WriteString(k.kind)
140 b.WriteByte(',')
141 if k.stringID != "" {
142 b.WriteString(k.stringID)
143 } else {
144 b.WriteString(strconv.FormatInt(k.intID, 10))
145 }
146}
147
148// String returns a string representation of the key.
149func (k *Key) String() string {
150 if k == nil {
151 return ""
152 }
153 b := bytes.NewBuffer(make([]byte, 0, 512))
154 k.marshal(b)
155 return b.String()
156}
157
158type gobKey struct {
159 Kind string
160 StringID string
161 IntID int64
162 Parent *gobKey
163 AppID string
164 Namespace string
165}
166
167func keyToGobKey(k *Key) *gobKey {
168 if k == nil {
169 return nil
170 }
171 return &gobKey{
172 Kind: k.kind,
173 StringID: k.stringID,
174 IntID: k.intID,
175 Parent: keyToGobKey(k.parent),
176 AppID: k.appID,
177 Namespace: k.namespace,
178 }
179}
180
181func gobKeyToKey(gk *gobKey) *Key {
182 if gk == nil {
183 return nil
184 }
185 return &Key{
186 kind: gk.Kind,
187 stringID: gk.StringID,
188 intID: gk.IntID,
189 parent: gobKeyToKey(gk.Parent),
190 appID: gk.AppID,
191 namespace: gk.Namespace,
192 }
193}
194
195func (k *Key) GobEncode() ([]byte, error) {
196 buf := new(bytes.Buffer)
197 if err := gob.NewEncoder(buf).Encode(keyToGobKey(k)); err != nil {
198 return nil, err
199 }
200 return buf.Bytes(), nil
201}
202
203func (k *Key) GobDecode(buf []byte) error {
204 gk := new(gobKey)
205 if err := gob.NewDecoder(bytes.NewBuffer(buf)).Decode(gk); err != nil {
206 return err
207 }
208 *k = *gobKeyToKey(gk)
209 return nil
210}
211
212func (k *Key) MarshalJSON() ([]byte, error) {
213 return []byte(`"` + k.Encode() + `"`), nil
214}
215
216func (k *Key) UnmarshalJSON(buf []byte) error {
217 if len(buf) < 2 || buf[0] != '"' || buf[len(buf)-1] != '"' {
218 return errors.New("datastore: bad JSON key")
219 }
220 k2, err := DecodeKey(string(buf[1 : len(buf)-1]))
221 if err != nil {
222 return err
223 }
224 *k = *k2
225 return nil
226}
227
228// Encode returns an opaque representation of the key
229// suitable for use in HTML and URLs.
230// This is compatible with the Python and Java runtimes.
231func (k *Key) Encode() string {
232 ref := keyToProto("", k)
233
234 b, err := proto.Marshal(ref)
235 if err != nil {
236 panic(err)
237 }
238
239 // Trailing padding is stripped.
240 return strings.TrimRight(base64.URLEncoding.EncodeToString(b), "=")
241}
242
243// DecodeKey decodes a key from the opaque representation returned by Encode.
244func DecodeKey(encoded string) (*Key, error) {
245 // Re-add padding.
246 if m := len(encoded) % 4; m != 0 {
247 encoded += strings.Repeat("=", 4-m)
248 }
249
250 b, err := base64.URLEncoding.DecodeString(encoded)
251 if err != nil {
252 return nil, err
253 }
254
255 ref := new(pb.Reference)
256 if err := proto.Unmarshal(b, ref); err != nil {
257 return nil, err
258 }
259
260 return protoToKey(ref)
261}
262
263// NewIncompleteKey creates a new incomplete key.
264// kind cannot be empty.
265func NewIncompleteKey(c context.Context, kind string, parent *Key) *Key {
266 return NewKey(c, kind, "", 0, parent)
267}
268
269// NewKey creates a new key.
270// kind cannot be empty.
271// Either one or both of stringID and intID must be zero. If both are zero,
272// the key returned is incomplete.
273// parent must either be a complete key or nil.
274func NewKey(c context.Context, kind, stringID string, intID int64, parent *Key) *Key {
275 // If there's a parent key, use its namespace.
276 // Otherwise, use any namespace attached to the context.
277 var namespace string
278 if parent != nil {
279 namespace = parent.namespace
280 } else {
281 namespace = internal.NamespaceFromContext(c)
282 }
283
284 return &Key{
285 kind: kind,
286 stringID: stringID,
287 intID: intID,
288 parent: parent,
289 appID: internal.FullyQualifiedAppID(c),
290 namespace: namespace,
291 }
292}
293
294// AllocateIDs returns a range of n integer IDs with the given kind and parent
295// combination. kind cannot be empty; parent may be nil. The IDs in the range
296// returned will not be used by the datastore's automatic ID sequence generator
297// and may be used with NewKey without conflict.
298//
299// The range is inclusive at the low end and exclusive at the high end. In
300// other words, valid intIDs x satisfy low <= x && x < high.
301//
302// If no error is returned, low + n == high.
303func AllocateIDs(c context.Context, kind string, parent *Key, n int) (low, high int64, err error) {
304 if kind == "" {
305 return 0, 0, errors.New("datastore: AllocateIDs given an empty kind")
306 }
307 if n < 0 {
308 return 0, 0, fmt.Errorf("datastore: AllocateIDs given a negative count: %d", n)
309 }
310 if n == 0 {
311 return 0, 0, nil
312 }
313 req := &pb.AllocateIdsRequest{
314 ModelKey: keyToProto("", NewIncompleteKey(c, kind, parent)),
315 Size: proto.Int64(int64(n)),
316 }
317 res := &pb.AllocateIdsResponse{}
318 if err := internal.Call(c, "datastore_v3", "AllocateIds", req, res); err != nil {
319 return 0, 0, err
320 }
321 // The protobuf is inclusive at both ends. Idiomatic Go (e.g. slices, for loops)
322 // is inclusive at the low end and exclusive at the high end, so we add 1.
323 low = res.GetStart()
324 high = res.GetEnd() + 1
325 if low+int64(n) != high {
326 return 0, 0, fmt.Errorf("datastore: internal error: could not allocate %d IDs", n)
327 }
328 return low, high, nil
329}
330
331// AllocateIDRange allocates a range of IDs with specific endpoints.
332// The range is inclusive at both the low and high end. Once these IDs have been
333// allocated, you can manually assign them to newly created entities.
334//
335// The Datastore's automatic ID allocator never assigns a key that has already
336// been allocated (either through automatic ID allocation or through an explicit
337// AllocateIDs call). As a result, entities written to the given key range will
338// never be overwritten. However, writing entities with manually assigned keys in
339// this range may overwrite existing entities (or new entities written by a separate
340// request), depending on the error returned.
341//
342// Use this only if you have an existing numeric ID range that you want to reserve
343// (for example, bulk loading entities that already have IDs). If you don't care
344// about which IDs you receive, use AllocateIDs instead.
345//
346// AllocateIDRange returns nil if the range is successfully allocated. If one or more
347// entities with an ID in the given range already exist, it returns a KeyRangeCollisionError.
348// If the Datastore has already cached IDs in this range (e.g. from a previous call to
349// AllocateIDRange), it returns a KeyRangeContentionError. Errors of other types indicate
350// problems with arguments or an error returned directly from the Datastore.
351func AllocateIDRange(c context.Context, kind string, parent *Key, start, end int64) (err error) {
352 if kind == "" {
353 return errors.New("datastore: AllocateIDRange given an empty kind")
354 }
355
356 if start < 1 || end < 1 {
357 return errors.New("datastore: AllocateIDRange start and end must both be greater than 0")
358 }
359
360 if start > end {
361 return errors.New("datastore: AllocateIDRange start must be before end")
362 }
363
364 req := &pb.AllocateIdsRequest{
365 ModelKey: keyToProto("", NewIncompleteKey(c, kind, parent)),
366 Max: proto.Int64(end),
367 }
368 res := &pb.AllocateIdsResponse{}
369 if err := internal.Call(c, "datastore_v3", "AllocateIds", req, res); err != nil {
370 return err
371 }
372
373 // Check for collisions, i.e. existing entities with IDs in this range.
374 // We could do this before the allocation, but we'd still have to do it
375 // afterward as well to catch the race condition where an entity is inserted
376 // after that initial check but before the allocation. Skip the up-front check
377 // and just do it once.
378 q := NewQuery(kind).Filter("__key__ >=", NewKey(c, kind, "", start, parent)).
379 Filter("__key__ <=", NewKey(c, kind, "", end, parent)).KeysOnly().Limit(1)
380
381 keys, err := q.GetAll(c, nil)
382 if err != nil {
383 return err
384 }
385 if len(keys) != 0 {
386 return &KeyRangeCollisionError{start: start, end: end}
387 }
388
389 // Check for a race condition, i.e. cases where the datastore may have
390 // cached ID batches that contain IDs in this range.
391 if start < res.GetStart() {
392 return &KeyRangeContentionError{start: start, end: end}
393 }
394
395 return nil
396}
diff --git a/vendor/google.golang.org/appengine/datastore/load.go b/vendor/google.golang.org/appengine/datastore/load.go
new file mode 100644
index 0000000..38a6365
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/load.go
@@ -0,0 +1,429 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import (
8 "fmt"
9 "reflect"
10 "strings"
11 "time"
12
13 "github.com/golang/protobuf/proto"
14 "google.golang.org/appengine"
15 pb "google.golang.org/appengine/internal/datastore"
16)
17
18var (
19 typeOfBlobKey = reflect.TypeOf(appengine.BlobKey(""))
20 typeOfByteSlice = reflect.TypeOf([]byte(nil))
21 typeOfByteString = reflect.TypeOf(ByteString(nil))
22 typeOfGeoPoint = reflect.TypeOf(appengine.GeoPoint{})
23 typeOfTime = reflect.TypeOf(time.Time{})
24 typeOfKeyPtr = reflect.TypeOf(&Key{})
25 typeOfEntityPtr = reflect.TypeOf(&Entity{})
26)
27
28// typeMismatchReason returns a string explaining why the property p could not
29// be stored in an entity field of type v.Type().
30func typeMismatchReason(pValue interface{}, v reflect.Value) string {
31 entityType := "empty"
32 switch pValue.(type) {
33 case int64:
34 entityType = "int"
35 case bool:
36 entityType = "bool"
37 case string:
38 entityType = "string"
39 case float64:
40 entityType = "float"
41 case *Key:
42 entityType = "*datastore.Key"
43 case time.Time:
44 entityType = "time.Time"
45 case appengine.BlobKey:
46 entityType = "appengine.BlobKey"
47 case appengine.GeoPoint:
48 entityType = "appengine.GeoPoint"
49 case ByteString:
50 entityType = "datastore.ByteString"
51 case []byte:
52 entityType = "[]byte"
53 }
54 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type())
55}
56
57type propertyLoader struct {
58 // m holds the number of times a substruct field like "Foo.Bar.Baz" has
59 // been seen so far. The map is constructed lazily.
60 m map[string]int
61}
62
63func (l *propertyLoader) load(codec *structCodec, structValue reflect.Value, p Property, requireSlice bool) string {
64 var v reflect.Value
65 var sliceIndex int
66
67 name := p.Name
68
69 // If name ends with a '.', the last field is anonymous.
70 // In this case, strings.Split will give us "" as the
71 // last element of our fields slice, which will match the ""
72 // field name in the substruct codec.
73 fields := strings.Split(name, ".")
74
75 for len(fields) > 0 {
76 var decoder fieldCodec
77 var ok bool
78
79 // Cut off the last field (delimited by ".") and find its parent
80 // in the codec.
81 // eg. for name "A.B.C.D", split off "A.B.C" and try to
82 // find a field in the codec with this name.
83 // Loop again with "A.B", etc.
84 for i := len(fields); i > 0; i-- {
85 parent := strings.Join(fields[:i], ".")
86 decoder, ok = codec.fields[parent]
87 if ok {
88 fields = fields[i:]
89 break
90 }
91 }
92
93 // If we never found a matching field in the codec, return
94 // error message.
95 if !ok {
96 return "no such struct field"
97 }
98
99 v = initField(structValue, decoder.path)
100 if !v.IsValid() {
101 return "no such struct field"
102 }
103 if !v.CanSet() {
104 return "cannot set struct field"
105 }
106
107 if decoder.structCodec != nil {
108 codec = decoder.structCodec
109 structValue = v
110 }
111
112 if v.Kind() == reflect.Slice && v.Type() != typeOfByteSlice {
113 if l.m == nil {
114 l.m = make(map[string]int)
115 }
116 sliceIndex = l.m[p.Name]
117 l.m[p.Name] = sliceIndex + 1
118 for v.Len() <= sliceIndex {
119 v.Set(reflect.Append(v, reflect.New(v.Type().Elem()).Elem()))
120 }
121 structValue = v.Index(sliceIndex)
122 requireSlice = false
123 }
124 }
125
126 var slice reflect.Value
127 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
128 slice = v
129 v = reflect.New(v.Type().Elem()).Elem()
130 } else if requireSlice {
131 return "multiple-valued property requires a slice field type"
132 }
133
134 // Convert indexValues to a Go value with a meaning derived from the
135 // destination type.
136 pValue := p.Value
137 if iv, ok := pValue.(indexValue); ok {
138 meaning := pb.Property_NO_MEANING
139 switch v.Type() {
140 case typeOfBlobKey:
141 meaning = pb.Property_BLOBKEY
142 case typeOfByteSlice:
143 meaning = pb.Property_BLOB
144 case typeOfByteString:
145 meaning = pb.Property_BYTESTRING
146 case typeOfGeoPoint:
147 meaning = pb.Property_GEORSS_POINT
148 case typeOfTime:
149 meaning = pb.Property_GD_WHEN
150 case typeOfEntityPtr:
151 meaning = pb.Property_ENTITY_PROTO
152 }
153 var err error
154 pValue, err = propValue(iv.value, meaning)
155 if err != nil {
156 return err.Error()
157 }
158 }
159
160 if errReason := setVal(v, pValue); errReason != "" {
161 // Set the slice back to its zero value.
162 if slice.IsValid() {
163 slice.Set(reflect.Zero(slice.Type()))
164 }
165 return errReason
166 }
167
168 if slice.IsValid() {
169 slice.Index(sliceIndex).Set(v)
170 }
171
172 return ""
173}
174
175// setVal sets v to the value pValue.
176func setVal(v reflect.Value, pValue interface{}) string {
177 switch v.Kind() {
178 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
179 x, ok := pValue.(int64)
180 if !ok && pValue != nil {
181 return typeMismatchReason(pValue, v)
182 }
183 if v.OverflowInt(x) {
184 return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type())
185 }
186 v.SetInt(x)
187 case reflect.Bool:
188 x, ok := pValue.(bool)
189 if !ok && pValue != nil {
190 return typeMismatchReason(pValue, v)
191 }
192 v.SetBool(x)
193 case reflect.String:
194 switch x := pValue.(type) {
195 case appengine.BlobKey:
196 v.SetString(string(x))
197 case ByteString:
198 v.SetString(string(x))
199 case string:
200 v.SetString(x)
201 default:
202 if pValue != nil {
203 return typeMismatchReason(pValue, v)
204 }
205 }
206 case reflect.Float32, reflect.Float64:
207 x, ok := pValue.(float64)
208 if !ok && pValue != nil {
209 return typeMismatchReason(pValue, v)
210 }
211 if v.OverflowFloat(x) {
212 return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type())
213 }
214 v.SetFloat(x)
215 case reflect.Ptr:
216 x, ok := pValue.(*Key)
217 if !ok && pValue != nil {
218 return typeMismatchReason(pValue, v)
219 }
220 if _, ok := v.Interface().(*Key); !ok {
221 return typeMismatchReason(pValue, v)
222 }
223 v.Set(reflect.ValueOf(x))
224 case reflect.Struct:
225 switch v.Type() {
226 case typeOfTime:
227 x, ok := pValue.(time.Time)
228 if !ok && pValue != nil {
229 return typeMismatchReason(pValue, v)
230 }
231 v.Set(reflect.ValueOf(x))
232 case typeOfGeoPoint:
233 x, ok := pValue.(appengine.GeoPoint)
234 if !ok && pValue != nil {
235 return typeMismatchReason(pValue, v)
236 }
237 v.Set(reflect.ValueOf(x))
238 default:
239 ent, ok := pValue.(*Entity)
240 if !ok {
241 return typeMismatchReason(pValue, v)
242 }
243
244 // Recursively load nested struct
245 pls, err := newStructPLS(v.Addr().Interface())
246 if err != nil {
247 return err.Error()
248 }
249
250 // if ent has a Key value and our struct has a Key field,
251 // load the Entity's Key value into the Key field on the struct.
252 if ent.Key != nil && pls.codec.keyField != -1 {
253
254 pls.v.Field(pls.codec.keyField).Set(reflect.ValueOf(ent.Key))
255 }
256
257 err = pls.Load(ent.Properties)
258 if err != nil {
259 return err.Error()
260 }
261 }
262 case reflect.Slice:
263 x, ok := pValue.([]byte)
264 if !ok {
265 if y, yok := pValue.(ByteString); yok {
266 x, ok = []byte(y), true
267 }
268 }
269 if !ok && pValue != nil {
270 return typeMismatchReason(pValue, v)
271 }
272 if v.Type().Elem().Kind() != reflect.Uint8 {
273 return typeMismatchReason(pValue, v)
274 }
275 v.SetBytes(x)
276 default:
277 return typeMismatchReason(pValue, v)
278 }
279 return ""
280}
281
282// initField is similar to reflect's Value.FieldByIndex, in that it
283// returns the nested struct field corresponding to index, but it
284// initialises any nil pointers encountered when traversing the structure.
285func initField(val reflect.Value, index []int) reflect.Value {
286 for _, i := range index[:len(index)-1] {
287 val = val.Field(i)
288 if val.Kind() == reflect.Ptr {
289 if val.IsNil() {
290 val.Set(reflect.New(val.Type().Elem()))
291 }
292 val = val.Elem()
293 }
294 }
295 return val.Field(index[len(index)-1])
296}
297
298// loadEntity loads an EntityProto into PropertyLoadSaver or struct pointer.
299func loadEntity(dst interface{}, src *pb.EntityProto) (err error) {
300 ent, err := protoToEntity(src)
301 if err != nil {
302 return err
303 }
304 if e, ok := dst.(PropertyLoadSaver); ok {
305 return e.Load(ent.Properties)
306 }
307 return LoadStruct(dst, ent.Properties)
308}
309
310func (s structPLS) Load(props []Property) error {
311 var fieldName, reason string
312 var l propertyLoader
313 for _, p := range props {
314 if errStr := l.load(s.codec, s.v, p, p.Multiple); errStr != "" {
315 // We don't return early, as we try to load as many properties as possible.
316 // It is valid to load an entity into a struct that cannot fully represent it.
317 // That case returns an error, but the caller is free to ignore it.
318 fieldName, reason = p.Name, errStr
319 }
320 }
321 if reason != "" {
322 return &ErrFieldMismatch{
323 StructType: s.v.Type(),
324 FieldName: fieldName,
325 Reason: reason,
326 }
327 }
328 return nil
329}
330
331func protoToEntity(src *pb.EntityProto) (*Entity, error) {
332 props, rawProps := src.Property, src.RawProperty
333 outProps := make([]Property, 0, len(props)+len(rawProps))
334 for {
335 var (
336 x *pb.Property
337 noIndex bool
338 )
339 if len(props) > 0 {
340 x, props = props[0], props[1:]
341 } else if len(rawProps) > 0 {
342 x, rawProps = rawProps[0], rawProps[1:]
343 noIndex = true
344 } else {
345 break
346 }
347
348 var value interface{}
349 if x.Meaning != nil && *x.Meaning == pb.Property_INDEX_VALUE {
350 value = indexValue{x.Value}
351 } else {
352 var err error
353 value, err = propValue(x.Value, x.GetMeaning())
354 if err != nil {
355 return nil, err
356 }
357 }
358 outProps = append(outProps, Property{
359 Name: x.GetName(),
360 Value: value,
361 NoIndex: noIndex,
362 Multiple: x.GetMultiple(),
363 })
364 }
365
366 var key *Key
367 if src.Key != nil {
368 // Ignore any error, since nested entity values
369 // are allowed to have an invalid key.
370 key, _ = protoToKey(src.Key)
371 }
372 return &Entity{key, outProps}, nil
373}
374
375// propValue returns a Go value that combines the raw PropertyValue with a
376// meaning. For example, an Int64Value with GD_WHEN becomes a time.Time.
377func propValue(v *pb.PropertyValue, m pb.Property_Meaning) (interface{}, error) {
378 switch {
379 case v.Int64Value != nil:
380 if m == pb.Property_GD_WHEN {
381 return fromUnixMicro(*v.Int64Value), nil
382 } else {
383 return *v.Int64Value, nil
384 }
385 case v.BooleanValue != nil:
386 return *v.BooleanValue, nil
387 case v.StringValue != nil:
388 if m == pb.Property_BLOB {
389 return []byte(*v.StringValue), nil
390 } else if m == pb.Property_BLOBKEY {
391 return appengine.BlobKey(*v.StringValue), nil
392 } else if m == pb.Property_BYTESTRING {
393 return ByteString(*v.StringValue), nil
394 } else if m == pb.Property_ENTITY_PROTO {
395 var ent pb.EntityProto
396 err := proto.Unmarshal([]byte(*v.StringValue), &ent)
397 if err != nil {
398 return nil, err
399 }
400 return protoToEntity(&ent)
401 } else {
402 return *v.StringValue, nil
403 }
404 case v.DoubleValue != nil:
405 return *v.DoubleValue, nil
406 case v.Referencevalue != nil:
407 key, err := referenceValueToKey(v.Referencevalue)
408 if err != nil {
409 return nil, err
410 }
411 return key, nil
412 case v.Pointvalue != nil:
413 // NOTE: Strangely, latitude maps to X, longitude to Y.
414 return appengine.GeoPoint{Lat: v.Pointvalue.GetX(), Lng: v.Pointvalue.GetY()}, nil
415 }
416 return nil, nil
417}
418
419// indexValue is a Property value that is created when entities are loaded from
420// an index, such as from a projection query.
421//
422// Such Property values do not contain all of the metadata required to be
423// faithfully represented as a Go value, and are instead represented as an
424// opaque indexValue. Load the properties into a concrete struct type (e.g. by
425// passing a struct pointer to Iterator.Next) to reconstruct actual Go values
426// of type int, string, time.Time, etc.
427type indexValue struct {
428 value *pb.PropertyValue
429}
diff --git a/vendor/google.golang.org/appengine/datastore/metadata.go b/vendor/google.golang.org/appengine/datastore/metadata.go
new file mode 100644
index 0000000..6acacc3
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/metadata.go
@@ -0,0 +1,78 @@
1// Copyright 2016 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import "golang.org/x/net/context"
8
9// Datastore kinds for the metadata entities.
10const (
11 namespaceKind = "__namespace__"
12 kindKind = "__kind__"
13 propertyKind = "__property__"
14)
15
16// Namespaces returns all the datastore namespaces.
17func Namespaces(ctx context.Context) ([]string, error) {
18 // TODO(djd): Support range queries.
19 q := NewQuery(namespaceKind).KeysOnly()
20 keys, err := q.GetAll(ctx, nil)
21 if err != nil {
22 return nil, err
23 }
24 // The empty namespace key uses a numeric ID (==1), but luckily
25 // the string ID defaults to "" for numeric IDs anyway.
26 return keyNames(keys), nil
27}
28
29// Kinds returns the names of all the kinds in the current namespace.
30func Kinds(ctx context.Context) ([]string, error) {
31 // TODO(djd): Support range queries.
32 q := NewQuery(kindKind).KeysOnly()
33 keys, err := q.GetAll(ctx, nil)
34 if err != nil {
35 return nil, err
36 }
37 return keyNames(keys), nil
38}
39
40// keyNames returns a slice of the provided keys' names (string IDs).
41func keyNames(keys []*Key) []string {
42 n := make([]string, 0, len(keys))
43 for _, k := range keys {
44 n = append(n, k.StringID())
45 }
46 return n
47}
48
49// KindProperties returns all the indexed properties for the given kind.
50// The properties are returned as a map of property names to a slice of the
51// representation types. The representation types for the supported Go property
52// types are:
53// "INT64": signed integers and time.Time
54// "DOUBLE": float32 and float64
55// "BOOLEAN": bool
56// "STRING": string, []byte and ByteString
57// "POINT": appengine.GeoPoint
58// "REFERENCE": *Key
59// "USER": (not used in the Go runtime)
60func KindProperties(ctx context.Context, kind string) (map[string][]string, error) {
61 // TODO(djd): Support range queries.
62 kindKey := NewKey(ctx, kindKind, kind, 0, nil)
63 q := NewQuery(propertyKind).Ancestor(kindKey)
64
65 propMap := map[string][]string{}
66 props := []struct {
67 Repr []string `datastore:"property_representation"`
68 }{}
69
70 keys, err := q.GetAll(ctx, &props)
71 if err != nil {
72 return nil, err
73 }
74 for i, p := range props {
75 propMap[keys[i].StringID()] = p.Repr
76 }
77 return propMap, nil
78}
diff --git a/vendor/google.golang.org/appengine/datastore/prop.go b/vendor/google.golang.org/appengine/datastore/prop.go
new file mode 100644
index 0000000..5cb2079
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/prop.go
@@ -0,0 +1,330 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import (
8 "fmt"
9 "reflect"
10 "strings"
11 "sync"
12 "unicode"
13)
14
15// Entities with more than this many indexed properties will not be saved.
16const maxIndexedProperties = 20000
17
18// []byte fields more than 1 megabyte long will not be loaded or saved.
19const maxBlobLen = 1 << 20
20
21// Property is a name/value pair plus some metadata. A datastore entity's
22// contents are loaded and saved as a sequence of Properties. An entity can
23// have multiple Properties with the same name, provided that p.Multiple is
24// true on all of that entity's Properties with that name.
25type Property struct {
26 // Name is the property name.
27 Name string
28 // Value is the property value. The valid types are:
29 // - int64
30 // - bool
31 // - string
32 // - float64
33 // - ByteString
34 // - *Key
35 // - time.Time
36 // - appengine.BlobKey
37 // - appengine.GeoPoint
38 // - []byte (up to 1 megabyte in length)
39 // - *Entity (representing a nested struct)
40 // This set is smaller than the set of valid struct field types that the
41 // datastore can load and save. A Property Value cannot be a slice (apart
42 // from []byte); use multiple Properties instead. Also, a Value's type
43 // must be explicitly on the list above; it is not sufficient for the
44 // underlying type to be on that list. For example, a Value of "type
45 // myInt64 int64" is invalid. Smaller-width integers and floats are also
46 // invalid. Again, this is more restrictive than the set of valid struct
47 // field types.
48 //
49 // A Value will have an opaque type when loading entities from an index,
50 // such as via a projection query. Load entities into a struct instead
51 // of a PropertyLoadSaver when using a projection query.
52 //
53 // A Value may also be the nil interface value; this is equivalent to
54 // Python's None but not directly representable by a Go struct. Loading
55 // a nil-valued property into a struct will set that field to the zero
56 // value.
57 Value interface{}
58 // NoIndex is whether the datastore cannot index this property.
59 NoIndex bool
60 // Multiple is whether the entity can have multiple properties with
61 // the same name. Even if a particular instance only has one property with
62 // a certain name, Multiple should be true if a struct would best represent
63 // it as a field of type []T instead of type T.
64 Multiple bool
65}
66
67// An Entity is the value type for a nested struct.
68// This type is only used for a Property's Value.
69type Entity struct {
70 Key *Key
71 Properties []Property
72}
73
74// ByteString is a short byte slice (up to 1500 bytes) that can be indexed.
75type ByteString []byte
76
77// PropertyLoadSaver can be converted from and to a slice of Properties.
78type PropertyLoadSaver interface {
79 Load([]Property) error
80 Save() ([]Property, error)
81}
82
83// PropertyList converts a []Property to implement PropertyLoadSaver.
84type PropertyList []Property
85
86var (
87 typeOfPropertyLoadSaver = reflect.TypeOf((*PropertyLoadSaver)(nil)).Elem()
88 typeOfPropertyList = reflect.TypeOf(PropertyList(nil))
89)
90
91// Load loads all of the provided properties into l.
92// It does not first reset *l to an empty slice.
93func (l *PropertyList) Load(p []Property) error {
94 *l = append(*l, p...)
95 return nil
96}
97
98// Save saves all of l's properties as a slice or Properties.
99func (l *PropertyList) Save() ([]Property, error) {
100 return *l, nil
101}
102
103// validPropertyName returns whether name consists of one or more valid Go
104// identifiers joined by ".".
105func validPropertyName(name string) bool {
106 if name == "" {
107 return false
108 }
109 for _, s := range strings.Split(name, ".") {
110 if s == "" {
111 return false
112 }
113 first := true
114 for _, c := range s {
115 if first {
116 first = false
117 if c != '_' && !unicode.IsLetter(c) {
118 return false
119 }
120 } else {
121 if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) {
122 return false
123 }
124 }
125 }
126 }
127 return true
128}
129
130// structCodec describes how to convert a struct to and from a sequence of
131// properties.
132type structCodec struct {
133 // fields gives the field codec for the structTag with the given name.
134 fields map[string]fieldCodec
135 // hasSlice is whether a struct or any of its nested or embedded structs
136 // has a slice-typed field (other than []byte).
137 hasSlice bool
138 // keyField is the index of a *Key field with structTag __key__.
139 // This field is not relevant for the top level struct, only for
140 // nested structs.
141 keyField int
142 // complete is whether the structCodec is complete. An incomplete
143 // structCodec may be encountered when walking a recursive struct.
144 complete bool
145}
146
147// fieldCodec is a struct field's index and, if that struct field's type is
148// itself a struct, that substruct's structCodec.
149type fieldCodec struct {
150 // path is the index path to the field
151 path []int
152 noIndex bool
153 // omitEmpty indicates that the field should be omitted on save
154 // if empty.
155 omitEmpty bool
156 // structCodec is the codec fot the struct field at index 'path',
157 // or nil if the field is not a struct.
158 structCodec *structCodec
159}
160
161// structCodecs collects the structCodecs that have already been calculated.
162var (
163 structCodecsMutex sync.Mutex
164 structCodecs = make(map[reflect.Type]*structCodec)
165)
166
167// getStructCodec returns the structCodec for the given struct type.
168func getStructCodec(t reflect.Type) (*structCodec, error) {
169 structCodecsMutex.Lock()
170 defer structCodecsMutex.Unlock()
171 return getStructCodecLocked(t)
172}
173
174// getStructCodecLocked implements getStructCodec. The structCodecsMutex must
175// be held when calling this function.
176func getStructCodecLocked(t reflect.Type) (ret *structCodec, retErr error) {
177 c, ok := structCodecs[t]
178 if ok {
179 return c, nil
180 }
181 c = &structCodec{
182 fields: make(map[string]fieldCodec),
183 // We initialize keyField to -1 so that the zero-value is not
184 // misinterpreted as index 0.
185 keyField: -1,
186 }
187
188 // Add c to the structCodecs map before we are sure it is good. If t is
189 // a recursive type, it needs to find the incomplete entry for itself in
190 // the map.
191 structCodecs[t] = c
192 defer func() {
193 if retErr != nil {
194 delete(structCodecs, t)
195 }
196 }()
197
198 for i := 0; i < t.NumField(); i++ {
199 f := t.Field(i)
200 // Skip unexported fields.
201 // Note that if f is an anonymous, unexported struct field,
202 // we will promote its fields.
203 if f.PkgPath != "" && !f.Anonymous {
204 continue
205 }
206
207 tags := strings.Split(f.Tag.Get("datastore"), ",")
208 name := tags[0]
209 opts := make(map[string]bool)
210 for _, t := range tags[1:] {
211 opts[t] = true
212 }
213 switch {
214 case name == "":
215 if !f.Anonymous {
216 name = f.Name
217 }
218 case name == "-":
219 continue
220 case name == "__key__":
221 if f.Type != typeOfKeyPtr {
222 return nil, fmt.Errorf("datastore: __key__ field on struct %v is not a *datastore.Key", t)
223 }
224 c.keyField = i
225 case !validPropertyName(name):
226 return nil, fmt.Errorf("datastore: struct tag has invalid property name: %q", name)
227 }
228
229 substructType, fIsSlice := reflect.Type(nil), false
230 switch f.Type.Kind() {
231 case reflect.Struct:
232 substructType = f.Type
233 case reflect.Slice:
234 if f.Type.Elem().Kind() == reflect.Struct {
235 substructType = f.Type.Elem()
236 }
237 fIsSlice = f.Type != typeOfByteSlice
238 c.hasSlice = c.hasSlice || fIsSlice
239 }
240
241 var sub *structCodec
242 if substructType != nil && substructType != typeOfTime && substructType != typeOfGeoPoint {
243 var err error
244 sub, err = getStructCodecLocked(substructType)
245 if err != nil {
246 return nil, err
247 }
248 if !sub.complete {
249 return nil, fmt.Errorf("datastore: recursive struct: field %q", f.Name)
250 }
251 if fIsSlice && sub.hasSlice {
252 return nil, fmt.Errorf(
253 "datastore: flattening nested structs leads to a slice of slices: field %q", f.Name)
254 }
255 c.hasSlice = c.hasSlice || sub.hasSlice
256 // If f is an anonymous struct field, we promote the substruct's fields up to this level
257 // in the linked list of struct codecs.
258 if f.Anonymous {
259 for subname, subfield := range sub.fields {
260 if name != "" {
261 subname = name + "." + subname
262 }
263 if _, ok := c.fields[subname]; ok {
264 return nil, fmt.Errorf("datastore: struct tag has repeated property name: %q", subname)
265 }
266 c.fields[subname] = fieldCodec{
267 path: append([]int{i}, subfield.path...),
268 noIndex: subfield.noIndex || opts["noindex"],
269 omitEmpty: subfield.omitEmpty,
270 structCodec: subfield.structCodec,
271 }
272 }
273 continue
274 }
275 }
276
277 if _, ok := c.fields[name]; ok {
278 return nil, fmt.Errorf("datastore: struct tag has repeated property name: %q", name)
279 }
280 c.fields[name] = fieldCodec{
281 path: []int{i},
282 noIndex: opts["noindex"],
283 omitEmpty: opts["omitempty"],
284 structCodec: sub,
285 }
286 }
287 c.complete = true
288 return c, nil
289}
290
291// structPLS adapts a struct to be a PropertyLoadSaver.
292type structPLS struct {
293 v reflect.Value
294 codec *structCodec
295}
296
297// newStructPLS returns a structPLS, which implements the
298// PropertyLoadSaver interface, for the struct pointer p.
299func newStructPLS(p interface{}) (*structPLS, error) {
300 v := reflect.ValueOf(p)
301 if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
302 return nil, ErrInvalidEntityType
303 }
304 v = v.Elem()
305 codec, err := getStructCodec(v.Type())
306 if err != nil {
307 return nil, err
308 }
309 return &structPLS{v, codec}, nil
310}
311
312// LoadStruct loads the properties from p to dst.
313// dst must be a struct pointer.
314func LoadStruct(dst interface{}, p []Property) error {
315 x, err := newStructPLS(dst)
316 if err != nil {
317 return err
318 }
319 return x.Load(p)
320}
321
322// SaveStruct returns the properties from src as a slice of Properties.
323// src must be a struct pointer.
324func SaveStruct(src interface{}) ([]Property, error) {
325 x, err := newStructPLS(src)
326 if err != nil {
327 return nil, err
328 }
329 return x.Save()
330}
diff --git a/vendor/google.golang.org/appengine/datastore/query.go b/vendor/google.golang.org/appengine/datastore/query.go
new file mode 100644
index 0000000..c1ea4ad
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/query.go
@@ -0,0 +1,757 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import (
8 "encoding/base64"
9 "errors"
10 "fmt"
11 "math"
12 "reflect"
13 "strings"
14
15 "github.com/golang/protobuf/proto"
16 "golang.org/x/net/context"
17
18 "google.golang.org/appengine/internal"
19 pb "google.golang.org/appengine/internal/datastore"
20)
21
22type operator int
23
24const (
25 lessThan operator = iota
26 lessEq
27 equal
28 greaterEq
29 greaterThan
30)
31
32var operatorToProto = map[operator]*pb.Query_Filter_Operator{
33 lessThan: pb.Query_Filter_LESS_THAN.Enum(),
34 lessEq: pb.Query_Filter_LESS_THAN_OR_EQUAL.Enum(),
35 equal: pb.Query_Filter_EQUAL.Enum(),
36 greaterEq: pb.Query_Filter_GREATER_THAN_OR_EQUAL.Enum(),
37 greaterThan: pb.Query_Filter_GREATER_THAN.Enum(),
38}
39
40// filter is a conditional filter on query results.
41type filter struct {
42 FieldName string
43 Op operator
44 Value interface{}
45}
46
47type sortDirection int
48
49const (
50 ascending sortDirection = iota
51 descending
52)
53
54var sortDirectionToProto = map[sortDirection]*pb.Query_Order_Direction{
55 ascending: pb.Query_Order_ASCENDING.Enum(),
56 descending: pb.Query_Order_DESCENDING.Enum(),
57}
58
59// order is a sort order on query results.
60type order struct {
61 FieldName string
62 Direction sortDirection
63}
64
65// NewQuery creates a new Query for a specific entity kind.
66//
67// An empty kind means to return all entities, including entities created and
68// managed by other App Engine features, and is called a kindless query.
69// Kindless queries cannot include filters or sort orders on property values.
70func NewQuery(kind string) *Query {
71 return &Query{
72 kind: kind,
73 limit: -1,
74 }
75}
76
77// Query represents a datastore query.
78type Query struct {
79 kind string
80 ancestor *Key
81 filter []filter
82 order []order
83 projection []string
84
85 distinct bool
86 keysOnly bool
87 eventual bool
88 limit int32
89 offset int32
90 count int32
91 start *pb.CompiledCursor
92 end *pb.CompiledCursor
93
94 err error
95}
96
97func (q *Query) clone() *Query {
98 x := *q
99 // Copy the contents of the slice-typed fields to a new backing store.
100 if len(q.filter) > 0 {
101 x.filter = make([]filter, len(q.filter))
102 copy(x.filter, q.filter)
103 }
104 if len(q.order) > 0 {
105 x.order = make([]order, len(q.order))
106 copy(x.order, q.order)
107 }
108 return &x
109}
110
111// Ancestor returns a derivative query with an ancestor filter.
112// The ancestor should not be nil.
113func (q *Query) Ancestor(ancestor *Key) *Query {
114 q = q.clone()
115 if ancestor == nil {
116 q.err = errors.New("datastore: nil query ancestor")
117 return q
118 }
119 q.ancestor = ancestor
120 return q
121}
122
123// EventualConsistency returns a derivative query that returns eventually
124// consistent results.
125// It only has an effect on ancestor queries.
126func (q *Query) EventualConsistency() *Query {
127 q = q.clone()
128 q.eventual = true
129 return q
130}
131
132// Filter returns a derivative query with a field-based filter.
133// The filterStr argument must be a field name followed by optional space,
134// followed by an operator, one of ">", "<", ">=", "<=", or "=".
135// Fields are compared against the provided value using the operator.
136// Multiple filters are AND'ed together.
137func (q *Query) Filter(filterStr string, value interface{}) *Query {
138 q = q.clone()
139 filterStr = strings.TrimSpace(filterStr)
140 if len(filterStr) < 1 {
141 q.err = errors.New("datastore: invalid filter: " + filterStr)
142 return q
143 }
144 f := filter{
145 FieldName: strings.TrimRight(filterStr, " ><=!"),
146 Value: value,
147 }
148 switch op := strings.TrimSpace(filterStr[len(f.FieldName):]); op {
149 case "<=":
150 f.Op = lessEq
151 case ">=":
152 f.Op = greaterEq
153 case "<":
154 f.Op = lessThan
155 case ">":
156 f.Op = greaterThan
157 case "=":
158 f.Op = equal
159 default:
160 q.err = fmt.Errorf("datastore: invalid operator %q in filter %q", op, filterStr)
161 return q
162 }
163 q.filter = append(q.filter, f)
164 return q
165}
166
167// Order returns a derivative query with a field-based sort order. Orders are
168// applied in the order they are added. The default order is ascending; to sort
169// in descending order prefix the fieldName with a minus sign (-).
170func (q *Query) Order(fieldName string) *Query {
171 q = q.clone()
172 fieldName = strings.TrimSpace(fieldName)
173 o := order{
174 Direction: ascending,
175 FieldName: fieldName,
176 }
177 if strings.HasPrefix(fieldName, "-") {
178 o.Direction = descending
179 o.FieldName = strings.TrimSpace(fieldName[1:])
180 } else if strings.HasPrefix(fieldName, "+") {
181 q.err = fmt.Errorf("datastore: invalid order: %q", fieldName)
182 return q
183 }
184 if len(o.FieldName) == 0 {
185 q.err = errors.New("datastore: empty order")
186 return q
187 }
188 q.order = append(q.order, o)
189 return q
190}
191
192// Project returns a derivative query that yields only the given fields. It
193// cannot be used with KeysOnly.
194func (q *Query) Project(fieldNames ...string) *Query {
195 q = q.clone()
196 q.projection = append([]string(nil), fieldNames...)
197 return q
198}
199
200// Distinct returns a derivative query that yields de-duplicated entities with
201// respect to the set of projected fields. It is only used for projection
202// queries.
203func (q *Query) Distinct() *Query {
204 q = q.clone()
205 q.distinct = true
206 return q
207}
208
209// KeysOnly returns a derivative query that yields only keys, not keys and
210// entities. It cannot be used with projection queries.
211func (q *Query) KeysOnly() *Query {
212 q = q.clone()
213 q.keysOnly = true
214 return q
215}
216
217// Limit returns a derivative query that has a limit on the number of results
218// returned. A negative value means unlimited.
219func (q *Query) Limit(limit int) *Query {
220 q = q.clone()
221 if limit < math.MinInt32 || limit > math.MaxInt32 {
222 q.err = errors.New("datastore: query limit overflow")
223 return q
224 }
225 q.limit = int32(limit)
226 return q
227}
228
229// Offset returns a derivative query that has an offset of how many keys to
230// skip over before returning results. A negative value is invalid.
231func (q *Query) Offset(offset int) *Query {
232 q = q.clone()
233 if offset < 0 {
234 q.err = errors.New("datastore: negative query offset")
235 return q
236 }
237 if offset > math.MaxInt32 {
238 q.err = errors.New("datastore: query offset overflow")
239 return q
240 }
241 q.offset = int32(offset)
242 return q
243}
244
245// BatchSize returns a derivative query to fetch the supplied number of results
246// at once. This value should be greater than zero, and equal to or less than
247// the Limit.
248func (q *Query) BatchSize(size int) *Query {
249 q = q.clone()
250 if size <= 0 || size > math.MaxInt32 {
251 q.err = errors.New("datastore: query batch size overflow")
252 return q
253 }
254 q.count = int32(size)
255 return q
256}
257
258// Start returns a derivative query with the given start point.
259func (q *Query) Start(c Cursor) *Query {
260 q = q.clone()
261 if c.cc == nil {
262 q.err = errors.New("datastore: invalid cursor")
263 return q
264 }
265 q.start = c.cc
266 return q
267}
268
269// End returns a derivative query with the given end point.
270func (q *Query) End(c Cursor) *Query {
271 q = q.clone()
272 if c.cc == nil {
273 q.err = errors.New("datastore: invalid cursor")
274 return q
275 }
276 q.end = c.cc
277 return q
278}
279
280// toProto converts the query to a protocol buffer.
281func (q *Query) toProto(dst *pb.Query, appID string) error {
282 if len(q.projection) != 0 && q.keysOnly {
283 return errors.New("datastore: query cannot both project and be keys-only")
284 }
285 dst.Reset()
286 dst.App = proto.String(appID)
287 if q.kind != "" {
288 dst.Kind = proto.String(q.kind)
289 }
290 if q.ancestor != nil {
291 dst.Ancestor = keyToProto(appID, q.ancestor)
292 if q.eventual {
293 dst.Strong = proto.Bool(false)
294 }
295 }
296 if q.projection != nil {
297 dst.PropertyName = q.projection
298 if q.distinct {
299 dst.GroupByPropertyName = q.projection
300 }
301 }
302 if q.keysOnly {
303 dst.KeysOnly = proto.Bool(true)
304 dst.RequirePerfectPlan = proto.Bool(true)
305 }
306 for _, qf := range q.filter {
307 if qf.FieldName == "" {
308 return errors.New("datastore: empty query filter field name")
309 }
310 p, errStr := valueToProto(appID, qf.FieldName, reflect.ValueOf(qf.Value), false)
311 if errStr != "" {
312 return errors.New("datastore: bad query filter value type: " + errStr)
313 }
314 xf := &pb.Query_Filter{
315 Op: operatorToProto[qf.Op],
316 Property: []*pb.Property{p},
317 }
318 if xf.Op == nil {
319 return errors.New("datastore: unknown query filter operator")
320 }
321 dst.Filter = append(dst.Filter, xf)
322 }
323 for _, qo := range q.order {
324 if qo.FieldName == "" {
325 return errors.New("datastore: empty query order field name")
326 }
327 xo := &pb.Query_Order{
328 Property: proto.String(qo.FieldName),
329 Direction: sortDirectionToProto[qo.Direction],
330 }
331 if xo.Direction == nil {
332 return errors.New("datastore: unknown query order direction")
333 }
334 dst.Order = append(dst.Order, xo)
335 }
336 if q.limit >= 0 {
337 dst.Limit = proto.Int32(q.limit)
338 }
339 if q.offset != 0 {
340 dst.Offset = proto.Int32(q.offset)
341 }
342 if q.count != 0 {
343 dst.Count = proto.Int32(q.count)
344 }
345 dst.CompiledCursor = q.start
346 dst.EndCompiledCursor = q.end
347 dst.Compile = proto.Bool(true)
348 return nil
349}
350
351// Count returns the number of results for the query.
352//
353// The running time and number of API calls made by Count scale linearly with
354// the sum of the query's offset and limit. Unless the result count is
355// expected to be small, it is best to specify a limit; otherwise Count will
356// continue until it finishes counting or the provided context expires.
357func (q *Query) Count(c context.Context) (int, error) {
358 // Check that the query is well-formed.
359 if q.err != nil {
360 return 0, q.err
361 }
362
363 // Run a copy of the query, with keysOnly true (if we're not a projection,
364 // since the two are incompatible), and an adjusted offset. We also set the
365 // limit to zero, as we don't want any actual entity data, just the number
366 // of skipped results.
367 newQ := q.clone()
368 newQ.keysOnly = len(newQ.projection) == 0
369 newQ.limit = 0
370 if q.limit < 0 {
371 // If the original query was unlimited, set the new query's offset to maximum.
372 newQ.offset = math.MaxInt32
373 } else {
374 newQ.offset = q.offset + q.limit
375 if newQ.offset < 0 {
376 // Do the best we can, in the presence of overflow.
377 newQ.offset = math.MaxInt32
378 }
379 }
380 req := &pb.Query{}
381 if err := newQ.toProto(req, internal.FullyQualifiedAppID(c)); err != nil {
382 return 0, err
383 }
384 res := &pb.QueryResult{}
385 if err := internal.Call(c, "datastore_v3", "RunQuery", req, res); err != nil {
386 return 0, err
387 }
388
389 // n is the count we will return. For example, suppose that our original
390 // query had an offset of 4 and a limit of 2008: the count will be 2008,
391 // provided that there are at least 2012 matching entities. However, the
392 // RPCs will only skip 1000 results at a time. The RPC sequence is:
393 // call RunQuery with (offset, limit) = (2012, 0) // 2012 == newQ.offset
394 // response has (skippedResults, moreResults) = (1000, true)
395 // n += 1000 // n == 1000
396 // call Next with (offset, limit) = (1012, 0) // 1012 == newQ.offset - n
397 // response has (skippedResults, moreResults) = (1000, true)
398 // n += 1000 // n == 2000
399 // call Next with (offset, limit) = (12, 0) // 12 == newQ.offset - n
400 // response has (skippedResults, moreResults) = (12, false)
401 // n += 12 // n == 2012
402 // // exit the loop
403 // n -= 4 // n == 2008
404 var n int32
405 for {
406 // The QueryResult should have no actual entity data, just skipped results.
407 if len(res.Result) != 0 {
408 return 0, errors.New("datastore: internal error: Count request returned too much data")
409 }
410 n += res.GetSkippedResults()
411 if !res.GetMoreResults() {
412 break
413 }
414 if err := callNext(c, res, newQ.offset-n, q.count); err != nil {
415 return 0, err
416 }
417 }
418 n -= q.offset
419 if n < 0 {
420 // If the offset was greater than the number of matching entities,
421 // return 0 instead of negative.
422 n = 0
423 }
424 return int(n), nil
425}
426
427// callNext issues a datastore_v3/Next RPC to advance a cursor, such as that
428// returned by a query with more results.
429func callNext(c context.Context, res *pb.QueryResult, offset, count int32) error {
430 if res.Cursor == nil {
431 return errors.New("datastore: internal error: server did not return a cursor")
432 }
433 req := &pb.NextRequest{
434 Cursor: res.Cursor,
435 }
436 if count >= 0 {
437 req.Count = proto.Int32(count)
438 }
439 if offset != 0 {
440 req.Offset = proto.Int32(offset)
441 }
442 if res.CompiledCursor != nil {
443 req.Compile = proto.Bool(true)
444 }
445 res.Reset()
446 return internal.Call(c, "datastore_v3", "Next", req, res)
447}
448
449// GetAll runs the query in the given context and returns all keys that match
450// that query, as well as appending the values to dst.
451//
452// dst must have type *[]S or *[]*S or *[]P, for some struct type S or some non-
453// interface, non-pointer type P such that P or *P implements PropertyLoadSaver.
454//
455// As a special case, *PropertyList is an invalid type for dst, even though a
456// PropertyList is a slice of structs. It is treated as invalid to avoid being
457// mistakenly passed when *[]PropertyList was intended.
458//
459// The keys returned by GetAll will be in a 1-1 correspondence with the entities
460// added to dst.
461//
462// If q is a ``keys-only'' query, GetAll ignores dst and only returns the keys.
463//
464// The running time and number of API calls made by GetAll scale linearly with
465// the sum of the query's offset and limit. Unless the result count is
466// expected to be small, it is best to specify a limit; otherwise GetAll will
467// continue until it finishes collecting results or the provided context
468// expires.
469func (q *Query) GetAll(c context.Context, dst interface{}) ([]*Key, error) {
470 var (
471 dv reflect.Value
472 mat multiArgType
473 elemType reflect.Type
474 errFieldMismatch error
475 )
476 if !q.keysOnly {
477 dv = reflect.ValueOf(dst)
478 if dv.Kind() != reflect.Ptr || dv.IsNil() {
479 return nil, ErrInvalidEntityType
480 }
481 dv = dv.Elem()
482 mat, elemType = checkMultiArg(dv)
483 if mat == multiArgTypeInvalid || mat == multiArgTypeInterface {
484 return nil, ErrInvalidEntityType
485 }
486 }
487
488 var keys []*Key
489 for t := q.Run(c); ; {
490 k, e, err := t.next()
491 if err == Done {
492 break
493 }
494 if err != nil {
495 return keys, err
496 }
497 if !q.keysOnly {
498 ev := reflect.New(elemType)
499 if elemType.Kind() == reflect.Map {
500 // This is a special case. The zero values of a map type are
501 // not immediately useful; they have to be make'd.
502 //
503 // Funcs and channels are similar, in that a zero value is not useful,
504 // but even a freshly make'd channel isn't useful: there's no fixed
505 // channel buffer size that is always going to be large enough, and
506 // there's no goroutine to drain the other end. Theoretically, these
507 // types could be supported, for example by sniffing for a constructor
508 // method or requiring prior registration, but for now it's not a
509 // frequent enough concern to be worth it. Programmers can work around
510 // it by explicitly using Iterator.Next instead of the Query.GetAll
511 // convenience method.
512 x := reflect.MakeMap(elemType)
513 ev.Elem().Set(x)
514 }
515 if err = loadEntity(ev.Interface(), e); err != nil {
516 if _, ok := err.(*ErrFieldMismatch); ok {
517 // We continue loading entities even in the face of field mismatch errors.
518 // If we encounter any other error, that other error is returned. Otherwise,
519 // an ErrFieldMismatch is returned.
520 errFieldMismatch = err
521 } else {
522 return keys, err
523 }
524 }
525 if mat != multiArgTypeStructPtr {
526 ev = ev.Elem()
527 }
528 dv.Set(reflect.Append(dv, ev))
529 }
530 keys = append(keys, k)
531 }
532 return keys, errFieldMismatch
533}
534
535// Run runs the query in the given context.
536func (q *Query) Run(c context.Context) *Iterator {
537 if q.err != nil {
538 return &Iterator{err: q.err}
539 }
540 t := &Iterator{
541 c: c,
542 limit: q.limit,
543 count: q.count,
544 q: q,
545 prevCC: q.start,
546 }
547 var req pb.Query
548 if err := q.toProto(&req, internal.FullyQualifiedAppID(c)); err != nil {
549 t.err = err
550 return t
551 }
552 if err := internal.Call(c, "datastore_v3", "RunQuery", &req, &t.res); err != nil {
553 t.err = err
554 return t
555 }
556 offset := q.offset - t.res.GetSkippedResults()
557 var count int32
558 if t.count > 0 && (t.limit < 0 || t.count < t.limit) {
559 count = t.count
560 } else {
561 count = t.limit
562 }
563 for offset > 0 && t.res.GetMoreResults() {
564 t.prevCC = t.res.CompiledCursor
565 if err := callNext(t.c, &t.res, offset, count); err != nil {
566 t.err = err
567 break
568 }
569 skip := t.res.GetSkippedResults()
570 if skip < 0 {
571 t.err = errors.New("datastore: internal error: negative number of skipped_results")
572 break
573 }
574 offset -= skip
575 }
576 if offset < 0 {
577 t.err = errors.New("datastore: internal error: query offset was overshot")
578 }
579 return t
580}
581
582// Iterator is the result of running a query.
583type Iterator struct {
584 c context.Context
585 err error
586 // res is the result of the most recent RunQuery or Next API call.
587 res pb.QueryResult
588 // i is how many elements of res.Result we have iterated over.
589 i int
590 // limit is the limit on the number of results this iterator should return.
591 // A negative value means unlimited.
592 limit int32
593 // count is the number of results this iterator should fetch at once. This
594 // should be equal to or greater than zero.
595 count int32
596 // q is the original query which yielded this iterator.
597 q *Query
598 // prevCC is the compiled cursor that marks the end of the previous batch
599 // of results.
600 prevCC *pb.CompiledCursor
601}
602
603// Done is returned when a query iteration has completed.
604var Done = errors.New("datastore: query has no more results")
605
606// Next returns the key of the next result. When there are no more results,
607// Done is returned as the error.
608//
609// If the query is not keys only and dst is non-nil, it also loads the entity
610// stored for that key into the struct pointer or PropertyLoadSaver dst, with
611// the same semantics and possible errors as for the Get function.
612func (t *Iterator) Next(dst interface{}) (*Key, error) {
613 k, e, err := t.next()
614 if err != nil {
615 return nil, err
616 }
617 if dst != nil && !t.q.keysOnly {
618 err = loadEntity(dst, e)
619 }
620 return k, err
621}
622
623func (t *Iterator) next() (*Key, *pb.EntityProto, error) {
624 if t.err != nil {
625 return nil, nil, t.err
626 }
627
628 // Issue datastore_v3/Next RPCs as necessary.
629 for t.i == len(t.res.Result) {
630 if !t.res.GetMoreResults() {
631 t.err = Done
632 return nil, nil, t.err
633 }
634 t.prevCC = t.res.CompiledCursor
635 var count int32
636 if t.count > 0 && (t.limit < 0 || t.count < t.limit) {
637 count = t.count
638 } else {
639 count = t.limit
640 }
641 if err := callNext(t.c, &t.res, 0, count); err != nil {
642 t.err = err
643 return nil, nil, t.err
644 }
645 if t.res.GetSkippedResults() != 0 {
646 t.err = errors.New("datastore: internal error: iterator has skipped results")
647 return nil, nil, t.err
648 }
649 t.i = 0
650 if t.limit >= 0 {
651 t.limit -= int32(len(t.res.Result))
652 if t.limit < 0 {
653 t.err = errors.New("datastore: internal error: query returned more results than the limit")
654 return nil, nil, t.err
655 }
656 }
657 }
658
659 // Extract the key from the t.i'th element of t.res.Result.
660 e := t.res.Result[t.i]
661 t.i++
662 if e.Key == nil {
663 return nil, nil, errors.New("datastore: internal error: server did not return a key")
664 }
665 k, err := protoToKey(e.Key)
666 if err != nil || k.Incomplete() {
667 return nil, nil, errors.New("datastore: internal error: server returned an invalid key")
668 }
669 return k, e, nil
670}
671
672// Cursor returns a cursor for the iterator's current location.
673func (t *Iterator) Cursor() (Cursor, error) {
674 if t.err != nil && t.err != Done {
675 return Cursor{}, t.err
676 }
677 // If we are at either end of the current batch of results,
678 // return the compiled cursor at that end.
679 skipped := t.res.GetSkippedResults()
680 if t.i == 0 && skipped == 0 {
681 if t.prevCC == nil {
682 // A nil pointer (of type *pb.CompiledCursor) means no constraint:
683 // passing it as the end cursor of a new query means unlimited results
684 // (glossing over the integer limit parameter for now).
685 // A non-nil pointer to an empty pb.CompiledCursor means the start:
686 // passing it as the end cursor of a new query means 0 results.
687 // If prevCC was nil, then the original query had no start cursor, but
688 // Iterator.Cursor should return "the start" instead of unlimited.
689 return Cursor{&zeroCC}, nil
690 }
691 return Cursor{t.prevCC}, nil
692 }
693 if t.i == len(t.res.Result) {
694 return Cursor{t.res.CompiledCursor}, nil
695 }
696 // Otherwise, re-run the query offset to this iterator's position, starting from
697 // the most recent compiled cursor. This is done on a best-effort basis, as it
698 // is racy; if a concurrent process has added or removed entities, then the
699 // cursor returned may be inconsistent.
700 q := t.q.clone()
701 q.start = t.prevCC
702 q.offset = skipped + int32(t.i)
703 q.limit = 0
704 q.keysOnly = len(q.projection) == 0
705 t1 := q.Run(t.c)
706 _, _, err := t1.next()
707 if err != Done {
708 if err == nil {
709 err = fmt.Errorf("datastore: internal error: zero-limit query did not have zero results")
710 }
711 return Cursor{}, err
712 }
713 return Cursor{t1.res.CompiledCursor}, nil
714}
715
716var zeroCC pb.CompiledCursor
717
718// Cursor is an iterator's position. It can be converted to and from an opaque
719// string. A cursor can be used from different HTTP requests, but only with a
720// query with the same kind, ancestor, filter and order constraints.
721type Cursor struct {
722 cc *pb.CompiledCursor
723}
724
725// String returns a base-64 string representation of a cursor.
726func (c Cursor) String() string {
727 if c.cc == nil {
728 return ""
729 }
730 b, err := proto.Marshal(c.cc)
731 if err != nil {
732 // The only way to construct a Cursor with a non-nil cc field is to
733 // unmarshal from the byte representation. We panic if the unmarshal
734 // succeeds but the marshaling of the unchanged protobuf value fails.
735 panic(fmt.Sprintf("datastore: internal error: malformed cursor: %v", err))
736 }
737 return strings.TrimRight(base64.URLEncoding.EncodeToString(b), "=")
738}
739
740// Decode decodes a cursor from its base-64 string representation.
741func DecodeCursor(s string) (Cursor, error) {
742 if s == "" {
743 return Cursor{&zeroCC}, nil
744 }
745 if n := len(s) % 4; n != 0 {
746 s += strings.Repeat("=", 4-n)
747 }
748 b, err := base64.URLEncoding.DecodeString(s)
749 if err != nil {
750 return Cursor{}, err
751 }
752 cc := &pb.CompiledCursor{}
753 if err := proto.Unmarshal(b, cc); err != nil {
754 return Cursor{}, err
755 }
756 return Cursor{cc}, nil
757}
diff --git a/vendor/google.golang.org/appengine/datastore/save.go b/vendor/google.golang.org/appengine/datastore/save.go
new file mode 100644
index 0000000..7b045a5
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/save.go
@@ -0,0 +1,333 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import (
8 "errors"
9 "fmt"
10 "math"
11 "reflect"
12 "time"
13
14 "github.com/golang/protobuf/proto"
15
16 "google.golang.org/appengine"
17 pb "google.golang.org/appengine/internal/datastore"
18)
19
20func toUnixMicro(t time.Time) int64 {
21 // We cannot use t.UnixNano() / 1e3 because we want to handle times more than
22 // 2^63 nanoseconds (which is about 292 years) away from 1970, and those cannot
23 // be represented in the numerator of a single int64 divide.
24 return t.Unix()*1e6 + int64(t.Nanosecond()/1e3)
25}
26
27func fromUnixMicro(t int64) time.Time {
28 return time.Unix(t/1e6, (t%1e6)*1e3).UTC()
29}
30
31var (
32 minTime = time.Unix(int64(math.MinInt64)/1e6, (int64(math.MinInt64)%1e6)*1e3)
33 maxTime = time.Unix(int64(math.MaxInt64)/1e6, (int64(math.MaxInt64)%1e6)*1e3)
34)
35
36// valueToProto converts a named value to a newly allocated Property.
37// The returned error string is empty on success.
38func valueToProto(defaultAppID, name string, v reflect.Value, multiple bool) (p *pb.Property, errStr string) {
39 var (
40 pv pb.PropertyValue
41 unsupported bool
42 )
43 switch v.Kind() {
44 case reflect.Invalid:
45 // No-op.
46 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
47 pv.Int64Value = proto.Int64(v.Int())
48 case reflect.Bool:
49 pv.BooleanValue = proto.Bool(v.Bool())
50 case reflect.String:
51 pv.StringValue = proto.String(v.String())
52 case reflect.Float32, reflect.Float64:
53 pv.DoubleValue = proto.Float64(v.Float())
54 case reflect.Ptr:
55 if k, ok := v.Interface().(*Key); ok {
56 if k != nil {
57 pv.Referencevalue = keyToReferenceValue(defaultAppID, k)
58 }
59 } else {
60 unsupported = true
61 }
62 case reflect.Struct:
63 switch t := v.Interface().(type) {
64 case time.Time:
65 if t.Before(minTime) || t.After(maxTime) {
66 return nil, "time value out of range"
67 }
68 pv.Int64Value = proto.Int64(toUnixMicro(t))
69 case appengine.GeoPoint:
70 if !t.Valid() {
71 return nil, "invalid GeoPoint value"
72 }
73 // NOTE: Strangely, latitude maps to X, longitude to Y.
74 pv.Pointvalue = &pb.PropertyValue_PointValue{X: &t.Lat, Y: &t.Lng}
75 default:
76 unsupported = true
77 }
78 case reflect.Slice:
79 if b, ok := v.Interface().([]byte); ok {
80 pv.StringValue = proto.String(string(b))
81 } else {
82 // nvToProto should already catch slice values.
83 // If we get here, we have a slice of slice values.
84 unsupported = true
85 }
86 default:
87 unsupported = true
88 }
89 if unsupported {
90 return nil, "unsupported datastore value type: " + v.Type().String()
91 }
92 p = &pb.Property{
93 Name: proto.String(name),
94 Value: &pv,
95 Multiple: proto.Bool(multiple),
96 }
97 if v.IsValid() {
98 switch v.Interface().(type) {
99 case []byte:
100 p.Meaning = pb.Property_BLOB.Enum()
101 case ByteString:
102 p.Meaning = pb.Property_BYTESTRING.Enum()
103 case appengine.BlobKey:
104 p.Meaning = pb.Property_BLOBKEY.Enum()
105 case time.Time:
106 p.Meaning = pb.Property_GD_WHEN.Enum()
107 case appengine.GeoPoint:
108 p.Meaning = pb.Property_GEORSS_POINT.Enum()
109 }
110 }
111 return p, ""
112}
113
114type saveOpts struct {
115 noIndex bool
116 multiple bool
117 omitEmpty bool
118}
119
120// saveEntity saves an EntityProto into a PropertyLoadSaver or struct pointer.
121func saveEntity(defaultAppID string, key *Key, src interface{}) (*pb.EntityProto, error) {
122 var err error
123 var props []Property
124 if e, ok := src.(PropertyLoadSaver); ok {
125 props, err = e.Save()
126 } else {
127 props, err = SaveStruct(src)
128 }
129 if err != nil {
130 return nil, err
131 }
132 return propertiesToProto(defaultAppID, key, props)
133}
134
135func saveStructProperty(props *[]Property, name string, opts saveOpts, v reflect.Value) error {
136 if opts.omitEmpty && isEmptyValue(v) {
137 return nil
138 }
139 p := Property{
140 Name: name,
141 NoIndex: opts.noIndex,
142 Multiple: opts.multiple,
143 }
144 switch x := v.Interface().(type) {
145 case *Key:
146 p.Value = x
147 case time.Time:
148 p.Value = x
149 case appengine.BlobKey:
150 p.Value = x
151 case appengine.GeoPoint:
152 p.Value = x
153 case ByteString:
154 p.Value = x
155 default:
156 switch v.Kind() {
157 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
158 p.Value = v.Int()
159 case reflect.Bool:
160 p.Value = v.Bool()
161 case reflect.String:
162 p.Value = v.String()
163 case reflect.Float32, reflect.Float64:
164 p.Value = v.Float()
165 case reflect.Slice:
166 if v.Type().Elem().Kind() == reflect.Uint8 {
167 p.NoIndex = true
168 p.Value = v.Bytes()
169 }
170 case reflect.Struct:
171 if !v.CanAddr() {
172 return fmt.Errorf("datastore: unsupported struct field: value is unaddressable")
173 }
174 sub, err := newStructPLS(v.Addr().Interface())
175 if err != nil {
176 return fmt.Errorf("datastore: unsupported struct field: %v", err)
177 }
178 return sub.save(props, name+".", opts)
179 }
180 }
181 if p.Value == nil {
182 return fmt.Errorf("datastore: unsupported struct field type: %v", v.Type())
183 }
184 *props = append(*props, p)
185 return nil
186}
187
188func (s structPLS) Save() ([]Property, error) {
189 var props []Property
190 if err := s.save(&props, "", saveOpts{}); err != nil {
191 return nil, err
192 }
193 return props, nil
194}
195
196func (s structPLS) save(props *[]Property, prefix string, opts saveOpts) error {
197 for name, f := range s.codec.fields {
198 name = prefix + name
199 v := s.v.FieldByIndex(f.path)
200 if !v.IsValid() || !v.CanSet() {
201 continue
202 }
203 var opts1 saveOpts
204 opts1.noIndex = opts.noIndex || f.noIndex
205 opts1.multiple = opts.multiple
206 opts1.omitEmpty = f.omitEmpty // don't propagate
207 // For slice fields that aren't []byte, save each element.
208 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
209 opts1.multiple = true
210 for j := 0; j < v.Len(); j++ {
211 if err := saveStructProperty(props, name, opts1, v.Index(j)); err != nil {
212 return err
213 }
214 }
215 continue
216 }
217 // Otherwise, save the field itself.
218 if err := saveStructProperty(props, name, opts1, v); err != nil {
219 return err
220 }
221 }
222 return nil
223}
224
225func propertiesToProto(defaultAppID string, key *Key, props []Property) (*pb.EntityProto, error) {
226 e := &pb.EntityProto{
227 Key: keyToProto(defaultAppID, key),
228 }
229 if key.parent == nil {
230 e.EntityGroup = &pb.Path{}
231 } else {
232 e.EntityGroup = keyToProto(defaultAppID, key.root()).Path
233 }
234 prevMultiple := make(map[string]bool)
235
236 for _, p := range props {
237 if pm, ok := prevMultiple[p.Name]; ok {
238 if !pm || !p.Multiple {
239 return nil, fmt.Errorf("datastore: multiple Properties with Name %q, but Multiple is false", p.Name)
240 }
241 } else {
242 prevMultiple[p.Name] = p.Multiple
243 }
244
245 x := &pb.Property{
246 Name: proto.String(p.Name),
247 Value: new(pb.PropertyValue),
248 Multiple: proto.Bool(p.Multiple),
249 }
250 switch v := p.Value.(type) {
251 case int64:
252 x.Value.Int64Value = proto.Int64(v)
253 case bool:
254 x.Value.BooleanValue = proto.Bool(v)
255 case string:
256 x.Value.StringValue = proto.String(v)
257 if p.NoIndex {
258 x.Meaning = pb.Property_TEXT.Enum()
259 }
260 case float64:
261 x.Value.DoubleValue = proto.Float64(v)
262 case *Key:
263 if v != nil {
264 x.Value.Referencevalue = keyToReferenceValue(defaultAppID, v)
265 }
266 case time.Time:
267 if v.Before(minTime) || v.After(maxTime) {
268 return nil, fmt.Errorf("datastore: time value out of range")
269 }
270 x.Value.Int64Value = proto.Int64(toUnixMicro(v))
271 x.Meaning = pb.Property_GD_WHEN.Enum()
272 case appengine.BlobKey:
273 x.Value.StringValue = proto.String(string(v))
274 x.Meaning = pb.Property_BLOBKEY.Enum()
275 case appengine.GeoPoint:
276 if !v.Valid() {
277 return nil, fmt.Errorf("datastore: invalid GeoPoint value")
278 }
279 // NOTE: Strangely, latitude maps to X, longitude to Y.
280 x.Value.Pointvalue = &pb.PropertyValue_PointValue{X: &v.Lat, Y: &v.Lng}
281 x.Meaning = pb.Property_GEORSS_POINT.Enum()
282 case []byte:
283 x.Value.StringValue = proto.String(string(v))
284 x.Meaning = pb.Property_BLOB.Enum()
285 if !p.NoIndex {
286 return nil, fmt.Errorf("datastore: cannot index a []byte valued Property with Name %q", p.Name)
287 }
288 case ByteString:
289 x.Value.StringValue = proto.String(string(v))
290 x.Meaning = pb.Property_BYTESTRING.Enum()
291 default:
292 if p.Value != nil {
293 return nil, fmt.Errorf("datastore: invalid Value type for a Property with Name %q", p.Name)
294 }
295 }
296
297 if p.NoIndex {
298 e.RawProperty = append(e.RawProperty, x)
299 } else {
300 e.Property = append(e.Property, x)
301 if len(e.Property) > maxIndexedProperties {
302 return nil, errors.New("datastore: too many indexed properties")
303 }
304 }
305 }
306 return e, nil
307}
308
309// isEmptyValue is taken from the encoding/json package in the standard library.
310func isEmptyValue(v reflect.Value) bool {
311 switch v.Kind() {
312 case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
313 // TODO(perfomance): Only reflect.String needed, other property types are not supported (copy/paste from json package)
314 return v.Len() == 0
315 case reflect.Bool:
316 return !v.Bool()
317 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
318 return v.Int() == 0
319 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
320 // TODO(perfomance): Uint* are unsupported property types - should be removed (copy/paste from json package)
321 return v.Uint() == 0
322 case reflect.Float32, reflect.Float64:
323 return v.Float() == 0
324 case reflect.Interface, reflect.Ptr:
325 return v.IsNil()
326 case reflect.Struct:
327 switch x := v.Interface().(type) {
328 case time.Time:
329 return x.IsZero()
330 }
331 }
332 return false
333}
diff --git a/vendor/google.golang.org/appengine/datastore/transaction.go b/vendor/google.golang.org/appengine/datastore/transaction.go
new file mode 100644
index 0000000..2ae8428
--- /dev/null
+++ b/vendor/google.golang.org/appengine/datastore/transaction.go
@@ -0,0 +1,96 @@
1// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package datastore
6
7import (
8 "errors"
9
10 "golang.org/x/net/context"
11
12 "google.golang.org/appengine/internal"
13 pb "google.golang.org/appengine/internal/datastore"
14)
15
16func init() {
17 internal.RegisterTransactionSetter(func(x *pb.Query, t *pb.Transaction) {
18 x.Transaction = t
19 })
20 internal.RegisterTransactionSetter(func(x *pb.GetRequest, t *pb.Transaction) {
21 x.Transaction = t
22 })
23 internal.RegisterTransactionSetter(func(x *pb.PutRequest, t *pb.Transaction) {
24 x.Transaction = t
25 })
26 internal.RegisterTransactionSetter(func(x *pb.DeleteRequest, t *pb.Transaction) {
27 x.Transaction = t
28 })
29}
30
31// ErrConcurrentTransaction is returned when a transaction is rolled back due
32// to a conflict with a concurrent transaction.
33var ErrConcurrentTransaction = errors.New("datastore: concurrent transaction")
34
35// RunInTransaction runs f in a transaction. It calls f with a transaction
36// context tc that f should use for all App Engine operations.
37//
38// If f returns nil, RunInTransaction attempts to commit the transaction,
39// returning nil if it succeeds. If the commit fails due to a conflicting
40// transaction, RunInTransaction retries f, each time with a new transaction
41// context. It gives up and returns ErrConcurrentTransaction after three
42// failed attempts. The number of attempts can be configured by specifying
43// TransactionOptions.Attempts.
44//
45// If f returns non-nil, then any datastore changes will not be applied and
46// RunInTransaction returns that same error. The function f is not retried.
47//
48// Note that when f returns, the transaction is not yet committed. Calling code
49// must be careful not to assume that any of f's changes have been committed
50// until RunInTransaction returns nil.
51//
52// Since f may be called multiple times, f should usually be idempotent.
53// datastore.Get is not idempotent when unmarshaling slice fields.
54//
55// Nested transactions are not supported; c may not be a transaction context.
56func RunInTransaction(c context.Context, f func(tc context.Context) error, opts *TransactionOptions) error {
57 xg := false
58 if opts != nil {
59 xg = opts.XG
60 }
61 readOnly := false
62 if opts != nil {
63 readOnly = opts.ReadOnly
64 }
65 attempts := 3
66 if opts != nil && opts.Attempts > 0 {
67 attempts = opts.Attempts
68 }
69 var t *pb.Transaction
70 var err error
71 for i := 0; i < attempts; i++ {
72 if t, err = internal.RunTransactionOnce(c, f, xg, readOnly, t); err != internal.ErrConcurrentTransaction {
73 return err
74 }
75 }
76 return ErrConcurrentTransaction
77}
78
79// TransactionOptions are the options for running a transaction.
80type TransactionOptions struct {
81 // XG is whether the transaction can cross multiple entity groups. In
82 // comparison, a single group transaction is one where all datastore keys
83 // used have the same root key. Note that cross group transactions do not
84 // have the same behavior as single group transactions. In particular, it
85 // is much more likely to see partially applied transactions in different
86 // entity groups, in global queries.
87 // It is valid to set XG to true even if the transaction is within a
88 // single entity group.
89 XG bool
90 // Attempts controls the number of retries to perform when commits fail
91 // due to a conflicting transaction. If omitted, it defaults to 3.
92 Attempts int
93 // ReadOnly controls whether the transaction is a read only transaction.
94 // Read only transactions are potentially more efficient.
95 ReadOnly bool
96}