Rename GetCreatingAssignments to GetAssignments

This commit is contained in:
Jinzhu 2018-02-27 08:54:19 +08:00
parent 816a206ddd
commit 58a22df1bb
2 changed files with 38 additions and 9 deletions

View File

@ -2,8 +2,11 @@ package model
import ( import (
"reflect" "reflect"
"sort"
"strings"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/builder"
"github.com/jinzhu/gorm/schema" "github.com/jinzhu/gorm/schema"
) )
@ -14,21 +17,21 @@ type Field struct {
Value reflect.Value Value reflect.Value
} }
// GetCreatingAssignments get creating assignments // GetAssignments get assignments
func GetCreatingAssignments(tx *gorm.DB) chan [][]*Field { func GetAssignments(tx *gorm.DB) chan [][]*Field {
fieldChan := make(chan [][]*Field) fieldChan := make(chan [][]*Field)
go func() { go func() {
// TODO handle select, omit, protected // TODO handle select, omit, protected
switch dest := tx.Statement.Dest.(type) { switch dest := tx.Statement.Dest.(type) {
case map[string]interface{}: 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{}: case []map[string]interface{}:
fields := [][]*Field{} fields := [][]*Field{}
tableSchema := schema.Parse(tx.Statement.Table) tableSchema := schema.Parse(tx.Statement.Table)
for _, v := range dest { for _, v := range dest {
fields = append(fields, mapToFields(v, tableSchema)) fields = append(fields, mapToFields(v, tx.Statement, tableSchema))
} }
fieldChan <- fields fieldChan <- fields
default: default:
@ -39,11 +42,11 @@ func GetCreatingAssignments(tx *gorm.DB) chan [][]*Field {
case reflect.Slice: case reflect.Slice:
fields := [][]*Field{} fields := [][]*Field{}
for i := 0; i < results.Len(); i++ { 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 fieldChan <- fields
case reflect.Struct: 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 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 { for k, v := range value {
if s != nil { if s != nil {
if f := s.FieldByName(k); f != 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)}) 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 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 { for _, sf := range s.Fields {
obj := value obj := value
for _, bn := range sf.BindNames { for _, bn := range sf.BindNames {
obj = value.FieldByName(bn) obj = value.FieldByName(bn)
} }
fields = append(fields, &Field{Field: sf, Value: obj}) fields = append(fields, &Field{Field: sf, Value: obj, IsBlank: isBlank(obj)})
} }
return return
} }

View File

@ -26,3 +26,22 @@ func indirect(reflectValue reflect.Value) reflect.Value {
} }
return reflectValue 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())
}