12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001 |
- 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.PointerTo(field.IndirectFieldType))
- }
- }
|