]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/google.golang.org/appengine/datastore/doc.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / google.golang.org / appengine / datastore / doc.go
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 /*
6 Package datastore provides a client for App Engine's datastore service.
7
8
9 Basic Operations
10
11 Entities are the unit of storage and are associated with a key. A key
12 consists 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
14 StringID is also known as an entity name or key name.
15
16 It is valid to create a key with a zero StringID and a zero IntID; this is
17 called an incomplete key, and does not refer to any saved entity. Putting an
18 entity into the datastore under an incomplete key will cause a unique key
19 to be generated for that entity, with a non-zero IntID.
20
21 An entity's contents are a mapping from case-sensitive field names to values.
22 Valid 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
37 Slices of structs are valid, as are structs that contain slices. However, if
38 one struct contains another, then at most one of those can be repeated. This
39 disqualifies recursively defined struct types: any struct T that (directly or
40 indirectly) contains a []T.
41
42 The Get and Put functions load and save an entity's contents. An entity's
43 contents are typically represented by a struct pointer.
44
45 Example 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
73 GetMulti, PutMulti and DeleteMulti are batch versions of the Get, Put and
74 Delete functions. They take a []*Key instead of a *Key, and may return an
75 appengine.MultiError when encountering partial failure.
76
77
78 Properties
79
80 An entity's contents can be represented by a variety of types. These are
81 typically struct pointers, but can also be any type that implements the
82 PropertyLoadSaver interface. If using a struct pointer, you do not have to
83 explicitly implement the PropertyLoadSaver interface; the datastore will
84 automatically convert via reflection. If a struct pointer does implement that
85 interface then those methods will be used in preference to the default
86 behavior for struct pointers. Struct pointers are more strongly typed and are
87 easier to use; PropertyLoadSavers are more flexible.
88
89 The actual types passed do not have to match between Get and Put calls or even
90 across different calls to datastore. It is valid to put a *PropertyList and
91 get that same entity as a *myStruct, or put a *myStruct0 and get a *myStruct1.
92 Conceptually, any entity is saved as a sequence of properties, and is loaded
93 into the destination value on a property-by-property basis. When loading into
94 a struct pointer, an entity that cannot be completely represented (such as a
95 missing field) will result in an ErrFieldMismatch error but it is up to the
96 caller whether this error is fatal, recoverable or ignorable.
97
98 By default, for struct pointers, all properties are potentially indexed, and
99 the property name is the same as the field name (and hence must start with an
100 upper case letter).
101
102 Fields may have a `datastore:"name,options"` tag. The tag name is the
103 property name, which must be one or more valid Go identifiers joined by ".",
104 but may start with a lower case letter. An empty tag name means to just use the
105 field name. A "-" tag name means that the datastore will ignore that field.
106
107 The only valid options are "omitempty" and "noindex".
108
109 If the options include "omitempty" and the value of the field is empty, then the field will be omitted on Save.
110 The empty values are false, 0, any nil interface value, and any array, slice, map, or string of length zero.
111 Struct field values will never be empty.
112
113 If options include "noindex" then the field will not be indexed. All fields are indexed
114 by default. Strings or byte slices longer than 1500 bytes cannot be indexed;
115 fields used to store long strings and byte slices must be tagged with "noindex"
116 or they will cause Put operations to fail.
117
118 To use multiple options together, separate them by a comma.
119 The order does not matter.
120
121 If the options is "" then the comma may be omitted.
122
123 Example 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
141 Structured Properties
142
143 If the struct pointed to contains other structs, then the nested or embedded
144 structs 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
166 then 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
176 If Outer's embedded Inner3 field was tagged as `datastore:"Foo"` then the
177 equivalent field would instead be: FooDotZ bool `datastore:"Foo.Z"`.
178
179 If an outer struct is tagged "noindex" then all of its implicit flattened
180 fields are effectively "noindex".
181
182
183 The PropertyLoadSaver Interface
184
185 An entity's contents can also be represented by any type that implements the
186 PropertyLoadSaver interface. This type may be a struct pointer, but it does
187 not have to be. The datastore package will call Load when getting the entity's
188 contents, and Save when putting the entity's contents.
189 Possible uses include deriving non-stored fields, verifying fields, or indexing
190 a field only if its value is positive.
191
192 Example 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
230 The *PropertyList type implements PropertyLoadSaver, and can therefore hold an
231 arbitrary entity's contents.
232
233
234 Queries
235
236 Queries retrieve entities based on their properties or key's ancestry. Running
237 a query yields an iterator of results: either keys or (key, entity) pairs.
238 Queries are re-usable and it is safe to call Query.Run from concurrent
239 goroutines. Iterators are not safe for concurrent use.
240
241 Queries are immutable, and are either created by calling NewQuery, or derived
242 from an existing query by calling a method like Filter or Order that returns a
243 new query value. A query is typically constructed by calling NewQuery followed
244 by 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
258 Example 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
288 Transactions
289
290 RunInTransaction runs a function in a transaction.
291
292 Example 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
327 Metadata
328
329 The datastore package provides access to some of App Engine's datastore
330 metadata. This metadata includes information about the entity groups,
331 namespaces, entity kinds, and properties in the datastore, as well as the
332 property representations for each property.
333
334 Example 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 */
361 package datastore // import "google.golang.org/appengine/datastore"