gorm/callback_save.go

169 lines
4.9 KiB
Go
Raw Normal View History

2014-01-26 13:10:33 +04:00
package gorm
import (
"reflect"
"strings"
)
2014-01-27 04:26:59 +04:00
2016-01-17 10:30:42 +03:00
func beginTransactionCallback(scope *Scope) {
2014-01-26 13:10:33 +04:00
scope.Begin()
}
2016-01-17 10:30:42 +03:00
func commitOrRollbackTransactionCallback(scope *Scope) {
2014-01-26 13:10:33 +04:00
scope.CommitOrRollback()
}
2014-01-26 15:34:06 +04:00
func saveAssociationCheck(scope *Scope, field *Field) (autoUpdate bool, autoCreate bool, saveReference bool, r *Relationship) {
checkTruth := func(value interface{}) bool {
if v, ok := value.(bool); ok && !v {
return false
}
if v, ok := value.(string); ok {
v = strings.ToLower(v)
if v == "false" || v != "skip" {
return false
}
}
return true
}
2017-10-10 21:20:56 +03:00
if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored {
if r = field.Relationship; r != nil {
autoUpdate, autoCreate, saveReference = true, true, true
if value, ok := scope.Get("gorm:save_associations"); ok {
autoUpdate = checkTruth(value)
autoCreate = autoUpdate
} else if value, ok := field.TagSettings["SAVE_ASSOCIATIONS"]; ok {
autoUpdate = checkTruth(value)
autoCreate = autoUpdate
}
if value, ok := scope.Get("gorm:association_autoupdate"); ok {
autoUpdate = checkTruth(value)
} else if value, ok := field.TagSettings["ASSOCIATION_AUTOUPDATE"]; ok {
autoUpdate = checkTruth(value)
}
if value, ok := scope.Get("gorm:association_autocreate"); ok {
autoCreate = checkTruth(value)
} else if value, ok := field.TagSettings["ASSOCIATION_AUTOCREATE"]; ok {
autoCreate = checkTruth(value)
}
if value, ok := field.TagSettings["ASSOCIATION_SAVE_REFERENCE"]; ok {
saveReference = checkTruth(value)
}
2017-10-10 21:20:56 +03:00
}
}
return
}
2016-01-17 10:30:42 +03:00
func saveBeforeAssociationsCallback(scope *Scope) {
2017-10-10 21:20:56 +03:00
for _, field := range scope.Fields() {
autoUpdate, autoCreate, saveReference, relationship := saveAssociationCheck(scope, field)
if relationship != nil && relationship.Kind == "belongs_to" {
2017-10-10 21:20:56 +03:00
fieldValue := field.Field.Addr().Interface()
newScope := scope.New(fieldValue)
if newScope.PrimaryKeyZero() {
if autoCreate {
scope.Err(scope.NewDB().Save(fieldValue).Error)
}
} else if autoUpdate {
2017-10-10 21:20:56 +03:00
scope.Err(scope.NewDB().Save(fieldValue).Error)
}
if saveReference {
if len(relationship.ForeignFieldNames) != 0 {
// set value's foreign key
for idx, fieldName := range relationship.ForeignFieldNames {
associationForeignName := relationship.AssociationForeignDBNames[idx]
if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok {
scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface()))
}
2017-10-10 21:20:56 +03:00
}
}
}
}
}
2014-01-26 15:34:06 +04:00
}
2016-01-17 10:30:42 +03:00
func saveAfterAssociationsCallback(scope *Scope) {
2014-01-27 04:26:59 +04:00
for _, field := range scope.Fields() {
autoUpdate, autoCreate, saveReference, relationship := saveAssociationCheck(scope, field)
if relationship != nil && (relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") {
value := field.Field
2014-01-27 04:26:59 +04:00
switch value.Kind() {
case reflect.Slice:
for i := 0; i < value.Len(); i++ {
newDB := scope.NewDB()
elem := value.Index(i).Addr().Interface()
newScope := newDB.NewScope(elem)
if saveReference {
if relationship.JoinTableHandler == nil && len(relationship.ForeignFieldNames) != 0 {
for idx, fieldName := range relationship.ForeignFieldNames {
associationForeignName := relationship.AssociationForeignDBNames[idx]
if f, ok := scope.FieldByName(associationForeignName); ok {
scope.Err(newScope.SetColumn(fieldName, f.Field.Interface()))
}
2015-07-30 09:26:48 +03:00
}
}
2014-01-27 04:26:59 +04:00
if relationship.PolymorphicType != "" {
scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue))
}
2014-07-30 07:32:18 +04:00
}
if newScope.PrimaryKeyZero() {
if autoCreate {
scope.Err(newDB.Save(elem).Error)
}
} else if autoUpdate {
scope.Err(newDB.Save(elem).Error)
}
if !scope.New(newScope.Value).PrimaryKeyZero() && saveReference {
if joinTableHandler := relationship.JoinTableHandler; joinTableHandler != nil {
scope.Err(joinTableHandler.Add(joinTableHandler, newDB, scope.Value, newScope.Value))
}
}
}
default:
elem := value.Addr().Interface()
newScope := scope.New(elem)
if saveReference {
if len(relationship.ForeignFieldNames) != 0 {
for idx, fieldName := range relationship.ForeignFieldNames {
associationForeignName := relationship.AssociationForeignDBNames[idx]
if f, ok := scope.FieldByName(associationForeignName); ok {
scope.Err(newScope.SetColumn(fieldName, f.Field.Interface()))
}
}
}
if relationship.PolymorphicType != "" {
scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue))
}
2014-01-27 04:26:59 +04:00
}
if newScope.PrimaryKeyZero() {
if autoCreate {
scope.Err(scope.NewDB().Save(elem).Error)
}
} else if autoUpdate {
scope.Err(scope.NewDB().Save(elem).Error)
}
2014-01-27 04:26:59 +04:00
}
}
}
2014-01-26 15:34:06 +04:00
}