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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user