fix: update panic if model is not ptr

This commit is contained in:
black 2023-02-09 14:43:18 +08:00
parent 72decd069b
commit e65f454c48
4 changed files with 23 additions and 6 deletions

View File

@ -13,14 +13,15 @@ func callMethod(db *gorm.DB, fc func(value interface{}, tx *gorm.DB) bool) {
case reflect.Slice, reflect.Array:
db.Statement.CurDestIndex = 0
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)
}
db.Statement.CurDestIndex++
}
case reflect.Struct:
if !db.Statement.ReflectValue.CanAddr() {
db.Statement.ReflectValue = reflect.New(db.Statement.ReflectValue.Type()).Elem()
}
if db.Statement.ReflectValue.CanAddr() {
fc(db.Statement.ReflectValue.Addr().Interface(), tx)
}
}
}
}

View File

@ -137,9 +137,11 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) {
case reflect.Slice, reflect.Array:
assignValue = func(field *schema.Field, value interface{}) {
for i := 0; i < stmt.ReflectValue.Len(); i++ {
if stmt.ReflectValue.CanAddr() {
field.Set(stmt.Context, stmt.ReflectValue.Index(i), value)
}
}
}
case reflect.Struct:
assignValue = func(field *schema.Field, value interface{}) {
if stmt.ReflectValue.CanAddr() {

View File

@ -134,7 +134,11 @@ func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect.Value,
elem := reflectValue.Index(i)
elemKey := elem.Interface()
if elem.Kind() != reflect.Ptr {
if elem.CanAddr() {
elemKey = elem.Addr().Interface()
} else {
elemKey = elem.Interface()
}
}
if _, ok := loaded[elemKey]; ok {

View File

@ -540,7 +540,17 @@ func TestUpdateCallbacks(t *testing.T) {
}
DB.Model(Product5{}).Where("id", p.ID).Update("name", "update_name_2")
if beforeUpdateCall != 1 {
t.Fatalf("before update should not be called")
}
DB.Model([1]*Product5{&p}).Update("name", "update_name_3")
if beforeUpdateCall != 2 {
t.Fatalf("before update should be called")
}
DB.Model([1]Product5{p}).Update("name", "update_name_4")
if beforeUpdateCall != 2 {
t.Fatalf("before update should not be called")
}
}