fix: soft delete for join.on

This commit is contained in:
chenrui 2022-03-07 14:39:56 +08:00
parent b566ed7913
commit ce13a2a7bc
4 changed files with 60 additions and 1 deletions

View File

@ -107,6 +107,7 @@ func BuildQuerySQL(db *gorm.DB) {
} }
} }
joinQueryClauses := make([]clause.Interface, 0)
for _, join := range db.Statement.Joins { for _, join := range db.Statement.Joins {
if db.Statement.Schema == nil { if db.Statement.Schema == nil {
joins = append(joins, clause.Join{ joins = append(joins, clause.Join{
@ -160,6 +161,10 @@ func BuildQuerySQL(db *gorm.DB) {
exprs = append(exprs, clause.Expr{SQL: onSQL, Vars: vars}) 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{ joins = append(joins, clause.Join{
Type: clause.LeftJoin, Type: clause.LeftJoin,
Table: clause.Table{Name: relation.FieldSchema.Table, Alias: tableAliasName}, 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}) db.Statement.AddClause(clause.From{Joins: joins})
if len(joinQueryClauses) > 0 {
for _, c := range joinQueryClauses {
db.Statement.UpdateModifierJoinClause(c)
}
}
db.Statement.Joins = nil
} else { } else {
db.Statement.AddClauseIfNotExists(clause.From{}) db.Statement.AddClauseIfNotExists(clause.From{})
} }

View File

@ -82,6 +82,24 @@ func (sd SoftDeleteQueryClause) ModifyStatement(stmt *Statement) {
}}) }})
stmt.Clauses["soft_delete_enabled"] = clause.Clause{} 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 { func (DeletedAt) UpdateClauses(f *schema.Field) []clause.Interface {

View File

@ -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 // BuildCondition build condition
func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []clause.Expression { func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []clause.Expression {
if s, ok := query.(string); ok { if s, ok := query.(string); ok {

View File

@ -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) 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
}