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 {
 | 
								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{})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -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 {
 | 
				
			||||||
 | 
				
			|||||||
@ -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 {
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user