feat(batch_insert) process creating assignments

This commit is contained in:
Jinzhu 2018-02-26 23:38:21 +08:00
parent 2d8faf10b4
commit 816a206ddd
4 changed files with 92 additions and 5 deletions

78
model/field.go Normal file
View File

@ -0,0 +1,78 @@
package model
import (
"reflect"
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/schema"
)
// Field GORM model field
type Field struct {
*schema.Field
IsBlank bool
Value reflect.Value
}
// GetCreatingAssignments get creating assignments
func GetCreatingAssignments(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))}
case []map[string]interface{}:
fields := [][]*Field{}
tableSchema := schema.Parse(tx.Statement.Table)
for _, v := range dest {
fields = append(fields, mapToFields(v, tableSchema))
}
fieldChan <- fields
default:
if s := schema.Parse(tx.Statement.Dest); s != nil {
results := indirect(reflect.ValueOf(tx.Statement.Dest))
switch results.Kind() {
case reflect.Slice:
fields := [][]*Field{}
for i := 0; i < results.Len(); i++ {
fields = append(fields, structToField(results.Index(i), s))
}
fieldChan <- fields
case reflect.Struct:
fieldChan <- [][]*Field{structToField(results, s)}
}
}
}
}()
return fieldChan
}
func mapToFields(value map[string]interface{}, s *schema.Schema) (fields []*Field) {
for k, v := range value {
if s != nil {
if f := s.FieldByName(k); f != nil {
fields = append(fields, &Field{Field: f, Value: reflect.ValueOf(v)})
continue
}
}
fields = append(fields, &Field{Field: &schema.Field{DBName: k}, Value: reflect.ValueOf(v)})
}
return
}
func structToField(value reflect.Value, s *schema.Schema) (fields []*Field) {
for _, sf := range s.Fields {
obj := value
for _, bn := range sf.BindNames {
obj = value.FieldByName(bn)
}
fields = append(fields, &Field{Field: sf, Value: obj})
}
return
}

View File

@ -12,11 +12,6 @@ import (
// }
var DefaultTableNameHandler func(tx *gorm.DB, tableName string) string
// GetCreatingAssignments get creating assignments
func GetCreatingAssignments(tx *gorm.DB) chan []schema.Field {
return nil
}
// GetTable get table name for current db operation
func GetTable(tx *gorm.DB) chan string {
tableChan := make(chan string)

View File

@ -1,5 +1,7 @@
package model
import "reflect"
// ToSearchableMap convert attrs to searchable map
func ToSearchableMap(attrs ...interface{}) (result interface{}) {
if len(attrs) > 1 {
@ -17,3 +19,10 @@ func ToSearchableMap(attrs ...interface{}) (result interface{}) {
}
return
}
func indirect(reflectValue reflect.Value) reflect.Value {
for reflectValue.Kind() == reflect.Ptr {
reflectValue = reflectValue.Elem()
}
return reflectValue
}

View File

@ -255,6 +255,11 @@ func (schema *Schema) MainPrimaryField() *Field {
return nil
}
// FieldByName get schema's field by name
func (schema *Schema) FieldByName(name string) *Field {
return getSchemaField(name, schema.Fields)
}
func (schemaField *Field) clone() *Field {
clone := *schemaField