mirror of https://github.com/go-gorm/gorm.git
Fix NamingStrategy with embedded struct, close #3513
This commit is contained in:
parent
68920449f9
commit
1a526e6802
|
@ -326,7 +326,7 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
|
|||
|
||||
cacheStore := &sync.Map{}
|
||||
cacheStore.Store(embeddedCacheKey, true)
|
||||
if field.EmbeddedSchema, err = Parse(fieldValue.Interface(), cacheStore, schema.namer); err != nil {
|
||||
if field.EmbeddedSchema, err = Parse(fieldValue.Interface(), cacheStore, embeddedNamer{Table: schema.Table, Namer: schema.namer}); err != nil {
|
||||
schema.err = err
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
type Namer interface {
|
||||
TableName(table string) string
|
||||
ColumnName(table, column string) string
|
||||
JoinTableName(table string) string
|
||||
JoinTableName(joinTable string) string
|
||||
RelationshipFKName(Relationship) string
|
||||
CheckerName(table, column string) string
|
||||
IndexName(table, column string) string
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package schema
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -32,3 +33,28 @@ func TestToDBName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
type NewNamingStrategy struct {
|
||||
NamingStrategy
|
||||
}
|
||||
|
||||
func (ns NewNamingStrategy) ColumnName(table, column string) string {
|
||||
baseColumnName := ns.NamingStrategy.ColumnName(table, column)
|
||||
|
||||
if table == "" {
|
||||
return baseColumnName
|
||||
}
|
||||
|
||||
s := strings.Split(table, "_")
|
||||
|
||||
var prefix string
|
||||
switch len(s) {
|
||||
case 1:
|
||||
prefix = s[0][:3]
|
||||
case 2:
|
||||
prefix = s[0][:1] + s[1][:2]
|
||||
default:
|
||||
prefix = s[0][:1] + s[1][:1] + s[2][:1]
|
||||
}
|
||||
return prefix + "_" + baseColumnName
|
||||
}
|
||||
|
|
|
@ -97,6 +97,9 @@ func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error)
|
|||
if tabler, ok := modelValue.Interface().(Tabler); ok {
|
||||
tableName = tabler.TableName()
|
||||
}
|
||||
if en, ok := namer.(embeddedNamer); ok {
|
||||
tableName = en.Table
|
||||
}
|
||||
|
||||
schema := &Schema{
|
||||
Name: modelType.Name(),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package schema_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
|
@ -227,3 +228,72 @@ func TestEmbeddedStruct(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
type CustomizedNamingStrategy struct {
|
||||
schema.NamingStrategy
|
||||
}
|
||||
|
||||
func (ns CustomizedNamingStrategy) ColumnName(table, column string) string {
|
||||
baseColumnName := ns.NamingStrategy.ColumnName(table, column)
|
||||
|
||||
if table == "" {
|
||||
return baseColumnName
|
||||
}
|
||||
|
||||
s := strings.Split(table, "_")
|
||||
|
||||
var prefix string
|
||||
switch len(s) {
|
||||
case 1:
|
||||
prefix = s[0][:3]
|
||||
case 2:
|
||||
prefix = s[0][:1] + s[1][:2]
|
||||
default:
|
||||
prefix = s[0][:1] + s[1][:1] + s[2][:1]
|
||||
}
|
||||
return prefix + "_" + baseColumnName
|
||||
}
|
||||
|
||||
func TestEmbeddedStructForCustomizedNamingStrategy(t *testing.T) {
|
||||
type CorpBase struct {
|
||||
gorm.Model
|
||||
OwnerID string
|
||||
}
|
||||
|
||||
type Company struct {
|
||||
ID int
|
||||
OwnerID int
|
||||
Name string
|
||||
Ignored string `gorm:"-"`
|
||||
}
|
||||
|
||||
type Corp struct {
|
||||
CorpBase
|
||||
Base Company `gorm:"embedded;embeddedPrefix:company_"`
|
||||
}
|
||||
|
||||
cropSchema, err := schema.Parse(&Corp{}, &sync.Map{}, CustomizedNamingStrategy{schema.NamingStrategy{}})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse embedded struct with primary key, got error %v", err)
|
||||
}
|
||||
|
||||
fields := []schema.Field{
|
||||
{Name: "ID", DBName: "cor_id", BindNames: []string{"CorpBase", "Model", "ID"}, DataType: schema.Uint, PrimaryKey: true, Size: 64, HasDefaultValue: true, AutoIncrement: true, TagSettings: map[string]string{"PRIMARYKEY": "PRIMARYKEY"}},
|
||||
{Name: "ID", DBName: "company_cor_id", BindNames: []string{"Base", "ID"}, DataType: schema.Int, Size: 64, TagSettings: map[string]string{"EMBEDDED": "EMBEDDED", "EMBEDDEDPREFIX": "company_"}},
|
||||
{Name: "Name", DBName: "company_cor_name", BindNames: []string{"Base", "Name"}, DataType: schema.String, TagSettings: map[string]string{"EMBEDDED": "EMBEDDED", "EMBEDDEDPREFIX": "company_"}},
|
||||
{Name: "Ignored", BindNames: []string{"Base", "Ignored"}, TagSettings: map[string]string{"-": "-", "EMBEDDED": "EMBEDDED", "EMBEDDEDPREFIX": "company_"}},
|
||||
{Name: "OwnerID", DBName: "company_cor_owner_id", BindNames: []string{"Base", "OwnerID"}, DataType: schema.Int, Size: 64, TagSettings: map[string]string{"EMBEDDED": "EMBEDDED", "EMBEDDEDPREFIX": "company_"}},
|
||||
{Name: "OwnerID", DBName: "cor_owner_id", BindNames: []string{"CorpBase", "OwnerID"}, DataType: schema.String},
|
||||
}
|
||||
|
||||
for _, f := range fields {
|
||||
checkSchemaField(t, cropSchema, &f, func(f *schema.Field) {
|
||||
if f.Name != "Ignored" {
|
||||
f.Creatable = true
|
||||
f.Updatable = true
|
||||
f.Readable = true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,3 +190,8 @@ func ToQueryValues(table string, foreignKeys []string, foreignValues [][]interfa
|
|||
return columns, queryValues
|
||||
}
|
||||
}
|
||||
|
||||
type embeddedNamer struct {
|
||||
Table string
|
||||
Namer
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ require (
|
|||
github.com/jinzhu/now v1.1.1
|
||||
github.com/lib/pq v1.6.0
|
||||
gorm.io/driver/mysql v1.0.1
|
||||
gorm.io/driver/postgres v1.0.0
|
||||
gorm.io/driver/postgres v1.0.1
|
||||
gorm.io/driver/sqlite v1.1.3
|
||||
gorm.io/driver/sqlserver v1.0.4
|
||||
gorm.io/gorm v1.20.1
|
||||
|
|
Loading…
Reference in New Issue