1002 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1002 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package schema
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"database/sql"
 | 
						|
	"database/sql/driver"
 | 
						|
	"fmt"
 | 
						|
	"reflect"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/jinzhu/now"
 | 
						|
	"gorm.io/gorm/clause"
 | 
						|
	"gorm.io/gorm/utils"
 | 
						|
)
 | 
						|
 | 
						|
// special types' reflect type
 | 
						|
var (
 | 
						|
	TimeReflectType    = reflect.TypeOf(time.Time{})
 | 
						|
	TimePtrReflectType = reflect.TypeOf(&time.Time{})
 | 
						|
	ByteReflectType    = reflect.TypeOf(uint8(0))
 | 
						|
)
 | 
						|
 | 
						|
type (
 | 
						|
	// DataType GORM data type
 | 
						|
	DataType string
 | 
						|
	// TimeType GORM time type
 | 
						|
	TimeType int64
 | 
						|
)
 | 
						|
 | 
						|
// GORM time types
 | 
						|
const (
 | 
						|
	UnixTime        TimeType = 1
 | 
						|
	UnixSecond      TimeType = 2
 | 
						|
	UnixMillisecond TimeType = 3
 | 
						|
	UnixNanosecond  TimeType = 4
 | 
						|
)
 | 
						|
 | 
						|
// GORM fields types
 | 
						|
const (
 | 
						|
	Bool   DataType = "bool"
 | 
						|
	Int    DataType = "int"
 | 
						|
	Uint   DataType = "uint"
 | 
						|
	Float  DataType = "float"
 | 
						|
	String DataType = "string"
 | 
						|
	Time   DataType = "time"
 | 
						|
	Bytes  DataType = "bytes"
 | 
						|
)
 | 
						|
 | 
						|
const DefaultAutoIncrementIncrement int64 = 1
 | 
						|
 | 
						|
// Field is the representation of model schema's field
 | 
						|
type Field struct {
 | 
						|
	Name                   string
 | 
						|
	DBName                 string
 | 
						|
	BindNames              []string
 | 
						|
	EmbeddedBindNames      []string
 | 
						|
	DataType               DataType
 | 
						|
	GORMDataType           DataType
 | 
						|
	PrimaryKey             bool
 | 
						|
	AutoIncrement          bool
 | 
						|
	AutoIncrementIncrement int64
 | 
						|
	Creatable              bool
 | 
						|
	Updatable              bool
 | 
						|
	Readable               bool
 | 
						|
	AutoCreateTime         TimeType
 | 
						|
	AutoUpdateTime         TimeType
 | 
						|
	HasDefaultValue        bool
 | 
						|
	DefaultValue           string
 | 
						|
	DefaultValueInterface  interface{}
 | 
						|
	NotNull                bool
 | 
						|
	Unique                 bool
 | 
						|
	Comment                string
 | 
						|
	Size                   int
 | 
						|
	Precision              int
 | 
						|
	Scale                  int
 | 
						|
	IgnoreMigration        bool
 | 
						|
	FieldType              reflect.Type
 | 
						|
	IndirectFieldType      reflect.Type
 | 
						|
	StructField            reflect.StructField
 | 
						|
	Tag                    reflect.StructTag
 | 
						|
	TagSettings            map[string]string
 | 
						|
	Schema                 *Schema
 | 
						|
	EmbeddedSchema         *Schema
 | 
						|
	OwnerSchema            *Schema
 | 
						|
	ReflectValueOf         func(context.Context, reflect.Value) reflect.Value
 | 
						|
	ValueOf                func(context.Context, reflect.Value) (value interface{}, zero bool)
 | 
						|
	Set                    func(context.Context, reflect.Value, interface{}) error
 | 
						|
	Serializer             SerializerInterface
 | 
						|
	NewValuePool           FieldNewValuePool
 | 
						|
 | 
						|
	// In some db (e.g. MySQL), Unique and UniqueIndex are indistinguishable.
 | 
						|
	// When a column has a (not Mul) UniqueIndex, Migrator always reports its gorm.ColumnType is Unique.
 | 
						|
	// It causes field unnecessarily migration.
 | 
						|
	// Therefore, we need to record the UniqueIndex on this column (exclude Mul UniqueIndex) for MigrateColumnUnique.
 | 
						|
	UniqueIndex string
 | 
						|
}
 | 
						|
 | 
						|
func (field *Field) BindName() string {
 | 
						|
	return strings.Join(field.BindNames, ".")
 | 
						|
}
 | 
						|
 | 
						|
// ParseField parses reflect.StructField to Field
 | 
						|
func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
						|
	var (
 | 
						|
		err        error
 | 
						|
		tagSetting = ParseTagSetting(fieldStruct.Tag.Get("gorm"), ";")
 | 
						|
	)
 | 
						|
 | 
						|
	field := &Field{
 | 
						|
		Name:                   fieldStruct.Name,
 | 
						|
		DBName:                 tagSetting["COLUMN"],
 | 
						|
		BindNames:              []string{fieldStruct.Name},
 | 
						|
		EmbeddedBindNames:      []string{fieldStruct.Name},
 | 
						|
		FieldType:              fieldStruct.Type,
 | 
						|
		IndirectFieldType:      fieldStruct.Type,
 | 
						|
		StructField:            fieldStruct,
 | 
						|
		Tag:                    fieldStruct.Tag,
 | 
						|
		TagSettings:            tagSetting,
 | 
						|
		Schema:                 schema,
 | 
						|
		Creatable:              true,
 | 
						|
		Updatable:              true,
 | 
						|
		Readable:               true,
 | 
						|
		PrimaryKey:             utils.CheckTruth(tagSetting["PRIMARYKEY"], tagSetting["PRIMARY_KEY"]),
 | 
						|
		AutoIncrement:          utils.CheckTruth(tagSetting["AUTOINCREMENT"]),
 | 
						|
		HasDefaultValue:        utils.CheckTruth(tagSetting["AUTOINCREMENT"]),
 | 
						|
		NotNull:                utils.CheckTruth(tagSetting["NOT NULL"], tagSetting["NOTNULL"]),
 | 
						|
		Unique:                 utils.CheckTruth(tagSetting["UNIQUE"]),
 | 
						|
		Comment:                tagSetting["COMMENT"],
 | 
						|
		AutoIncrementIncrement: DefaultAutoIncrementIncrement,
 | 
						|
	}
 | 
						|
 | 
						|
	for field.IndirectFieldType.Kind() == reflect.Ptr {
 | 
						|
		field.IndirectFieldType = field.IndirectFieldType.Elem()
 | 
						|
	}
 | 
						|
 | 
						|
	fieldValue := reflect.New(field.IndirectFieldType)
 | 
						|
	// if field is valuer, used its value or first field as data type
 | 
						|
	valuer, isValuer := fieldValue.Interface().(driver.Valuer)
 | 
						|
	if isValuer {
 | 
						|
		if _, ok := fieldValue.Interface().(GormDataTypeInterface); !ok {
 | 
						|
			if v, err := valuer.Value(); reflect.ValueOf(v).IsValid() && err == nil {
 | 
						|
				fieldValue = reflect.ValueOf(v)
 | 
						|
			}
 | 
						|
 | 
						|
			// Use the field struct's first field type as data type, e.g: use `string` for sql.NullString
 | 
						|
			var getRealFieldValue func(reflect.Value)
 | 
						|
			getRealFieldValue = func(v reflect.Value) {
 | 
						|
				var (
 | 
						|
					rv     = reflect.Indirect(v)
 | 
						|
					rvType = rv.Type()
 | 
						|
				)
 | 
						|
 | 
						|
				if rv.Kind() == reflect.Struct && !rvType.ConvertibleTo(TimeReflectType) {
 | 
						|
					for i := 0; i < rvType.NumField(); i++ {
 | 
						|
						for key, value := range ParseTagSetting(rvType.Field(i).Tag.Get("gorm"), ";") {
 | 
						|
							if _, ok := field.TagSettings[key]; !ok {
 | 
						|
								field.TagSettings[key] = value
 | 
						|
							}
 | 
						|
						}
 | 
						|
					}
 | 
						|
 | 
						|
					for i := 0; i < rvType.NumField(); i++ {
 | 
						|
						newFieldType := rvType.Field(i).Type
 | 
						|
						for newFieldType.Kind() == reflect.Ptr {
 | 
						|
							newFieldType = newFieldType.Elem()
 | 
						|
						}
 | 
						|
 | 
						|
						fieldValue = reflect.New(newFieldType)
 | 
						|
						if rvType != reflect.Indirect(fieldValue).Type() {
 | 
						|
							getRealFieldValue(fieldValue)
 | 
						|
						}
 | 
						|
 | 
						|
						if fieldValue.IsValid() {
 | 
						|
							return
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			getRealFieldValue(fieldValue)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if v, isSerializer := fieldValue.Interface().(SerializerInterface); isSerializer {
 | 
						|
		field.DataType = String
 | 
						|
		field.Serializer = v
 | 
						|
	} else {
 | 
						|
		serializerName := field.TagSettings["JSON"]
 | 
						|
		if serializerName == "" {
 | 
						|
			serializerName = field.TagSettings["SERIALIZER"]
 | 
						|
		}
 | 
						|
		if serializerName != "" {
 | 
						|
			if serializer, ok := GetSerializer(serializerName); ok {
 | 
						|
				// Set default data type to string for serializer
 | 
						|
				field.DataType = String
 | 
						|
				field.Serializer = serializer
 | 
						|
			} else {
 | 
						|
				schema.err = fmt.Errorf("invalid serializer type %v", serializerName)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if num, ok := field.TagSettings["AUTOINCREMENTINCREMENT"]; ok {
 | 
						|
		field.AutoIncrementIncrement, _ = strconv.ParseInt(num, 10, 64)
 | 
						|
	}
 | 
						|
 | 
						|
	if v, ok := field.TagSettings["DEFAULT"]; ok {
 | 
						|
		field.HasDefaultValue = true
 | 
						|
		field.DefaultValue = v
 | 
						|
	}
 | 
						|
 | 
						|
	if num, ok := field.TagSettings["SIZE"]; ok {
 | 
						|
		if field.Size, err = strconv.Atoi(num); err != nil {
 | 
						|
			field.Size = -1
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if p, ok := field.TagSettings["PRECISION"]; ok {
 | 
						|
		field.Precision, _ = strconv.Atoi(p)
 | 
						|
	}
 | 
						|
 | 
						|
	if s, ok := field.TagSettings["SCALE"]; ok {
 | 
						|
		field.Scale, _ = strconv.Atoi(s)
 | 
						|
	}
 | 
						|
 | 
						|
	// default value is function or null or blank (primary keys)
 | 
						|
	field.DefaultValue = strings.TrimSpace(field.DefaultValue)
 | 
						|
	skipParseDefaultValue := strings.Contains(field.DefaultValue, "(") &&
 | 
						|
		strings.Contains(field.DefaultValue, ")") || strings.ToLower(field.DefaultValue) == "null" || field.DefaultValue == ""
 | 
						|
	switch reflect.Indirect(fieldValue).Kind() {
 | 
						|
	case reflect.Bool:
 | 
						|
		field.DataType = Bool
 | 
						|
		if field.HasDefaultValue && !skipParseDefaultValue {
 | 
						|
			if field.DefaultValueInterface, err = strconv.ParseBool(field.DefaultValue); err != nil {
 | 
						|
				schema.err = fmt.Errorf("failed to parse %s as default value for bool, got error: %v", field.DefaultValue, err)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
						|
		field.DataType = Int
 | 
						|
		if field.HasDefaultValue && !skipParseDefaultValue {
 | 
						|
			if field.DefaultValueInterface, err = strconv.ParseInt(field.DefaultValue, 0, 64); err != nil {
 | 
						|
				schema.err = fmt.Errorf("failed to parse %s as default value for int, got error: %v", field.DefaultValue, err)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
						|
		field.DataType = Uint
 | 
						|
		if field.HasDefaultValue && !skipParseDefaultValue {
 | 
						|
			if field.DefaultValueInterface, err = strconv.ParseUint(field.DefaultValue, 0, 64); err != nil {
 | 
						|
				schema.err = fmt.Errorf("failed to parse %s as default value for uint, got error: %v", field.DefaultValue, err)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	case reflect.Float32, reflect.Float64:
 | 
						|
		field.DataType = Float
 | 
						|
		if field.HasDefaultValue && !skipParseDefaultValue {
 | 
						|
			if field.DefaultValueInterface, err = strconv.ParseFloat(field.DefaultValue, 64); err != nil {
 | 
						|
				schema.err = fmt.Errorf("failed to parse %s as default value for float, got error: %v", field.DefaultValue, err)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	case reflect.String:
 | 
						|
		field.DataType = String
 | 
						|
		if field.HasDefaultValue && !skipParseDefaultValue {
 | 
						|
			field.DefaultValue = strings.Trim(field.DefaultValue, "'")
 | 
						|
			field.DefaultValue = strings.Trim(field.DefaultValue, `"`)
 | 
						|
			field.DefaultValueInterface = field.DefaultValue
 | 
						|
		}
 | 
						|
	case reflect.Struct:
 | 
						|
		if _, ok := fieldValue.Interface().(*time.Time); ok {
 | 
						|
			field.DataType = Time
 | 
						|
		} else if fieldValue.Type().ConvertibleTo(TimeReflectType) {
 | 
						|
			field.DataType = Time
 | 
						|
		} else if fieldValue.Type().ConvertibleTo(TimePtrReflectType) {
 | 
						|
			field.DataType = Time
 | 
						|
		}
 | 
						|
		if field.HasDefaultValue && !skipParseDefaultValue && field.DataType == Time {
 | 
						|
			if t, err := now.Parse(field.DefaultValue); err == nil {
 | 
						|
				field.DefaultValueInterface = t
 | 
						|
			}
 | 
						|
		}
 | 
						|
	case reflect.Array, reflect.Slice:
 | 
						|
		if reflect.Indirect(fieldValue).Type().Elem() == ByteReflectType && field.DataType == "" {
 | 
						|
			field.DataType = Bytes
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if dataTyper, ok := fieldValue.Interface().(GormDataTypeInterface); ok {
 | 
						|
		field.DataType = DataType(dataTyper.GormDataType())
 | 
						|
	}
 | 
						|
 | 
						|
	if v, ok := field.TagSettings["AUTOCREATETIME"]; (ok && utils.CheckTruth(v)) || (!ok && field.Name == "CreatedAt" && (field.DataType == Time || field.DataType == Int || field.DataType == Uint)) {
 | 
						|
		if field.DataType == Time {
 | 
						|
			field.AutoCreateTime = UnixTime
 | 
						|
		} else if strings.ToUpper(v) == "NANO" {
 | 
						|
			field.AutoCreateTime = UnixNanosecond
 | 
						|
		} else if strings.ToUpper(v) == "MILLI" {
 | 
						|
			field.AutoCreateTime = UnixMillisecond
 | 
						|
		} else {
 | 
						|
			field.AutoCreateTime = UnixSecond
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if v, ok := field.TagSettings["AUTOUPDATETIME"]; (ok && utils.CheckTruth(v)) || (!ok && field.Name == "UpdatedAt" && (field.DataType == Time || field.DataType == Int || field.DataType == Uint)) {
 | 
						|
		if field.DataType == Time {
 | 
						|
			field.AutoUpdateTime = UnixTime
 | 
						|
		} else if strings.ToUpper(v) == "NANO" {
 | 
						|
			field.AutoUpdateTime = UnixNanosecond
 | 
						|
		} else if strings.ToUpper(v) == "MILLI" {
 | 
						|
			field.AutoUpdateTime = UnixMillisecond
 | 
						|
		} else {
 | 
						|
			field.AutoUpdateTime = UnixSecond
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if field.GORMDataType == "" {
 | 
						|
		field.GORMDataType = field.DataType
 | 
						|
	}
 | 
						|
 | 
						|
	if val, ok := field.TagSettings["TYPE"]; ok {
 | 
						|
		switch DataType(strings.ToLower(val)) {
 | 
						|
		case Bool, Int, Uint, Float, String, Time, Bytes:
 | 
						|
			field.DataType = DataType(strings.ToLower(val))
 | 
						|
		default:
 | 
						|
			field.DataType = DataType(val)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if field.Size == 0 {
 | 
						|
		switch reflect.Indirect(fieldValue).Kind() {
 | 
						|
		case reflect.Int, reflect.Int64, reflect.Uint, reflect.Uint64, reflect.Float64:
 | 
						|
			field.Size = 64
 | 
						|
		case reflect.Int8, reflect.Uint8:
 | 
						|
			field.Size = 8
 | 
						|
		case reflect.Int16, reflect.Uint16:
 | 
						|
			field.Size = 16
 | 
						|
		case reflect.Int32, reflect.Uint32, reflect.Float32:
 | 
						|
			field.Size = 32
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// setup permission
 | 
						|
	if val, ok := field.TagSettings["-"]; ok {
 | 
						|
		val = strings.ToLower(strings.TrimSpace(val))
 | 
						|
		switch val {
 | 
						|
		case "-":
 | 
						|
			field.Creatable = false
 | 
						|
			field.Updatable = false
 | 
						|
			field.Readable = false
 | 
						|
			field.DataType = ""
 | 
						|
		case "all":
 | 
						|
			field.Creatable = false
 | 
						|
			field.Updatable = false
 | 
						|
			field.Readable = false
 | 
						|
			field.DataType = ""
 | 
						|
			field.IgnoreMigration = true
 | 
						|
		case "migration":
 | 
						|
			field.IgnoreMigration = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if v, ok := field.TagSettings["->"]; ok {
 | 
						|
		field.Creatable = false
 | 
						|
		field.Updatable = false
 | 
						|
		if strings.ToLower(v) == "false" {
 | 
						|
			field.Readable = false
 | 
						|
		} else {
 | 
						|
			field.Readable = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if v, ok := field.TagSettings["<-"]; ok {
 | 
						|
		field.Creatable = true
 | 
						|
		field.Updatable = true
 | 
						|
 | 
						|
		if v != "<-" {
 | 
						|
			if !strings.Contains(v, "create") {
 | 
						|
				field.Creatable = false
 | 
						|
			}
 | 
						|
 | 
						|
			if !strings.Contains(v, "update") {
 | 
						|
				field.Updatable = false
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Normal anonymous field or having `EMBEDDED` tag
 | 
						|
	if _, ok := field.TagSettings["EMBEDDED"]; ok || (field.GORMDataType != Time && field.GORMDataType != Bytes && !isValuer &&
 | 
						|
		fieldStruct.Anonymous && (field.Creatable || field.Updatable || field.Readable)) {
 | 
						|
		kind := reflect.Indirect(fieldValue).Kind()
 | 
						|
		switch kind {
 | 
						|
		case reflect.Struct:
 | 
						|
			var err error
 | 
						|
			field.Creatable = false
 | 
						|
			field.Updatable = false
 | 
						|
			field.Readable = false
 | 
						|
 | 
						|
			cacheStore := &sync.Map{}
 | 
						|
			cacheStore.Store(embeddedCacheKey, true)
 | 
						|
			if field.EmbeddedSchema, err = getOrParse(fieldValue.Interface(), cacheStore, embeddedNamer{Table: schema.Table, Namer: schema.namer}); err != nil {
 | 
						|
				schema.err = err
 | 
						|
			}
 | 
						|
 | 
						|
			for _, ef := range field.EmbeddedSchema.Fields {
 | 
						|
				ef.Schema = schema
 | 
						|
				ef.OwnerSchema = field.EmbeddedSchema
 | 
						|
				ef.BindNames = append([]string{fieldStruct.Name}, ef.BindNames...)
 | 
						|
				if _, ok := field.TagSettings["EMBEDDED"]; ok || !fieldStruct.Anonymous {
 | 
						|
					ef.EmbeddedBindNames = append([]string{fieldStruct.Name}, ef.EmbeddedBindNames...)
 | 
						|
				}
 | 
						|
				// index is negative means is pointer
 | 
						|
				if field.FieldType.Kind() == reflect.Struct {
 | 
						|
					ef.StructField.Index = append([]int{fieldStruct.Index[0]}, ef.StructField.Index...)
 | 
						|
				} else {
 | 
						|
					ef.StructField.Index = append([]int{-fieldStruct.Index[0] - 1}, ef.StructField.Index...)
 | 
						|
				}
 | 
						|
 | 
						|
				if prefix, ok := field.TagSettings["EMBEDDEDPREFIX"]; ok && ef.DBName != "" {
 | 
						|
					ef.DBName = prefix + ef.DBName
 | 
						|
				}
 | 
						|
 | 
						|
				if ef.PrimaryKey {
 | 
						|
					if !utils.CheckTruth(ef.TagSettings["PRIMARYKEY"], ef.TagSettings["PRIMARY_KEY"]) {
 | 
						|
						ef.PrimaryKey = false
 | 
						|
 | 
						|
						if val, ok := ef.TagSettings["AUTOINCREMENT"]; !ok || !utils.CheckTruth(val) {
 | 
						|
							ef.AutoIncrement = false
 | 
						|
						}
 | 
						|
 | 
						|
						if !ef.AutoIncrement && ef.DefaultValue == "" {
 | 
						|
							ef.HasDefaultValue = false
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				for k, v := range field.TagSettings {
 | 
						|
					ef.TagSettings[k] = v
 | 
						|
				}
 | 
						|
			}
 | 
						|
		case reflect.Invalid, reflect.Uintptr, reflect.Array, reflect.Chan, reflect.Func, reflect.Interface,
 | 
						|
			reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer, reflect.Complex64, reflect.Complex128:
 | 
						|
			schema.err = fmt.Errorf("invalid embedded struct for %s's field %s, should be struct, but got %v", field.Schema.Name, field.Name, field.FieldType)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return field
 | 
						|
}
 | 
						|
 | 
						|
// create valuer, setter when parse struct
 | 
						|
func (field *Field) setupValuerAndSetter() {
 | 
						|
	// Setup NewValuePool
 | 
						|
	field.setupNewValuePool()
 | 
						|
 | 
						|
	// ValueOf returns field's value and if it is zero
 | 
						|
	fieldIndex := field.StructField.Index[0]
 | 
						|
	switch {
 | 
						|
	case len(field.StructField.Index) == 1 && fieldIndex > 0:
 | 
						|
		field.ValueOf = func(ctx context.Context, value reflect.Value) (interface{}, bool) {
 | 
						|
			fieldValue := reflect.Indirect(value).Field(fieldIndex)
 | 
						|
			return fieldValue.Interface(), fieldValue.IsZero()
 | 
						|
		}
 | 
						|
	default:
 | 
						|
		field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
 | 
						|
			v = reflect.Indirect(v)
 | 
						|
			for _, fieldIdx := range field.StructField.Index {
 | 
						|
				if fieldIdx >= 0 {
 | 
						|
					v = v.Field(fieldIdx)
 | 
						|
				} else {
 | 
						|
					v = v.Field(-fieldIdx - 1)
 | 
						|
 | 
						|
					if !v.IsNil() {
 | 
						|
						v = v.Elem()
 | 
						|
					} else {
 | 
						|
						return nil, true
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			fv, zero := v.Interface(), v.IsZero()
 | 
						|
			return fv, zero
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if field.Serializer != nil {
 | 
						|
		oldValuerOf := field.ValueOf
 | 
						|
		field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
 | 
						|
			value, zero := oldValuerOf(ctx, v)
 | 
						|
 | 
						|
			s, ok := value.(SerializerValuerInterface)
 | 
						|
			if !ok {
 | 
						|
				s = field.Serializer
 | 
						|
			}
 | 
						|
 | 
						|
			return &serializer{
 | 
						|
				Field:           field,
 | 
						|
				SerializeValuer: s,
 | 
						|
				Destination:     v,
 | 
						|
				Context:         ctx,
 | 
						|
				fieldValue:      value,
 | 
						|
			}, zero
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// ReflectValueOf returns field's reflect value
 | 
						|
	switch {
 | 
						|
	case len(field.StructField.Index) == 1 && fieldIndex > 0:
 | 
						|
		field.ReflectValueOf = func(ctx context.Context, value reflect.Value) reflect.Value {
 | 
						|
			return reflect.Indirect(value).Field(fieldIndex)
 | 
						|
		}
 | 
						|
	default:
 | 
						|
		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
 | 
						|
			v = reflect.Indirect(v)
 | 
						|
			for idx, fieldIdx := range field.StructField.Index {
 | 
						|
				if fieldIdx >= 0 {
 | 
						|
					v = v.Field(fieldIdx)
 | 
						|
				} else {
 | 
						|
					v = v.Field(-fieldIdx - 1)
 | 
						|
 | 
						|
					if v.IsNil() {
 | 
						|
						v.Set(reflect.New(v.Type().Elem()))
 | 
						|
					}
 | 
						|
 | 
						|
					if idx < len(field.StructField.Index)-1 {
 | 
						|
						v = v.Elem()
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return v
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	fallbackSetter := func(ctx context.Context, value reflect.Value, v interface{}, setter func(context.Context, reflect.Value, interface{}) error) (err error) {
 | 
						|
		if v == nil {
 | 
						|
			field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
 | 
						|
		} else {
 | 
						|
			reflectV := reflect.ValueOf(v)
 | 
						|
			// Optimal value type acquisition for v
 | 
						|
			reflectValType := reflectV.Type()
 | 
						|
 | 
						|
			if reflectValType.AssignableTo(field.FieldType) {
 | 
						|
				if reflectV.Kind() == reflect.Ptr && reflectV.Elem().Kind() == reflect.Ptr {
 | 
						|
					reflectV = reflect.Indirect(reflectV)
 | 
						|
				}
 | 
						|
				field.ReflectValueOf(ctx, value).Set(reflectV)
 | 
						|
				return
 | 
						|
			} else if reflectValType.ConvertibleTo(field.FieldType) {
 | 
						|
				field.ReflectValueOf(ctx, value).Set(reflectV.Convert(field.FieldType))
 | 
						|
				return
 | 
						|
			} else if field.FieldType.Kind() == reflect.Ptr {
 | 
						|
				fieldValue := field.ReflectValueOf(ctx, value)
 | 
						|
				fieldType := field.FieldType.Elem()
 | 
						|
 | 
						|
				if reflectValType.AssignableTo(fieldType) {
 | 
						|
					if !fieldValue.IsValid() {
 | 
						|
						fieldValue = reflect.New(fieldType)
 | 
						|
					} else if fieldValue.IsNil() {
 | 
						|
						fieldValue.Set(reflect.New(fieldType))
 | 
						|
					}
 | 
						|
					fieldValue.Elem().Set(reflectV)
 | 
						|
					return
 | 
						|
				} else if reflectValType.ConvertibleTo(fieldType) {
 | 
						|
					if fieldValue.IsNil() {
 | 
						|
						fieldValue.Set(reflect.New(fieldType))
 | 
						|
					}
 | 
						|
 | 
						|
					fieldValue.Elem().Set(reflectV.Convert(fieldType))
 | 
						|
					return
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if reflectV.Kind() == reflect.Ptr {
 | 
						|
				if reflectV.IsNil() {
 | 
						|
					field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
 | 
						|
				} else if reflectV.Type().Elem().AssignableTo(field.FieldType) {
 | 
						|
					field.ReflectValueOf(ctx, value).Set(reflectV.Elem())
 | 
						|
					return
 | 
						|
				} else {
 | 
						|
					err = setter(ctx, value, reflectV.Elem().Interface())
 | 
						|
				}
 | 
						|
			} else if valuer, ok := v.(driver.Valuer); ok {
 | 
						|
				if v, err = valuer.Value(); err == nil {
 | 
						|
					err = setter(ctx, value, v)
 | 
						|
				}
 | 
						|
			} else if _, ok := v.(clause.Expr); !ok {
 | 
						|
				return fmt.Errorf("failed to set value %#v to field %s", v, field.Name)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Set
 | 
						|
	switch field.FieldType.Kind() {
 | 
						|
	case reflect.Bool:
 | 
						|
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) error {
 | 
						|
			switch data := v.(type) {
 | 
						|
			case **bool:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetBool(**data)
 | 
						|
				}
 | 
						|
			case bool:
 | 
						|
				field.ReflectValueOf(ctx, value).SetBool(data)
 | 
						|
			case int64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetBool(data > 0)
 | 
						|
			case string:
 | 
						|
				b, _ := strconv.ParseBool(data)
 | 
						|
				field.ReflectValueOf(ctx, value).SetBool(b)
 | 
						|
			default:
 | 
						|
				return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
			}
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
						|
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
			switch data := v.(type) {
 | 
						|
			case **int64:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(**data)
 | 
						|
				}
 | 
						|
			case **int:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(int64(**data))
 | 
						|
				}
 | 
						|
			case **int8:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(int64(**data))
 | 
						|
				}
 | 
						|
			case **int16:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(int64(**data))
 | 
						|
				}
 | 
						|
			case **int32:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(int64(**data))
 | 
						|
				}
 | 
						|
			case int64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(data)
 | 
						|
			case int:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case int8:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case int16:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case int32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case uint:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case uint8:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case uint16:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case uint32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case uint64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case float32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case float64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetInt(int64(data))
 | 
						|
			case []byte:
 | 
						|
				return field.Set(ctx, value, string(data))
 | 
						|
			case string:
 | 
						|
				if i, err := strconv.ParseInt(data, 0, 64); err == nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(i)
 | 
						|
				} else {
 | 
						|
					return err
 | 
						|
				}
 | 
						|
			case time.Time:
 | 
						|
				if field.AutoCreateTime == UnixNanosecond || field.AutoUpdateTime == UnixNanosecond {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(data.UnixNano())
 | 
						|
				} else if field.AutoCreateTime == UnixMillisecond || field.AutoUpdateTime == UnixMillisecond {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(data.UnixMilli())
 | 
						|
				} else {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(data.Unix())
 | 
						|
				}
 | 
						|
			case *time.Time:
 | 
						|
				if data != nil {
 | 
						|
					if field.AutoCreateTime == UnixNanosecond || field.AutoUpdateTime == UnixNanosecond {
 | 
						|
						field.ReflectValueOf(ctx, value).SetInt(data.UnixNano())
 | 
						|
					} else if field.AutoCreateTime == UnixMillisecond || field.AutoUpdateTime == UnixMillisecond {
 | 
						|
						field.ReflectValueOf(ctx, value).SetInt(data.UnixMilli())
 | 
						|
					} else {
 | 
						|
						field.ReflectValueOf(ctx, value).SetInt(data.Unix())
 | 
						|
					}
 | 
						|
				} else {
 | 
						|
					field.ReflectValueOf(ctx, value).SetInt(0)
 | 
						|
				}
 | 
						|
			default:
 | 
						|
				return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
			}
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
						|
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
			switch data := v.(type) {
 | 
						|
			case **uint64:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(**data)
 | 
						|
				}
 | 
						|
			case **uint:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
 | 
						|
				}
 | 
						|
			case **uint8:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
 | 
						|
				}
 | 
						|
			case **uint16:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
 | 
						|
				}
 | 
						|
			case **uint32:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
 | 
						|
				}
 | 
						|
			case uint64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(data)
 | 
						|
			case uint:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case uint8:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case uint16:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case uint32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case int64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case int:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case int8:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case int16:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case int32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case float32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case float64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetUint(uint64(data))
 | 
						|
			case []byte:
 | 
						|
				return field.Set(ctx, value, string(data))
 | 
						|
			case time.Time:
 | 
						|
				if field.AutoCreateTime == UnixNanosecond || field.AutoUpdateTime == UnixNanosecond {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(uint64(data.UnixNano()))
 | 
						|
				} else if field.AutoCreateTime == UnixMillisecond || field.AutoUpdateTime == UnixMillisecond {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(uint64(data.UnixMilli()))
 | 
						|
				} else {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(uint64(data.Unix()))
 | 
						|
				}
 | 
						|
			case string:
 | 
						|
				if i, err := strconv.ParseUint(data, 0, 64); err == nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetUint(i)
 | 
						|
				} else {
 | 
						|
					return err
 | 
						|
				}
 | 
						|
			default:
 | 
						|
				return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
			}
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	case reflect.Float32, reflect.Float64:
 | 
						|
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
			switch data := v.(type) {
 | 
						|
			case **float64:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetFloat(**data)
 | 
						|
				}
 | 
						|
			case **float32:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetFloat(float64(**data))
 | 
						|
				}
 | 
						|
			case float64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(data)
 | 
						|
			case float32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case int64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case int:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case int8:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case int16:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case int32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case uint:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case uint8:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case uint16:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case uint32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case uint64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetFloat(float64(data))
 | 
						|
			case []byte:
 | 
						|
				return field.Set(ctx, value, string(data))
 | 
						|
			case string:
 | 
						|
				if i, err := strconv.ParseFloat(data, 64); err == nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetFloat(i)
 | 
						|
				} else {
 | 
						|
					return err
 | 
						|
				}
 | 
						|
			default:
 | 
						|
				return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
			}
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	case reflect.String:
 | 
						|
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
			switch data := v.(type) {
 | 
						|
			case **string:
 | 
						|
				if data != nil && *data != nil {
 | 
						|
					field.ReflectValueOf(ctx, value).SetString(**data)
 | 
						|
				}
 | 
						|
			case string:
 | 
						|
				field.ReflectValueOf(ctx, value).SetString(data)
 | 
						|
			case []byte:
 | 
						|
				field.ReflectValueOf(ctx, value).SetString(string(data))
 | 
						|
			case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
 | 
						|
				field.ReflectValueOf(ctx, value).SetString(utils.ToString(data))
 | 
						|
			case float64, float32:
 | 
						|
				field.ReflectValueOf(ctx, value).SetString(fmt.Sprintf("%."+strconv.Itoa(field.Precision)+"f", data))
 | 
						|
			default:
 | 
						|
				return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
			}
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	default:
 | 
						|
		fieldValue := reflect.New(field.FieldType)
 | 
						|
		switch fieldValue.Elem().Interface().(type) {
 | 
						|
		case time.Time:
 | 
						|
			field.Set = func(ctx context.Context, value reflect.Value, v interface{}) error {
 | 
						|
				switch data := v.(type) {
 | 
						|
				case **time.Time:
 | 
						|
					if data != nil && *data != nil {
 | 
						|
						field.Set(ctx, value, *data)
 | 
						|
					}
 | 
						|
				case time.Time:
 | 
						|
					field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(v))
 | 
						|
				case *time.Time:
 | 
						|
					if data != nil {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(data).Elem())
 | 
						|
					} else {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(time.Time{}))
 | 
						|
					}
 | 
						|
				case string:
 | 
						|
					if t, err := now.Parse(data); err == nil {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(t))
 | 
						|
					} else {
 | 
						|
						return fmt.Errorf("failed to set string %v to time.Time field %s, failed to parse it as time, got error %v", v, field.Name, err)
 | 
						|
					}
 | 
						|
				default:
 | 
						|
					return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
				}
 | 
						|
				return nil
 | 
						|
			}
 | 
						|
		case *time.Time:
 | 
						|
			field.Set = func(ctx context.Context, value reflect.Value, v interface{}) error {
 | 
						|
				switch data := v.(type) {
 | 
						|
				case **time.Time:
 | 
						|
					if data != nil && *data != nil {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(*data))
 | 
						|
					}
 | 
						|
				case time.Time:
 | 
						|
					fieldValue := field.ReflectValueOf(ctx, value)
 | 
						|
					if fieldValue.IsNil() {
 | 
						|
						fieldValue.Set(reflect.New(field.FieldType.Elem()))
 | 
						|
					}
 | 
						|
					fieldValue.Elem().Set(reflect.ValueOf(v))
 | 
						|
				case *time.Time:
 | 
						|
					field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(v))
 | 
						|
				case string:
 | 
						|
					if t, err := now.Parse(data); err == nil {
 | 
						|
						fieldValue := field.ReflectValueOf(ctx, value)
 | 
						|
						if fieldValue.IsNil() {
 | 
						|
							if v == "" {
 | 
						|
								return nil
 | 
						|
							}
 | 
						|
							fieldValue.Set(reflect.New(field.FieldType.Elem()))
 | 
						|
						}
 | 
						|
						fieldValue.Elem().Set(reflect.ValueOf(t))
 | 
						|
					} else {
 | 
						|
						return fmt.Errorf("failed to set string %v to time.Time field %s, failed to parse it as time, got error %v", v, field.Name, err)
 | 
						|
					}
 | 
						|
				default:
 | 
						|
					return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
				}
 | 
						|
				return nil
 | 
						|
			}
 | 
						|
		default:
 | 
						|
			if _, ok := fieldValue.Elem().Interface().(sql.Scanner); ok {
 | 
						|
				// pointer scanner
 | 
						|
				field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
					reflectV := reflect.ValueOf(v)
 | 
						|
					if !reflectV.IsValid() {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
 | 
						|
					} else if reflectV.Kind() == reflect.Ptr && reflectV.IsNil() {
 | 
						|
						return
 | 
						|
					} else if reflectV.Type().AssignableTo(field.FieldType) {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflectV)
 | 
						|
					} else if reflectV.Kind() == reflect.Ptr {
 | 
						|
						return field.Set(ctx, value, reflectV.Elem().Interface())
 | 
						|
					} else {
 | 
						|
						fieldValue := field.ReflectValueOf(ctx, value)
 | 
						|
						if fieldValue.IsNil() {
 | 
						|
							fieldValue.Set(reflect.New(field.FieldType.Elem()))
 | 
						|
						}
 | 
						|
 | 
						|
						if valuer, ok := v.(driver.Valuer); ok {
 | 
						|
							v, _ = valuer.Value()
 | 
						|
						}
 | 
						|
 | 
						|
						err = fieldValue.Interface().(sql.Scanner).Scan(v)
 | 
						|
					}
 | 
						|
					return
 | 
						|
				}
 | 
						|
			} else if _, ok := fieldValue.Interface().(sql.Scanner); ok {
 | 
						|
				// struct scanner
 | 
						|
				field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
					reflectV := reflect.ValueOf(v)
 | 
						|
					if !reflectV.IsValid() {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
 | 
						|
					} else if reflectV.Kind() == reflect.Ptr && reflectV.IsNil() {
 | 
						|
						return
 | 
						|
					} else if reflectV.Type().AssignableTo(field.FieldType) {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflectV)
 | 
						|
					} else if reflectV.Kind() == reflect.Ptr {
 | 
						|
						return field.Set(ctx, value, reflectV.Elem().Interface())
 | 
						|
					} else {
 | 
						|
						if valuer, ok := v.(driver.Valuer); ok {
 | 
						|
							v, _ = valuer.Value()
 | 
						|
						}
 | 
						|
 | 
						|
						err = field.ReflectValueOf(ctx, value).Addr().Interface().(sql.Scanner).Scan(v)
 | 
						|
					}
 | 
						|
					return
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
					return fallbackSetter(ctx, value, v, field.Set)
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if field.Serializer != nil {
 | 
						|
		var (
 | 
						|
			oldFieldSetter = field.Set
 | 
						|
			sameElemType   bool
 | 
						|
			sameType       = field.FieldType == reflect.ValueOf(field.Serializer).Type()
 | 
						|
		)
 | 
						|
 | 
						|
		if reflect.ValueOf(field.Serializer).Kind() == reflect.Ptr {
 | 
						|
			sameElemType = field.FieldType == reflect.ValueOf(field.Serializer).Type().Elem()
 | 
						|
		}
 | 
						|
 | 
						|
		serializerValue := reflect.Indirect(reflect.ValueOf(field.Serializer))
 | 
						|
		serializerType := serializerValue.Type()
 | 
						|
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
						|
			if s, ok := v.(*serializer); ok {
 | 
						|
				if s.fieldValue != nil {
 | 
						|
					err = oldFieldSetter(ctx, value, s.fieldValue)
 | 
						|
				} else if err = s.Serializer.Scan(ctx, field, value, s.value); err == nil {
 | 
						|
					if sameElemType {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(s.Serializer).Elem())
 | 
						|
					} else if sameType {
 | 
						|
						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(s.Serializer))
 | 
						|
					}
 | 
						|
					si := reflect.New(serializerType)
 | 
						|
					si.Elem().Set(serializerValue)
 | 
						|
					s.Serializer = si.Interface().(SerializerInterface)
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				err = oldFieldSetter(ctx, value, v)
 | 
						|
			}
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (field *Field) setupNewValuePool() {
 | 
						|
	if field.Serializer != nil {
 | 
						|
		serializerValue := reflect.Indirect(reflect.ValueOf(field.Serializer))
 | 
						|
		serializerType := serializerValue.Type()
 | 
						|
		field.NewValuePool = &sync.Pool{
 | 
						|
			New: func() interface{} {
 | 
						|
				si := reflect.New(serializerType)
 | 
						|
				si.Elem().Set(serializerValue)
 | 
						|
				return &serializer{
 | 
						|
					Field:      field,
 | 
						|
					Serializer: si.Interface().(SerializerInterface),
 | 
						|
				}
 | 
						|
			},
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if field.NewValuePool == nil {
 | 
						|
		field.NewValuePool = poolInitializer(reflect.PtrTo(field.IndirectFieldType))
 | 
						|
	}
 | 
						|
}
 |