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