forked from mirror/gorm
Don't do real delete when deleted_at column exist
This commit is contained in:
parent
bc785a9173
commit
7e5dc40f6f
7
chain.go
7
chain.go
|
@ -24,6 +24,7 @@ type Chain struct {
|
||||||
offsetStr string
|
offsetStr string
|
||||||
limitStr string
|
limitStr string
|
||||||
specifiedTableName string
|
specifiedTableName string
|
||||||
|
unscoped bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Chain) err(err error) error {
|
func (s *Chain) err(err error) error {
|
||||||
|
@ -47,6 +48,7 @@ func (s *Chain) do(value interface{}) *Do {
|
||||||
do.offsetStr = s.offsetStr
|
do.offsetStr = s.offsetStr
|
||||||
do.limitStr = s.limitStr
|
do.limitStr = s.limitStr
|
||||||
do.specifiedTableName = s.specifiedTableName
|
do.specifiedTableName = s.specifiedTableName
|
||||||
|
do.unscoped = s.unscoped
|
||||||
|
|
||||||
s.value = value
|
s.value = value
|
||||||
do.setModel(value)
|
do.setModel(value)
|
||||||
|
@ -177,6 +179,11 @@ func (s *Chain) CreateTable(value interface{}) *Chain {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Chain) Unscoped() *Chain {
|
||||||
|
s.unscoped = true
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Chain) Table(name string) *Chain {
|
func (s *Chain) Table(name string) *Chain {
|
||||||
s.specifiedTableName = name
|
s.specifiedTableName = name
|
||||||
return s
|
return s
|
||||||
|
|
25
do.go
25
do.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -25,13 +26,13 @@ type Do struct {
|
||||||
sql string
|
sql string
|
||||||
sqlVars []interface{}
|
sqlVars []interface{}
|
||||||
|
|
||||||
whereClause []map[string]interface{}
|
whereClause []map[string]interface{}
|
||||||
orClause []map[string]interface{}
|
orClause []map[string]interface{}
|
||||||
selectStr string
|
selectStr string
|
||||||
orderStrs []string
|
orderStrs []string
|
||||||
offsetStr string
|
offsetStr string
|
||||||
limitStr string
|
limitStr string
|
||||||
|
unscoped bool
|
||||||
updateAttrs map[string]interface{}
|
updateAttrs map[string]interface{}
|
||||||
ignoreProtectedAttrs bool
|
ignoreProtectedAttrs bool
|
||||||
}
|
}
|
||||||
|
@ -184,9 +185,15 @@ func (s *Do) prepareDeleteSql() {
|
||||||
func (s *Do) delete() {
|
func (s *Do) delete() {
|
||||||
s.err(s.model.callMethod("BeforeDelete"))
|
s.err(s.model.callMethod("BeforeDelete"))
|
||||||
|
|
||||||
s.prepareDeleteSql()
|
|
||||||
if !s.hasError() {
|
if !s.hasError() {
|
||||||
s.exec()
|
if s.model.hasColumn("DeletedAt") {
|
||||||
|
delete_sql := "deleted_at=" + s.addToVars(time.Now())
|
||||||
|
s.sql = fmt.Sprintf("UPDATE %v SET %v %v", s.tableName(), delete_sql, s.combinedSql())
|
||||||
|
s.exec()
|
||||||
|
} else {
|
||||||
|
s.prepareDeleteSql()
|
||||||
|
s.exec()
|
||||||
|
}
|
||||||
if !s.hasError() {
|
if !s.hasError() {
|
||||||
s.err(s.model.callMethod("AfterDelete"))
|
s.err(s.model.callMethod("AfterDelete"))
|
||||||
}
|
}
|
||||||
|
|
26
gorm_test.go
26
gorm_test.go
|
@ -53,7 +53,6 @@ func init() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Got error when try to delete table uses, %+v\n", err)
|
fmt.Printf("Got error when try to delete table uses, %+v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Exec("drop table products;")
|
db.Exec("drop table products;")
|
||||||
|
|
||||||
orm := db.CreateTable(&User{})
|
orm := db.CreateTable(&User{})
|
||||||
|
@ -691,3 +690,28 @@ func TestUpdates(t *testing.T) {
|
||||||
t.Errorf("We should have Product fgh")
|
t.Errorf("We should have Product fgh")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSoftDelete(t *testing.T) {
|
||||||
|
type Order struct {
|
||||||
|
Id int64
|
||||||
|
Amount int64
|
||||||
|
DeletedAt time.Time
|
||||||
|
}
|
||||||
|
db.Exec("drop table orders;")
|
||||||
|
db.CreateTable(&Order{})
|
||||||
|
|
||||||
|
order := Order{Amount: 1234}
|
||||||
|
db.Save(&order)
|
||||||
|
if db.Find(&Order{}, "amount = 1234").Error != nil {
|
||||||
|
t.Errorf("No errors should happen when save an order")
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Delete(&order)
|
||||||
|
if db.Find(&Order{}, "amount = 1234").Error == nil {
|
||||||
|
t.Errorf("Can't find the user because it is soft deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
if db.Unscoped().Find(&Order{}, "amount = 1234").Error != nil {
|
||||||
|
t.Errorf("Should be able to find out the soft deleted user with unscoped")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
main.go
4
main.go
|
@ -57,6 +57,10 @@ func (s *DB) Delete(value interface{}) *Chain {
|
||||||
return s.buildChain().Delete(value)
|
return s.buildChain().Delete(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DB) Unscoped() *Chain {
|
||||||
|
return s.buildChain().Unscoped()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DB) Exec(sql string) *Chain {
|
func (s *DB) Exec(sql string) *Chain {
|
||||||
return s.buildChain().Exec(sql)
|
return s.buildChain().Exec(sql)
|
||||||
}
|
}
|
||||||
|
|
9
model.go
9
model.go
|
@ -104,6 +104,15 @@ func (m *Model) columnsAndValues(operation string) map[string]interface{} {
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Model) hasColumn(name string) bool {
|
||||||
|
if m.data == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
value := reflect.ValueOf(m.data).Elem().FieldByName(name)
|
||||||
|
return value.IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Model) tableName() (str string, err error) {
|
func (m *Model) tableName() (str string, err error) {
|
||||||
if m.data == nil {
|
if m.data == nil {
|
||||||
err = errors.New("Model haven't been set")
|
err = errors.New("Model haven't been set")
|
||||||
|
|
Loading…
Reference in New Issue