diff options
Diffstat (limited to 'vendor/google.golang.org/appengine/datastore/doc.go')
-rw-r--r-- | vendor/google.golang.org/appengine/datastore/doc.go | 361 |
1 files changed, 361 insertions, 0 deletions
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 | /* | ||
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" | ||