Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(416)

Unified Diff: service/datastore/pls.go

Issue 1259593005: Add 'user friendly' datastore API. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: more docs Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « service/datastore/multiarg.go ('k') | service/datastore/pls_impl.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/pls.go
diff --git a/service/datastore/pls.go b/service/datastore/pls.go
index 63a07eb25191256722200721e89195307c22434a..35eb42dc3c03a94be6313915ea5ed85f40b631b7 100644
--- a/service/datastore/pls.go
+++ b/service/datastore/pls.go
@@ -8,24 +8,106 @@ import (
"reflect"
)
-// GetPLS resolves o into a PropertyLoadSaver. o must be a pointer to a
-// struct of some sort.
-func GetPLS(o interface{}) PropertyLoadSaver {
- v := reflect.ValueOf(o)
+// GetPLS resolves obj into a PropertyLoadSaver.
+//
+// obj must be a non-nil pointer to a struct of some sort.
+//
+// By default, exported fields will be serialized to/from the datastore. If the
+// field is not exported, it will be skipped by the serialization routines.
+//
+// If a field is of a non-supported type (see Property for the list of supported
+// property types), the resulting PropertyLoadSaver will have a non-nil
+// Problem(). Other problems include duplicate field names (due to tagging),
+// recursively defined structs, nested structures with multiple slices (e.g.
+// slices of slices, either directly `[][]type` or indirectly `[]Embedded` where
+// Embedded contains a slice.)
+//
+// GetPLS supports the following struct tag syntax:
+// `gae:"fieldName[,noindex]"` -- an alternate fieldname for an exportable
+// field. When the struct is serialized or deserialized, fieldName will be
+// associated with the struct field instead of the field's Go name. This is
+// useful when writing Go code which interfaces with appengine code written
+// in other languages (like python) which use lowercase as their default
+// datastore field names.
+//
+// A fieldName of "-" means that gae will ignore the field for all
+// serialization/deserialization.
+//
+// if noindex is specified, then this field will not be indexed in the
+// datastore, even if it was an otherwise indexable type. If fieldName is
+// blank, and noindex is specifed, then fieldName will default to the
+// field's actual name. Note that by default, all fields (with indexable
+// types) are indexed.
+//
+// `gae:"$metaKey[,<value>]` -- indicates a field is metadata. Metadata
+// can be used to control filter behavior, or to store key data when using
+// the Interface.KeyForObj* methods. The supported field types are:
+// - Key
+// - int64
+// - string
+// - Toggle (GetMeta and SetMeta treat the field as if it were bool)
+// Additionally, int64, string and Toggle allow setting a default value
+// in the struct field tag (the "<value>" portion).
+//
+// Only exported fields allow SetMeta, but all fields of appropriate type
+// allow tagged defaults. See Examples.
+//
+// Example "special" structure. This is supposed to be some sort of datastore
+// singleton object.
+// struct secretFoo {
+// // _id and _kind are not exported, so setting their values will not be
+// // reflected by GetMeta.
+// _id int64 `gae:"$id,1"`
+// _kind string `gae:"$kind,InternalFooSingleton"`
+//
+// // Value is exported, so can be read and written by the PropertyLoadSaver,
+// // but secretFoo is shared with a python appengine module which has
+// // stored this field as 'value' instead of 'Value'.
+// Value int64 `gae:"value"`
+// }
+//
+// Example "normal" structure that you might use in a go-only appengine app.
+// struct User {
+// ID string `gae:"$id"`
+// // "kind" is automatically implied by the struct name: "User"
+// // "parent" is nil... Users are root entities
+//
+// // 'Name' will serialized to the datastore in the field 'Name'
+// Name string
+// }
+//
+// struct Comment {
+// ID int64 `gae:"$id"`
+// // "kind" is automatically implied by the struct name: "Comment"
+//
+// // Parent will be enforced by the application to be a User key.
+// Parent Key `gae:"$parent"`
+//
+// // 'Lines' will serialized to the datastore in the field 'Lines'
+// Lines []string
+// }
+func GetPLS(obj interface{}) PropertyLoadSaver {
+ v := reflect.ValueOf(obj)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}}
}
+ if v.IsNil() {
+ return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}}
+ }
v = v.Elem()
- t := v.Type()
+ c := getCodec(v.Type())
+ return &structPLS{v, c}
+}
+func getCodec(structType reflect.Type) *structCodec {
structCodecsMutex.RLock()
- if c, ok := structCodecs[t]; ok {
- structCodecsMutex.RUnlock()
- return &structPLS{v, c}
- }
+ c, ok := structCodecs[structType]
structCodecsMutex.RUnlock()
+ if ok {
+ return c
+ }
structCodecsMutex.Lock()
defer structCodecsMutex.Unlock()
- return &structPLS{v, getStructCodecLocked(t)}
+ return getStructCodecLocked(structType)
}
« no previous file with comments | « service/datastore/multiarg.go ('k') | service/datastore/pls_impl.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698