OSDN Git Service

feat: init cross_tx keepers (#146)
[bytom/vapor.git] / vendor / github.com / jinzhu / gorm / callback_save.go
1 package gorm
2
3 import (
4         "reflect"
5         "strings"
6 )
7
8 func beginTransactionCallback(scope *Scope) {
9         scope.Begin()
10 }
11
12 func commitOrRollbackTransactionCallback(scope *Scope) {
13         scope.CommitOrRollback()
14 }
15
16 func saveAssociationCheck(scope *Scope, field *Field) (autoUpdate bool, autoCreate bool, saveReference bool, r *Relationship) {
17         checkTruth := func(value interface{}) bool {
18                 if v, ok := value.(bool); ok && !v {
19                         return false
20                 }
21
22                 if v, ok := value.(string); ok {
23                         v = strings.ToLower(v)
24                         return v == "true"
25                 }
26
27                 return true
28         }
29
30         if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored {
31                 if r = field.Relationship; r != nil {
32                         autoUpdate, autoCreate, saveReference = true, true, true
33
34                         if value, ok := scope.Get("gorm:save_associations"); ok {
35                                 autoUpdate = checkTruth(value)
36                                 autoCreate = autoUpdate
37                                 saveReference = autoUpdate
38                         } else if value, ok := field.TagSettingsGet("SAVE_ASSOCIATIONS"); ok {
39                                 autoUpdate = checkTruth(value)
40                                 autoCreate = autoUpdate
41                                 saveReference = autoUpdate
42                         }
43
44                         if value, ok := scope.Get("gorm:association_autoupdate"); ok {
45                                 autoUpdate = checkTruth(value)
46                         } else if value, ok := field.TagSettingsGet("ASSOCIATION_AUTOUPDATE"); ok {
47                                 autoUpdate = checkTruth(value)
48                         }
49
50                         if value, ok := scope.Get("gorm:association_autocreate"); ok {
51                                 autoCreate = checkTruth(value)
52                         } else if value, ok := field.TagSettingsGet("ASSOCIATION_AUTOCREATE"); ok {
53                                 autoCreate = checkTruth(value)
54                         }
55
56                         if value, ok := scope.Get("gorm:association_save_reference"); ok {
57                                 saveReference = checkTruth(value)
58                         } else if value, ok := field.TagSettingsGet("ASSOCIATION_SAVE_REFERENCE"); ok {
59                                 saveReference = checkTruth(value)
60                         }
61                 }
62         }
63
64         return
65 }
66
67 func saveBeforeAssociationsCallback(scope *Scope) {
68         for _, field := range scope.Fields() {
69                 autoUpdate, autoCreate, saveReference, relationship := saveAssociationCheck(scope, field)
70
71                 if relationship != nil && relationship.Kind == "belongs_to" {
72                         fieldValue := field.Field.Addr().Interface()
73                         newScope := scope.New(fieldValue)
74
75                         if newScope.PrimaryKeyZero() {
76                                 if autoCreate {
77                                         scope.Err(scope.NewDB().Save(fieldValue).Error)
78                                 }
79                         } else if autoUpdate {
80                                 scope.Err(scope.NewDB().Save(fieldValue).Error)
81                         }
82
83                         if saveReference {
84                                 if len(relationship.ForeignFieldNames) != 0 {
85                                         // set value's foreign key
86                                         for idx, fieldName := range relationship.ForeignFieldNames {
87                                                 associationForeignName := relationship.AssociationForeignDBNames[idx]
88                                                 if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok {
89                                                         scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface()))
90                                                 }
91                                         }
92                                 }
93                         }
94                 }
95         }
96 }
97
98 func saveAfterAssociationsCallback(scope *Scope) {
99         for _, field := range scope.Fields() {
100                 autoUpdate, autoCreate, saveReference, relationship := saveAssociationCheck(scope, field)
101
102                 if relationship != nil && (relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") {
103                         value := field.Field
104
105                         switch value.Kind() {
106                         case reflect.Slice:
107                                 for i := 0; i < value.Len(); i++ {
108                                         newDB := scope.NewDB()
109                                         elem := value.Index(i).Addr().Interface()
110                                         newScope := newDB.NewScope(elem)
111
112                                         if saveReference {
113                                                 if relationship.JoinTableHandler == nil && len(relationship.ForeignFieldNames) != 0 {
114                                                         for idx, fieldName := range relationship.ForeignFieldNames {
115                                                                 associationForeignName := relationship.AssociationForeignDBNames[idx]
116                                                                 if f, ok := scope.FieldByName(associationForeignName); ok {
117                                                                         scope.Err(newScope.SetColumn(fieldName, f.Field.Interface()))
118                                                                 }
119                                                         }
120                                                 }
121
122                                                 if relationship.PolymorphicType != "" {
123                                                         scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue))
124                                                 }
125                                         }
126
127                                         if newScope.PrimaryKeyZero() {
128                                                 if autoCreate {
129                                                         scope.Err(newDB.Save(elem).Error)
130                                                 }
131                                         } else if autoUpdate {
132                                                 scope.Err(newDB.Save(elem).Error)
133                                         }
134
135                                         if !scope.New(newScope.Value).PrimaryKeyZero() && saveReference {
136                                                 if joinTableHandler := relationship.JoinTableHandler; joinTableHandler != nil {
137                                                         scope.Err(joinTableHandler.Add(joinTableHandler, newDB, scope.Value, newScope.Value))
138                                                 }
139                                         }
140                                 }
141                         default:
142                                 elem := value.Addr().Interface()
143                                 newScope := scope.New(elem)
144
145                                 if saveReference {
146                                         if len(relationship.ForeignFieldNames) != 0 {
147                                                 for idx, fieldName := range relationship.ForeignFieldNames {
148                                                         associationForeignName := relationship.AssociationForeignDBNames[idx]
149                                                         if f, ok := scope.FieldByName(associationForeignName); ok {
150                                                                 scope.Err(newScope.SetColumn(fieldName, f.Field.Interface()))
151                                                         }
152                                                 }
153                                         }
154
155                                         if relationship.PolymorphicType != "" {
156                                                 scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue))
157                                         }
158                                 }
159
160                                 if newScope.PrimaryKeyZero() {
161                                         if autoCreate {
162                                                 scope.Err(scope.NewDB().Save(elem).Error)
163                                         }
164                                 } else if autoUpdate {
165                                         scope.Err(scope.NewDB().Save(elem).Error)
166                                 }
167                         }
168                 }
169         }
170 }