123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- package gorm
- import (
- "reflect"
- "strings"
- )
- func beginTransactionCallback(scope *Scope) {
- scope.Begin()
- }
- func commitOrRollbackTransactionCallback(scope *Scope) {
- scope.CommitOrRollback()
- }
- 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
- }
- 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 := scope.Get("gorm:association_save_reference"); ok {
- saveReference = checkTruth(value)
- } else if value, ok := field.TagSettings["ASSOCIATION_SAVE_REFERENCE"]; ok {
- saveReference = checkTruth(value)
- }
- }
- }
- return
- }
- func saveBeforeAssociationsCallback(scope *Scope) {
- for _, field := range scope.Fields() {
- autoUpdate, autoCreate, saveReference, relationship := saveAssociationCheck(scope, field)
- if relationship != nil && relationship.Kind == "belongs_to" {
- fieldValue := field.Field.Addr().Interface()
- newScope := scope.New(fieldValue)
- if newScope.PrimaryKeyZero() {
- if autoCreate {
- scope.Err(scope.NewDB().Save(fieldValue).Error)
- }
- } else if autoUpdate {
- 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()))
- }
- }
- }
- }
- }
- }
- }
- func saveAfterAssociationsCallback(scope *Scope) {
- 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
- 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()))
- }
- }
- }
- if relationship.PolymorphicType != "" {
- scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue))
- }
- }
- 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))
- }
- }
- if newScope.PrimaryKeyZero() {
- if autoCreate {
- scope.Err(scope.NewDB().Save(elem).Error)
- }
- } else if autoUpdate {
- scope.Err(scope.NewDB().Save(elem).Error)
- }
- }
- }
- }
- }
|