Proper handling of fromString in the types

This commit is contained in:
Hein 2025-12-09 13:55:51 +02:00
parent c52afe2825
commit 3ec2e5f15a
2 changed files with 12 additions and 16 deletions

View File

@ -78,7 +78,6 @@ func (n *SqlNull[T]) Scan(value any) error {
return n.fromString(fmt.Sprintf("%v", value)) return n.fromString(fmt.Sprintf("%v", value))
} }
} }
func (n *SqlNull[T]) fromString(s string) error { func (n *SqlNull[T]) fromString(s string) error {
s = strings.TrimSpace(s) s = strings.TrimSpace(s)
n.Valid = false n.Valid = false
@ -90,19 +89,14 @@ func (n *SqlNull[T]) fromString(s string) error {
var zero T var zero T
switch any(zero).(type) { switch any(zero).(type) {
case int, int8, int16, int32, int64: case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
if i, err := strconv.ParseInt(s, 10, 64); err == nil { if i, err := strconv.ParseInt(s, 10, 64); err == nil {
n.Val = any(int64(i)).(T) // Cast to T (e.g., int16) reflect.ValueOf(&n.Val).Elem().SetInt(i)
n.Valid = true
}
case uint, uint8, uint16, uint32, uint64:
if u, err := strconv.ParseUint(s, 10, 64); err == nil {
n.Val = any(u).(T)
n.Valid = true n.Valid = true
} }
case float32, float64: case float32, float64:
if f, err := strconv.ParseFloat(s, 64); err == nil { if f, err := strconv.ParseFloat(s, 64); err == nil {
n.Val = any(f).(T) reflect.ValueOf(&n.Val).Elem().SetFloat(f)
n.Valid = true n.Valid = true
} }
case bool: case bool:
@ -124,7 +118,6 @@ func (n *SqlNull[T]) fromString(s string) error {
n.Val = any(s).(T) n.Val = any(s).(T)
n.Valid = true n.Valid = true
} }
return nil return nil
} }
@ -517,6 +510,9 @@ func TryIfInt64(v any, def int64) int64 {
} }
// Constructor helpers - clean and fast value creation // Constructor helpers - clean and fast value creation
func Null[T any](v T, valid bool) SqlNull[T] {
return SqlNull[T]{Val: v, Valid: valid}
}
func NewSqlInt16(v int16) SqlInt16 { func NewSqlInt16(v int16) SqlInt16 {
return SqlInt16{Val: v, Valid: true} return SqlInt16{Val: v, Valid: true}

View File

@ -16,11 +16,11 @@ func TestNewSqlInt16(t *testing.T) {
input interface{} input interface{}
expected SqlInt16 expected SqlInt16
}{ }{
{"int", 42, NewSqlInt16(42)}, {"int", 42, Null(int16(42), true)},
{"int32", int32(100), NewSqlInt16(100)}, {"int32", int32(100), NewSqlInt16(100)},
{"int64", int64(200), NewSqlInt16(200)}, {"int64", int64(200), NewSqlInt16(200)},
{"string", "123", NewSqlInt16(123)}, {"string", "123", NewSqlInt16(123)},
{"nil", nil, NewSqlInt16(0)}, {"nil", nil, Null(int16(0), false)},
} }
for _, tt := range tests { for _, tt := range tests {
@ -42,9 +42,9 @@ func TestNewSqlInt16_Value(t *testing.T) {
input SqlInt16 input SqlInt16
expected driver.Value expected driver.Value
}{ }{
{"zero", NewSqlInt16(0), nil}, {"zero", Null(int16(0), false), nil},
{"positive", NewSqlInt16(42), int64(42)}, {"positive", NewSqlInt16(42), int16(42)},
{"negative", NewSqlInt16(-10), int64(-10)}, {"negative", NewSqlInt16(-10), int16(-10)},
} }
for _, tt := range tests { for _, tt := range tests {
@ -486,7 +486,7 @@ func TestSqlUUID_Value(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Value failed: %v", err) t.Fatalf("Value failed: %v", err)
} }
if val != testUUID.String() { if val != testUUID {
t.Errorf("expected %s, got %s", testUUID.String(), val) t.Errorf("expected %s, got %s", testUUID.String(), val)
} }