Fix multiple M2M relations on one table, close #3347

This commit is contained in:
Jinzhu 2020-09-01 11:30:16 +08:00
parent 0273856e4d
commit 162367be7d
2 changed files with 66 additions and 27 deletions

View File

@ -254,12 +254,18 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel
}) })
} }
joinTableFields = append(joinTableFields, reflect.StructField{
Name: schema.Name + field.Name,
Type: schema.ModelType,
Tag: `gorm:"-"`,
})
if relation.JoinTable, err = Parse(reflect.New(reflect.StructOf(joinTableFields)).Interface(), schema.cacheStore, schema.namer); err != nil { if relation.JoinTable, err = Parse(reflect.New(reflect.StructOf(joinTableFields)).Interface(), schema.cacheStore, schema.namer); err != nil {
schema.err = err schema.err = err
} }
relation.JoinTable.Name = many2many relation.JoinTable.Name = many2many
relation.JoinTable.Table = schema.namer.JoinTableName(many2many) relation.JoinTable.Table = schema.namer.JoinTableName(many2many)
relation.JoinTable.PrimaryFields = make([]*Field, len(relation.JoinTable.Fields)) relation.JoinTable.PrimaryFields = make([]*Field, 0, len(relation.JoinTable.Fields))
relName := relation.Schema.Name relName := relation.Schema.Name
relRefName := relation.FieldSchema.Name relRefName := relation.FieldSchema.Name
@ -290,36 +296,38 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel
} }
// build references // build references
for idx, f := range relation.JoinTable.Fields { for _, f := range relation.JoinTable.Fields {
// use same data type for foreign keys if f.Creatable {
f.DataType = fieldsMap[f.Name].DataType // use same data type for foreign keys
f.GORMDataType = fieldsMap[f.Name].GORMDataType f.DataType = fieldsMap[f.Name].DataType
relation.JoinTable.PrimaryFields[idx] = f f.GORMDataType = fieldsMap[f.Name].GORMDataType
ownPriamryField := schema == fieldsMap[f.Name].Schema && ownFieldsMap[f.Name] relation.JoinTable.PrimaryFields = append(relation.JoinTable.PrimaryFields, f)
ownPriamryField := schema == fieldsMap[f.Name].Schema && ownFieldsMap[f.Name]
if ownPriamryField { if ownPriamryField {
joinRel := relation.JoinTable.Relationships.Relations[relName] joinRel := relation.JoinTable.Relationships.Relations[relName]
joinRel.Field = relation.Field joinRel.Field = relation.Field
joinRel.References = append(joinRel.References, &Reference{ joinRel.References = append(joinRel.References, &Reference{
PrimaryKey: fieldsMap[f.Name], PrimaryKey: fieldsMap[f.Name],
ForeignKey: f, ForeignKey: f,
}) })
} else { } else {
joinRefRel := relation.JoinTable.Relationships.Relations[relRefName] joinRefRel := relation.JoinTable.Relationships.Relations[relRefName]
if joinRefRel.Field == nil { if joinRefRel.Field == nil {
joinRefRel.Field = relation.Field joinRefRel.Field = relation.Field
}
joinRefRel.References = append(joinRefRel.References, &Reference{
PrimaryKey: fieldsMap[f.Name],
ForeignKey: f,
})
} }
joinRefRel.References = append(joinRefRel.References, &Reference{
PrimaryKey: fieldsMap[f.Name], relation.References = append(relation.References, &Reference{
ForeignKey: f, PrimaryKey: fieldsMap[f.Name],
ForeignKey: f,
OwnPrimaryKey: ownPriamryField,
}) })
} }
relation.References = append(relation.References, &Reference{
PrimaryKey: fieldsMap[f.Name],
ForeignKey: f,
OwnPrimaryKey: ownPriamryField,
})
} }
} }

View File

@ -267,3 +267,34 @@ func TestMany2ManyWithMultiPrimaryKeys(t *testing.T) {
}, },
) )
} }
func TestMultipleMany2Many(t *testing.T) {
type Thing struct {
ID int
}
type Person struct {
ID int
Likes []Thing `gorm:"many2many:likes"`
Dislikes []Thing `gorm:"many2many:dislikes"`
}
checkStructRelation(t, &Person{},
Relation{
Name: "Likes", Type: schema.Many2Many, Schema: "Person", FieldSchema: "Thing",
JoinTable: JoinTable{Name: "likes", Table: "likes"},
References: []Reference{
{"ID", "Person", "PersonID", "likes", "", true},
{"ID", "Thing", "ThingID", "likes", "", false},
},
},
Relation{
Name: "Dislikes", Type: schema.Many2Many, Schema: "Person", FieldSchema: "Thing",
JoinTable: JoinTable{Name: "dislikes", Table: "dislikes"},
References: []Reference{
{"ID", "Person", "PersonID", "dislikes", "", true},
{"ID", "Thing", "ThingID", "dislikes", "", false},
},
},
)
}