mirror of https://github.com/go-gorm/gorm.git
Support UpdateColumn with Select and Omit
This commit is contained in:
parent
187eae8d9c
commit
2989e42d4d
|
@ -43,8 +43,10 @@ func Update(scope *Scope) {
|
||||||
|
|
||||||
if updateAttrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
|
if updateAttrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
|
||||||
for key, value := range updateAttrs.(map[string]interface{}) {
|
for key, value := range updateAttrs.(map[string]interface{}) {
|
||||||
|
if scope.changeableDBColumn(key) {
|
||||||
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(key), scope.AddToVars(value)))
|
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(key), scope.AddToVars(value)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fields := scope.Fields()
|
fields := scope.Fields()
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
|
|
30
scope.go
30
scope.go
|
@ -20,6 +20,7 @@ type Scope struct {
|
||||||
primaryKeyField *Field
|
primaryKeyField *Field
|
||||||
skipLeft bool
|
skipLeft bool
|
||||||
fields map[string]*Field
|
fields map[string]*Field
|
||||||
|
selectAttrs *[]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scope *Scope) IndirectValue() reflect.Value {
|
func (scope *Scope) IndirectValue() reflect.Value {
|
||||||
|
@ -334,7 +335,9 @@ func (scope *Scope) CommitOrRollback() *Scope {
|
||||||
return scope
|
return scope
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scope *Scope) SelectAttrs() (attrs []string) {
|
func (scope *Scope) SelectAttrs() []string {
|
||||||
|
if scope.selectAttrs == nil {
|
||||||
|
attrs := []string{}
|
||||||
for _, value := range scope.Search.selects {
|
for _, value := range scope.Search.selects {
|
||||||
if str, ok := value.(string); ok {
|
if str, ok := value.(string); ok {
|
||||||
attrs = append(attrs, str)
|
attrs = append(attrs, str)
|
||||||
|
@ -344,13 +347,36 @@ func (scope *Scope) SelectAttrs() (attrs []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return attrs
|
scope.selectAttrs = &attrs
|
||||||
|
}
|
||||||
|
return *scope.selectAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scope *Scope) OmitAttrs() []string {
|
func (scope *Scope) OmitAttrs() []string {
|
||||||
return scope.Search.omits
|
return scope.Search.omits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (scope *Scope) changeableDBColumn(column string) bool {
|
||||||
|
selectAttrs := scope.SelectAttrs()
|
||||||
|
omitAttrs := scope.OmitAttrs()
|
||||||
|
|
||||||
|
if len(selectAttrs) > 0 {
|
||||||
|
for _, attr := range selectAttrs {
|
||||||
|
if column == ToDBName(attr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, attr := range omitAttrs {
|
||||||
|
if column == ToDBName(attr) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (scope *Scope) changeableField(field *Field) bool {
|
func (scope *Scope) changeableField(field *Field) bool {
|
||||||
selectAttrs := scope.SelectAttrs()
|
selectAttrs := scope.SelectAttrs()
|
||||||
omitAttrs := scope.OmitAttrs()
|
omitAttrs := scope.OmitAttrs()
|
||||||
|
|
110
update_test.go
110
update_test.go
|
@ -241,6 +241,42 @@ func TestSelectWithUpdate(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSelectWithUpdateWithMap(t *testing.T) {
|
||||||
|
user := getPreparedUser("select_user", "select_with_update_map")
|
||||||
|
DB.Create(user)
|
||||||
|
|
||||||
|
updateValues := map[string]interface{}{
|
||||||
|
"Name": "new_name",
|
||||||
|
"Age": 50,
|
||||||
|
"BillingAddress": Address{Address1: "New Billing Address"},
|
||||||
|
"ShippingAddress": Address{Address1: "New ShippingAddress Address"},
|
||||||
|
"CreditCard": CreditCard{Number: "987654321"},
|
||||||
|
"Emails": []Email{
|
||||||
|
{Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"},
|
||||||
|
},
|
||||||
|
"Company": Company{Name: "new company"},
|
||||||
|
}
|
||||||
|
|
||||||
|
var reloadUser User
|
||||||
|
DB.First(&reloadUser, user.Id)
|
||||||
|
DB.Model(&reloadUser).Select("Name", "BillingAddress", "CreditCard", "Company", "Emails").Update(updateValues)
|
||||||
|
|
||||||
|
var queryUser User
|
||||||
|
DB.Preload("BillingAddress").Preload("ShippingAddress").
|
||||||
|
Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id)
|
||||||
|
|
||||||
|
if queryUser.Name == user.Name || queryUser.Age != user.Age {
|
||||||
|
t.Errorf("Should only update users with name column")
|
||||||
|
}
|
||||||
|
|
||||||
|
if queryUser.BillingAddressID.Int64 == user.BillingAddressID.Int64 ||
|
||||||
|
queryUser.ShippingAddressId != user.ShippingAddressId ||
|
||||||
|
queryUser.CreditCard.ID == user.CreditCard.ID ||
|
||||||
|
len(queryUser.Emails) == len(user.Emails) || queryUser.Company.Id == user.Company.Id {
|
||||||
|
t.Errorf("Should only update selected relationships")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestOmitWithUpdate(t *testing.T) {
|
func TestOmitWithUpdate(t *testing.T) {
|
||||||
user := getPreparedUser("omit_user", "omit_with_update")
|
user := getPreparedUser("omit_user", "omit_with_update")
|
||||||
DB.Create(user)
|
DB.Create(user)
|
||||||
|
@ -271,6 +307,78 @@ func TestOmitWithUpdate(t *testing.T) {
|
||||||
queryUser.ShippingAddressId == user.ShippingAddressId ||
|
queryUser.ShippingAddressId == user.ShippingAddressId ||
|
||||||
queryUser.CreditCard.ID != user.CreditCard.ID ||
|
queryUser.CreditCard.ID != user.CreditCard.ID ||
|
||||||
len(queryUser.Emails) != len(user.Emails) || queryUser.Company.Id != user.Company.Id {
|
len(queryUser.Emails) != len(user.Emails) || queryUser.Company.Id != user.Company.Id {
|
||||||
t.Errorf("Should only update selected relationships")
|
t.Errorf("Should only update relationships that not omited")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOmitWithUpdateWithMap(t *testing.T) {
|
||||||
|
user := getPreparedUser("select_user", "select_with_update_map")
|
||||||
|
DB.Create(user)
|
||||||
|
|
||||||
|
updateValues := map[string]interface{}{
|
||||||
|
"Name": "new_name",
|
||||||
|
"Age": 50,
|
||||||
|
"BillingAddress": Address{Address1: "New Billing Address"},
|
||||||
|
"ShippingAddress": Address{Address1: "New ShippingAddress Address"},
|
||||||
|
"CreditCard": CreditCard{Number: "987654321"},
|
||||||
|
"Emails": []Email{
|
||||||
|
{Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"},
|
||||||
|
},
|
||||||
|
"Company": Company{Name: "new company"},
|
||||||
|
}
|
||||||
|
|
||||||
|
var reloadUser User
|
||||||
|
DB.First(&reloadUser, user.Id)
|
||||||
|
DB.Model(&reloadUser).Omit("Name", "BillingAddress", "CreditCard", "Company", "Emails").Update(updateValues)
|
||||||
|
|
||||||
|
var queryUser User
|
||||||
|
DB.Preload("BillingAddress").Preload("ShippingAddress").
|
||||||
|
Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id)
|
||||||
|
|
||||||
|
if queryUser.Name != user.Name || queryUser.Age == user.Age {
|
||||||
|
t.Errorf("Should only update users with name column")
|
||||||
|
}
|
||||||
|
|
||||||
|
if queryUser.BillingAddressID.Int64 != user.BillingAddressID.Int64 ||
|
||||||
|
queryUser.ShippingAddressId == user.ShippingAddressId ||
|
||||||
|
queryUser.CreditCard.ID != user.CreditCard.ID ||
|
||||||
|
len(queryUser.Emails) != len(user.Emails) || queryUser.Company.Id != user.Company.Id {
|
||||||
|
t.Errorf("Should only update relationships not omited")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectWithUpdateColumn(t *testing.T) {
|
||||||
|
user := getPreparedUser("select_user", "select_with_update_map")
|
||||||
|
DB.Create(user)
|
||||||
|
|
||||||
|
updateValues := map[string]interface{}{"Name": "new_name", "Age": 50}
|
||||||
|
|
||||||
|
var reloadUser User
|
||||||
|
DB.First(&reloadUser, user.Id)
|
||||||
|
DB.Model(&reloadUser).Select("Name").UpdateColumn(updateValues)
|
||||||
|
|
||||||
|
var queryUser User
|
||||||
|
DB.First(&queryUser, user.Id)
|
||||||
|
|
||||||
|
if queryUser.Name == user.Name || queryUser.Age != user.Age {
|
||||||
|
t.Errorf("Should only update users with name column")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOmitWithUpdateColumn(t *testing.T) {
|
||||||
|
user := getPreparedUser("select_user", "select_with_update_map")
|
||||||
|
DB.Create(user)
|
||||||
|
|
||||||
|
updateValues := map[string]interface{}{"Name": "new_name", "Age": 50}
|
||||||
|
|
||||||
|
var reloadUser User
|
||||||
|
DB.First(&reloadUser, user.Id)
|
||||||
|
DB.Model(&reloadUser).Omit("Name").UpdateColumn(updateValues)
|
||||||
|
|
||||||
|
var queryUser User
|
||||||
|
DB.First(&queryUser, user.Id)
|
||||||
|
|
||||||
|
if queryUser.Name != user.Name || queryUser.Age == user.Age {
|
||||||
|
t.Errorf("Should omit name column when update user")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue