diff --git a/callbacks/create.go b/callbacks/create.go index d8701f51..a245429f 100644 --- a/callbacks/create.go +++ b/callbacks/create.go @@ -183,7 +183,7 @@ func Create(config *Config) func(db *gorm.DB) { _, isZero := pkField.ValueOf(db.Statement.Context, rv) if isZero { - db.AddError(pkField.Set(db.Statement.Context, rv, insertID)) + db.AddError(newSetFieldValueError(pkField, pkField.Set(db.Statement.Context, rv, insertID))) insertID -= pkField.AutoIncrementIncrement } } @@ -195,7 +195,7 @@ func Create(config *Config) func(db *gorm.DB) { } if _, isZero := pkField.ValueOf(db.Statement.Context, rv); isZero { - db.AddError(pkField.Set(db.Statement.Context, rv, insertID)) + db.AddError(newSetFieldValueError(pkField, pkField.Set(db.Statement.Context, rv, insertID))) insertID += pkField.AutoIncrementIncrement } } @@ -203,7 +203,7 @@ func Create(config *Config) func(db *gorm.DB) { case reflect.Struct: _, isZero := pkField.ValueOf(db.Statement.Context, db.Statement.ReflectValue) if isZero { - db.AddError(pkField.Set(db.Statement.Context, db.Statement.ReflectValue, insertID)) + db.AddError(newSetFieldValueError(pkField, pkField.Set(db.Statement.Context, db.Statement.ReflectValue, insertID))) } } } @@ -289,13 +289,13 @@ func ConvertToCreateValues(stmt *gorm.Statement) (values clause.Values) { if values.Values[i][idx], isZero = field.ValueOf(stmt.Context, rv); isZero { if field.DefaultValueInterface != nil { values.Values[i][idx] = field.DefaultValueInterface - stmt.AddError(field.Set(stmt.Context, rv, field.DefaultValueInterface)) + stmt.AddError(newSetFieldValueError(field, field.Set(stmt.Context, rv, field.DefaultValueInterface))) } else if field.AutoCreateTime > 0 || field.AutoUpdateTime > 0 { - stmt.AddError(field.Set(stmt.Context, rv, curTime)) + stmt.AddError(newSetFieldValueError(field, field.Set(stmt.Context, rv, curTime))) values.Values[i][idx], _ = field.ValueOf(stmt.Context, rv) } } else if field.AutoUpdateTime > 0 && updateTrackTime { - stmt.AddError(field.Set(stmt.Context, rv, curTime)) + stmt.AddError(newSetFieldValueError(field, field.Set(stmt.Context, rv, curTime))) values.Values[i][idx], _ = field.ValueOf(stmt.Context, rv) } } @@ -331,13 +331,13 @@ func ConvertToCreateValues(stmt *gorm.Statement) (values clause.Values) { if values.Values[0][idx], isZero = field.ValueOf(stmt.Context, stmt.ReflectValue); isZero { if field.DefaultValueInterface != nil { values.Values[0][idx] = field.DefaultValueInterface - stmt.AddError(field.Set(stmt.Context, stmt.ReflectValue, field.DefaultValueInterface)) + stmt.AddError(newSetFieldValueError(field, field.Set(stmt.Context, stmt.ReflectValue, field.DefaultValueInterface))) } else if field.AutoCreateTime > 0 || field.AutoUpdateTime > 0 { - stmt.AddError(field.Set(stmt.Context, stmt.ReflectValue, curTime)) + stmt.AddError(newSetFieldValueError(field, field.Set(stmt.Context, stmt.ReflectValue, curTime))) values.Values[0][idx], _ = field.ValueOf(stmt.Context, stmt.ReflectValue) } } else if field.AutoUpdateTime > 0 && updateTrackTime { - stmt.AddError(field.Set(stmt.Context, stmt.ReflectValue, curTime)) + stmt.AddError(newSetFieldValueError(field, field.Set(stmt.Context, stmt.ReflectValue, curTime))) values.Values[0][idx], _ = field.ValueOf(stmt.Context, stmt.ReflectValue) } } @@ -351,7 +351,7 @@ func ConvertToCreateValues(stmt *gorm.Statement) (values clause.Values) { } } default: - stmt.AddError(gorm.ErrInvalidData) + stmt.AddError(fmt.Errorf("%w: expected slice, array or struct, but got %v", gorm.ErrInvalidData, stmt.ReflectValue.Kind())) } } diff --git a/callbacks/errors.go b/callbacks/errors.go new file mode 100644 index 00000000..03e639e7 --- /dev/null +++ b/callbacks/errors.go @@ -0,0 +1,36 @@ +package callbacks + +import ( + "fmt" + "gorm.io/gorm/schema" +) + +type _SetFieldValueError struct { + Field *schema.Field + Err error +} + +func (e _SetFieldValueError) Error() string { + return fmt.Sprintf("error when set value for field %s: %v", e.Field.Name, e.Err) +} + +func (e _SetFieldValueError) Unwrap() error { + return e.Err +} + +func newSetFieldValueError(field *schema.Field, e error) error { + if e == nil { + return nil + } + //goland:noinspection GoTypeAssertionOnErrors + if we, ok := e.(*_SetFieldValueError); ok && we.Field == field { + return e + } + if field == nil { + panic("field is nil") + } + return &_SetFieldValueError{ + Field: field, + Err: e, + } +} diff --git a/callbacks/update.go b/callbacks/update.go index 8e2782e1..aeafd2e0 100644 --- a/callbacks/update.go +++ b/callbacks/update.go @@ -21,7 +21,7 @@ func SetupUpdateReflectValue(db *gorm.DB) { if dest, ok := db.Statement.Dest.(map[string]interface{}); ok { for _, rel := range db.Statement.Schema.Relationships.BelongsTo { if _, ok := dest[rel.Name]; ok { - db.AddError(rel.Field.Set(db.Statement.Context, db.Statement.ReflectValue, dest[rel.Name])) + db.AddError(newSetFieldValueError(rel.Field, rel.Field.Set(db.Statement.Context, db.Statement.ReflectValue, dest[rel.Name]))) } } }