aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/google.golang.org/appengine/datastore/save.go
diff options
context:
space:
mode:
authorGravatar Frédéric Guillot <fred@miniflux.net>2018-07-06 21:18:14 -0700
committerGravatar Frédéric Guillot <fred@miniflux.net>2018-07-06 21:18:14 -0700
commit459bb4531f92f8663afb6f36aa9be5b789bd591f (patch)
treef14e6c06b8e5c63612d1ff36f8cab40ae8a99d20 /vendor/google.golang.org/appengine/datastore/save.go
parent34a3fe426b33a63f2d8e02d4a70c88f137fa5410 (diff)
Update vendor dependencies
Diffstat (limited to 'vendor/google.golang.org/appengine/datastore/save.go')
-rw-r--r--vendor/google.golang.org/appengine/datastore/save.go69
1 files changed, 51 insertions, 18 deletions
diff --git a/vendor/google.golang.org/appengine/datastore/save.go b/vendor/google.golang.org/appengine/datastore/save.go
index b5f9592..7b045a5 100644
--- a/vendor/google.golang.org/appengine/datastore/save.go
+++ b/vendor/google.golang.org/appengine/datastore/save.go
@@ -111,6 +111,12 @@ func valueToProto(defaultAppID, name string, v reflect.Value, multiple bool) (p
return p, ""
}
+type saveOpts struct {
+ noIndex bool
+ multiple bool
+ omitEmpty bool
+}
+
// saveEntity saves an EntityProto into a PropertyLoadSaver or struct pointer.
func saveEntity(defaultAppID string, key *Key, src interface{}) (*pb.EntityProto, error) {
var err error
@@ -126,11 +132,14 @@ func saveEntity(defaultAppID string, key *Key, src interface{}) (*pb.EntityProto
return propertiesToProto(defaultAppID, key, props)
}
-func saveStructProperty(props *[]Property, name string, noIndex, multiple bool, v reflect.Value) error {
+func saveStructProperty(props *[]Property, name string, opts saveOpts, v reflect.Value) error {
+ if opts.omitEmpty && isEmptyValue(v) {
+ return nil
+ }
p := Property{
Name: name,
- NoIndex: noIndex,
- Multiple: multiple,
+ NoIndex: opts.noIndex,
+ Multiple: opts.multiple,
}
switch x := v.Interface().(type) {
case *Key:
@@ -166,7 +175,7 @@ func saveStructProperty(props *[]Property, name string, noIndex, multiple bool,
if err != nil {
return fmt.Errorf("datastore: unsupported struct field: %v", err)
}
- return sub.(structPLS).save(props, name, noIndex, multiple)
+ return sub.save(props, name+".", opts)
}
}
if p.Value == nil {
@@ -178,37 +187,35 @@ func saveStructProperty(props *[]Property, name string, noIndex, multiple bool,
func (s structPLS) Save() ([]Property, error) {
var props []Property
- if err := s.save(&props, "", false, false); err != nil {
+ if err := s.save(&props, "", saveOpts{}); err != nil {
return nil, err
}
return props, nil
}
-func (s structPLS) save(props *[]Property, prefix string, noIndex, multiple bool) error {
- for i, t := range s.codec.byIndex {
- if t.name == "-" {
- continue
- }
- name := t.name
- if prefix != "" {
- name = prefix + name
- }
- v := s.v.Field(i)
+func (s structPLS) save(props *[]Property, prefix string, opts saveOpts) error {
+ for name, f := range s.codec.fields {
+ name = prefix + name
+ v := s.v.FieldByIndex(f.path)
if !v.IsValid() || !v.CanSet() {
continue
}
- noIndex1 := noIndex || t.noIndex
+ var opts1 saveOpts
+ opts1.noIndex = opts.noIndex || f.noIndex
+ opts1.multiple = opts.multiple
+ opts1.omitEmpty = f.omitEmpty // don't propagate
// For slice fields that aren't []byte, save each element.
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
+ opts1.multiple = true
for j := 0; j < v.Len(); j++ {
- if err := saveStructProperty(props, name, noIndex1, true, v.Index(j)); err != nil {
+ if err := saveStructProperty(props, name, opts1, v.Index(j)); err != nil {
return err
}
}
continue
}
// Otherwise, save the field itself.
- if err := saveStructProperty(props, name, noIndex1, multiple, v); err != nil {
+ if err := saveStructProperty(props, name, opts1, v); err != nil {
return err
}
}
@@ -298,3 +305,29 @@ func propertiesToProto(defaultAppID string, key *Key, props []Property) (*pb.Ent
}
return e, nil
}
+
+// isEmptyValue is taken from the encoding/json package in the standard library.
+func isEmptyValue(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ // TODO(perfomance): Only reflect.String needed, other property types are not supported (copy/paste from json package)
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ // TODO(perfomance): Uint* are unsupported property types - should be removed (copy/paste from json package)
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ case reflect.Struct:
+ switch x := v.Interface().(type) {
+ case time.Time:
+ return x.IsZero()
+ }
+ }
+ return false
+}