diff --git a/callbacks/associations.go b/callbacks/associations.go index 6d74f20d..ccadf0a6 100644 --- a/callbacks/associations.go +++ b/callbacks/associations.go @@ -22,15 +22,16 @@ func SaveBeforeAssociations(create bool) func(db *gorm.DB) { setupReferences := func(obj reflect.Value, elem reflect.Value) { for _, ref := range rel.References { - if !ref.OwnPrimaryKey { - pv, _ := ref.PrimaryKey.ValueOf(elem) - db.AddError(ref.ForeignKey.Set(obj, pv)) + if ref.OwnPrimaryKey { + continue + } - if dest, ok := db.Statement.Dest.(map[string]interface{}); ok { - dest[ref.ForeignKey.DBName] = pv - if _, ok := dest[rel.Name]; ok { - dest[rel.Name] = elem.Interface() - } + pv, _ := ref.PrimaryKey.ValueOf(elem) + db.AddError(ref.ForeignKey.Set(obj, pv)) + if dest, ok := db.Statement.Dest.(map[string]interface{}); ok { + dest[ref.ForeignKey.DBName] = pv + if _, ok := dest[rel.Name]; ok { + dest[rel.Name] = elem.Interface() } } } @@ -51,27 +52,24 @@ func SaveBeforeAssociations(create bool) func(db *gorm.DB) { elems := reflect.MakeSlice(reflect.SliceOf(fieldType), 0, 10) for i := 0; i < db.Statement.ReflectValue.Len(); i++ { obj := db.Statement.ReflectValue.Index(i) - - if reflect.Indirect(obj).Kind() == reflect.Struct { - if _, zero := rel.Field.ValueOf(obj); !zero { // check belongs to relation value - rv := rel.Field.ReflectValueOf(obj) // relation reflect value - objs = append(objs, obj) - if isPtr { - elems = reflect.Append(elems, rv) - } else { - elems = reflect.Append(elems, rv.Addr()) - } - } - } else { + if reflect.Indirect(obj).Kind() != reflect.Struct { break } + + if _, zero := rel.Field.ValueOf(obj); !zero { // check belongs to relation value + rv := rel.Field.ReflectValueOf(obj) // relation reflect value + objs = append(objs, obj) + if isPtr { + elems = reflect.Append(elems, rv) + } else { + elems = reflect.Append(elems, rv.Addr()) + } + } } - if elems.Len() > 0 { - if saveAssociations(db, rel, elems.Interface(), selectColumns, restricted, nil) == nil { - for i := 0; i < elems.Len(); i++ { - setupReferences(objs[i], elems.Index(i)) - } + if elems.Len() > 0 && saveAssociations(db, rel, elems.Interface(), selectColumns, restricted, nil) == nil { + for i := 0; i < elems.Len(); i++ { + setupReferences(objs[i], elems.Index(i)) } } case reflect.Struct: diff --git a/callbacks/query.go b/callbacks/query.go index d0341284..3299d015 100644 --- a/callbacks/query.go +++ b/callbacks/query.go @@ -209,7 +209,7 @@ func Preload(db *gorm.DB) { if rel := db.Statement.Schema.Relationships.Relations[name]; rel != nil { preload(db, rel, db.Statement.Preloads[name], preloadMap[name]) } else { - db.AddError(fmt.Errorf("%v: %w for schema %v", name, gorm.ErrUnsupportedRelation, db.Statement.Schema.Name)) + db.AddError(fmt.Errorf("%s: %w for schema %s", name, gorm.ErrUnsupportedRelation, db.Statement.Schema.Name)) } } } diff --git a/schema/field.go b/schema/field.go index 9efaa44a..ce0e3c13 100644 --- a/schema/field.go +++ b/schema/field.go @@ -490,21 +490,22 @@ func (field *Field) setupValuerAndSetter() { return } else if field.FieldType.Kind() == reflect.Ptr { fieldValue := field.ReflectValueOf(value) + fieldType := field.FieldType.Elem() - if reflectValType.AssignableTo(field.FieldType.Elem()) { + if reflectValType.AssignableTo(fieldType) { if !fieldValue.IsValid() { - fieldValue = reflect.New(field.FieldType.Elem()) + fieldValue = reflect.New(fieldType) } else if fieldValue.IsNil() { - fieldValue.Set(reflect.New(field.FieldType.Elem())) + fieldValue.Set(reflect.New(fieldType)) } fieldValue.Elem().Set(reflectV) return - } else if reflectValType.ConvertibleTo(field.FieldType.Elem()) { + } else if reflectValType.ConvertibleTo(fieldType) { if fieldValue.IsNil() { - fieldValue.Set(reflect.New(field.FieldType.Elem())) + fieldValue.Set(reflect.New(fieldType)) } - fieldValue.Elem().Set(reflectV.Convert(field.FieldType.Elem())) + fieldValue.Elem().Set(reflectV.Convert(fieldType)) return } } @@ -520,7 +521,7 @@ func (field *Field) setupValuerAndSetter() { err = setter(value, v) } } else { - return fmt.Errorf("failed to set value %+v to field %v", v, field.Name) + return fmt.Errorf("failed to set value %+v to field %s", v, field.Name) } }