(create bool)
| 11 | ) |
| 12 | |
| 13 | func SaveBeforeAssociations(create bool) func(db *gorm.DB) { |
| 14 | return func(db *gorm.DB) { |
| 15 | if db.Error == nil && db.Statement.Schema != nil { |
| 16 | selectColumns, restricted := db.Statement.SelectAndOmitColumns(create, !create) |
| 17 | |
| 18 | // Save Belongs To associations |
| 19 | for _, rel := range db.Statement.Schema.Relationships.BelongsTo { |
| 20 | if v, ok := selectColumns[rel.Name]; (ok && !v) || (!ok && restricted) { |
| 21 | continue |
| 22 | } |
| 23 | |
| 24 | setupReferences := func(obj reflect.Value, elem reflect.Value) { |
| 25 | for _, ref := range rel.References { |
| 26 | if !ref.OwnPrimaryKey { |
| 27 | pv, _ := ref.PrimaryKey.ValueOf(db.Statement.Context, elem) |
| 28 | db.AddError(ref.ForeignKey.Set(db.Statement.Context, obj, pv)) |
| 29 | |
| 30 | if dest, ok := db.Statement.Dest.(map[string]interface{}); ok { |
| 31 | dest[ref.ForeignKey.DBName] = pv |
| 32 | if _, ok := dest[rel.Name]; ok { |
| 33 | dest[rel.Name] = elem.Interface() |
| 34 | } |
| 35 | } |
| 36 | } |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | switch db.Statement.ReflectValue.Kind() { |
| 41 | case reflect.Slice, reflect.Array: |
| 42 | var ( |
| 43 | rValLen = db.Statement.ReflectValue.Len() |
| 44 | objs = make([]reflect.Value, 0, rValLen) |
| 45 | fieldType = rel.Field.FieldType |
| 46 | isPtr = fieldType.Kind() == reflect.Ptr |
| 47 | ) |
| 48 | |
| 49 | if !isPtr { |
| 50 | fieldType = reflect.PointerTo(fieldType) |
| 51 | } |
| 52 | |
| 53 | elems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10) |
| 54 | distinctElems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10) |
| 55 | identityMap := map[string]bool{} |
| 56 | for i := 0; i < rValLen; i++ { |
| 57 | obj := db.Statement.ReflectValue.Index(i) |
| 58 | if reflect.Indirect(obj).Kind() != reflect.Struct { |
| 59 | break |
| 60 | } |
| 61 | if _, zero := rel.Field.ValueOf(db.Statement.Context, obj); !zero { // check belongs to relation value |
| 62 | rv := rel.Field.ReflectValueOf(db.Statement.Context, obj) // relation reflect value |
| 63 | if !isPtr { |
| 64 | rv = rv.Addr() |
| 65 | } |
| 66 | objs = append(objs, obj) |
| 67 | elems = reflect.Append(elems, rv) |
| 68 | |
| 69 | relPrimaryValues := make([]interface{}, 0, len(rel.FieldSchema.PrimaryFields)) |
| 70 | for _, pf := range rel.FieldSchema.PrimaryFields { |
no test coverage detected