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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 black-06
						black-06