`Alive' column soft-deletion support.

This commit is contained in:
Jay Taylor 2015-05-20 13:20:30 -07:00
parent c2dda88f9a
commit 240f60e864
3 changed files with 42 additions and 7 deletions

View File

@ -84,6 +84,7 @@ type User struct{} // struct User's database table name is "users" by default, w
* Use `CreatedAt` to store record's created time if field exists * Use `CreatedAt` to store record's created time if field exists
* Use `UpdatedAt` to store record's updated time if field exists * Use `UpdatedAt` to store record's updated time if field exists
* Use `DeletedAt` to store record's deleted time if field exists [Soft Delete](#soft-delete) * Use `DeletedAt` to store record's deleted time if field exists [Soft Delete](#soft-delete)
* Use nullable `Alive` to store record's aliveness if field exists [Soft Delete](#soft-delete)
* Gorm provide a default model struct, you could embed it in your struct * Gorm provide a default model struct, you could embed it in your struct
```go ```go
@ -446,10 +447,32 @@ db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
//// DELETE from emails where email LIKE "%jinhu%"; //// DELETE from emails where email LIKE "%jinhu%";
``` ```
### Soft Delete ### Soft-Delete
If struct has `DeletedAt` field, it will get soft delete ability automatically! If a struct has a `DeletedAt` field, it will get soft-delete ability automatically!
Then it won't be deleted from database permanently when call `Delete`. Then it won't be deleted from database permanently when `Delete()` is called.
Or alternatively..
If a struct has an `Alive` field it will get soft-delete ability automatically!
Then it won't be deleted from the database permanently when `Delete()` is called.
`Alive` will be set to `null`. This makes it possible to still enforce unique
constraints (e.g. "name", "alive"), but not have the unique constraint enforced
for "deleted" records.
```go
type Friend struct {
ID int64
Name string `sql:"type:varchar(255)`
Alive int `json:"-" sql:"type:integer;DEFAULT: 1;"`
}
db.Delete(&friend)
//// UPDATE friends SET alive=null WHERE id = 42;
```
Note: Choose only one or the other. It won't work right if both `DeletedAt` and
`Alive` columns are defined.
```go ```go
db.Delete(&user) db.Delete(&user)

View File

@ -8,13 +8,20 @@ func BeforeDelete(scope *Scope) {
func Delete(scope *Scope) { func Delete(scope *Scope) {
if !scope.HasError() { if !scope.HasError() {
if !scope.Search.Unscoped && scope.HasColumn("DeletedAt") { unscoped := scope.Search.Unscoped
if !unscoped && scope.HasColumn("DeletedAt") {
scope.Raw( scope.Raw(
fmt.Sprintf("UPDATE %v SET deleted_at=%v %v", fmt.Sprintf("UPDATE %v SET deleted_at=%v %v",
scope.QuotedTableName(), scope.QuotedTableName(),
scope.AddToVars(NowFunc()), scope.AddToVars(NowFunc()),
scope.CombinedConditionSql(), scope.CombinedConditionSql(),
)) ))
} else if !unscoped && scope.HasColumn("Alive") {
scope.Raw(
fmt.Sprintf("UPDATE %v SET alive=null %v",
scope.QuotedTableName(),
scope.CombinedConditionSql(),
))
} else { } else {
scope.Raw(fmt.Sprintf("DELETE FROM %v %v", scope.QuotedTableName(), scope.CombinedConditionSql())) scope.Raw(fmt.Sprintf("DELETE FROM %v %v", scope.QuotedTableName(), scope.CombinedConditionSql()))
} }

View File

@ -158,9 +158,14 @@ func (scope *Scope) buildSelectQuery(clause map[string]interface{}) (str string)
func (scope *Scope) whereSql() (sql string) { func (scope *Scope) whereSql() (sql string) {
var primaryConditions, andConditions, orConditions []string var primaryConditions, andConditions, orConditions []string
if !scope.Search.Unscoped && scope.Fields()["deleted_at"] != nil { if !scope.Search.Unscoped {
sql := fmt.Sprintf("(%v.deleted_at IS NULL OR %v.deleted_at <= '0001-01-02')", scope.QuotedTableName(), scope.QuotedTableName()) if scope.Fields()["deleted_at"] != nil {
primaryConditions = append(primaryConditions, sql) sql := fmt.Sprintf("(%v.deleted_at IS NULL OR %v.deleted_at <= '0001-01-02')", scope.QuotedTableName(), scope.QuotedTableName())
primaryConditions = append(primaryConditions, sql)
} else if scope.Fields()["alive"] != nil {
sql := fmt.Sprintf("(%v.alive IS NOT NULL)", scope.QuotedTableName())
primaryConditions = append(primaryConditions, sql)
}
} }
if !scope.PrimaryKeyZero() { if !scope.PrimaryKeyZero() {