save.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  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. "github.com/golang/protobuf/proto"
  21. pb "google.golang.org/cloud/internal/datastore"
  22. )
  23. // saveEntity saves an EntityProto into a PropertyLoadSaver or struct pointer.
  24. func saveEntity(key *Key, src interface{}) (*pb.Entity, error) {
  25. var err error
  26. var props []Property
  27. if e, ok := src.(PropertyLoadSaver); ok {
  28. props, err = e.Save()
  29. } else {
  30. props, err = SaveStruct(src)
  31. }
  32. if err != nil {
  33. return nil, err
  34. }
  35. return propertiesToProto(key, props)
  36. }
  37. func saveStructProperty(props *[]Property, name string, noIndex, multiple bool, v reflect.Value) error {
  38. p := Property{
  39. Name: name,
  40. NoIndex: noIndex,
  41. Multiple: multiple,
  42. }
  43. switch x := v.Interface().(type) {
  44. case *Key, time.Time:
  45. p.Value = x
  46. default:
  47. switch v.Kind() {
  48. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  49. p.Value = v.Int()
  50. case reflect.Bool:
  51. p.Value = v.Bool()
  52. case reflect.String:
  53. p.Value = v.String()
  54. case reflect.Float32, reflect.Float64:
  55. p.Value = v.Float()
  56. case reflect.Slice:
  57. if v.Type().Elem().Kind() == reflect.Uint8 {
  58. p.Value = v.Bytes()
  59. }
  60. case reflect.Struct:
  61. if !v.CanAddr() {
  62. return fmt.Errorf("datastore: unsupported struct field: value is unaddressable")
  63. }
  64. sub, err := newStructPLS(v.Addr().Interface())
  65. if err != nil {
  66. return fmt.Errorf("datastore: unsupported struct field: %v", err)
  67. }
  68. return sub.(structPLS).save(props, name, noIndex, multiple)
  69. }
  70. }
  71. if p.Value == nil {
  72. return fmt.Errorf("datastore: unsupported struct field type: %v", v.Type())
  73. }
  74. *props = append(*props, p)
  75. return nil
  76. }
  77. func (s structPLS) Save() ([]Property, error) {
  78. var props []Property
  79. if err := s.save(&props, "", false, false); err != nil {
  80. return nil, err
  81. }
  82. return props, nil
  83. }
  84. func (s structPLS) save(props *[]Property, prefix string, noIndex, multiple bool) error {
  85. for i, t := range s.codec.byIndex {
  86. if t.name == "-" {
  87. continue
  88. }
  89. name := t.name
  90. if prefix != "" {
  91. name = prefix + name
  92. }
  93. v := s.v.Field(i)
  94. if !v.IsValid() || !v.CanSet() {
  95. continue
  96. }
  97. noIndex1 := noIndex || t.noIndex
  98. // For slice fields that aren't []byte, save each element.
  99. if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
  100. for j := 0; j < v.Len(); j++ {
  101. if err := saveStructProperty(props, name, noIndex1, true, v.Index(j)); err != nil {
  102. return err
  103. }
  104. }
  105. continue
  106. }
  107. // Otherwise, save the field itself.
  108. if err := saveStructProperty(props, name, noIndex1, multiple, v); err != nil {
  109. return err
  110. }
  111. }
  112. return nil
  113. }
  114. func propertiesToProto(key *Key, props []Property) (*pb.Entity, error) {
  115. e := &pb.Entity{
  116. Key: keyToProto(key),
  117. }
  118. indexedProps := 0
  119. prevMultiple := make(map[string]*pb.Property)
  120. for _, p := range props {
  121. val, err := interfaceToProto(p.Value)
  122. if err != "" {
  123. return nil, fmt.Errorf("datastore: %s for a Property with Name %q", err, p.Name)
  124. }
  125. if !p.NoIndex {
  126. rVal := reflect.ValueOf(p.Value)
  127. if rVal.Kind() == reflect.Slice && rVal.Type().Elem().Kind() != reflect.Uint8 {
  128. indexedProps += rVal.Len()
  129. } else {
  130. indexedProps++
  131. }
  132. }
  133. if indexedProps > maxIndexedProperties {
  134. return nil, errors.New("datastore: too many indexed properties")
  135. }
  136. switch v := p.Value.(type) {
  137. case string:
  138. if len(v) > 1500 && !p.NoIndex {
  139. return nil, fmt.Errorf("datastore: Property with Name %q is too long to index", p.Name)
  140. }
  141. case []byte:
  142. if len(v) > 1500 && !p.NoIndex {
  143. return nil, fmt.Errorf("datastore: Property with Name %q is too long to index", p.Name)
  144. }
  145. }
  146. val.Indexed = proto.Bool(!p.NoIndex)
  147. if p.Multiple {
  148. x, ok := prevMultiple[p.Name]
  149. if !ok {
  150. x = &pb.Property{
  151. Name: proto.String(p.Name),
  152. Value: &pb.Value{},
  153. }
  154. prevMultiple[p.Name] = x
  155. e.Property = append(e.Property, x)
  156. }
  157. x.Value.ListValue = append(x.Value.ListValue, val)
  158. } else {
  159. e.Property = append(e.Property, &pb.Property{
  160. Name: proto.String(p.Name),
  161. Value: val,
  162. })
  163. }
  164. }
  165. return e, nil
  166. }
  167. func interfaceToProto(iv interface{}) (p *pb.Value, errStr string) {
  168. val := new(pb.Value)
  169. switch v := iv.(type) {
  170. case int:
  171. val.IntegerValue = proto.Int64(int64(v))
  172. case int32:
  173. val.IntegerValue = proto.Int64(int64(v))
  174. case int64:
  175. val.IntegerValue = proto.Int64(v)
  176. case bool:
  177. val.BooleanValue = proto.Bool(v)
  178. case string:
  179. val.StringValue = proto.String(v)
  180. case float32:
  181. val.DoubleValue = proto.Float64(float64(v))
  182. case float64:
  183. val.DoubleValue = proto.Float64(v)
  184. case *Key:
  185. if v != nil {
  186. val.KeyValue = keyToProto(v)
  187. }
  188. case time.Time:
  189. if v.Before(minTime) || v.After(maxTime) {
  190. return nil, fmt.Sprintf("time value out of range")
  191. }
  192. val.TimestampMicrosecondsValue = proto.Int64(toUnixMicro(v))
  193. case []byte:
  194. val.BlobValue = v
  195. default:
  196. if iv != nil {
  197. return nil, fmt.Sprintf("invalid Value type %t", iv)
  198. }
  199. }
  200. // TODO(jbd): Support ListValue and EntityValue.
  201. // TODO(jbd): Support types whose underlying type is one of the types above.
  202. return val, ""
  203. }