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  }