From dc3f2394b72a13c94faa0893f155ac4893ee85df Mon Sep 17 00:00:00 2001 From: sirius <916108538@qq.com> Date: Thu, 17 Apr 2025 11:43:14 +0800 Subject: [PATCH] FIX:Optimistic Lock in BeforeUpdate: PK Condition Placement Affecting DB Plan Efficiency --- callbacks/update.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/callbacks/update.go b/callbacks/update.go index 7cde7f61..be18e181 100644 --- a/callbacks/update.go +++ b/callbacks/update.go @@ -259,6 +259,7 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) { switch updatingValue.Kind() { case reflect.Struct: set = make([]clause.Assignment, 0, len(stmt.Schema.FieldsByDBName)) + priExpr := make([]clause.Expression, 0) for _, dbName := range stmt.Schema.DBNames { if field := updatingSchema.LookUpField(dbName); field != nil { if !field.PrimaryKey || !updatingValue.CanAddr() || stmt.Dest != stmt.Model { @@ -290,11 +291,26 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) { } } else { if value, isZero := field.ValueOf(stmt.Context, updatingValue); !isZero { - stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.Eq{Column: field.DBName, Value: value}}}) + // stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.Eq{Column: field.DBName, Value: value}}}) + priExpr = append(priExpr, clause.Eq{Column: field.DBName, Value: value}) + } } } } + if len(priExpr) > 0 { + where := clause.Where{Exprs: priExpr} + wname := where.Name() + existWc := stmt.Clauses[wname] + existWc.Name = wname + if existingWhere, ok := existWc.Expression.(clause.Where); ok { + where.Exprs = append(priExpr, existingWhere.Exprs...) + existWc.Expression = where + stmt.Clauses[wname] = existWc + } + existWc.Expression = where + stmt.Clauses[wname] = existWc + } default: stmt.AddError(gorm.ErrInvalidData) }