Go version
go version go1.24.2 darwin/arm64
Output of go env
in your module/workspace:
Not relevant
What did you do?
I ran the example: https://go.dev/play/p/ay6-djssQwi with both go versions (1.23, 1.24).
package main
import (
"database/sql"
"fmt"
)
func main() {
v := sql.Null[int32]{V: 42, Valid: true}
value, err := v.Value()
fmt.Printf("%T, %v\n", value, err)
}
What did you see happen?
With go version 1.24, the return type from Value()
method is int64 instead of it being int32.
int64, <nil>
With go version 1.23, its working as expected and the return type from Value()
method is int32.
int32, <nil>
What did you expect to see?
I am expecting to see int32
type as the type parameter passed to sql.Null
is int32
.
int32, <nil>
On looking the implementation I see a recent change in Value
method for Null[T any]
type.
In go version 1.23.9: https://github.com/golang/go/blob/f77084d15d53e6aa09d2e7f867e69cc9766da2c5/src/database/sql/sql.go#L431
func (n Null[T]) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.V, nil
}
In go version 1.24: https://github.com/golang/go/blob/431f75a0b9890faa2b6a5ade8e19d4c23d0aaaf0/src/database/sql/sql.go#L429
func (n Null[T]) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
v := any(n.V)
// See issue 69728.
if valuer, ok := v.(driver.Valuer); ok {
val, err := callValuerValue(valuer)
if err != nil {
return val, err
}
v = val
}
// See issue 69837.
return driver.DefaultParameterConverter.ConvertValue(v)
}
Upon checking further, noticed that driver.DefaultParameterConverter.ConvertValue(v)
is the culprit here as this method will always return int64
for any signed int type because of
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int(), nil
Comment From: gabyhelp
Related Issues
- database/sql: sql.Null[T] allows types incompatible with driver.Value, leading to runtime errors #69837 (closed)
- database/sql: Inconsistent Behavior with Custom Null Types #66621 (closed)
- database/sql: sql.Null[T].Value method does not recognize T implementing driver.Valuer interface itself #69728 (closed)
- database/sql: the Null* types naively/prematurely set .Valid=true before converting and scanning data #45662
- database/sql: (n *NullInt64) Scan identity #35228 (closed)
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: seankhliao
I believe the new behaviour is correct: driver.Value only lists int64 as a supported type https://pkg.go.dev/database/sql/driver#Value
Note that there's an Int32 converter that converts int32 into int64 https://pkg.go.dev/database/sql/driver#Int32
Comment From: mahendrabishnoi2
I believe the new behaviour is correct: driver.Value only lists int64 as a supported type https://pkg.go.dev/database/sql/driver#Value
Note that there's an Int32 converter that converts int32 into int64 https://pkg.go.dev/database/sql/driver#Int32
In that case, shouldn't there be a type constraint on this type instead of allowing any? I'm not sure if that's doable or not.
Comment From: mahendrabishnoi2
I believe the new behaviour is correct: driver.Value only lists int64 as a supported type https://pkg.go.dev/database/sql/driver#Value
Note that there's an Int32 converter that converts int32 into int64 https://pkg.go.dev/database/sql/driver#Int32
In that case, shouldn't there be a type constraint on this type instead of allowing any? I'm not sure if that's doable or not.
Ping @seankhliao