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.
 
 
 

467 lines
12 KiB

  1. // Copyright 4 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. return saveStructProperty(props, name, opts, v.Elem())
  90. }
  91. if v.Type().Elem().Kind() != reflect.Struct {
  92. return fmt.Errorf("datastore: unsupported struct field type: %s", v.Type())
  93. }
  94. // Pointer to struct is a special case.
  95. if v.IsNil() {
  96. return nil
  97. }
  98. v = v.Elem()
  99. fallthrough
  100. case reflect.Struct:
  101. if !v.CanAddr() {
  102. return fmt.Errorf("datastore: unsupported struct field: value is unaddressable")
  103. }
  104. vi := v.Addr().Interface()
  105. sub, err := newStructPLS(vi)
  106. if err != nil {
  107. return fmt.Errorf("datastore: unsupported struct field: %v", err)
  108. }
  109. if opts.flatten {
  110. return sub.save(props, opts, name+".")
  111. }
  112. var subProps []Property
  113. err = sub.save(&subProps, opts, "")
  114. if err != nil {
  115. return err
  116. }
  117. subKey, err := sub.key(v)
  118. if err != nil {
  119. return err
  120. }
  121. p.Value = &Entity{
  122. Key: subKey,
  123. Properties: subProps,
  124. }
  125. }
  126. }
  127. if p.Value == nil {
  128. return fmt.Errorf("datastore: unsupported struct field type: %v", v.Type())
  129. }
  130. *props = append(*props, p)
  131. return nil
  132. }
  133. // plsFieldSave first tries to converts v's value to a PLS, then v's addressed
  134. // value to a PLS. If neither succeeds, plsFieldSave returns false for first return
  135. // value.
  136. // If v is successfully converted to a PLS, plsFieldSave will then add the
  137. // Value to property p by way of the PLS's Save method, and append it to props.
  138. //
  139. // If the flatten option is present in opts, name must be prepended to each property's
  140. // name before it is appended to props. Eg. if name were "A" and a subproperty's name
  141. // were "B", the resultant name of the property to be appended to props would be "A.B".
  142. func plsFieldSave(props *[]Property, p Property, name string, opts saveOpts, v reflect.Value) (ok bool, err error) {
  143. vpls, err := plsForSave(v)
  144. if err != nil {
  145. return false, err
  146. }
  147. if vpls == nil {
  148. return false, nil
  149. }
  150. subProps, err := vpls.Save()
  151. if err != nil {
  152. return true, err
  153. }
  154. if opts.flatten {
  155. for _, subp := range subProps {
  156. subp.Name = name + "." + subp.Name
  157. *props = append(*props, subp)
  158. }
  159. return true, nil
  160. }
  161. p.Value = &Entity{Properties: subProps}
  162. *props = append(*props, p)
  163. return true, nil
  164. }
  165. // key extracts the *Key struct field from struct v based on the structCodec of s.
  166. func (s structPLS) key(v reflect.Value) (*Key, error) {
  167. if v.Kind() != reflect.Struct {
  168. return nil, errors.New("datastore: cannot save key of non-struct type")
  169. }
  170. keyField := s.codec.Match(keyFieldName)
  171. if keyField == nil {
  172. return nil, nil
  173. }
  174. f := v.FieldByIndex(keyField.Index)
  175. k, ok := f.Interface().(*Key)
  176. if !ok {
  177. return nil, fmt.Errorf("datastore: %s field on struct %T is not a *datastore.Key", keyFieldName, v.Interface())
  178. }
  179. return k, nil
  180. }
  181. func saveSliceProperty(props *[]Property, name string, opts saveOpts, v reflect.Value) error {
  182. // Easy case: if the slice is empty, we're done.
  183. if v.Len() == 0 {
  184. return nil
  185. }
  186. // Work out the properties generated by the first element in the slice. This will
  187. // usually be a single property, but will be more if this is a slice of structs.
  188. var headProps []Property
  189. if err := saveStructProperty(&headProps, name, opts, v.Index(0)); err != nil {
  190. return err
  191. }
  192. // Convert the first element's properties into slice properties, and
  193. // keep track of the values in a map.
  194. values := make(map[string][]interface{}, len(headProps))
  195. for _, p := range headProps {
  196. values[p.Name] = append(make([]interface{}, 0, v.Len()), p.Value)
  197. }
  198. // Find the elements for the subsequent elements.
  199. for i := 1; i < v.Len(); i++ {
  200. elemProps := make([]Property, 0, len(headProps))
  201. if err := saveStructProperty(&elemProps, name, opts, v.Index(i)); err != nil {
  202. return err
  203. }
  204. for _, p := range elemProps {
  205. v, ok := values[p.Name]
  206. if !ok {
  207. return fmt.Errorf("datastore: unexpected property %q in elem %d of slice", p.Name, i)
  208. }
  209. values[p.Name] = append(v, p.Value)
  210. }
  211. }
  212. // Convert to the final properties.
  213. for _, p := range headProps {
  214. p.Value = values[p.Name]
  215. *props = append(*props, p)
  216. }
  217. return nil
  218. }
  219. func (s structPLS) Save() ([]Property, error) {
  220. var props []Property
  221. if err := s.save(&props, saveOpts{}, ""); err != nil {
  222. return nil, err
  223. }
  224. return props, nil
  225. }
  226. func (s structPLS) save(props *[]Property, opts saveOpts, prefix string) error {
  227. for _, f := range s.codec {
  228. name := prefix + f.Name
  229. v := getField(s.v, f.Index)
  230. if !v.IsValid() || !v.CanSet() {
  231. continue
  232. }
  233. var tagOpts saveOpts
  234. if f.ParsedTag != nil {
  235. tagOpts = f.ParsedTag.(saveOpts)
  236. }
  237. var opts1 saveOpts
  238. opts1.noIndex = opts.noIndex || tagOpts.noIndex
  239. opts1.flatten = opts.flatten || tagOpts.flatten
  240. opts1.omitEmpty = tagOpts.omitEmpty // don't propagate
  241. if err := saveStructProperty(props, name, opts1, v); err != nil {
  242. return err
  243. }
  244. }
  245. return nil
  246. }
  247. // getField returns the field from v at the given index path.
  248. // If it encounters a nil-valued field in the path, getField
  249. // stops and returns a zero-valued reflect.Value, preventing the
  250. // panic that would have been caused by reflect's FieldByIndex.
  251. func getField(v reflect.Value, index []int) reflect.Value {
  252. var zero reflect.Value
  253. if v.Type().Kind() != reflect.Struct {
  254. return zero
  255. }
  256. for _, i := range index {
  257. if v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {
  258. if v.IsNil() {
  259. return zero
  260. }
  261. v = v.Elem()
  262. }
  263. v = v.Field(i)
  264. }
  265. return v
  266. }
  267. func propertiesToProto(key *Key, props []Property) (*pb.Entity, error) {
  268. e := &pb.Entity{
  269. Key: keyToProto(key),
  270. Properties: map[string]*pb.Value{},
  271. }
  272. indexedProps := 0
  273. for _, p := range props {
  274. // Do not send a Key value a a field to datastore.
  275. if p.Name == keyFieldName {
  276. continue
  277. }
  278. val, err := interfaceToProto(p.Value, p.NoIndex)
  279. if err != nil {
  280. return nil, fmt.Errorf("datastore: %v for a Property with Name %q", err, p.Name)
  281. }
  282. if !p.NoIndex {
  283. rVal := reflect.ValueOf(p.Value)
  284. if rVal.Kind() == reflect.Slice && rVal.Type().Elem().Kind() != reflect.Uint8 {
  285. indexedProps += rVal.Len()
  286. } else {
  287. indexedProps++
  288. }
  289. }
  290. if indexedProps > maxIndexedProperties {
  291. return nil, errors.New("datastore: too many indexed properties")
  292. }
  293. if _, ok := e.Properties[p.Name]; ok {
  294. return nil, fmt.Errorf("datastore: duplicate Property with Name %q", p.Name)
  295. }
  296. e.Properties[p.Name] = val
  297. }
  298. return e, nil
  299. }
  300. func interfaceToProto(iv interface{}, noIndex bool) (*pb.Value, error) {
  301. val := &pb.Value{ExcludeFromIndexes: noIndex}
  302. switch v := iv.(type) {
  303. case int:
  304. val.ValueType = &pb.Value_IntegerValue{IntegerValue: int64(v)}
  305. case int32:
  306. val.ValueType = &pb.Value_IntegerValue{IntegerValue: int64(v)}
  307. case int64:
  308. val.ValueType = &pb.Value_IntegerValue{IntegerValue: v}
  309. case bool:
  310. val.ValueType = &pb.Value_BooleanValue{BooleanValue: v}
  311. case string:
  312. if len(v) > 1500 && !noIndex {
  313. return nil, errors.New("string property too long to index")
  314. }
  315. if !utf8.ValidString(v) {
  316. return nil, fmt.Errorf("string is not valid utf8: %q", v)
  317. }
  318. val.ValueType = &pb.Value_StringValue{StringValue: v}
  319. case float32:
  320. val.ValueType = &pb.Value_DoubleValue{DoubleValue: float64(v)}
  321. case float64:
  322. val.ValueType = &pb.Value_DoubleValue{DoubleValue: v}
  323. case *Key:
  324. if v == nil {
  325. val.ValueType = &pb.Value_NullValue{}
  326. } else {
  327. val.ValueType = &pb.Value_KeyValue{KeyValue: keyToProto(v)}
  328. }
  329. case GeoPoint:
  330. if !v.Valid() {
  331. return nil, errors.New("invalid GeoPoint value")
  332. }
  333. val.ValueType = &pb.Value_GeoPointValue{GeoPointValue: &llpb.LatLng{
  334. Latitude: v.Lat,
  335. Longitude: v.Lng,
  336. }}
  337. case time.Time:
  338. if v.Before(minTime) || v.After(maxTime) {
  339. return nil, errors.New("time value out of range")
  340. }
  341. val.ValueType = &pb.Value_TimestampValue{TimestampValue: &timepb.Timestamp{
  342. Seconds: v.Unix(),
  343. Nanos: int32(v.Nanosecond()),
  344. }}
  345. case []byte:
  346. if len(v) > 1500 && !noIndex {
  347. return nil, errors.New("[]byte property too long to index")
  348. }
  349. val.ValueType = &pb.Value_BlobValue{BlobValue: v}
  350. case *Entity:
  351. e, err := propertiesToProto(v.Key, v.Properties)
  352. if err != nil {
  353. return nil, err
  354. }
  355. val.ValueType = &pb.Value_EntityValue{EntityValue: e}
  356. case []interface{}:
  357. arr := make([]*pb.Value, 0, len(v))
  358. for i, v := range v {
  359. elem, err := interfaceToProto(v, noIndex)
  360. if err != nil {
  361. return nil, fmt.Errorf("%v at index %d", err, i)
  362. }
  363. arr = append(arr, elem)
  364. }
  365. val.ValueType = &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{Values: arr}}
  366. // ArrayValues have ExcludeFromIndexes set on the individual items, rather
  367. // than the top-level value.
  368. val.ExcludeFromIndexes = false
  369. default:
  370. rv := reflect.ValueOf(iv)
  371. if !rv.IsValid() {
  372. val.ValueType = &pb.Value_NullValue{}
  373. } else if rv.Kind() == reflect.Ptr { // non-nil pointer: dereference
  374. if rv.IsNil() {
  375. val.ValueType = &pb.Value_NullValue{}
  376. return val, nil
  377. }
  378. return interfaceToProto(rv.Elem().Interface(), noIndex)
  379. } else {
  380. return nil, fmt.Errorf("invalid Value type %T", iv)
  381. }
  382. }
  383. // TODO(jbd): Support EntityValue.
  384. return val, nil
  385. }
  386. // isEmptyValue is taken from the encoding/json package in the
  387. // standard library.
  388. func isEmptyValue(v reflect.Value) bool {
  389. switch v.Kind() {
  390. case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
  391. return v.Len() == 0
  392. case reflect.Bool:
  393. return !v.Bool()
  394. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  395. return v.Int() == 0
  396. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  397. return v.Uint() == 0
  398. case reflect.Float32, reflect.Float64:
  399. return v.Float() == 0
  400. case reflect.Interface, reflect.Ptr:
  401. return v.IsNil()
  402. case reflect.Struct:
  403. if t, ok := v.Interface().(time.Time); ok {
  404. return t.IsZero()
  405. }
  406. }
  407. return false
  408. }
  409. // isValidPointerType reports whether a struct field can be a pointer to type t
  410. // for the purposes of saving and loading.
  411. func isValidPointerType(t reflect.Type) bool {
  412. if t == typeOfTime || t == typeOfGeoPoint {
  413. return true
  414. }
  415. switch t.Kind() {
  416. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  417. return true
  418. case reflect.Bool:
  419. return true
  420. case reflect.String:
  421. return true
  422. case reflect.Float32, reflect.Float64:
  423. return true
  424. }
  425. return false
  426. }