gorm/callback_update.go

122 lines
4.0 KiB
Go
Raw Normal View History

2014-01-26 08:46:04 +04:00
package gorm
2014-01-27 07:06:13 +04:00
import (
"errors"
2014-01-27 07:06:13 +04:00
"fmt"
"sort"
2014-01-27 07:06:13 +04:00
"strings"
)
2016-01-17 13:38:18 +03:00
// Define callbacks for updating
2016-01-17 11:28:32 +03:00
func init() {
DefaultCallback.Update().Register("gorm:assign_updating_attributes", assignUpdatingAttributesCallback)
DefaultCallback.Update().Register("gorm:begin_transaction", beginTransactionCallback)
DefaultCallback.Update().Register("gorm:before_update", beforeUpdateCallback)
DefaultCallback.Update().Register("gorm:save_before_associations", saveBeforeAssociationsCallback)
DefaultCallback.Update().Register("gorm:update_time_stamp", updateTimeStampForUpdateCallback)
DefaultCallback.Update().Register("gorm:update", updateCallback)
DefaultCallback.Update().Register("gorm:save_after_associations", saveAfterAssociationsCallback)
DefaultCallback.Update().Register("gorm:after_update", afterUpdateCallback)
DefaultCallback.Update().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback)
2016-01-17 11:28:32 +03:00
}
2016-01-17 13:38:18 +03:00
// assignUpdatingAttributesCallback assign updating attributes to model
func assignUpdatingAttributesCallback(scope *Scope) {
if attrs, ok := scope.InstanceGet("gorm:update_interface"); ok {
2016-03-09 11:18:01 +03:00
if updateMaps, hasUpdate := scope.updatedAttrsWithValues(attrs); hasUpdate {
scope.InstanceSet("gorm:update_attrs", updateMaps)
} else {
scope.SkipLeft()
2014-01-27 18:36:08 +04:00
}
}
}
2016-01-17 13:38:18 +03:00
// beforeUpdateCallback will invoke `BeforeSave`, `BeforeUpdate` method before updating
2016-01-17 10:30:42 +03:00
func beforeUpdateCallback(scope *Scope) {
if scope.DB().HasBlockGlobalUpdate() && !scope.hasConditions() {
2019-09-12 17:16:52 +03:00
scope.Err(errors.New("missing WHERE clause while updating"))
return
}
2014-08-30 18:39:28 +04:00
if _, ok := scope.Get("gorm:update_column"); !ok {
if !scope.HasError() {
scope.CallMethod("BeforeSave")
}
if !scope.HasError() {
scope.CallMethod("BeforeUpdate")
}
}
2014-01-26 08:46:04 +04:00
}
2016-01-17 13:38:18 +03:00
// updateTimeStampForUpdateCallback will set `UpdatedAt` when updating
2016-01-17 10:30:42 +03:00
func updateTimeStampForUpdateCallback(scope *Scope) {
2014-08-30 18:39:28 +04:00
if _, ok := scope.Get("gorm:update_column"); !ok {
scope.SetColumn("UpdatedAt", scope.db.nowFunc())
2014-01-27 07:06:13 +04:00
}
}
2016-01-17 13:38:18 +03:00
// updateCallback the callback used to update data to database
2016-01-17 10:30:42 +03:00
func updateCallback(scope *Scope) {
2014-01-26 08:46:04 +04:00
if !scope.HasError() {
2014-01-27 07:06:13 +04:00
var sqls []string
2014-01-27 18:36:08 +04:00
2015-02-17 17:55:14 +03:00
if updateAttrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
// Sort the column names so that the generated SQL is the same every time.
updateMap := updateAttrs.(map[string]interface{})
var columns []string
for c := range updateMap {
columns = append(columns, c)
}
sort.Strings(columns)
for _, column := range columns {
value := updateMap[column]
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(column), scope.AddToVars(value)))
2014-01-27 18:36:08 +04:00
}
} else {
2016-03-07 07:15:15 +03:00
for _, field := range scope.Fields() {
2016-01-17 13:38:18 +03:00
if scope.changeableField(field) {
if !field.IsPrimaryKey && field.IsNormal && (field.Name != "CreatedAt" || !field.IsBlank) {
if !field.IsForeignKey || !field.IsBlank || !field.HasDefaultValue {
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface())))
}
2016-01-17 13:38:18 +03:00
} else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" {
for _, foreignKey := range relationship.ForeignDBNames {
2016-03-07 07:15:15 +03:00
if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) {
2016-01-17 13:38:18 +03:00
sqls = append(sqls,
fmt.Sprintf("%v = %v", scope.Quote(foreignField.DBName), scope.AddToVars(foreignField.Field.Interface())))
}
2015-03-12 13:30:59 +03:00
}
}
2014-01-27 18:36:08 +04:00
}
2014-01-26 08:46:04 +04:00
}
}
var extraOption string
if str, ok := scope.Get("gorm:update_option"); ok {
extraOption = fmt.Sprint(str)
}
if len(sqls) > 0 {
scope.Raw(fmt.Sprintf(
"UPDATE %v SET %v%v%v",
scope.QuotedTableName(),
strings.Join(sqls, ", "),
addExtraSpaceIfExist(scope.CombinedConditionSql()),
addExtraSpaceIfExist(extraOption),
2016-01-17 13:38:18 +03:00
)).Exec()
}
2014-01-26 08:46:04 +04:00
}
}
2016-01-17 13:38:18 +03:00
// afterUpdateCallback will invoke `AfterUpdate`, `AfterSave` method after updating
2016-01-17 10:30:42 +03:00
func afterUpdateCallback(scope *Scope) {
2015-02-17 17:55:14 +03:00
if _, ok := scope.Get("gorm:update_column"); !ok {
if !scope.HasError() {
scope.CallMethod("AfterUpdate")
}
if !scope.HasError() {
scope.CallMethod("AfterSave")
}
}
2014-01-26 08:46:04 +04:00
}