You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

471 lines
13 KiB

  1. // Copyright 2014 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package datastore
  15. import (
  16. "errors"
  17. "fmt"
  18. "reflect"
  19. "time"
  20. "unicode/utf8"
  21. timepb "github.com/golang/protobuf/ptypes/timestamp"
  22. pb "google.golang.org/genproto/googleapis/datastore/v1"
  23. llpb "google.golang.org/genproto/googleapis/type/latlng"
  24. )
  25. type saveOpts struct {
  26. noIndex bool
  27. flatten bool
  28. omitEmpty bool
  29. }
  30. // saveEntity saves an EntityProto into a PropertyLoadSaver or struct pointer.
  31. func saveEntity(key *Key, src interface{}) (*pb.Entity, error) {
  32. var err error
  33. var props []Property
  34. if e, ok := src.(PropertyLoadSaver); ok {
  35. props, err = e.Save()
  36. } else {
  37. props, err = SaveStruct(src)
  38. }
  39. if err != nil {
  40. return nil, err
  41. }
  42. return propertiesToProto(key, props)
  43. }
  44. // TODO(djd): Convert this and below to return ([]Property, error).
  45. func saveStructProperty(props *[]Property, name string, opts saveOpts, v reflect.Value) error {
  46. p := Property{
  47. Name: name,
  48. NoIndex: opts.noIndex,
  49. }
  50. if opts.omitEmpty && isEmptyValue(v) {
  51. return nil
  52. }
  53. // First check if field type implements PLS. If so, use PLS to
  54. // save.
  55. ok, err := plsFieldSave(props, p, name, opts, v)
  56. if err != nil {
  57. return err
  58. }
  59. if ok {
  60. return nil
  61. }
  62. switch x := v.Interface().(type) {
  63. case *Key, time.Time, GeoPoint:
  64. p.Value = x
  65. default:
  66. switch v.Kind() {
  67. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  68. p.Value = v.Int()
  69. case reflect.Bool:
  70. p.Value = v.Bool()
  71. case reflect.String:
  72. p.Value = v.String()
  73. case reflect.Float32, reflect.Float64:
  74. p.Value = v.Float()
  75. case reflect.Slice:
  76. if v.Type().Elem().Kind() == reflect.Uint8 {
  77. p.Value = v.Bytes()
  78. } else {
  79. return saveSliceProperty(props, name, opts, v)
  80. }
  81. case reflect.Ptr:
  82. if isValidPointerType(v.Type().Elem()) {
  83. if v.IsNil() {
  84. // Nil pointer becomes a nil property value (unless omitempty, handled above).
  85. p.Value = nil
  86. *props = append(*props, p)
  87. return nil
  88. }
  89. // When we recurse on the derefenced pointer, omitempty no longer applies:
  90. // we already know the pointer is not empty, it doesn't matter if its referent
  91. // is empty or not.
  92. opts.omitEmpty = false
  93. return saveStructProperty(props, name, opts, v.Elem())
  94. }
  95. if v.Type().Elem().Kind() != reflect.Struct {
  96. return fmt.Errorf("datastore: unsupported struct field type: %s", v.Type())
  97. }
  98. // Pointer to struct is a special case.
  99. if v.IsNil() {
  100. return nil
  101. }
  102. v = v.Elem()
  103. fallthrough
  104. case reflect.Struct:
  105. if !v.CanAddr() {
  106. return fmt.Errorf("datastore: unsupported struct field: value is unaddressable")
  107. }
  108. vi := v.Addr().Interface()
  109. sub, err := newStructPLS(vi)
  110. if err != nil {
  111. return fmt.Errorf("datastore: unsupported struct field: %v", err)
  112. }
  113. if opts.flatten {
  114. return sub.save(props, opts, name+".")
  115. }
  116. var subProps []Property
  117. err = sub.save(&subProps, opts, "")
  118. if err != nil {
  119. return err
  120. }
  121. subKey, err := sub.key(v)
  122. if err != nil {
  123. return err
  124. }
  125. p.Value = &Entity{
  126. Key: subKey,
  127. Properties: subProps,
  128. }
  129. }
  130. }
  131. if p.Value == nil {
  132. return fmt.Errorf("datastore: unsupported struct field type: %v", v.Type())
  133. }
  134. *props = append(*props, p)
  135. return nil
  136. }
  137. // plsFieldSave first tries to converts v's value to a PLS, then v's addressed
  138. // value to a PLS. If neither succeeds, plsFieldSave returns false for first return
  139. // value.
  140. // If v is successfully converted to a PLS, plsFieldSave will then add the
  141. // Value to property p by way of the PLS's Save method, and append it to props.
  142. //
  143. // If the flatten option is present in opts, name must be prepended to each property's
  144. // name before it is appended to props. Eg. if name were "A" and a subproperty's name
  145. // were "B", the resultant name of the property to be appended to props would be "A.B".
  146. func plsFieldSave(props *[]Property, p Property, name string, opts saveOpts, v reflect.Value) (ok bool, err error) {
  147. vpls, err := plsForSave(v)
  148. if err != nil {
  149. return false, err
  150. }
  151. if vpls == nil {
  152. return false, nil
  153. }
  154. subProps, err := vpls.Save()
  155. if err != nil {
  156. return true, err
  157. }
  158. if opts.flatten {
  159. for _, subp := range subProps {
  160. subp.Name = name + "." + subp.Name
  161. *props = append(*props, subp)
  162. }
  163. return true, nil
  164. }
  165. p.Value = &Entity{Properties: subProps}
  166. *props = append(*props, p)
  167. return true, nil
  168. }
  169. // key extracts the *Key struct field from struct v based on the structCodec of s.
  170. func (s structPLS) key(v reflect.Value) (*Key, error) {
  171. if v.Kind() != reflect.Struct {
  172. return nil, errors.New("datastore: cannot save key of non-struct type")
  173. }
  174. keyField := s.codec.Match(keyFieldName)
  175. if keyField == nil {
  176. return nil, nil
  177. }
  178. f := v.FieldByIndex(keyField.Index)
  179. k, ok := f.Interface().(*Key)
  180. if !ok {
  181. return nil, fmt.Errorf("datastore: %s field on struct %T is not a *datastore.Key", keyFieldName, v.Interface())
  182. }
  183. return k, nil
  184. }
  185. func saveSliceProperty(props *[]Property, name string, opts saveOpts, v reflect.Value) error {
  186. // Easy case: if the slice is empty, we're done.
  187. if v.Len() == 0 {
  188. return nil
  189. }
  190. // Work out the properties generated by the first element in the slice. This will
  191. // usually be a single property, but will be more if this is a slice of structs.
  192. var headProps []Property
  193. if err := saveStructProperty(&headProps, name, opts, v.Index(0)); err != nil {
  194. return err
  195. }
  196. // Convert the first element's properties into slice properties, and
  197. // keep track of the values in a map.
  198. values := make(map[string][]interface{}, len(headProps))
  199. for _, p := range headProps {
  200. values[p.Name] = append(make([]interface{}, 0, v.Len()), p.Value)
  201. }
  202. // Find the elements for the subsequent elements.
  203. for i := 1; i < v.Len(); i++ {
  204. elemProps := make([]Property, 0, len(headProps))
  205. if err := saveStructProperty(&elemProps, name, opts, v.Index(i)); err != nil {
  206. return err
  207. }
  208. for _, p := range elemProps {
  209. v, ok := values[p.Name]
  210. if !ok {
  211. return fmt.Errorf("datastore: unexpected property %q in elem %d of slice", p.Name, i)
  212. }
  213. values[p.Name] = append(v, p.Value)
  214. }
  215. }
  216. // Convert to the final properties.
  217. for _, p := range headProps {
  218. p.Value = values[p.Name]
  219. *props = append(*props, p)
  220. }
  221. return nil
  222. }
  223. func (s structPLS) Save() ([]Property, error) {
  224. var props []Property
  225. if err := s.save(&props, saveOpts{}, ""); err != nil {
  226. return nil, err
  227. }
  228. return props, nil
  229. }
  230. func (s structPLS) save(props *[]Property, opts saveOpts, prefix string) error {
  231. for _, f := range s.codec {
  232. name := prefix + f.Name
  233. v := getField(s.v, f.Index)
  234. if !v.IsValid() || !v.CanSet() {
  235. continue
  236. }
  237. var tagOpts saveOpts
  238. if f.ParsedTag != nil {
  239. tagOpts = f.ParsedTag.(saveOpts)
  240. }
  241. var opts1 saveOpts
  242. opts1.noIndex = opts.noIndex || tagOpts.noIndex
  243. opts1.flatten = opts.flatten || tagOpts.flatten
  244. opts1.omitEmpty = tagOpts.omitEmpty // don't propagate
  245. if err := saveStructProperty(props, name, opts1, v); err != nil {
  246. return err
  247. }
  248. }
  249. return nil
  250. }
  251. // getField returns the field from v at the given index path.
  252. // If it encounters a nil-valued field in the path, getField
  253. // stops and returns a zero-valued reflect.Value, preventing the
  254. // panic that would have been caused by reflect's FieldByIndex.
  255. func getField(v reflect.Value, index []int) reflect.Value {
  256. var zero reflect.Value
  257. if v.Type().Kind() != reflect.Struct {
  258. return zero
  259. }
  260. for _, i := range index {
  261. if v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {
  262. if v.IsNil() {
  263. return zero
  264. }
  265. v = v.Elem()
  266. }
  267. v = v.Field(i)
  268. }
  269. return v
  270. }
  271. func propertiesToProto(key *Key, props []Property) (*pb.Entity, error) {
  272. e := &pb.Entity{
  273. Key: keyToProto(key),
  274. Properties: map[string]*pb.Value{},
  275. }
  276. indexedProps := 0
  277. for _, p := range props {
  278. // Do not send a Key value a field to datastore.
  279. if p.Name == keyFieldName {
  280. continue
  281. }
  282. val, err := interfaceToProto(p.Value, p.NoIndex)
  283. if err != nil {
  284. return nil, fmt.Errorf("datastore: %v for a Property with Name %q", err, p.Name)
  285. }
  286. if !p.NoIndex {
  287. rVal := reflect.ValueOf(p.Value)
  288. if rVal.Kind() == reflect.Slice && rVal.Type().Elem().Kind() != reflect.Uint8 {
  289. indexedProps += rVal.Len()
  290. } else {
  291. indexedProps++
  292. }
  293. }
  294. if indexedProps > maxIndexedProperties {
  295. return nil, errors.New("datastore: too many indexed properties")
  296. }
  297. if _, ok := e.Properties[p.Name]; ok {
  298. return nil, fmt.Errorf("datastore: duplicate Property with Name %q", p.Name)
  299. }
  300. e.Properties[p.Name] = val
  301. }
  302. return e, nil
  303. }
  304. func interfaceToProto(iv interface{}, noIndex bool) (*pb.Value, error) {
  305. val := &pb.Value{ExcludeFromIndexes: noIndex}
  306. switch v := iv.(type) {
  307. case int:
  308. val.ValueType = &pb.Value_IntegerValue{IntegerValue: int64(v)}
  309. case int32:
  310. val.ValueType = &pb.Value_IntegerValue{IntegerValue: int64(v)}
  311. case int64:
  312. val.ValueType = &pb.Value_IntegerValue{IntegerValue: v}
  313. case bool:
  314. val.ValueType = &pb.Value_BooleanValue{BooleanValue: v}
  315. case string:
  316. if len(v) > 1500 && !noIndex {
  317. return nil, errors.New("string property too long to index")
  318. }
  319. if !utf8.ValidString(v) {
  320. return nil, fmt.Errorf("string is not valid utf8: %q", v)
  321. }
  322. val.ValueType = &pb.Value_StringValue{StringValue: v}
  323. case float32:
  324. val.ValueType = &pb.Value_DoubleValue{DoubleValue: float64(v)}
  325. case float64:
  326. val.ValueType = &pb.Value_DoubleValue{DoubleValue: v}
  327. case *Key:
  328. if v == nil {
  329. val.ValueType = &pb.Value_NullValue{}
  330. } else {
  331. val.ValueType = &pb.Value_KeyValue{KeyValue: keyToProto(v)}
  332. }
  333. case GeoPoint:
  334. if !v.Valid() {
  335. return nil, errors.New("invalid GeoPoint value")
  336. }
  337. val.ValueType = &pb.Value_GeoPointValue{GeoPointValue: &llpb.LatLng{
  338. Latitude: v.Lat,
  339. Longitude: v.Lng,
  340. }}
  341. case time.Time:
  342. if v.Before(minTime) || v.After(maxTime) {
  343. return nil, errors.New("time value out of range")
  344. }
  345. val.ValueType = &pb.Value_TimestampValue{TimestampValue: &timepb.Timestamp{
  346. Seconds: v.Unix(),
  347. Nanos: int32(v.Nanosecond()),
  348. }}
  349. case []byte:
  350. if len(v) > 1500 && !noIndex {
  351. return nil, errors.New("[]byte property too long to index")
  352. }
  353. val.ValueType = &pb.Value_BlobValue{BlobValue: v}
  354. case *Entity:
  355. e, err := propertiesToProto(v.Key, v.Properties)
  356. if err != nil {
  357. return nil, err
  358. }
  359. val.ValueType = &pb.Value_EntityValue{EntityValue: e}
  360. case []interface{}:
  361. arr := make([]*pb.Value, 0, len(v))
  362. for i, v := range v {
  363. elem, err := interfaceToProto(v, noIndex)
  364. if err != nil {
  365. return nil, fmt.Errorf("%v at index %d", err, i)
  366. }
  367. arr = append(arr, elem)
  368. }
  369. val.ValueType = &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{Values: arr}}
  370. // ArrayValues have ExcludeFromIndexes set on the individual items, rather
  371. // than the top-level value.
  372. val.ExcludeFromIndexes = false
  373. default:
  374. rv := reflect.ValueOf(iv)
  375. if !rv.IsValid() {
  376. val.ValueType = &pb.Value_NullValue{}
  377. } else if rv.Kind() == reflect.Ptr { // non-nil pointer: dereference
  378. if rv.IsNil() {
  379. val.ValueType = &pb.Value_NullValue{}
  380. return val, nil
  381. }
  382. return interfaceToProto(rv.Elem().Interface(), noIndex)
  383. } else {
  384. return nil, fmt.Errorf("invalid Value type %T", iv)
  385. }
  386. }
  387. // TODO(jbd): Support EntityValue.
  388. return val, nil
  389. }
  390. // isEmptyValue is taken from the encoding/json package in the
  391. // standard library.
  392. func isEmptyValue(v reflect.Value) bool {
  393. switch v.Kind() {
  394. case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
  395. return v.Len() == 0
  396. case reflect.Bool:
  397. return !v.Bool()
  398. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  399. return v.Int() == 0
  400. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  401. return v.Uint() == 0
  402. case reflect.Float32, reflect.Float64:
  403. return v.Float() == 0
  404. case reflect.Interface, reflect.Ptr:
  405. return v.IsNil()
  406. case reflect.Struct:
  407. if t, ok := v.Interface().(time.Time); ok {
  408. return t.IsZero()
  409. }
  410. }
  411. return false
  412. }
  413. // isValidPointerType reports whether a struct field can be a pointer to type t
  414. // for the purposes of saving and loading.
  415. func isValidPointerType(t reflect.Type) bool {
  416. if t == typeOfTime || t == typeOfGeoPoint {
  417. return true
  418. }
  419. switch t.Kind() {
  420. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  421. return true
  422. case reflect.Bool:
  423. return true
  424. case reflect.String:
  425. return true
  426. case reflect.Float32, reflect.Float64:
  427. return true
  428. }
  429. return false
  430. }