allow use struct field tag in Exec() and Raw()

This commit is contained in:
houbaron 2023-02-17 19:41:39 +08:00
parent 02b7e26f6b
commit 15d16fba42
7 changed files with 56 additions and 47 deletions

View File

@ -4,6 +4,7 @@ import (
"database/sql"
"database/sql/driver"
"go/ast"
"gorm.io/gorm/utils"
"reflect"
)
@ -107,7 +108,11 @@ func (expr NamedExpr) Build(builder Builder) {
modelType := reflectValue.Type()
for i := 0; i < modelType.NumField(); i++ {
if fieldStruct := modelType.Field(i); ast.IsExported(fieldStruct.Name) {
namedMap[fieldStruct.Name] = reflectValue.Field(i).Interface()
fieldName, exist := utils.ParseTagSetting(fieldStruct.Tag.Get("gorm"), ";")["COLUMN"]
if !exist {
fieldName = fieldStruct.Name
}
namedMap[fieldName] = reflectValue.Field(i).Interface()
if fieldStruct.Anonymous {
appendFieldsToMap(reflectValue.Field(i))

View File

@ -93,7 +93,7 @@ type Field struct {
func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
var (
err error
tagSetting = ParseTagSetting(fieldStruct.Tag.Get("gorm"), ";")
tagSetting = utils.ParseTagSetting(fieldStruct.Tag.Get("gorm"), ";")
)
field := &Field{
@ -141,7 +141,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
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"), ";") {
for key, value := range utils.ParseTagSetting(rvType.Field(i).Tag.Get("gorm"), ";") {
if _, ok := field.TagSettings[key]; !ok {
field.TagSettings[key] = value
}

View File

@ -2,6 +2,7 @@ package schema
import (
"fmt"
"gorm.io/gorm/utils"
"sort"
"strconv"
"strings"
@ -103,7 +104,7 @@ func parseFieldIndexes(field *Field) (indexes []Index, err error) {
tag = strings.Join(v[1:], ":")
idx = strings.Index(tag, ",")
tagSetting = strings.Join(strings.Split(tag, ",")[1:], ",")
settings = ParseTagSetting(tagSetting, ",")
settings = utils.ParseTagSetting(tagSetting, ",")
length, _ = strconv.Atoi(settings["LENGTH"])
)

View File

@ -3,6 +3,7 @@ package schema
import (
"context"
"fmt"
"gorm.io/gorm/utils"
"reflect"
"strings"
@ -123,16 +124,17 @@ func (schema *Schema) parseRelation(field *Field) *Relationship {
}
// User has many Toys, its `Polymorphic` is `Owner`, Pet has one Toy, its `Polymorphic` is `Owner`
// type User struct {
// Toys []Toy `gorm:"polymorphic:Owner;"`
// }
// type Pet struct {
// Toy Toy `gorm:"polymorphic:Owner;"`
// }
// type Toy struct {
// OwnerID int
// OwnerType string
// }
//
// type User struct {
// Toys []Toy `gorm:"polymorphic:Owner;"`
// }
// type Pet struct {
// Toy Toy `gorm:"polymorphic:Owner;"`
// }
// type Toy struct {
// OwnerID int
// OwnerType string
// }
func (schema *Schema) buildPolymorphicRelation(relation *Relationship, field *Field, polymorphic string) {
relation.Polymorphic = &Polymorphic{
Value: schema.Table,
@ -555,7 +557,7 @@ func (rel *Relationship) ParseConstraint() *Constraint {
var (
name string
idx = strings.Index(str, ",")
settings = ParseTagSetting(str, ",")
settings = utils.ParseTagSetting(str, ",")
)
// optimize match english letters and midline

View File

@ -3,6 +3,7 @@ package schema_test
import (
"context"
"fmt"
"gorm.io/gorm/utils"
"reflect"
"strings"
"testing"
@ -44,7 +45,7 @@ func checkSchemaField(t *testing.T, s *schema.Schema, f *schema.Field, fc func(*
if f.TagSettings == nil {
if f.Tag != "" {
f.TagSettings = schema.ParseTagSetting(f.Tag.Get("gorm"), ";")
f.TagSettings = utils.ParseTagSetting(f.Tag.Get("gorm"), ";")
} else {
f.TagSettings = map[string]string{}
}

View File

@ -13,37 +13,6 @@ import (
var embeddedCacheKey = "embedded_cache_store"
func ParseTagSetting(str string, sep string) map[string]string {
settings := map[string]string{}
names := strings.Split(str, sep)
for i := 0; i < len(names); i++ {
j := i
if len(names[j]) > 0 {
for {
if names[j][len(names[j])-1] == '\\' {
i++
names[j] = names[j][0:len(names[j])-1] + sep + names[i]
names[i] = ""
} else {
break
}
}
}
values := strings.Split(names[j], ":")
k := strings.TrimSpace(strings.ToUpper(values[0]))
if len(values) >= 2 {
settings[k] = strings.Join(values[1:], ":")
} else if k != "" {
settings[k] = k
}
}
return settings
}
func toColumns(val string) (results []string) {
if val != "" {
for _, v := range strings.Split(val, ",") {

View File

@ -131,3 +131,34 @@ func ToString(value interface{}) string {
}
return ""
}
func ParseTagSetting(str string, sep string) map[string]string {
settings := map[string]string{}
names := strings.Split(str, sep)
for i := 0; i < len(names); i++ {
j := i
if len(names[j]) > 0 {
for {
if names[j][len(names[j])-1] == '\\' {
i++
names[j] = names[j][0:len(names[j])-1] + sep + names[i]
names[i] = ""
} else {
break
}
}
}
values := strings.Split(names[j], ":")
k := strings.TrimSpace(strings.ToUpper(values[0]))
if len(values) >= 2 {
settings[k] = strings.Join(values[1:], ":")
} else if k != "" {
settings[k] = k
}
}
return settings
}