Unscoped on belongs_to association
This commit is contained in:
parent
59d4c98621
commit
d7e625bdae
@ -74,14 +74,30 @@ func (association *Association) Append(values ...interface{}) error {
|
|||||||
|
|
||||||
func (association *Association) Replace(values ...interface{}) error {
|
func (association *Association) Replace(values ...interface{}) error {
|
||||||
if association.Error == nil {
|
if association.Error == nil {
|
||||||
|
reflectValue := association.DB.Statement.ReflectValue
|
||||||
|
rel := association.Relationship
|
||||||
|
|
||||||
|
var oldBelongsToExpr clause.Expression
|
||||||
|
// we have to record the old BelongsTo value
|
||||||
|
if association.Unscope && rel.Type == schema.BelongsTo {
|
||||||
|
var foreignFields []*schema.Field
|
||||||
|
for _, ref := range rel.References {
|
||||||
|
if !ref.OwnPrimaryKey {
|
||||||
|
foreignFields = append(foreignFields, ref.ForeignKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, fvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, foreignFields); len(fvs) > 0 {
|
||||||
|
column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, fvs)
|
||||||
|
oldBelongsToExpr = clause.IN{Column: column, Values: values}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// save associations
|
// save associations
|
||||||
if association.saveAssociation( /*clear*/ true, values...); association.Error != nil {
|
if association.saveAssociation( /*clear*/ true, values...); association.Error != nil {
|
||||||
return association.Error
|
return association.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// set old associations's foreign key to null
|
// set old associations's foreign key to null
|
||||||
reflectValue := association.DB.Statement.ReflectValue
|
|
||||||
rel := association.Relationship
|
|
||||||
switch rel.Type {
|
switch rel.Type {
|
||||||
case schema.BelongsTo:
|
case schema.BelongsTo:
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
@ -101,6 +117,9 @@ func (association *Association) Replace(values ...interface{}) error {
|
|||||||
|
|
||||||
association.Error = association.DB.UpdateColumns(updateMap).Error
|
association.Error = association.DB.UpdateColumns(updateMap).Error
|
||||||
}
|
}
|
||||||
|
if association.Unscope && oldBelongsToExpr != nil {
|
||||||
|
association.Error = association.DB.Model(nil).Where(oldBelongsToExpr).Delete(reflect.New(rel.FieldSchema.ModelType).Interface()).Error
|
||||||
|
}
|
||||||
case schema.HasOne, schema.HasMany:
|
case schema.HasOne, schema.HasMany:
|
||||||
var (
|
var (
|
||||||
primaryFields []*schema.Field
|
primaryFields []*schema.Field
|
||||||
@ -198,7 +217,8 @@ func (association *Association) Delete(values ...interface{}) error {
|
|||||||
|
|
||||||
switch rel.Type {
|
switch rel.Type {
|
||||||
case schema.BelongsTo:
|
case schema.BelongsTo:
|
||||||
tx := association.DB.Model(reflect.New(rel.Schema.ModelType).Interface())
|
associationDB := association.DB.Session(&Session{})
|
||||||
|
tx := associationDB.Model(reflect.New(rel.Schema.ModelType).Interface())
|
||||||
|
|
||||||
_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, rel.Schema.PrimaryFields)
|
_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, rel.Schema.PrimaryFields)
|
||||||
if pcolumn, pvalues := schema.ToQueryValues(rel.Schema.Table, rel.Schema.PrimaryFieldDBNames, pvs); len(pvalues) > 0 {
|
if pcolumn, pvalues := schema.ToQueryValues(rel.Schema.Table, rel.Schema.PrimaryFieldDBNames, pvs); len(pvalues) > 0 {
|
||||||
@ -212,6 +232,18 @@ func (association *Association) Delete(values ...interface{}) error {
|
|||||||
conds = append(conds, clause.IN{Column: relColumn, Values: relValues})
|
conds = append(conds, clause.IN{Column: relColumn, Values: relValues})
|
||||||
|
|
||||||
association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
|
association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
|
||||||
|
if association.Unscope {
|
||||||
|
var foreignFields []*schema.Field
|
||||||
|
for _, ref := range rel.References {
|
||||||
|
if !ref.OwnPrimaryKey {
|
||||||
|
foreignFields = append(foreignFields, ref.ForeignKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, fvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, foreignFields); len(fvs) > 0 {
|
||||||
|
column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, fvs)
|
||||||
|
association.Error = associationDB.Model(nil).Where(clause.IN{Column: column, Values: values}).Delete(reflect.New(rel.FieldSchema.ModelType).Interface()).Error
|
||||||
|
}
|
||||||
|
}
|
||||||
case schema.HasOne, schema.HasMany:
|
case schema.HasOne, schema.HasMany:
|
||||||
model := reflect.New(rel.FieldSchema.ModelType).Interface()
|
model := reflect.New(rel.FieldSchema.ModelType).Interface()
|
||||||
tx := association.DB.Model(model)
|
tx := association.DB.Model(model)
|
||||||
|
@ -251,3 +251,58 @@ func TestBelongsToDefaultValue(t *testing.T) {
|
|||||||
err := DB.Create(&user).Error
|
err := DB.Create(&user).Error
|
||||||
AssertEqual(t, err, nil)
|
AssertEqual(t, err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBelongsToAssociationUnscoped(t *testing.T) {
|
||||||
|
type ItemParent struct {
|
||||||
|
gorm.Model
|
||||||
|
Logo string `gorm:"not null;type:varchar(50)"`
|
||||||
|
}
|
||||||
|
type ItemChild struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string `gorm:"type:varchar(50)"`
|
||||||
|
ItemParentID uint
|
||||||
|
ItemParent ItemParent
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := DB.Session(&gorm.Session{})
|
||||||
|
tx.Migrator().DropTable(&ItemParent{}, &ItemChild{})
|
||||||
|
tx.AutoMigrate(&ItemParent{}, &ItemChild{})
|
||||||
|
|
||||||
|
item := ItemChild{
|
||||||
|
Name: "name",
|
||||||
|
ItemParent: ItemParent{
|
||||||
|
Logo: "logo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := tx.Create(&item).Error; err != nil {
|
||||||
|
t.Fatalf("failed to create items, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx = tx.Debug()
|
||||||
|
|
||||||
|
// test replace
|
||||||
|
if err := tx.Model(&item).Association("ItemParent").Unscoped().Replace(&ItemParent{
|
||||||
|
Logo: "updated logo",
|
||||||
|
}); err != nil {
|
||||||
|
t.Errorf("failed to replace item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var parents []ItemParent
|
||||||
|
if err := tx.Find(&parents).Error; err != nil {
|
||||||
|
t.Errorf("failed to find item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
if len(parents) != 1 {
|
||||||
|
t.Errorf("expected %d parents, got %d", 1, len(parents))
|
||||||
|
}
|
||||||
|
|
||||||
|
// test delete
|
||||||
|
if err := tx.Model(&item).Association("ItemParent").Unscoped().Delete(&parents); err != nil {
|
||||||
|
t.Errorf("failed to delete item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
if err := tx.Find(&parents).Error; err != nil {
|
||||||
|
t.Errorf("failed to find item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
if len(parents) != 0 {
|
||||||
|
t.Errorf("expected %d parents, got %d", 0, len(parents))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user