-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathds.go
193 lines (150 loc) · 4.2 KB
/
ds.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package ds
import (
"errors"
"golang.org/x/net/context"
)
var ErrNoEntity = errors.New("no entity")
type Error []error
func (e Error) Error() string {
if len(e) == 1 {
return e[0].Error()
}
return "multiple errors"
}
type Key struct {
Namespace string
Path []struct {
Kind string
ID interface{}
}
}
func NewKey(namespace string) Key {
return Key{
Namespace: namespace,
}
}
func (k Key) Append(kind string, ID interface{}) Key {
return Key{
Namespace: k.Namespace,
Path: append(k.Path, struct {
Kind string
ID interface{}
}{
Kind: kind,
ID: ID,
}),
}
}
func (k Key) Equal(key Key) bool {
if k.Namespace != key.Namespace {
return false
}
if len(k.Path) != len(key.Path) {
return false
}
for i, p := range k.Path {
if p != key.Path[i] {
return false
}
}
return true
}
func (k Key) Copy() Key {
path := make([]struct {
Kind string
ID interface{}
}, len(k.Path))
copy(path, k.Path)
return Key{
Namespace: k.Namespace,
Path: path,
}
}
type Ds interface {
Get(context.Context, []Key, interface{}) error
Put(context.Context, []Key, interface{}) ([]Key, error)
Delete(context.Context, []Key) error
AllocateKeys(context.Context, Key, int) ([]Key, error)
Run(context.Context, Query) (Iterator, error)
RunInTransaction(context.Context, func(context.Context) error) error
}
// Iterator is used to get entities from the datastore. A new instance can be
// created by calling Run from the Datastore service.
type Iterator interface {
// Next returns the next entity and key pair from the iterator. Unlike the
// official google.golang.org/appengine/datastore.Iterator implementation,
// the returned key will be nil to signify no more iterables to return.
Next(entity interface{}) (Key, error)
}
// FilterOp is a type that describes one of the datastore filter comparators
// that can be used when querying for entites by property name and value.
type FilterOp string
const (
// EqualOp is equivalent to = on the offical App Engine API.
EqualOp FilterOp = "="
// LessThanOp is equivalent to < on the official App Engine API.
LessThanOp = "<"
// LessThanEqualOp is equivalent to <= on the official App Engine API.
LessThanEqualOp = "<="
// GreaterThanOp is equivalent to > on the official App Engine API.
GreaterThanOp = ">"
// GreaterThanEqualOp is equivalent to >= on the official App Engine API.
GreaterThanEqualOp = ">="
)
// Filter is used to describe a filter when querying entity properties.
type Filter struct {
Name string
Op FilterOp
Value interface{}
}
// OrderDir is used to describe which to return results from datastore queries.
type OrderDir string
const (
// AscDir orders entites from smallest to largest.
AscDir OrderDir = ""
// DescDir orders entities from largest to smallest.
DescDir = "-"
)
// Order is used to describe an order on an entity property when querying the
// datastore.
type Order struct {
Name string
Dir OrderDir
}
// KeyName is the special name given to the key property of an entity.
// Using this as the name in query orders or filters will apply the operation
// to the entity key, not one of its properties.
const KeyName = "__key__"
// Query is used to construct a datastore query.
type Query struct {
Root Key
KeysOnly bool
Orders []Order
Filters []Filter
}
func Get(ctx context.Context, keys []Key, entities interface{}) error {
return fromContext(ctx).Get(ctx, keys, entities)
}
func Put(ctx context.Context, keys []Key, entities interface{}) ([]Key, error) {
return fromContext(ctx).Put(ctx, keys, entities)
}
func Delete(ctx context.Context, keys []Key) error {
return fromContext(ctx).Delete(ctx, keys)
}
func AllocateKeys(ctx context.Context, parent Key, n int) ([]Key, error) {
return fromContext(ctx).AllocateKeys(ctx, parent, n)
}
func Run(ctx context.Context, q Query) (Iterator, error) {
return fromContext(ctx).Run(ctx, q)
}
func RunInTransaction(ctx context.Context,
f func(context.Context) error) error {
return fromContext(ctx).RunInTransaction(ctx, f)
}
var contextKey = "ds context key"
func NewContext(ctx context.Context, ds Ds) context.Context {
return context.WithValue(ctx, &contextKey, ds)
}
func fromContext(ctx context.Context) Ds {
return ctx.Value(&contextKey).(Ds)
}