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 {
|
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…
Reference in New Issue