prop.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. package datastore
  5. import (
  6. "fmt"
  7. "reflect"
  8. "strings"
  9. "sync"
  10. "unicode"
  11. )
  12. // Entities with more than this many indexed properties will not be saved.
  13. const maxIndexedProperties = 20000
  14. // []byte fields more than 1 megabyte long will not be loaded or saved.
  15. const maxBlobLen = 1 << 20
  16. // Property is a name/value pair plus some metadata. A datastore entity's
  17. // contents are loaded and saved as a sequence of Properties. An entity can
  18. // have multiple Properties with the same name, provided that p.Multiple is
  19. // true on all of that entity's Properties with that name.
  20. type Property struct {
  21. // Name is the property name.
  22. Name string
  23. // Value is the property value. The valid types are:
  24. // - int64
  25. // - bool
  26. // - string
  27. // - float64
  28. // - ByteString
  29. // - *Key
  30. // - time.Time
  31. // - appengine.BlobKey
  32. // - appengine.GeoPoint
  33. // - []byte (up to 1 megabyte in length)
  34. // - *Entity (representing a nested struct)
  35. // This set is smaller than the set of valid struct field types that the
  36. // datastore can load and save. A Property Value cannot be a slice (apart
  37. // from []byte); use multiple Properties instead. Also, a Value's type
  38. // must be explicitly on the list above; it is not sufficient for the
  39. // underlying type to be on that list. For example, a Value of "type
  40. // myInt64 int64" is invalid. Smaller-width integers and floats are also
  41. // invalid. Again, this is more restrictive than the set of valid struct
  42. // field types.
  43. //
  44. // A Value will have an opaque type when loading entities from an index,
  45. // such as via a projection query. Load entities into a struct instead
  46. // of a PropertyLoadSaver when using a projection query.
  47. //
  48. // A Value may also be the nil interface value; this is equivalent to
  49. // Python's None but not directly representable by a Go struct. Loading
  50. // a nil-valued property into a struct will set that field to the zero
  51. // value.
  52. Value interface{}
  53. // NoIndex is whether the datastore cannot index this property.
  54. NoIndex bool
  55. // Multiple is whether the entity can have multiple properties with
  56. // the same name. Even if a particular instance only has one property with
  57. // a certain name, Multiple should be true if a struct would best represent
  58. // it as a field of type []T instead of type T.
  59. Multiple bool
  60. }
  61. // An Entity is the value type for a nested struct.
  62. // This type is only used for a Property's Value.
  63. type Entity struct {
  64. Key *Key
  65. Properties []Property
  66. }
  67. // ByteString is a short byte slice (up to 1500 bytes) that can be indexed.
  68. type ByteString []byte
  69. // PropertyLoadSaver can be converted from and to a slice of Properties.
  70. type PropertyLoadSaver interface {
  71. Load([]Property) error
  72. Save() ([]Property, error)
  73. }
  74. // PropertyList converts a []Property to implement PropertyLoadSaver.
  75. type PropertyList []Property
  76. var (
  77. typeOfPropertyLoadSaver = reflect.TypeOf((*PropertyLoadSaver)(nil)).Elem()
  78. typeOfPropertyList = reflect.TypeOf(PropertyList(nil))
  79. )
  80. // Load loads all of the provided properties into l.
  81. // It does not first reset *l to an empty slice.
  82. func (l *PropertyList) Load(p []Property) error {
  83. *l = append(*l, p...)
  84. return nil
  85. }
  86. // Save saves all of l's properties as a slice or Properties.
  87. func (l *PropertyList) Save() ([]Property, error) {
  88. return *l, nil
  89. }
  90. // validPropertyName returns whether name consists of one or more valid Go
  91. // identifiers joined by ".".
  92. func validPropertyName(name string) bool {
  93. if name == "" {
  94. return false
  95. }
  96. for _, s := range strings.Split(name, ".") {
  97. if s == "" {
  98. return false
  99. }
  100. first := true
  101. for _, c := range s {
  102. if first {
  103. first = false
  104. if c != '_' && !unicode.IsLetter(c) {
  105. return false
  106. }
  107. } else {
  108. if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) {
  109. return false
  110. }
  111. }
  112. }
  113. }
  114. return true
  115. }
  116. // structCodec describes how to convert a struct to and from a sequence of
  117. // properties.
  118. type structCodec struct {
  119. // fields gives the field codec for the structTag with the given name.
  120. fields map[string]fieldCodec
  121. // hasSlice is whether a struct or any of its nested or embedded structs
  122. // has a slice-typed field (other than []byte).
  123. hasSlice bool
  124. // keyField is the index of a *Key field with structTag __key__.
  125. // This field is not relevant for the top level struct, only for
  126. // nested structs.
  127. keyField int
  128. // complete is whether the structCodec is complete. An incomplete
  129. // structCodec may be encountered when walking a recursive struct.
  130. complete bool
  131. }
  132. // fieldCodec is a struct field's index and, if that struct field's type is
  133. // itself a struct, that substruct's structCodec.
  134. type fieldCodec struct {
  135. // path is the index path to the field
  136. path []int
  137. noIndex bool
  138. // omitEmpty indicates that the field should be omitted on save
  139. // if empty.
  140. omitEmpty bool
  141. // structCodec is the codec fot the struct field at index 'path',
  142. // or nil if the field is not a struct.
  143. structCodec *structCodec
  144. }
  145. // structCodecs collects the structCodecs that have already been calculated.
  146. var (
  147. structCodecsMutex sync.Mutex
  148. structCodecs = make(map[reflect.Type]*structCodec)
  149. )
  150. // getStructCodec returns the structCodec for the given struct type.
  151. func getStructCodec(t reflect.Type) (*structCodec, error) {
  152. structCodecsMutex.Lock()
  153. defer structCodecsMutex.Unlock()
  154. return getStructCodecLocked(t)
  155. }
  156. // getStructCodecLocked implements getStructCodec. The structCodecsMutex must
  157. // be held when calling this function.
  158. func getStructCodecLocked(t reflect.Type) (ret *structCodec, retErr error) {
  159. c, ok := structCodecs[t]
  160. if ok {
  161. return c, nil
  162. }
  163. c = &structCodec{
  164. fields: make(map[string]fieldCodec),
  165. // We initialize keyField to -1 so that the zero-value is not
  166. // misinterpreted as index 0.
  167. keyField: -1,
  168. }
  169. // Add c to the structCodecs map before we are sure it is good. If t is
  170. // a recursive type, it needs to find the incomplete entry for itself in
  171. // the map.
  172. structCodecs[t] = c
  173. defer func() {
  174. if retErr != nil {
  175. delete(structCodecs, t)
  176. }
  177. }()
  178. for i := 0; i < t.NumField(); i++ {
  179. f := t.Field(i)
  180. // Skip unexported fields.
  181. // Note that if f is an anonymous, unexported struct field,
  182. // we will promote its fields.
  183. if f.PkgPath != "" && !f.Anonymous {
  184. continue
  185. }
  186. tags := strings.Split(f.Tag.Get("datastore"), ",")
  187. name := tags[0]
  188. opts := make(map[string]bool)
  189. for _, t := range tags[1:] {
  190. opts[t] = true
  191. }
  192. switch {
  193. case name == "":
  194. if !f.Anonymous {
  195. name = f.Name
  196. }
  197. case name == "-":
  198. continue
  199. case name == "__key__":
  200. if f.Type != typeOfKeyPtr {
  201. return nil, fmt.Errorf("datastore: __key__ field on struct %v is not a *datastore.Key", t)
  202. }
  203. c.keyField = i
  204. case !validPropertyName(name):
  205. return nil, fmt.Errorf("datastore: struct tag has invalid property name: %q", name)
  206. }
  207. substructType, fIsSlice := reflect.Type(nil), false
  208. switch f.Type.Kind() {
  209. case reflect.Struct:
  210. substructType = f.Type
  211. case reflect.Slice:
  212. if f.Type.Elem().Kind() == reflect.Struct {
  213. substructType = f.Type.Elem()
  214. }
  215. fIsSlice = f.Type != typeOfByteSlice
  216. c.hasSlice = c.hasSlice || fIsSlice
  217. }
  218. var sub *structCodec
  219. if substructType != nil && substructType != typeOfTime && substructType != typeOfGeoPoint {
  220. var err error
  221. sub, err = getStructCodecLocked(substructType)
  222. if err != nil {
  223. return nil, err
  224. }
  225. if !sub.complete {
  226. return nil, fmt.Errorf("datastore: recursive struct: field %q", f.Name)
  227. }
  228. if fIsSlice && sub.hasSlice {
  229. return nil, fmt.Errorf(
  230. "datastore: flattening nested structs leads to a slice of slices: field %q", f.Name)
  231. }
  232. c.hasSlice = c.hasSlice || sub.hasSlice
  233. // If f is an anonymous struct field, we promote the substruct's fields up to this level
  234. // in the linked list of struct codecs.
  235. if f.Anonymous {
  236. for subname, subfield := range sub.fields {
  237. if name != "" {
  238. subname = name + "." + subname
  239. }
  240. if _, ok := c.fields[subname]; ok {
  241. return nil, fmt.Errorf("datastore: struct tag has repeated property name: %q", subname)
  242. }
  243. c.fields[subname] = fieldCodec{
  244. path: append([]int{i}, subfield.path...),
  245. noIndex: subfield.noIndex || opts["noindex"],
  246. omitEmpty: subfield.omitEmpty,
  247. structCodec: subfield.structCodec,
  248. }
  249. }
  250. continue
  251. }
  252. }
  253. if _, ok := c.fields[name]; ok {
  254. return nil, fmt.Errorf("datastore: struct tag has repeated property name: %q", name)
  255. }
  256. c.fields[name] = fieldCodec{
  257. path: []int{i},
  258. noIndex: opts["noindex"],
  259. omitEmpty: opts["omitempty"],
  260. structCodec: sub,
  261. }
  262. }
  263. c.complete = true
  264. return c, nil
  265. }
  266. // structPLS adapts a struct to be a PropertyLoadSaver.
  267. type structPLS struct {
  268. v reflect.Value
  269. codec *structCodec
  270. }
  271. // newStructPLS returns a structPLS, which implements the
  272. // PropertyLoadSaver interface, for the struct pointer p.
  273. func newStructPLS(p interface{}) (*structPLS, error) {
  274. v := reflect.ValueOf(p)
  275. if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
  276. return nil, ErrInvalidEntityType
  277. }
  278. v = v.Elem()
  279. codec, err := getStructCodec(v.Type())
  280. if err != nil {
  281. return nil, err
  282. }
  283. return &structPLS{v, codec}, nil
  284. }
  285. // LoadStruct loads the properties from p to dst.
  286. // dst must be a struct pointer.
  287. func LoadStruct(dst interface{}, p []Property) error {
  288. x, err := newStructPLS(dst)
  289. if err != nil {
  290. return err
  291. }
  292. return x.Load(p)
  293. }
  294. // SaveStruct returns the properties from src as a slice of Properties.
  295. // src must be a struct pointer.
  296. func SaveStruct(src interface{}) ([]Property, error) {
  297. x, err := newStructPLS(src)
  298. if err != nil {
  299. return nil, err
  300. }
  301. return x.Save()
  302. }