mirror of
https://github.com/golang/go
synced 2024-11-14 13:30:30 -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 {
|
// } else {
|
||||||
// // NULL value
|
// // NULL value
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// T should be one of the types accepted by [driver.Value].
|
||||||
type Null[T any] struct {
|
type Null[T any] struct {
|
||||||
V T
|
V T
|
||||||
Valid bool
|
Valid bool
|
||||||
@ -428,7 +430,17 @@ func (n Null[T]) Value() (driver.Value, error) {
|
|||||||
if !n.Valid {
|
if !n.Valid {
|
||||||
return nil, nil
|
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].
|
// 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