github.com/wfusion/gofusion@v1.1.14/db/softdelete/deleted.go (about) 1 package softdelete 2 3 import ( 4 "database/sql/driver" 5 "strconv" 6 7 "gorm.io/gorm" 8 "gorm.io/gorm/clause" 9 "gorm.io/gorm/schema" 10 11 "github.com/wfusion/gofusion/common/utils/serialize/json" 12 ) 13 14 type Deleted bool 15 16 // Scan implements the Scanner interface. 17 func (s *Deleted) Scan(value any) (err error) { 18 var b bool 19 if err = convertAssignRows(&b, value, nil); err != nil { 20 return 21 } 22 *s = Deleted(b) 23 return 24 } 25 26 // Value implements the driver Valuer interface. 27 func (s Deleted) Value() (driver.Value, error) { 28 return bool(s), nil 29 } 30 31 func (s Deleted) MarshalJSON() ([]byte, error) { 32 return json.Marshal(bool(s)) 33 } 34 func (s *Deleted) UnmarshalJSON(bs []byte) error { 35 if string(bs) == "null" { 36 return nil 37 } 38 var b bool 39 err := json.Unmarshal(bs, &b) 40 if err == nil { 41 *s = Deleted(b) 42 } 43 44 return err 45 } 46 47 func (Deleted) QueryClauses(f *schema.Field) []clause.Interface { 48 return []clause.Interface{deletedQueryClause{Field: f, ZeroValue: parseStatusZeroValueTag(f)}} 49 } 50 51 type deletedQueryClause struct { 52 ZeroValue Deleted 53 Field *schema.Field 54 } 55 56 func (s deletedQueryClause) Name() string { 57 return "" 58 } 59 func (s deletedQueryClause) Build(clause.Builder) { 60 } 61 func (s deletedQueryClause) MergeClause(*clause.Clause) { 62 } 63 func (s deletedQueryClause) ModifyStatement(stmt *gorm.Statement) { 64 if _, ok := stmt.Clauses[statusEnabledFlag]; ok || stmt.Statement.Unscoped { 65 return 66 } 67 68 if c, ok := stmt.Clauses["WHERE"]; ok { 69 if where, ok := c.Expression.(clause.Where); ok && len(where.Exprs) >= 1 { 70 for _, expr := range where.Exprs { 71 if orCond, ok := expr.(clause.OrConditions); ok && len(orCond.Exprs) == 1 { 72 where.Exprs = []clause.Expression{clause.And(where.Exprs...)} 73 c.Expression = where 74 stmt.Clauses["WHERE"] = c 75 break 76 } 77 } 78 } 79 } 80 81 stmt.AddClause(clause.Where{Exprs: []clause.Expression{ 82 clause.Eq{Column: clause.Column{Table: clause.CurrentTable, Name: s.Field.DBName}, Value: s.ZeroValue}, 83 }}) 84 stmt.Clauses[statusEnabledFlag] = clause.Clause{} 85 } 86 87 func (Deleted) UpdateClauses(f *schema.Field) []clause.Interface { 88 return []clause.Interface{deletedUpdateClause{Field: f, ZeroValue: parseStatusZeroValueTag(f)}} 89 } 90 91 type deletedUpdateClause struct { 92 ZeroValue Deleted 93 Field *schema.Field 94 } 95 96 func (s deletedUpdateClause) Name() string { 97 return "" 98 } 99 func (s deletedUpdateClause) Build(clause.Builder) { 100 } 101 func (s deletedUpdateClause) MergeClause(*clause.Clause) { 102 } 103 func (s deletedUpdateClause) ModifyStatement(stmt *gorm.Statement) { 104 if stmt.SQL.Len() == 0 && !stmt.Statement.Unscoped { 105 deletedQueryClause(s).ModifyStatement(stmt) 106 } 107 } 108 109 func (Deleted) DeleteClauses(f *schema.Field) []clause.Interface { 110 return []clause.Interface{deletedDeleteClause{Field: f, ZeroValue: parseStatusZeroValueTag(f)}} 111 } 112 113 type deletedDeleteClause struct { 114 ZeroValue Deleted 115 Field *schema.Field 116 } 117 118 func (s deletedDeleteClause) Name() string { 119 return "" 120 } 121 func (s deletedDeleteClause) Build(clause.Builder) { 122 } 123 func (s deletedDeleteClause) MergeClause(*clause.Clause) { 124 } 125 func (s deletedDeleteClause) ModifyStatement(stmt *gorm.Statement) { 126 deleted := true 127 setClauses := clause.Set{{Column: clause.Column{Name: s.Field.DBName}, Value: deleted}} 128 if clauses, ok := stmt.Clauses[setClauses.Name()]; ok { 129 if exprClauses, ok := clauses.Expression.(clause.Set); ok { 130 setClauses = append(setClauses, exprClauses...) 131 } 132 } 133 stmt.AddClause(setClauses) 134 stmt.SetColumn(s.Field.DBName, deleted, true) 135 136 deletedQueryClause(s).ModifyStatement(stmt) 137 } 138 139 func parseStatusZeroValueTag(f *schema.Field) (s Deleted) { 140 if v, ok := f.TagSettings["ZEROVALUE"]; ok { 141 if vv, err := strconv.ParseBool(v); err == nil { 142 return Deleted(vv) 143 } 144 } 145 return Deleted(false) 146 }