mirror of https://github.com/go-gorm/gorm.git
Test override foreign key, reference
This commit is contained in:
parent
aa959ec383
commit
49310d0974
|
@ -168,29 +168,74 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel
|
|||
joinTableFields []reflect.StructField
|
||||
fieldsMap = map[string]*Field{}
|
||||
ownFieldsMap = map[string]bool{} // fix self join many2many
|
||||
joinForeignKeys = toColumns(field.TagSettings["JOINFOREIGNKEY"])
|
||||
joinReferences = toColumns(field.TagSettings["JOINREFERENCES"])
|
||||
)
|
||||
|
||||
for _, s := range []*Schema{schema, relation.FieldSchema} {
|
||||
for _, primaryField := range s.PrimaryFields {
|
||||
fieldName := s.Name + primaryField.Name
|
||||
if _, ok := fieldsMap[fieldName]; ok {
|
||||
if field.Name != s.Name {
|
||||
fieldName = inflection.Singular(field.Name) + primaryField.Name
|
||||
ownForeignFields := schema.PrimaryFields
|
||||
refForeignFields := relation.FieldSchema.PrimaryFields
|
||||
|
||||
if len(relation.foreignKeys) > 0 {
|
||||
ownForeignFields = []*Field{}
|
||||
for _, foreignKey := range relation.foreignKeys {
|
||||
if field := schema.LookUpField(foreignKey); field != nil {
|
||||
ownForeignFields = append(ownForeignFields, field)
|
||||
} else {
|
||||
fieldName = s.Name + primaryField.Name + "Reference"
|
||||
schema.err = fmt.Errorf("invalid foreign key: %v", foreignKey)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ownFieldsMap[fieldName] = true
|
||||
}
|
||||
|
||||
fieldsMap[fieldName] = primaryField
|
||||
if len(relation.primaryKeys) > 0 {
|
||||
refForeignFields = []*Field{}
|
||||
for _, foreignKey := range relation.primaryKeys {
|
||||
if field := relation.FieldSchema.LookUpField(foreignKey); field != nil {
|
||||
refForeignFields = append(refForeignFields, field)
|
||||
} else {
|
||||
schema.err = fmt.Errorf("invalid foreign key: %v", foreignKey)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for idx, ownField := range ownForeignFields {
|
||||
joinFieldName := schema.Name + ownField.Name
|
||||
if len(joinForeignKeys) > idx {
|
||||
joinFieldName = joinForeignKeys[idx]
|
||||
}
|
||||
|
||||
ownFieldsMap[joinFieldName] = true
|
||||
fieldsMap[joinFieldName] = ownField
|
||||
joinTableFields = append(joinTableFields, reflect.StructField{
|
||||
Name: fieldName,
|
||||
PkgPath: primaryField.StructField.PkgPath,
|
||||
Type: primaryField.StructField.Type,
|
||||
Tag: removeSettingFromTag(primaryField.StructField.Tag, "column"),
|
||||
Name: joinFieldName,
|
||||
PkgPath: ownField.StructField.PkgPath,
|
||||
Type: ownField.StructField.Type,
|
||||
Tag: removeSettingFromTag(ownField.StructField.Tag, "column"),
|
||||
})
|
||||
}
|
||||
|
||||
for idx, relField := range refForeignFields {
|
||||
joinFieldName := relation.FieldSchema.Name + relField.Name
|
||||
if len(joinReferences) > idx {
|
||||
joinFieldName = joinReferences[idx]
|
||||
}
|
||||
|
||||
if _, ok := ownFieldsMap[joinFieldName]; ok {
|
||||
if field.Name != relation.FieldSchema.Name {
|
||||
joinFieldName = inflection.Singular(field.Name) + relField.Name
|
||||
} else {
|
||||
joinFieldName += "Reference"
|
||||
}
|
||||
}
|
||||
|
||||
fieldsMap[joinFieldName] = relField
|
||||
joinTableFields = append(joinTableFields, reflect.StructField{
|
||||
Name: joinFieldName,
|
||||
PkgPath: relField.StructField.PkgPath,
|
||||
Type: relField.StructField.Type,
|
||||
Tag: removeSettingFromTag(relField.StructField.Tag, "column"),
|
||||
})
|
||||
}
|
||||
|
||||
if relation.JoinTable, err = Parse(reflect.New(reflect.StructOf(joinTableFields)).Interface(), schema.cacheStore, schema.namer); err != nil {
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
package schema_test
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/jinzhu/gorm/schema"
|
||||
)
|
||||
|
||||
func checkStructRelation(t *testing.T, data interface{}, relations ...Relation) {
|
||||
if s, err := schema.Parse(data, &sync.Map{}, schema.NamingStrategy{}); err != nil {
|
||||
t.Errorf("Failed to parse schema")
|
||||
} else {
|
||||
for _, rel := range relations {
|
||||
checkSchemaRelation(t, s, rel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBelongsToOverrideForeignKey(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Profile Profile `gorm:"ForeignKey:ProfileRefer"`
|
||||
ProfileRefer int
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile",
|
||||
References: []Reference{{"ID", "Profile", "ProfileRefer", "User", "", false}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestBelongsToOverrideReferences(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Refer string
|
||||
Name string
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Profile Profile `gorm:"ForeignKey:ProfileID;References:Refer"`
|
||||
ProfileID int
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile",
|
||||
References: []Reference{{"Refer", "Profile", "ProfileID", "User", "", false}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestHasOneOverrideForeignKey(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
UserRefer uint
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Profile Profile `gorm:"ForeignKey:UserRefer"`
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
||||
References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestHasOneOverrideReferences(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
UserID uint
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Refer string
|
||||
Profile Profile `gorm:"ForeignKey:UserID;References:Refer"`
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
||||
References: []Reference{{"Refer", "User", "UserID", "Profile", "", true}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestHasManyOverrideForeignKey(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
UserRefer uint
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Profile []Profile `gorm:"ForeignKey:UserRefer"`
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profile", Type: schema.HasMany, Schema: "User", FieldSchema: "Profile",
|
||||
References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestHasManyOverrideReferences(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
UserID uint
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Refer string
|
||||
Profile []Profile `gorm:"ForeignKey:UserID;References:Refer"`
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profile", Type: schema.HasMany, Schema: "User", FieldSchema: "Profile",
|
||||
References: []Reference{{"Refer", "User", "UserID", "Profile", "", true}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestMany2ManyOverrideForeignKeyAndReferences(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
UserRefer uint
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Profiles []Profile `gorm:"many2many:user_profiles;ForeignKey:Refer;JoinForeignKey:UserReferID;References:UserRefer;JoinReferences:ProfileRefer"`
|
||||
Refer uint
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
||||
JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"},
|
||||
References: []Reference{
|
||||
{"Refer", "User", "UserReferID", "user_profiles", "", true},
|
||||
{"UserRefer", "Profile", "ProfileRefer", "user_profiles", "", false},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestMany2ManyOverrideForeignKey(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
UserRefer uint
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Profiles []Profile `gorm:"many2many:user_profiles;ForeignKey:Refer;References:UserRefer"`
|
||||
Refer uint
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
||||
JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"},
|
||||
References: []Reference{
|
||||
{"Refer", "User", "UserRefer", "user_profiles", "", true},
|
||||
{"UserRefer", "Profile", "ProfileUserRefer", "user_profiles", "", false},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestMany2ManyOverrideJoinForeignKey(t *testing.T) {
|
||||
type Profile struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
UserRefer uint
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Profiles []Profile `gorm:"many2many:user_profiles;JoinForeignKey:UserReferID;JoinReferences:ProfileRefer"`
|
||||
Refer uint
|
||||
}
|
||||
|
||||
checkStructRelation(t, &User{}, Relation{
|
||||
Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
||||
JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"},
|
||||
References: []Reference{
|
||||
{"ID", "User", "UserReferID", "user_profiles", "", true},
|
||||
{"ID", "Profile", "ProfileRefer", "user_profiles", "", false},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -127,7 +127,7 @@ func checkSchemaRelation(t *testing.T, s *schema.Schema, relation Relation) {
|
|||
}
|
||||
|
||||
if r.FieldSchema.Name != relation.FieldSchema {
|
||||
t.Errorf("schema %v relation's schema expects %v, but got %v", s, relation.Schema, r.Schema.Name)
|
||||
t.Errorf("schema %v field relation's schema expects %v, but got %v", s, relation.FieldSchema, r.FieldSchema.Name)
|
||||
}
|
||||
|
||||
if r.Polymorphic != nil {
|
||||
|
|
Loading…
Reference in New Issue