forked from mirror/gorm
Fix associations using composite primary keys without ID field, close #3365
This commit is contained in:
parent
130f24090d
commit
fcb666cfa3
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
|
"gorm.io/gorm/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SaveBeforeAssociations(db *gorm.DB) {
|
func SaveBeforeAssociations(db *gorm.DB) {
|
||||||
|
@ -145,7 +146,7 @@ func SaveAfterAssociations(db *gorm.DB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
db.AddError(db.Session(&gorm.Session{}).Clauses(clause.OnConflict{
|
db.AddError(db.Session(&gorm.Session{}).Clauses(clause.OnConflict{
|
||||||
Columns: []clause.Column{{Name: rel.FieldSchema.PrioritizedPrimaryField.DBName}},
|
Columns: onConflictColumns(rel.FieldSchema),
|
||||||
DoUpdates: clause.AssignmentColumns(assignmentColumns),
|
DoUpdates: clause.AssignmentColumns(assignmentColumns),
|
||||||
}).Create(elems.Interface()).Error)
|
}).Create(elems.Interface()).Error)
|
||||||
}
|
}
|
||||||
|
@ -168,7 +169,7 @@ func SaveAfterAssociations(db *gorm.DB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
db.AddError(db.Session(&gorm.Session{}).Clauses(clause.OnConflict{
|
db.AddError(db.Session(&gorm.Session{}).Clauses(clause.OnConflict{
|
||||||
Columns: []clause.Column{{Name: rel.FieldSchema.PrioritizedPrimaryField.DBName}},
|
Columns: onConflictColumns(rel.FieldSchema),
|
||||||
DoUpdates: clause.AssignmentColumns(assignmentColumns),
|
DoUpdates: clause.AssignmentColumns(assignmentColumns),
|
||||||
}).Create(f.Interface()).Error)
|
}).Create(f.Interface()).Error)
|
||||||
}
|
}
|
||||||
|
@ -230,7 +231,7 @@ func SaveAfterAssociations(db *gorm.DB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
db.AddError(db.Session(&gorm.Session{}).Clauses(clause.OnConflict{
|
db.AddError(db.Session(&gorm.Session{}).Clauses(clause.OnConflict{
|
||||||
Columns: []clause.Column{{Name: rel.FieldSchema.PrioritizedPrimaryField.DBName}},
|
Columns: onConflictColumns(rel.FieldSchema),
|
||||||
DoUpdates: clause.AssignmentColumns(assignmentColumns),
|
DoUpdates: clause.AssignmentColumns(assignmentColumns),
|
||||||
}).Create(elems.Interface()).Error)
|
}).Create(elems.Interface()).Error)
|
||||||
}
|
}
|
||||||
|
@ -310,3 +311,14 @@ func SaveAfterAssociations(db *gorm.DB) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func onConflictColumns(s *schema.Schema) (columns []clause.Column) {
|
||||||
|
if s.PrioritizedPrimaryField != nil {
|
||||||
|
return []clause.Column{{Name: s.PrioritizedPrimaryField.DBName}}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dbName := range s.PrimaryFieldDBNames {
|
||||||
|
columns = append(columns, clause.Column{Name: dbName})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
. "gorm.io/gorm/utils/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Blog struct {
|
type Blog struct {
|
||||||
|
@ -410,3 +411,38 @@ func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) {
|
||||||
t.Fatalf("EN Blog's tags should be cleared")
|
t.Fatalf("EN Blog's tags should be cleared")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompositePrimaryKeysAssociations(t *testing.T) {
|
||||||
|
type Label struct {
|
||||||
|
BookID *uint `gorm:"primarykey"`
|
||||||
|
Name string `gorm:"primarykey"`
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Book struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Labels []Label
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&Label{}, &Book{})
|
||||||
|
if err := DB.AutoMigrate(&Label{}, &Book{}); err != nil {
|
||||||
|
t.Fatalf("failed to migrate")
|
||||||
|
}
|
||||||
|
|
||||||
|
book := Book{
|
||||||
|
Name: "my book",
|
||||||
|
Labels: []Label{
|
||||||
|
{Name: "region", Value: "emea"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Create(&book)
|
||||||
|
|
||||||
|
var result Book
|
||||||
|
if err := DB.Preload("Labels").First(&result, book.ID).Error; err != nil {
|
||||||
|
t.Fatalf("failed to preload, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertEqual(t, book, result)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue