This patch provides a new method UpdateAll() that will update all fields. It doesn not ignore initialized values...
This commit is contained in:
parent
1ad419004f
commit
cf471d3842
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
gorm.test
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
func AssignUpdateAttributes(scope *Scope) {
|
func AssignUpdateAttributes(scope *Scope) {
|
||||||
if attrs, ok := scope.InstanceGet("gorm:update_interface"); ok {
|
if attrs, ok := scope.InstanceGet("gorm:update_interface"); ok {
|
||||||
if maps := convertInterfaceToMap(attrs); len(maps) > 0 {
|
if maps := convertInterfaceToMap(attrs, false); len(maps) > 0 {
|
||||||
protected, ok := scope.Get("gorm:ignore_protected_attrs")
|
protected, ok := scope.Get("gorm:ignore_protected_attrs")
|
||||||
_, updateColumn := scope.Get("gorm:update_column")
|
_, updateColumn := scope.Get("gorm:update_column")
|
||||||
updateAttrs, hasUpdate := scope.updatedAttrsWithValues(maps, ok && protected.(bool))
|
updateAttrs, hasUpdate := scope.updatedAttrsWithValues(maps, ok && protected.(bool))
|
||||||
|
8
main.go
8
main.go
@ -200,7 +200,7 @@ func (s *DB) FirstOrInit(out interface{}, where ...interface{}) *DB {
|
|||||||
}
|
}
|
||||||
c.NewScope(out).inlineCondition(where...).initialize()
|
c.NewScope(out).inlineCondition(where...).initialize()
|
||||||
} else {
|
} else {
|
||||||
c.NewScope(out).updatedAttrsWithValues(convertInterfaceToMap(s.search.AssignAttrs), false)
|
c.NewScope(out).updatedAttrsWithValues(convertInterfaceToMap(s.search.AssignAttrs, false), false)
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@ -223,6 +223,12 @@ func (s *DB) Update(attrs ...interface{}) *DB {
|
|||||||
return s.Updates(toSearchableMap(attrs...), true)
|
return s.Updates(toSearchableMap(attrs...), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DB) UpdateAll(value interface{}) *DB {
|
||||||
|
return s.clone().NewScope(value).
|
||||||
|
InstanceSet("gorm:update_interface", convertInterfaceToMap(value, true)).
|
||||||
|
callCallbacks(s.parent.callback.updates).db
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DB) Updates(values interface{}, ignoreProtectedAttrs ...bool) *DB {
|
func (s *DB) Updates(values interface{}, ignoreProtectedAttrs ...bool) *DB {
|
||||||
return s.clone().NewScope(s.Value).
|
return s.clone().NewScope(s.Value).
|
||||||
Set("gorm:ignore_protected_attrs", len(ignoreProtectedAttrs) > 0).
|
Set("gorm:ignore_protected_attrs", len(ignoreProtectedAttrs) > 0).
|
||||||
|
@ -375,10 +375,10 @@ func (scope *Scope) rows() (*sql.Rows, error) {
|
|||||||
|
|
||||||
func (scope *Scope) initialize() *Scope {
|
func (scope *Scope) initialize() *Scope {
|
||||||
for _, clause := range scope.Search.WhereConditions {
|
for _, clause := range scope.Search.WhereConditions {
|
||||||
scope.updatedAttrsWithValues(convertInterfaceToMap(clause["query"]), false)
|
scope.updatedAttrsWithValues(convertInterfaceToMap(clause["query"], false), false)
|
||||||
}
|
}
|
||||||
scope.updatedAttrsWithValues(convertInterfaceToMap(scope.Search.InitAttrs), false)
|
scope.updatedAttrsWithValues(convertInterfaceToMap(scope.Search.InitAttrs, false), false)
|
||||||
scope.updatedAttrsWithValues(convertInterfaceToMap(scope.Search.AssignAttrs), false)
|
scope.updatedAttrsWithValues(convertInterfaceToMap(scope.Search.AssignAttrs, false), false)
|
||||||
return scope
|
return scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,3 +158,44 @@ func TestUpdateColumn(t *testing.T) {
|
|||||||
t.Errorf("updatedAt should not be updated with update column")
|
t.Errorf("updatedAt should not be updated with update column")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAlwaysUpdate(t *testing.T) {
|
||||||
|
type Always struct {
|
||||||
|
Id int64
|
||||||
|
Name string
|
||||||
|
Code string
|
||||||
|
Price int64
|
||||||
|
IsActive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.DropTable(&Always{})
|
||||||
|
DB.CreateTable(&Always{})
|
||||||
|
|
||||||
|
obj1 := Always{Name: "obj1", Code: "code_1", Price: 10, IsActive: true}
|
||||||
|
obj2 := Always{Name: "obj2", Code: "code_2", Price: 20, IsActive: true}
|
||||||
|
obj3 := Always{Name: "obj3", Code: "code_10", Price: 100, IsActive: true}
|
||||||
|
|
||||||
|
// save initial
|
||||||
|
DB.Save(&obj1).Save(&obj2).Save(&obj3)
|
||||||
|
|
||||||
|
// now update via struct price should change to zero
|
||||||
|
obj2.Price = 0
|
||||||
|
DB.UpdateAll(obj2)
|
||||||
|
|
||||||
|
var obj2_1 Always
|
||||||
|
DB.First(&obj2_1, obj2.Id)
|
||||||
|
if obj2_1.Price != 0 {
|
||||||
|
t.Errorf("UpdateAll did not update Price for obj2: %#v", obj2_1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test bool
|
||||||
|
obj3.IsActive = false
|
||||||
|
DB.UpdateAll(obj3)
|
||||||
|
|
||||||
|
var obj3_1 Always
|
||||||
|
DB.First(&obj3_1, obj3.Id)
|
||||||
|
if obj3_1.IsActive {
|
||||||
|
t.Errorf("UpdateAll did not update IsActive for obj3: %#v", obj3_1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -40,7 +40,7 @@ func toSearchableMap(attrs ...interface{}) (result interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertInterfaceToMap(values interface{}) map[string]interface{} {
|
func convertInterfaceToMap(values interface{}, skipBlankCheck bool) map[string]interface{} {
|
||||||
attrs := map[string]interface{}{}
|
attrs := map[string]interface{}{}
|
||||||
|
|
||||||
switch value := values.(type) {
|
switch value := values.(type) {
|
||||||
@ -50,7 +50,7 @@ func convertInterfaceToMap(values interface{}) map[string]interface{} {
|
|||||||
}
|
}
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
for _, v := range value {
|
for _, v := range value {
|
||||||
for key, value := range convertInterfaceToMap(v) {
|
for key, value := range convertInterfaceToMap(v, skipBlankCheck) {
|
||||||
attrs[key] = value
|
attrs[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ func convertInterfaceToMap(values interface{}) map[string]interface{} {
|
|||||||
default:
|
default:
|
||||||
scope := Scope{Value: values}
|
scope := Scope{Value: values}
|
||||||
for _, field := range scope.Fields() {
|
for _, field := range scope.Fields() {
|
||||||
if !field.IsBlank {
|
if skipBlankCheck || !field.IsBlank {
|
||||||
attrs[field.DBName] = field.Field.Interface()
|
attrs[field.DBName] = field.Field.Interface()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user