1
0
mirror of https://github.com/golang/go synced 2024-11-13 12:30:21 -07:00

database/sql: rewrite Null[T].Value method, update doc for Null[T]

Update doc for Null[T] to clarify that T should be one of the types
accepted by driver.Value.

Modify the Value() method of Null[T]:
1) recognize T implementing driver.Valuer interface and invoke it.
2) use the DefaultParameterConverter to convert native types that
are not directly supported as driver.Value types.

Fixes #69728
Fixes #69837

Change-Id: Iba782c878b2bde168125f5390abf319b88424149
GitHub-Last-Rev: 3df182d23d
GitHub-Pull-Request: golang/go#69938
Reviewed-on: https://go-review.googlesource.com/c/go/+/620858
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
Jes Cok 2024-10-21 04:42:51 +00:00 committed by Gopher Robot
parent b3a9bf1f62
commit 971ab11ee2
2 changed files with 60 additions and 1 deletions

View File

@ -410,6 +410,8 @@ func (n NullTime) Value() (driver.Value, error) {
// } else {
// // NULL value
// }
//
// T should be one of the types accepted by [driver.Value].
type Null[T any] struct {
V T
Valid bool
@ -428,7 +430,17 @@ func (n Null[T]) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.V, 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)
}
// Scanner is an interface used by [Rows.Scan].

View File

@ -4957,3 +4957,50 @@ func BenchmarkConnRequestSet(b *testing.B) {
}
}
}
func TestIssue69837(t *testing.T) {
u := Null[uint]{V: 1, Valid: true}
val, err := driver.DefaultParameterConverter.ConvertValue(u)
if err != nil {
t.Errorf("ConvertValue() error = %v, want nil", err)
}
if v, ok := val.(int64); !ok {
t.Errorf("val.(type): got %T, expected int64", val)
} else if v != 1 {
t.Errorf("val: got %d, expected 1", v)
}
}
type issue69728Type struct {
ID int
Name string
}
func (t issue69728Type) Value() (driver.Value, error) {
return []byte(fmt.Sprintf("%d, %s", t.ID, t.Name)), nil
}
func TestIssue69728(t *testing.T) {
forValue := Null[issue69728Type]{
Valid: true,
V: issue69728Type{
ID: 42,
Name: "foobar",
},
}
v1, err := forValue.Value()
if err != nil {
t.Errorf("forValue.Value() error = %v, want nil", err)
}
v2, err := forValue.V.Value()
if err != nil {
t.Errorf("forValue.V.Value() error = %v, want nil", err)
}
if !reflect.DeepEqual(v1, v2) {
t.Errorf("not equal; v1 = %v, v2 = %v", v1, v2)
}
}