forked from mirror/gorm
fix: soft delete for join.on
This commit is contained in:
parent
b566ed7913
commit
ce13a2a7bc
|
@ -107,6 +107,7 @@ func BuildQuerySQL(db *gorm.DB) {
|
|||
}
|
||||
}
|
||||
|
||||
joinQueryClauses := make([]clause.Interface, 0)
|
||||
for _, join := range db.Statement.Joins {
|
||||
if db.Statement.Schema == nil {
|
||||
joins = append(joins, clause.Join{
|
||||
|
@ -160,6 +161,10 @@ func BuildQuerySQL(db *gorm.DB) {
|
|||
exprs = append(exprs, clause.Expr{SQL: onSQL, Vars: vars})
|
||||
}
|
||||
|
||||
if len(relation.FieldSchema.QueryClauses) > 0 {
|
||||
joinQueryClauses = append(joinQueryClauses, relation.FieldSchema.QueryClauses...)
|
||||
}
|
||||
|
||||
joins = append(joins, clause.Join{
|
||||
Type: clause.LeftJoin,
|
||||
Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName},
|
||||
|
@ -172,8 +177,14 @@ func BuildQuerySQL(db *gorm.DB) {
|
|||
}
|
||||
}
|
||||
|
||||
db.Statement.Joins = nil
|
||||
db.Statement.AddClause(clause.From{Joins: joins})
|
||||
|
||||
if len(joinQueryClauses) > 0 {
|
||||
for _, c := range joinQueryClauses {
|
||||
db.Statement.UpdateModifierJoinClause(c)
|
||||
}
|
||||
}
|
||||
db.Statement.Joins = nil
|
||||
} else {
|
||||
db.Statement.AddClauseIfNotExists(clause.From{})
|
||||
}
|
||||
|
|
|
@ -82,6 +82,24 @@ func (sd SoftDeleteQueryClause) ModifyStatement(stmt *Statement) {
|
|||
}})
|
||||
stmt.Clauses["soft_delete_enabled"] = clause.Clause{}
|
||||
}
|
||||
|
||||
// Modify for Joins[i].ON exprs
|
||||
if _, ok := stmt.Clauses["soft_delete_join_enabled"]; !ok && !stmt.Statement.Unscoped {
|
||||
if c, ok := stmt.Clauses["FROM"]; ok && len(stmt.Joins) > 0 {
|
||||
if fromClause, ok := c.Expression.(clause.From); ok && len(fromClause.Joins) > 0 {
|
||||
for i, j := range fromClause.Joins {
|
||||
if sd.Field.Schema != nil && j.Table.Name == sd.Field.Schema.Table {
|
||||
j.ON.Exprs = append(j.ON.Exprs, clause.Eq{
|
||||
Column: clause.Column{Table: j.Table.Alias, Name: sd.Field.DBName}, Value: nil,
|
||||
})
|
||||
}
|
||||
fromClause.Joins[i] = j
|
||||
}
|
||||
}
|
||||
stmt.Clauses["FROM"] = c
|
||||
stmt.Clauses["soft_delete_join_enabled"] = clause.Clause{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (DeletedAt) UpdateClauses(f *schema.Field) []clause.Interface {
|
||||
|
|
|
@ -271,6 +271,13 @@ func (stmt *Statement) AddClauseIfNotExists(v clause.Interface) {
|
|||
}
|
||||
}
|
||||
|
||||
// UpdateModifierJoinClause update join clause for modifier
|
||||
func (stmt *Statement) UpdateModifierJoinClause(v clause.Interface) {
|
||||
if optimizer, ok := v.(StatementModifier); ok {
|
||||
optimizer.ModifyStatement(stmt)
|
||||
}
|
||||
}
|
||||
|
||||
// BuildCondition build condition
|
||||
func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []clause.Expression {
|
||||
if s, ok := query.(string); ok {
|
||||
|
|
|
@ -200,3 +200,26 @@ func TestJoinCount(t *testing.T) {
|
|||
t.Fatalf("result's id, %d, doesn't match user's id, %d", result.ID, user.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/go-gorm/gorm/issues/4918
|
||||
func TestJoinWithSoftDeleted(t *testing.T) {
|
||||
user := User{Name: "TestJoinWithSoftDeleted"}
|
||||
DB.Create(&user)
|
||||
|
||||
pet := Pet{Name: "A", UserID: &user.ID}
|
||||
DB.Create(&pet)
|
||||
|
||||
DB = DB.Debug()
|
||||
|
||||
var user1 User
|
||||
DB.Debug().Model(&User{}).Joins("NamedPet").First(&user1, user.ID)
|
||||
AssertEqual(t, user1.ID, user.ID)
|
||||
AssertEqual(t, user1.NamedPet.ID, pet.ID)
|
||||
|
||||
DB.Delete(&pet)
|
||||
|
||||
var user3 User
|
||||
DB.Model(&User{}).Joins("NamedPet").First(&user3, user.ID)
|
||||
AssertEqual(t, user3.ID, user.ID)
|
||||
AssertEqual(t, user3.NamedPet, nil) // soft deleted for join.on
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue