mirror of
https://github.com/golang/go
synced 2024-11-14 05:40:29 -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:
parent
b3a9bf1f62
commit
971ab11ee2
@ -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].
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user