forked from mirror/gorm
Try to cache struct fields
This commit is contained in:
parent
6864d5e5bd
commit
5d692a6bf2
61
field.go
61
field.go
|
@ -4,51 +4,11 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type relationship struct {
|
|
||||||
JoinTable string
|
|
||||||
ForeignKey string
|
|
||||||
ForeignType string
|
|
||||||
AssociationForeignKey string
|
|
||||||
Kind string
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME
|
|
||||||
func (r relationship) ForeignDBName() string {
|
|
||||||
return ToSnake(r.ForeignKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r relationship) AssociationForeignDBName(name string) string {
|
|
||||||
return ToSnake(r.AssociationForeignKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Field struct {
|
type Field struct {
|
||||||
Name string
|
*StructField
|
||||||
DBName string
|
Field reflect.Value
|
||||||
Field reflect.Value
|
|
||||||
Tag reflect.StructTag
|
|
||||||
Relationship *relationship
|
|
||||||
IsNormal bool
|
|
||||||
IsBlank bool
|
|
||||||
IsIgnored bool
|
|
||||||
IsPrimaryKey bool
|
|
||||||
DefaultValue interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (field *Field) IsScanner() bool {
|
|
||||||
_, isScanner := reflect.New(field.Field.Type()).Interface().(sql.Scanner)
|
|
||||||
return isScanner
|
|
||||||
}
|
|
||||||
|
|
||||||
func (field *Field) IsTime() bool {
|
|
||||||
reflectValue := field.Field
|
|
||||||
if reflectValue.Kind() == reflect.Ptr {
|
|
||||||
reflectValue = reflect.New(reflectValue.Type().Elem()).Elem()
|
|
||||||
}
|
|
||||||
_, isTime := reflectValue.Interface().(time.Time)
|
|
||||||
return isTime
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (field *Field) Set(value interface{}) (err error) {
|
func (field *Field) Set(value interface{}) (err error) {
|
||||||
|
@ -76,3 +36,20 @@ func (field *Field) Set(value interface{}) (err error) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type relationship struct {
|
||||||
|
JoinTable string
|
||||||
|
ForeignKey string
|
||||||
|
ForeignType string
|
||||||
|
AssociationForeignKey string
|
||||||
|
Kind string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
func (r relationship) ForeignDBName() string {
|
||||||
|
return ToSnake(r.ForeignKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r relationship) AssociationForeignDBName(name string) string {
|
||||||
|
return ToSnake(r.AssociationForeignKey)
|
||||||
|
}
|
||||||
|
|
179
scope.go
179
scope.go
|
@ -3,7 +3,6 @@ package gorm
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -154,7 +153,7 @@ func (scope *Scope) HasColumn(column string) bool {
|
||||||
|
|
||||||
dbName := ToSnake(column)
|
dbName := ToSnake(column)
|
||||||
|
|
||||||
field, hasColumn := clone.Fields(false)[dbName]
|
field, hasColumn := clone.Fields()[dbName]
|
||||||
return hasColumn && !field.IsIgnored
|
return hasColumn && !field.IsIgnored
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,177 +297,13 @@ func (scope *Scope) FieldByName(name string) (field *Field, ok bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scope *Scope) fieldFromStruct(fieldStruct reflect.StructField, withRelation bool) []*Field {
|
|
||||||
var field Field
|
|
||||||
field.Name = fieldStruct.Name
|
|
||||||
|
|
||||||
value := scope.IndirectValue().FieldByName(fieldStruct.Name)
|
|
||||||
indirectValue := reflect.Indirect(value)
|
|
||||||
field.Field = value
|
|
||||||
field.IsBlank = isBlank(value)
|
|
||||||
|
|
||||||
// Search for primary key tag identifier
|
|
||||||
settings := parseTagSetting(fieldStruct.Tag.Get("gorm"))
|
|
||||||
if _, ok := settings["PRIMARY_KEY"]; ok {
|
|
||||||
field.IsPrimaryKey = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if def, ok := parseTagSetting(fieldStruct.Tag.Get("sql"))["DEFAULT"]; ok {
|
|
||||||
field.DefaultValue = def
|
|
||||||
}
|
|
||||||
|
|
||||||
field.Tag = fieldStruct.Tag
|
|
||||||
|
|
||||||
if value, ok := settings["COLUMN"]; ok {
|
|
||||||
field.DBName = value
|
|
||||||
} else {
|
|
||||||
field.DBName = ToSnake(fieldStruct.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
tagIdentifier := "sql"
|
|
||||||
if scope.db != nil {
|
|
||||||
tagIdentifier = scope.db.parent.tagIdentifier
|
|
||||||
}
|
|
||||||
if fieldStruct.Tag.Get(tagIdentifier) == "-" {
|
|
||||||
field.IsIgnored = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !field.IsIgnored {
|
|
||||||
// parse association
|
|
||||||
if !indirectValue.IsValid() {
|
|
||||||
indirectValue = reflect.New(value.Type())
|
|
||||||
}
|
|
||||||
typ := indirectValue.Type()
|
|
||||||
scopeTyp := scope.IndirectValue().Type()
|
|
||||||
|
|
||||||
foreignKey := SnakeToUpperCamel(settings["FOREIGNKEY"])
|
|
||||||
foreignType := SnakeToUpperCamel(settings["FOREIGNTYPE"])
|
|
||||||
associationForeignKey := SnakeToUpperCamel(settings["ASSOCIATIONFOREIGNKEY"])
|
|
||||||
many2many := settings["MANY2MANY"]
|
|
||||||
polymorphic := SnakeToUpperCamel(settings["POLYMORPHIC"])
|
|
||||||
|
|
||||||
if polymorphic != "" {
|
|
||||||
foreignKey = polymorphic + "Id"
|
|
||||||
foreignType = polymorphic + "Type"
|
|
||||||
}
|
|
||||||
|
|
||||||
switch indirectValue.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
typ = typ.Elem()
|
|
||||||
|
|
||||||
if field.IsScanner() {
|
|
||||||
field.IsNormal = true
|
|
||||||
} else if (typ.Kind() == reflect.Struct) && withRelation {
|
|
||||||
if foreignKey == "" {
|
|
||||||
foreignKey = scopeTyp.Name() + "Id"
|
|
||||||
}
|
|
||||||
if associationForeignKey == "" {
|
|
||||||
associationForeignKey = typ.Name() + "Id"
|
|
||||||
}
|
|
||||||
|
|
||||||
// if not many to many, foreign key could be null
|
|
||||||
if many2many == "" {
|
|
||||||
if !reflect.New(typ).Elem().FieldByName(foreignKey).IsValid() {
|
|
||||||
foreignKey = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
field.Relationship = &relationship{
|
|
||||||
JoinTable: many2many,
|
|
||||||
ForeignKey: foreignKey,
|
|
||||||
ForeignType: foreignType,
|
|
||||||
AssociationForeignKey: associationForeignKey,
|
|
||||||
Kind: "has_many",
|
|
||||||
}
|
|
||||||
|
|
||||||
if many2many != "" {
|
|
||||||
field.Relationship.Kind = "many_to_many"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
field.IsNormal = true
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
if field.IsTime() || field.IsScanner() {
|
|
||||||
field.IsNormal = true
|
|
||||||
} else if _, ok := settings["EMBEDDED"]; ok || fieldStruct.Anonymous {
|
|
||||||
var fields []*Field
|
|
||||||
if field.Field.CanAddr() {
|
|
||||||
for _, field := range scope.New(field.Field.Addr().Interface()).Fields() {
|
|
||||||
field.DBName = field.DBName
|
|
||||||
fields = append(fields, field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fields
|
|
||||||
} else if withRelation {
|
|
||||||
var belongsToForeignKey, hasOneForeignKey, kind string
|
|
||||||
|
|
||||||
if foreignKey == "" {
|
|
||||||
belongsToForeignKey = field.Name + "Id"
|
|
||||||
hasOneForeignKey = scopeTyp.Name() + "Id"
|
|
||||||
} else {
|
|
||||||
belongsToForeignKey = foreignKey
|
|
||||||
hasOneForeignKey = foreignKey
|
|
||||||
}
|
|
||||||
|
|
||||||
if scope.HasColumn(belongsToForeignKey) {
|
|
||||||
foreignKey = belongsToForeignKey
|
|
||||||
kind = "belongs_to"
|
|
||||||
} else {
|
|
||||||
foreignKey = hasOneForeignKey
|
|
||||||
kind = "has_one"
|
|
||||||
}
|
|
||||||
|
|
||||||
field.Relationship = &relationship{ForeignKey: foreignKey, ForeignType: foreignType, Kind: kind}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
field.IsNormal = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []*Field{&field}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields get value's fields
|
// Fields get value's fields
|
||||||
func (scope *Scope) Fields(noRelations ...bool) map[string]*Field {
|
func (scope *Scope) Fields() map[string]*Field {
|
||||||
var withRelation = len(noRelations) == 0
|
fields := map[string]*Field{}
|
||||||
|
structFields := scope.GetStructFields()
|
||||||
if withRelation && scope.fields != nil {
|
for _, structField := range structFields {
|
||||||
return scope.fields
|
field := Field{StructField: structField}
|
||||||
}
|
fields[field.DBName] = &field
|
||||||
|
|
||||||
var fields = map[string]*Field{}
|
|
||||||
if scope.IndirectValue().IsValid() && scope.IndirectValue().Kind() == reflect.Struct {
|
|
||||||
scopeTyp := scope.IndirectValue().Type()
|
|
||||||
var hasPrimaryKey = false
|
|
||||||
for i := 0; i < scopeTyp.NumField(); i++ {
|
|
||||||
fieldStruct := scopeTyp.Field(i)
|
|
||||||
if !ast.IsExported(fieldStruct.Name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, field := range scope.fieldFromStruct(fieldStruct, withRelation) {
|
|
||||||
if field.IsPrimaryKey {
|
|
||||||
hasPrimaryKey = true
|
|
||||||
}
|
|
||||||
if value, ok := fields[field.DBName]; ok {
|
|
||||||
if value.IsIgnored {
|
|
||||||
fields[field.DBName] = field
|
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("Duplicated column name for %v (%v)\n", scope.typeName(), fileWithLineNum()))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fields[field.DBName] = field
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasPrimaryKey {
|
|
||||||
if field, ok := fields["id"]; ok {
|
|
||||||
field.IsPrimaryKey = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if withRelation {
|
|
||||||
scope.fields = fields
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -403,7 +402,7 @@ func (scope *Scope) sqlTagForField(field *Field) (typ string) {
|
||||||
return typ + " " + additionalType
|
return typ + " " + additionalType
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if field.IsScanner() {
|
if field.IsScanner {
|
||||||
var getScannerValue func(reflect.Value)
|
var getScannerValue func(reflect.Value)
|
||||||
getScannerValue = func(value reflect.Value) {
|
getScannerValue = func(value reflect.Value) {
|
||||||
reflectValue = value
|
reflectValue = value
|
||||||
|
@ -412,7 +411,7 @@ func (scope *Scope) sqlTagForField(field *Field) (typ string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getScannerValue(reflectValue.Field(0))
|
getScannerValue(reflectValue.Field(0))
|
||||||
} else if !field.IsTime() {
|
} else if !field.IsTime {
|
||||||
return typ + " " + additionalType
|
return typ + " " + additionalType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -578,24 +577,11 @@ func (scope *Scope) createJoinTable(field *Field) {
|
||||||
|
|
||||||
func (scope *Scope) createTable() *Scope {
|
func (scope *Scope) createTable() *Scope {
|
||||||
var sqls []string
|
var sqls []string
|
||||||
fields := scope.Fields()
|
for _, structField := range scope.GetStructFields() {
|
||||||
scopeType := scope.IndirectValue().Type()
|
if structField.IsNormal {
|
||||||
for i := 0; i < scopeType.NumField(); i++ {
|
sqls = append(sqls, scope.Quote(structField.DBName)+" "+structField.SqlTag)
|
||||||
if !ast.IsExported(scopeType.Field(i).Name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, field := range scope.fieldFromStruct(scopeType.Field(i), false) {
|
|
||||||
name := field.Name
|
|
||||||
for _, field := range fields {
|
|
||||||
if field.Name == name {
|
|
||||||
if field.IsNormal {
|
|
||||||
sqlTag := scope.sqlTagForField(field)
|
|
||||||
sqls = append(sqls, scope.Quote(field.DBName)+" "+sqlTag)
|
|
||||||
}
|
|
||||||
scope.createJoinTable(field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
scope.createJoinTable(structField)
|
||||||
}
|
}
|
||||||
scope.Raw(fmt.Sprintf("CREATE TABLE %v (%v)", scope.QuotedTableName(), strings.Join(sqls, ","))).Exec()
|
scope.Raw(fmt.Sprintf("CREATE TABLE %v (%v)", scope.QuotedTableName(), strings.Join(sqls, ","))).Exec()
|
||||||
return scope
|
return scope
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
package gorm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"go/ast"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StructField struct {
|
||||||
|
Name string
|
||||||
|
DBName string
|
||||||
|
IsBlank bool
|
||||||
|
IsPrimaryKey bool
|
||||||
|
IsScanner bool
|
||||||
|
IsTime bool
|
||||||
|
IsNormal bool
|
||||||
|
IsIgnored bool
|
||||||
|
DefaultValue *string
|
||||||
|
SqlTag string
|
||||||
|
Relationship *relationship
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scope *Scope) GetStructFields() (fields []*StructField) {
|
||||||
|
reflectValue := reflect.Indirect(reflect.ValueOf(scope.Value))
|
||||||
|
if reflectValue.Kind() == reflect.Slice {
|
||||||
|
reflectValue = reflect.Indirect(reflect.New(reflectValue.Elem().Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeTyp := reflectValue.Type()
|
||||||
|
hasPrimaryKey := false
|
||||||
|
for i := 0; i < scopeTyp.NumField(); i++ {
|
||||||
|
fieldStruct := scopeTyp.Field(i)
|
||||||
|
if !ast.IsExported(fieldStruct.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var field *StructField
|
||||||
|
|
||||||
|
if fieldStruct.Tag.Get("sql") == "-" {
|
||||||
|
field.IsIgnored = true
|
||||||
|
} else {
|
||||||
|
sqlSettings := parseTagSetting(fieldStruct.Tag.Get("sql"))
|
||||||
|
settings := parseTagSetting(fieldStruct.Tag.Get("gorm"))
|
||||||
|
if _, ok := settings["PRIMARY_KEY"]; ok {
|
||||||
|
field.IsPrimaryKey = true
|
||||||
|
hasPrimaryKey = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := sqlSettings["DEFAULT"]; ok {
|
||||||
|
field.DefaultValue = &value
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := settings["COLUMN"]; ok {
|
||||||
|
field.DBName = value
|
||||||
|
} else {
|
||||||
|
field.DBName = ToSnake(fieldStruct.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldType, indirectType := fieldStruct.Type, fieldStruct.Type
|
||||||
|
if indirectType.Kind() == reflect.Ptr {
|
||||||
|
indirectType = indirectType.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, isScanner := reflect.New(fieldType).Interface().(sql.Scanner); isScanner {
|
||||||
|
field.IsScanner, field.IsNormal = true, true
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, isTime := reflect.New(indirectType).Interface().(time.Time); isTime {
|
||||||
|
field.IsTime, field.IsNormal = true, true
|
||||||
|
}
|
||||||
|
|
||||||
|
many2many := settings["MANY2MANY"]
|
||||||
|
foreignKey := SnakeToUpperCamel(settings["FOREIGNKEY"])
|
||||||
|
foreignType := SnakeToUpperCamel(settings["FOREIGNTYPE"])
|
||||||
|
associationForeignKey := SnakeToUpperCamel(settings["ASSOCIATIONFOREIGNKEY"])
|
||||||
|
if polymorphic := SnakeToUpperCamel(settings["POLYMORPHIC"]); polymorphic != "" {
|
||||||
|
foreignKey = polymorphic + "Id"
|
||||||
|
foreignType = polymorphic + "Type"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !field.IsNormal {
|
||||||
|
switch indirectType.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
typ := indirectType.Elem()
|
||||||
|
if typ.Kind() == reflect.Ptr {
|
||||||
|
typ = typ.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if typ.Kind() == reflect.Struct {
|
||||||
|
kind := "has_many"
|
||||||
|
|
||||||
|
if foreignKey == "" {
|
||||||
|
foreignKey = indirectType.Name() + "Id"
|
||||||
|
}
|
||||||
|
|
||||||
|
if associationForeignKey == "" {
|
||||||
|
associationForeignKey = typ.Name() + "Id"
|
||||||
|
}
|
||||||
|
|
||||||
|
if many2many != "" {
|
||||||
|
kind = "many_to_many"
|
||||||
|
} else if !reflect.New(typ).FieldByName(foreignKey).IsValid() {
|
||||||
|
foreignKey = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
field.Relationship = &relationship{
|
||||||
|
JoinTable: many2many,
|
||||||
|
ForeignKey: foreignKey,
|
||||||
|
ForeignType: foreignType,
|
||||||
|
AssociationForeignKey: associationForeignKey,
|
||||||
|
Kind: kind,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
field.IsNormal = true
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
if _, ok := settings["EMBEDDED"]; ok || fieldStruct.Anonymous {
|
||||||
|
for _, field := range scope.New(reflect.New(indirectType).Interface()).GetStructFields() {
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
var belongsToForeignKey, hasOneForeignKey, kind string
|
||||||
|
|
||||||
|
if foreignKey == "" {
|
||||||
|
belongsToForeignKey = indirectType.Name() + "Id"
|
||||||
|
hasOneForeignKey = scopeTyp.Name() + "Id"
|
||||||
|
} else {
|
||||||
|
belongsToForeignKey = foreignKey
|
||||||
|
hasOneForeignKey = foreignKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := scopeTyp.FieldByName(belongsToForeignKey); ok {
|
||||||
|
foreignKey = belongsToForeignKey
|
||||||
|
kind = "belongs_to"
|
||||||
|
} else {
|
||||||
|
foreignKey = hasOneForeignKey
|
||||||
|
kind = "has_one"
|
||||||
|
}
|
||||||
|
|
||||||
|
field.Relationship = &relationship{ForeignKey: foreignKey, ForeignType: foreignType, Kind: kind}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
field.IsNormal = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasPrimaryKey {
|
||||||
|
for _, field := range fields {
|
||||||
|
if field.DBName == "id" {
|
||||||
|
field.IsPrimaryKey = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range fields {
|
||||||
|
var sqlType string
|
||||||
|
size := 255
|
||||||
|
sqlTag := field.Tag.Get("sql")
|
||||||
|
sqlSetting = parseTagSetting(sqlTag)
|
||||||
|
|
||||||
|
if value, ok := sqlSetting["SIZE"]; ok {
|
||||||
|
if i, err := strconv.Atoi(value); err == nil {
|
||||||
|
size = i
|
||||||
|
} else {
|
||||||
|
size = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := sqlSetting["TYPE"]; ok {
|
||||||
|
typ = value
|
||||||
|
}
|
||||||
|
|
||||||
|
additionalType := sqlSetting["NOT NULL"] + " " + sqlSetting["UNIQUE"]
|
||||||
|
if value, ok := sqlSetting["DEFAULT"]; ok {
|
||||||
|
additionalType = additionalType + "DEFAULT " + value
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.IsScanner {
|
||||||
|
var getScannerValue func(reflect.Value)
|
||||||
|
getScannerValue = func(reflectValue reflect.Value) {
|
||||||
|
if _, isScanner := reflect.New(reflectValue.Type()).Interface().(sql.Scanner); isScanner {
|
||||||
|
getScannerValue(reflectValue.Field(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getScannerValue(reflectValue.Field(0))
|
||||||
|
}
|
||||||
|
if field.IsNormal {
|
||||||
|
typ + " " + additionalType
|
||||||
|
}
|
||||||
|
} else if !field.IsTime {
|
||||||
|
return typ + " " + additionalType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(typ) == 0 {
|
||||||
|
if field.IsPrimaryKey {
|
||||||
|
typ = scope.Dialect().PrimaryKeyTag(reflectValue, size)
|
||||||
|
} else {
|
||||||
|
typ = scope.Dialect().SqlTag(reflectValue, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return typ + " " + additionalType
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in New Issue