From 58a22df1bb6dc37d5703439c48f15614fbc57208 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Tue, 27 Feb 2018 08:54:19 +0800 Subject: [PATCH] Rename GetCreatingAssignments to GetAssignments --- model/field.go | 28 +++++++++++++++++++--------- model/utils.go | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/model/field.go b/model/field.go index 714170b6..e207e86c 100644 --- a/model/field.go +++ b/model/field.go @@ -2,8 +2,11 @@ package model import ( "reflect" + "sort" + "strings" "github.com/jinzhu/gorm" + "github.com/jinzhu/gorm/builder" "github.com/jinzhu/gorm/schema" ) @@ -14,21 +17,21 @@ type Field struct { Value reflect.Value } -// GetCreatingAssignments get creating assignments -func GetCreatingAssignments(tx *gorm.DB) chan [][]*Field { +// GetAssignments get assignments +func GetAssignments(tx *gorm.DB) chan [][]*Field { fieldChan := make(chan [][]*Field) go func() { // TODO handle select, omit, protected switch dest := tx.Statement.Dest.(type) { case map[string]interface{}: - fieldChan <- [][]*Field{mapToFields(dest, schema.Parse(tx.Statement.Table))} + fieldChan <- [][]*Field{mapToFields(dest, tx.Statement, schema.Parse(tx.Statement.Table))} case []map[string]interface{}: fields := [][]*Field{} tableSchema := schema.Parse(tx.Statement.Table) for _, v := range dest { - fields = append(fields, mapToFields(v, tableSchema)) + fields = append(fields, mapToFields(v, tx.Statement, tableSchema)) } fieldChan <- fields default: @@ -39,11 +42,11 @@ func GetCreatingAssignments(tx *gorm.DB) chan [][]*Field { case reflect.Slice: fields := [][]*Field{} for i := 0; i < results.Len(); i++ { - fields = append(fields, structToField(results.Index(i), s)) + fields = append(fields, structToField(results.Index(i), tx.Statement, s)) } fieldChan <- fields case reflect.Struct: - fieldChan <- [][]*Field{structToField(results, s)} + fieldChan <- [][]*Field{structToField(results, tx.Statement, s)} } } } @@ -52,7 +55,9 @@ func GetCreatingAssignments(tx *gorm.DB) chan [][]*Field { return fieldChan } -func mapToFields(value map[string]interface{}, s *schema.Schema) (fields []*Field) { +func mapToFields(value map[string]interface{}, stmt *builder.Statement, s *schema.Schema) (fields []*Field) { + // sort + // TODO assign those value to dest for k, v := range value { if s != nil { if f := s.FieldByName(k); f != nil { @@ -63,16 +68,21 @@ func mapToFields(value map[string]interface{}, s *schema.Schema) (fields []*Fiel fields = append(fields, &Field{Field: &schema.Field{DBName: k}, Value: reflect.ValueOf(v)}) } + + sort.SliceStable(fields, func(i, j int) bool { + return strings.Compare(fields[i].Field.DBName, fields[j].Field.DBName) < 0 + }) return } -func structToField(value reflect.Value, s *schema.Schema) (fields []*Field) { +func structToField(value reflect.Value, stmt *builder.Statement, s *schema.Schema) (fields []*Field) { + // TODO use Offset to replace FieldByName? for _, sf := range s.Fields { obj := value for _, bn := range sf.BindNames { obj = value.FieldByName(bn) } - fields = append(fields, &Field{Field: sf, Value: obj}) + fields = append(fields, &Field{Field: sf, Value: obj, IsBlank: isBlank(obj)}) } return } diff --git a/model/utils.go b/model/utils.go index dfeba195..da3d3dac 100644 --- a/model/utils.go +++ b/model/utils.go @@ -26,3 +26,22 @@ func indirect(reflectValue reflect.Value) reflect.Value { } return reflectValue } + +func isBlank(value reflect.Value) bool { + switch value.Kind() { + case reflect.String: + return value.Len() == 0 + case reflect.Bool: + return !value.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return value.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return value.Uint() == 0 + case reflect.Float32, reflect.Float64: + return value.Float() == 0 + case reflect.Interface, reflect.Ptr: + return value.IsNil() + } + + return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) +}