Skip to content

Commit

Permalink
Fix type conversion handling in convertToType function
Browse files Browse the repository at this point in the history
  • Loading branch information
LukaGiorgadze committed Dec 28, 2023
1 parent 882c001 commit 66a531f
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 19 deletions.
33 changes: 19 additions & 14 deletions gonull.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,27 @@ func zeroValue[T any]() T {

// convertToType is a helper function that attempts to convert the given value to type T.
// This function is used by Scan to properly handle value conversion, ensuring that Nullable values are always of the correct type.
// ErrUnsupportedConversion is returned when a conversion cannot be made to the generic type T.
func convertToType[T any](value interface{}) (T, error) {
switch v := value.(type) {
case T:
return v, nil
case int64:
// This case handles the situation when the input value is of type int64.
// It attempts to convert the int64 value to the target numeric type T if possible.
// If the conversion is successful, it returns the converted value of type T and a nil error.
// If the conversion is not possible, the function will continue to the next case (return an error).
switch t := reflect.Zero(reflect.TypeOf((*T)(nil)).Elem()).Interface().(type) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
if reflect.TypeOf(t).ConvertibleTo(reflect.TypeOf((*T)(nil)).Elem()) {
return reflect.ValueOf(value).Convert(reflect.TypeOf((*T)(nil)).Elem()).Interface().(T), nil
}
var zero T
if value == nil {
return zero, nil
}

if reflect.TypeOf(value) == reflect.TypeOf(zero) {
return value.(T), nil
}

// Check if the value is a numeric type and if T is also a numeric type.
valueType := reflect.TypeOf(value)
targetType := reflect.TypeOf(zero)
if valueType.Kind() >= reflect.Int && valueType.Kind() <= reflect.Float64 &&
targetType.Kind() >= reflect.Int && targetType.Kind() <= reflect.Float64 {
if valueType.ConvertibleTo(targetType) {
convertedValue := reflect.ValueOf(value).Convert(targetType)
return convertedValue.Interface().(T), nil
}
}
var zero T

return zero, ErrUnsupportedConversion
}
7 changes: 2 additions & 5 deletions gonull_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,8 @@ func TestNullableScanWithCustomEnum(t *testing.T) {
model := TestModel{ID: 1, Field: gonull.NewNullable(TestEnumA)}

err := model.Field.Scan(sqlReturnedValue)
if err != nil {
assert.Error(t, err, "Scan failed with unsupported type conversion")
} else {
assert.Equal(t, TestEnumA, model.Field.Val, "Scanned value does not match expected enum value")
}
assert.NoError(t, err, "Scan failed with unsupported type conversion")
assert.Equal(t, TestEnumA, model.Field.Val, "Scanned value does not match expected enum value")

}

Expand Down

0 comments on commit 66a531f

Please sign in to comment.