mirror of https://github.com/go-gorm/gorm.git
fix: update panic if model is not ptr (#6037)
* fix: update panic if model is not ptr * fix: update panic if model is not ptr * fix: update panic if model is not ptr * fix: raise an error if the value is not addressable * fix: return
This commit is contained in:
parent
42fc75cb2c
commit
e66a059b82
|
@ -13,11 +13,20 @@ func callMethod(db *gorm.DB, fc func(value interface{}, tx *gorm.DB) bool) {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
db.Statement.CurDestIndex = 0
|
db.Statement.CurDestIndex = 0
|
||||||
for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
|
for i := 0; i < db.Statement.ReflectValue.Len(); i++ {
|
||||||
fc(reflect.Indirect(db.Statement.ReflectValue.Index(i)).Addr().Interface(), tx)
|
if value := reflect.Indirect(db.Statement.ReflectValue.Index(i)); value.CanAddr() {
|
||||||
|
fc(value.Addr().Interface(), tx)
|
||||||
|
} else {
|
||||||
|
db.AddError(gorm.ErrInvalidValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
db.Statement.CurDestIndex++
|
db.Statement.CurDestIndex++
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
fc(db.Statement.ReflectValue.Addr().Interface(), tx)
|
if db.Statement.ReflectValue.CanAddr() {
|
||||||
|
fc(db.Statement.ReflectValue.Addr().Interface(), tx)
|
||||||
|
} else {
|
||||||
|
db.AddError(gorm.ErrInvalidValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,9 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
assignValue = func(field *schema.Field, value interface{}) {
|
assignValue = func(field *schema.Field, value interface{}) {
|
||||||
for i := 0; i < stmt.ReflectValue.Len(); i++ {
|
for i := 0; i < stmt.ReflectValue.Len(); i++ {
|
||||||
field.Set(stmt.Context, stmt.ReflectValue.Index(i), value)
|
if stmt.ReflectValue.CanAddr() {
|
||||||
|
field.Set(stmt.Context, stmt.ReflectValue.Index(i), value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
|
|
|
@ -133,7 +133,7 @@ func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect.Value,
|
||||||
for i := 0; i < reflectValue.Len(); i++ {
|
for i := 0; i < reflectValue.Len(); i++ {
|
||||||
elem := reflectValue.Index(i)
|
elem := reflectValue.Index(i)
|
||||||
elemKey := elem.Interface()
|
elemKey := elem.Interface()
|
||||||
if elem.Kind() != reflect.Ptr {
|
if elem.Kind() != reflect.Ptr && elem.CanAddr() {
|
||||||
elemKey = elem.Addr().Interface()
|
elemKey = elem.Addr().Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -514,3 +514,55 @@ func TestFailedToSaveAssociationShouldRollback(t *testing.T) {
|
||||||
t.Fatalf("AfterFind should not be called times:%d", productWithItem.Item.AfterFindCallTimes)
|
t.Fatalf("AfterFind should not be called times:%d", productWithItem.Item.AfterFindCallTimes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Product5 struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
var beforeUpdateCall int
|
||||||
|
|
||||||
|
func (p *Product5) BeforeUpdate(*gorm.DB) error {
|
||||||
|
beforeUpdateCall = beforeUpdateCall + 1
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateCallbacks(t *testing.T) {
|
||||||
|
DB.Migrator().DropTable(&Product5{})
|
||||||
|
DB.AutoMigrate(&Product5{})
|
||||||
|
|
||||||
|
p := Product5{Name: "unique_code"}
|
||||||
|
DB.Model(&Product5{}).Create(&p)
|
||||||
|
|
||||||
|
err := DB.Model(&Product5{}).Where("id", p.ID).Update("name", "update_name_1").Error
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should update success, but got err %v", err)
|
||||||
|
}
|
||||||
|
if beforeUpdateCall != 1 {
|
||||||
|
t.Fatalf("before update should be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = DB.Model(Product5{}).Where("id", p.ID).Update("name", "update_name_2").Error
|
||||||
|
if !errors.Is(err, gorm.ErrInvalidValue) {
|
||||||
|
t.Fatalf("should got RecordNotFound, but got %v", err)
|
||||||
|
}
|
||||||
|
if beforeUpdateCall != 1 {
|
||||||
|
t.Fatalf("before update should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = DB.Model([1]*Product5{&p}).Update("name", "update_name_3").Error
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should update success, but got err %v", err)
|
||||||
|
}
|
||||||
|
if beforeUpdateCall != 2 {
|
||||||
|
t.Fatalf("before update should be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = DB.Model([1]Product5{p}).Update("name", "update_name_4").Error
|
||||||
|
if !errors.Is(err, gorm.ErrInvalidValue) {
|
||||||
|
t.Fatalf("should got RecordNotFound, but got %v", err)
|
||||||
|
}
|
||||||
|
if beforeUpdateCall != 2 {
|
||||||
|
t.Fatalf("before update should not be called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue