gorm/schema/field.go

789 lines
24 KiB
Go
Raw Normal View History

2020-01-31 07:22:37 +03:00
package schema
import (
2020-02-15 11:04:21 +03:00
"database/sql"
2020-01-31 07:22:37 +03:00
"database/sql/driver"
2020-02-15 11:04:21 +03:00
"fmt"
2020-01-31 07:22:37 +03:00
"reflect"
"strconv"
2020-02-18 17:56:37 +03:00
"strings"
2020-01-31 07:22:37 +03:00
"sync"
"time"
2020-02-15 11:04:21 +03:00
2020-06-02 04:25:55 +03:00
"github.com/jinzhu/now"
2020-06-02 04:16:07 +03:00
"gorm.io/gorm/utils"
2020-01-31 07:22:37 +03:00
)
type DataType string
2020-01-31 07:22:37 +03:00
2020-02-18 17:56:37 +03:00
type TimeType int64
const (
UnixSecond TimeType = 1
UnixMillisecond TimeType = 2
UnixNanosecond TimeType = 3
2020-02-18 17:56:37 +03:00
)
2020-01-31 07:22:37 +03:00
const (
Bool DataType = "bool"
2020-07-16 06:27:04 +03:00
Int DataType = "int"
Uint DataType = "uint"
Float DataType = "float"
String DataType = "string"
Time DataType = "time"
Bytes DataType = "bytes"
2020-01-31 07:22:37 +03:00
)
type Field struct {
2020-02-18 17:56:37 +03:00
Name string
DBName string
BindNames []string
DataType DataType
2020-07-20 13:59:28 +03:00
GORMDataType DataType
2020-02-18 17:56:37 +03:00
PrimaryKey bool
AutoIncrement bool
Creatable bool
Updatable bool
Readable bool
2020-02-18 17:56:37 +03:00
HasDefaultValue bool
AutoCreateTime TimeType
AutoUpdateTime TimeType
DefaultValue string
DefaultValueInterface interface{}
NotNull bool
Unique bool
Comment string
Size int
Precision int
FieldType reflect.Type
IndirectFieldType reflect.Type
StructField reflect.StructField
Tag reflect.StructTag
TagSettings map[string]string
Schema *Schema
EmbeddedSchema *Schema
OwnerSchema *Schema
2020-02-18 17:56:37 +03:00
ReflectValueOf func(reflect.Value) reflect.Value
ValueOf func(reflect.Value) (value interface{}, zero bool)
Set func(reflect.Value, interface{}) error
2020-01-31 07:22:37 +03:00
}
func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
field := &Field{
2020-02-15 14:45:27 +03:00
Name: fieldStruct.Name,
BindNames: []string{fieldStruct.Name},
FieldType: fieldStruct.Type,
IndirectFieldType: fieldStruct.Type,
StructField: fieldStruct,
Creatable: true,
Updatable: true,
Readable: true,
2020-02-15 14:45:27 +03:00
Tag: fieldStruct.Tag,
2020-02-21 19:02:05 +03:00
TagSettings: ParseTagSetting(fieldStruct.Tag.Get("gorm"), ";"),
2020-02-15 14:45:27 +03:00
Schema: schema,
2020-01-31 07:22:37 +03:00
}
2020-02-15 14:45:27 +03:00
for field.IndirectFieldType.Kind() == reflect.Ptr {
field.IndirectFieldType = field.IndirectFieldType.Elem()
2020-01-31 07:22:37 +03:00
}
2020-02-15 14:45:27 +03:00
fieldValue := reflect.New(field.IndirectFieldType)
2020-01-31 07:22:37 +03:00
// if field is valuer, used its value or first fields 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)
}
2020-01-31 07:22:37 +03:00
var getRealFieldValue func(reflect.Value)
getRealFieldValue = func(v reflect.Value) {
rv := reflect.Indirect(v)
if rv.Kind() == reflect.Struct && !rv.Type().ConvertibleTo(reflect.TypeOf(time.Time{})) {
for i := 0; i < rv.Type().NumField(); i++ {
newFieldType := rv.Type().Field(i).Type
for newFieldType.Kind() == reflect.Ptr {
newFieldType = newFieldType.Elem()
}
2020-01-31 07:22:37 +03:00
fieldValue = reflect.New(newFieldType)
2020-01-31 07:22:37 +03:00
if rv.Type() != reflect.Indirect(fieldValue).Type() {
getRealFieldValue(fieldValue)
}
if fieldValue.IsValid() {
return
}
for key, value := range ParseTagSetting(field.IndirectFieldType.Field(i).Tag.Get("gorm"), ";") {
if _, ok := field.TagSettings[key]; !ok {
field.TagSettings[key] = value
}
}
2020-01-31 07:22:37 +03:00
}
}
}
getRealFieldValue(fieldValue)
2020-01-31 07:22:37 +03:00
}
}
if dbName, ok := field.TagSettings["COLUMN"]; ok {
field.DBName = dbName
}
if val, ok := field.TagSettings["PRIMARYKEY"]; ok && utils.CheckTruth(val) {
2020-01-31 07:22:37 +03:00
field.PrimaryKey = true
} else if val, ok := field.TagSettings["PRIMARY_KEY"]; ok && utils.CheckTruth(val) {
2020-04-12 08:16:15 +03:00
field.PrimaryKey = true
2020-01-31 07:22:37 +03:00
}
if val, ok := field.TagSettings["AUTOINCREMENT"]; ok && utils.CheckTruth(val) {
2020-01-31 07:22:37 +03:00
field.AutoIncrement = true
field.HasDefaultValue = true
}
if v, ok := field.TagSettings["DEFAULT"]; ok {
field.HasDefaultValue = true
field.DefaultValue = v
}
if num, ok := field.TagSettings["SIZE"]; ok {
2020-02-22 12:53:57 +03:00
var err error
if field.Size, err = strconv.Atoi(num); err != nil {
field.Size = -1
}
2020-01-31 07:22:37 +03:00
}
if p, ok := field.TagSettings["PRECISION"]; ok {
field.Precision, _ = strconv.Atoi(p)
}
if val, ok := field.TagSettings["NOT NULL"]; ok && utils.CheckTruth(val) {
2020-01-31 07:22:37 +03:00
field.NotNull = true
}
if val, ok := field.TagSettings["UNIQUE"]; ok && utils.CheckTruth(val) {
2020-01-31 07:22:37 +03:00
field.Unique = true
}
if val, ok := field.TagSettings["COMMENT"]; ok {
field.Comment = val
}
2020-05-30 16:05:27 +03:00
switch reflect.Indirect(fieldValue).Kind() {
2020-01-31 07:22:37 +03:00
case reflect.Bool:
field.DataType = Bool
if field.HasDefaultValue && field.DefaultValue != "" {
2020-02-18 17:56:37 +03:00
field.DefaultValueInterface, _ = strconv.ParseBool(field.DefaultValue)
}
2020-01-31 07:22:37 +03:00
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
field.DataType = Int
if field.HasDefaultValue && field.DefaultValue != "" {
2020-02-18 17:56:37 +03:00
field.DefaultValueInterface, _ = strconv.ParseInt(field.DefaultValue, 0, 64)
}
2020-01-31 07:22:37 +03:00
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
field.DataType = Uint
if field.HasDefaultValue && field.DefaultValue != "" {
2020-02-18 17:56:37 +03:00
field.DefaultValueInterface, _ = strconv.ParseUint(field.DefaultValue, 0, 64)
}
2020-01-31 07:22:37 +03:00
case reflect.Float32, reflect.Float64:
field.DataType = Float
if field.HasDefaultValue && field.DefaultValue != "" {
2020-02-18 17:56:37 +03:00
field.DefaultValueInterface, _ = strconv.ParseFloat(field.DefaultValue, 64)
}
2020-01-31 07:22:37 +03:00
case reflect.String:
field.DataType = String
2020-06-18 03:20:41 +03:00
isFunc := strings.Contains(field.DefaultValue, "(") &&
strings.Contains(field.DefaultValue, ")")
if field.HasDefaultValue && !isFunc {
field.DefaultValue = strings.Trim(field.DefaultValue, "'")
field.DefaultValue = strings.Trim(field.DefaultValue, "\"")
2020-02-18 17:56:37 +03:00
field.DefaultValueInterface = field.DefaultValue
}
2020-01-31 07:22:37 +03:00
case reflect.Struct:
if _, ok := fieldValue.Interface().(*time.Time); ok {
2020-01-31 07:22:37 +03:00
field.DataType = Time
} else if fieldValue.Type().ConvertibleTo(reflect.TypeOf(time.Time{})) {
field.DataType = Time
2020-02-15 19:37:59 +03:00
} else if fieldValue.Type().ConvertibleTo(reflect.TypeOf(&time.Time{})) {
field.DataType = Time
2020-01-31 07:22:37 +03:00
}
case reflect.Array, reflect.Slice:
2020-06-18 04:32:31 +03:00
if reflect.Indirect(fieldValue).Type().Elem() == reflect.TypeOf(uint8(0)) {
2020-01-31 07:22:37 +03:00
field.DataType = Bytes
}
}
2020-07-20 13:59:28 +03:00
field.GORMDataType = field.DataType
2020-06-06 05:47:32 +03:00
if dataTyper, ok := fieldValue.Interface().(GormDataTypeInterface); ok {
field.DataType = DataType(dataTyper.GormDataType())
}
if v, ok := field.TagSettings["AUTOCREATETIME"]; ok || (field.Name == "CreatedAt" && (field.DataType == Time || field.DataType == Int || field.DataType == Uint)) {
2020-03-08 08:24:08 +03:00
if strings.ToUpper(v) == "NANO" {
field.AutoCreateTime = UnixNanosecond
} else if strings.ToUpper(v) == "MILLI" {
field.AutoCreateTime = UnixMillisecond
2020-03-08 08:24:08 +03:00
} else {
field.AutoCreateTime = UnixSecond
}
}
if v, ok := field.TagSettings["AUTOUPDATETIME"]; ok || (field.Name == "UpdatedAt" && (field.DataType == Time || field.DataType == Int || field.DataType == Uint)) {
2020-03-08 08:24:08 +03:00
if strings.ToUpper(v) == "NANO" {
field.AutoUpdateTime = UnixNanosecond
} else if strings.ToUpper(v) == "MILLI" {
field.AutoUpdateTime = UnixMillisecond
2020-03-08 08:24:08 +03:00
} else {
field.AutoUpdateTime = UnixSecond
}
}
2020-06-26 02:26:45 +03:00
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)
}
}
2020-07-20 13:59:28 +03:00
if field.GORMDataType == "" {
field.GORMDataType = field.DataType
}
2020-01-31 07:22:37 +03:00
if field.Size == 0 {
2020-03-12 03:39:42 +03:00
switch reflect.Indirect(fieldValue).Kind() {
2020-01-31 07:22:37 +03:00
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
}
}
2020-06-05 14:18:22 +03:00
// setup permission
if _, ok := field.TagSettings["-"]; ok {
field.Creatable = false
field.Updatable = false
field.Readable = false
field.DataType = ""
}
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
}
}
}
2020-08-11 16:22:51 +03:00
if _, ok := field.TagSettings["EMBEDDED"]; ok || (fieldStruct.Anonymous && !isValuer && (field.Creatable || field.Updatable || field.Readable)) {
if reflect.Indirect(fieldValue).Kind() == 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 = Parse(fieldValue.Interface(), cacheStore, schema.namer); err != nil {
schema.err = err
2020-02-15 11:04:21 +03:00
}
for _, ef := range field.EmbeddedSchema.Fields {
ef.Schema = schema
ef.OwnerSchema = field.EmbeddedSchema
ef.BindNames = append([]string{fieldStruct.Name}, ef.BindNames...)
// 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...)
}
2020-01-31 07:22:37 +03:00
if prefix, ok := field.TagSettings["EMBEDDEDPREFIX"]; ok {
ef.DBName = prefix + ef.DBName
}
2020-01-31 07:22:37 +03:00
if val, ok := ef.TagSettings["PRIMARYKEY"]; ok && utils.CheckTruth(val) {
ef.PrimaryKey = true
} else if val, ok := ef.TagSettings["PRIMARY_KEY"]; ok && utils.CheckTruth(val) {
ef.PrimaryKey = true
} else {
ef.PrimaryKey = false
if val, ok := ef.TagSettings["AUTOINCREMENT"]; !ok || !utils.CheckTruth(val) {
ef.AutoIncrement = false
}
if ef.DefaultValue == "" {
ef.HasDefaultValue = false
}
}
2020-05-31 09:18:07 +03:00
for k, v := range field.TagSettings {
ef.TagSettings[k] = v
}
2020-01-31 07:22:37 +03:00
}
} else {
schema.err = fmt.Errorf("invalid embedded struct for %v's field %v, should be struct, but got %v", field.Schema.Name, field.Name, field.FieldType)
}
2020-01-31 07:22:37 +03:00
}
return field
}
2020-02-15 11:04:21 +03:00
// create valuer, setter when parse struct
func (field *Field) setupValuerAndSetter() {
2020-02-18 17:56:37 +03:00
// ValueOf
2020-02-15 11:04:21 +03:00
switch {
case len(field.StructField.Index) == 1:
2020-02-18 17:56:37 +03:00
field.ValueOf = func(value reflect.Value) (interface{}, bool) {
fieldValue := reflect.Indirect(value).Field(field.StructField.Index[0])
return fieldValue.Interface(), fieldValue.IsZero()
2020-02-15 11:04:21 +03:00
}
case len(field.StructField.Index) == 2 && field.StructField.Index[0] >= 0:
2020-02-18 17:56:37 +03:00
field.ValueOf = func(value reflect.Value) (interface{}, bool) {
fieldValue := reflect.Indirect(value).Field(field.StructField.Index[0]).Field(field.StructField.Index[1])
return fieldValue.Interface(), fieldValue.IsZero()
2020-02-15 11:04:21 +03:00
}
default:
2020-02-18 17:56:37 +03:00
field.ValueOf = func(value reflect.Value) (interface{}, bool) {
2020-02-15 14:45:27 +03:00
v := reflect.Indirect(value)
for _, idx := range field.StructField.Index {
if idx >= 0 {
v = v.Field(idx)
} else {
v = v.Field(-idx - 1)
2020-02-15 11:04:21 +03:00
if v.Type().Elem().Kind() == reflect.Struct {
if !v.IsNil() {
2020-02-15 14:45:27 +03:00
v = v.Elem()
2020-06-01 14:41:33 +03:00
} else {
return nil, true
2020-02-15 11:04:21 +03:00
}
2020-02-15 14:45:27 +03:00
} else {
2020-02-18 17:56:37 +03:00
return nil, true
2020-02-15 11:04:21 +03:00
}
}
}
2020-02-18 17:56:37 +03:00
return v.Interface(), v.IsZero()
2020-02-15 11:04:21 +03:00
}
}
2020-02-18 17:56:37 +03:00
// ReflectValueOf
2020-02-15 11:04:21 +03:00
switch {
case len(field.StructField.Index) == 1:
if field.FieldType.Kind() == reflect.Ptr {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf = func(value reflect.Value) reflect.Value {
2020-02-15 14:45:27 +03:00
fieldValue := reflect.Indirect(value).Field(field.StructField.Index[0])
2020-02-15 11:04:21 +03:00
return fieldValue
}
} else {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf = func(value reflect.Value) reflect.Value {
2020-02-15 14:45:27 +03:00
return reflect.Indirect(value).Field(field.StructField.Index[0])
2020-02-15 11:04:21 +03:00
}
}
case len(field.StructField.Index) == 2 && field.StructField.Index[0] >= 0 && field.FieldType.Kind() != reflect.Ptr:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf = func(value reflect.Value) reflect.Value {
2020-02-15 14:45:27 +03:00
return reflect.Indirect(value).Field(field.StructField.Index[0]).Field(field.StructField.Index[1])
2020-02-15 11:04:21 +03:00
}
default:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf = func(value reflect.Value) reflect.Value {
2020-02-15 14:45:27 +03:00
v := reflect.Indirect(value)
for idx, fieldIdx := range field.StructField.Index {
if fieldIdx >= 0 {
v = v.Field(fieldIdx)
2020-02-15 14:45:27 +03:00
} else {
v = v.Field(-fieldIdx - 1)
2020-02-15 14:45:27 +03:00
}
2020-02-15 11:04:21 +03:00
if v.Kind() == reflect.Ptr {
if v.Type().Elem().Kind() == reflect.Struct {
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
2020-02-15 14:45:27 +03:00
}
2020-02-15 11:04:21 +03:00
2020-02-15 14:45:27 +03:00
if idx < len(field.StructField.Index)-1 {
v = v.Elem()
2020-02-15 11:04:21 +03:00
}
}
}
return v
}
}
fallbackSetter := func(value reflect.Value, v interface{}, setter func(reflect.Value, interface{}) error) (err error) {
2020-05-24 12:24:23 +03:00
if v == nil {
field.ReflectValueOf(value).Set(reflect.New(field.FieldType).Elem())
2020-02-15 19:37:59 +03:00
} else {
2020-05-24 12:24:23 +03:00
reflectV := reflect.ValueOf(v)
if reflectV.Type().AssignableTo(field.FieldType) {
field.ReflectValueOf(value).Set(reflectV)
return
} else if reflectV.Type().ConvertibleTo(field.FieldType) {
2020-05-24 12:24:23 +03:00
field.ReflectValueOf(value).Set(reflectV.Convert(field.FieldType))
return
} else if field.FieldType.Kind() == reflect.Ptr {
2020-05-29 18:38:03 +03:00
fieldValue := field.ReflectValueOf(value)
if reflectV.Type().AssignableTo(field.FieldType.Elem()) {
if !fieldValue.IsValid() {
fieldValue = reflect.New(field.FieldType.Elem())
} else if fieldValue.IsNil() {
fieldValue.Set(reflect.New(field.FieldType.Elem()))
}
fieldValue.Elem().Set(reflectV)
return
} else if reflectV.Type().ConvertibleTo(field.FieldType.Elem()) {
if fieldValue.IsNil() {
fieldValue.Set(reflect.New(field.FieldType.Elem()))
2020-05-29 18:38:03 +03:00
}
fieldValue.Elem().Set(reflectV.Convert(field.FieldType.Elem()))
return
}
}
if valuer, ok := v.(driver.Valuer); ok {
if v, err = valuer.Value(); err == nil {
2020-07-16 06:27:04 +03:00
err = setter(value, v)
2020-05-29 18:38:03 +03:00
}
2020-05-24 12:24:23 +03:00
} else if reflectV.Kind() == reflect.Ptr {
if reflectV.IsNil() {
field.ReflectValueOf(value).Set(reflect.New(field.FieldType).Elem())
} else {
2020-07-16 06:27:04 +03:00
err = setter(value, reflectV.Elem().Interface())
}
2020-05-24 12:24:23 +03:00
} else {
return fmt.Errorf("failed to set value %+v to field %v", v, field.Name)
}
2020-02-15 19:37:59 +03:00
}
return
2020-02-15 19:37:59 +03:00
}
2020-02-18 17:56:37 +03:00
// Set
2020-02-15 11:04:21 +03:00
switch field.FieldType.Kind() {
case reflect.Bool:
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) error {
2020-02-15 11:04:21 +03:00
switch data := v.(type) {
case bool:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetBool(data)
2020-02-15 11:04:21 +03:00
case *bool:
2020-07-04 03:21:23 +03:00
if data != nil {
field.ReflectValueOf(value).SetBool(*data)
} else {
field.ReflectValueOf(value).SetBool(false)
}
case int64:
if data > 0 {
field.ReflectValueOf(value).SetBool(true)
} else {
field.ReflectValueOf(value).SetBool(false)
}
case string:
b, _ := strconv.ParseBool(data)
field.ReflectValueOf(value).SetBool(b)
2020-02-15 11:04:21 +03:00
default:
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
return nil
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) (err error) {
2020-02-15 11:04:21 +03:00
switch data := v.(type) {
case int64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(data)
2020-02-15 11:04:21 +03:00
case int:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case int8:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case int16:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case int32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case uint:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case uint8:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case uint16:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case uint32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case uint64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case float32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case float64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(int64(data))
2020-02-15 11:04:21 +03:00
case []byte:
2020-02-18 17:56:37 +03:00
return field.Set(value, string(data))
2020-02-15 11:04:21 +03:00
case string:
if i, err := strconv.ParseInt(data, 0, 64); err == nil {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(i)
2020-02-15 11:04:21 +03:00
} else {
return err
}
2020-02-18 17:56:37 +03:00
case time.Time:
2020-06-05 14:18:22 +03:00
if field.AutoCreateTime == UnixNanosecond || field.AutoUpdateTime == UnixNanosecond {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(data.UnixNano())
} else if field.AutoCreateTime == UnixMillisecond || field.AutoUpdateTime == UnixMillisecond {
field.ReflectValueOf(value).SetInt(data.UnixNano() / 1e6)
2020-02-18 17:56:37 +03:00
} else {
field.ReflectValueOf(value).SetInt(data.Unix())
}
case *time.Time:
if data != nil {
2020-06-05 14:18:22 +03:00
if field.AutoCreateTime == UnixNanosecond || field.AutoUpdateTime == UnixNanosecond {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetInt(data.UnixNano())
} else if field.AutoCreateTime == UnixMillisecond || field.AutoUpdateTime == UnixMillisecond {
field.ReflectValueOf(value).SetInt(data.UnixNano() / 1e6)
2020-02-18 17:56:37 +03:00
} else {
field.ReflectValueOf(value).SetInt(data.Unix())
}
} else {
field.ReflectValueOf(value).SetInt(0)
}
2020-02-15 11:04:21 +03:00
default:
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
2020-02-15 19:37:59 +03:00
return err
2020-02-15 11:04:21 +03:00
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) (err error) {
2020-02-15 11:04:21 +03:00
switch data := v.(type) {
case uint64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(data)
2020-02-15 11:04:21 +03:00
case uint:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case uint8:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case uint16:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case uint32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case int64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case int:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case int8:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case int16:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case int32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case float32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case float64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(uint64(data))
2020-02-15 11:04:21 +03:00
case []byte:
2020-02-18 17:56:37 +03:00
return field.Set(value, string(data))
2020-02-15 11:04:21 +03:00
case string:
if i, err := strconv.ParseUint(data, 0, 64); err == nil {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetUint(i)
2020-02-15 11:04:21 +03:00
} else {
return err
}
default:
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
2020-02-15 19:37:59 +03:00
return err
2020-02-15 11:04:21 +03:00
}
case reflect.Float32, reflect.Float64:
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) (err error) {
2020-02-15 11:04:21 +03:00
switch data := v.(type) {
case float64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(data)
2020-02-15 11:04:21 +03:00
case float32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case int64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case int:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case int8:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case int16:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case int32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case uint:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case uint8:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case uint16:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case uint32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case uint64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(float64(data))
2020-02-15 11:04:21 +03:00
case []byte:
2020-02-18 17:56:37 +03:00
return field.Set(value, string(data))
2020-02-15 11:04:21 +03:00
case string:
if i, err := strconv.ParseFloat(data, 64); err == nil {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetFloat(i)
2020-02-15 11:04:21 +03:00
} else {
return err
}
default:
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
2020-02-15 19:37:59 +03:00
return err
2020-02-15 11:04:21 +03:00
}
case reflect.String:
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) (err error) {
2020-02-15 11:04:21 +03:00
switch data := v.(type) {
case string:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetString(data)
2020-02-15 11:04:21 +03:00
case []byte:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetString(string(data))
2020-02-15 11:04:21 +03:00
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetString(fmt.Sprint(data))
2020-02-15 11:04:21 +03:00
case float64, float32:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).SetString(fmt.Sprintf("%."+strconv.Itoa(field.Precision)+"f", data))
2020-02-15 11:04:21 +03:00
default:
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
2020-02-15 19:37:59 +03:00
return err
2020-02-15 11:04:21 +03:00
}
default:
fieldValue := reflect.New(field.FieldType)
2020-02-15 14:45:27 +03:00
switch fieldValue.Elem().Interface().(type) {
2020-02-15 11:04:21 +03:00
case time.Time:
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) error {
2020-02-15 11:04:21 +03:00
switch data := v.(type) {
case time.Time:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).Set(reflect.ValueOf(v))
2020-02-15 11:04:21 +03:00
case *time.Time:
if data != nil {
field.ReflectValueOf(value).Set(reflect.ValueOf(data).Elem())
} else {
field.ReflectValueOf(value).Set(reflect.ValueOf(time.Time{}))
}
2020-02-15 11:04:21 +03:00
case string:
if t, err := now.Parse(data); err == nil {
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).Set(reflect.ValueOf(t))
2020-02-15 11:04:21 +03:00
} else {
return fmt.Errorf("failed to set string %v to time.Time field %v, failed to parse it as time, got error %v", v, field.Name, err)
}
default:
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
return nil
}
case *time.Time:
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) error {
2020-02-15 11:04:21 +03:00
switch data := v.(type) {
case time.Time:
2020-05-29 18:38:03 +03:00
fieldValue := field.ReflectValueOf(value)
if fieldValue.IsNil() {
fieldValue.Set(reflect.New(field.FieldType.Elem()))
}
fieldValue.Elem().Set(reflect.ValueOf(v))
2020-02-15 11:04:21 +03:00
case *time.Time:
2020-02-18 17:56:37 +03:00
field.ReflectValueOf(value).Set(reflect.ValueOf(v))
2020-02-15 11:04:21 +03:00
case string:
if t, err := now.Parse(data); err == nil {
2020-05-29 18:38:03 +03:00
fieldValue := field.ReflectValueOf(value)
if fieldValue.IsNil() {
if v == "" {
return nil
}
fieldValue.Set(reflect.New(field.FieldType.Elem()))
}
fieldValue.Elem().Set(reflect.ValueOf(t))
2020-02-15 11:04:21 +03:00
} else {
return fmt.Errorf("failed to set string %v to time.Time field %v, failed to parse it as time, got error %v", v, field.Name, err)
}
default:
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
return nil
}
default:
if _, ok := fieldValue.Elem().Interface().(sql.Scanner); ok {
// pointer scanner
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) (err error) {
reflectV := reflect.ValueOf(v)
if reflectV.Type().AssignableTo(field.FieldType) {
field.ReflectValueOf(value).Set(reflectV)
} else if reflectV.Kind() == reflect.Ptr {
if reflectV.IsNil() {
field.ReflectValueOf(value).Set(reflect.New(field.FieldType).Elem())
} else {
err = field.Set(value, reflectV.Elem().Interface())
}
2020-05-24 17:52:16 +03:00
} else {
fieldValue := field.ReflectValueOf(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)
2020-02-15 11:04:21 +03:00
}
return
}
} else if _, ok := fieldValue.Interface().(sql.Scanner); ok {
// struct scanner
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) (err error) {
reflectV := reflect.ValueOf(v)
if !reflectV.IsValid() {
field.ReflectValueOf(value).Set(reflect.New(field.FieldType).Elem())
} else if reflectV.Type().AssignableTo(field.FieldType) {
field.ReflectValueOf(value).Set(reflectV)
} else if reflectV.Kind() == reflect.Ptr {
if reflectV.IsNil() || !reflectV.IsValid() {
field.ReflectValueOf(value).Set(reflect.New(field.FieldType).Elem())
} else {
return field.Set(value, reflectV.Elem().Interface())
}
2020-05-24 17:52:16 +03:00
} else {
if valuer, ok := v.(driver.Valuer); ok {
v, _ = valuer.Value()
2020-02-15 19:37:59 +03:00
}
err = field.ReflectValueOf(value).Addr().Interface().(sql.Scanner).Scan(v)
2020-02-15 14:45:27 +03:00
}
2020-02-15 19:37:59 +03:00
return
2020-02-15 14:45:27 +03:00
}
} else {
2020-02-18 17:56:37 +03:00
field.Set = func(value reflect.Value, v interface{}) (err error) {
return fallbackSetter(value, v, field.Set)
2020-02-15 11:04:21 +03:00
}
}
}
}
}