aboutsummaryrefslogtreecommitdiff
path: root/src/database/sql
diff options
context:
space:
mode:
authorJes Cok <xigua67damn@gmail.com>2024-10-21 04:42:51 +0000
committerGopher Robot <gobot@golang.org>2024-10-21 18:42:47 +0000
commit971ab11ee2477cf81f7b7db520bb5c151440d298 (patch)
tree14cc53873537014da6b11808e2d3b001f4130f98 /src/database/sql
parentb3a9bf1f62a1cdc792916f7fb8042c07732d8f16 (diff)
downloadgo-971ab11ee2477cf81f7b7db520bb5c151440d298.tar.xz
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: 3df182d23dd57bd04828c3e9bd0c5222d8bef152 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>
Diffstat (limited to 'src/database/sql')
-rw-r--r--src/database/sql/sql.go14
-rw-r--r--src/database/sql/sql_test.go47
2 files changed, 60 insertions, 1 deletions
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index b7cf3d12fa..eddb647ed0 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -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].
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 110a2bae5b..db1d8b3c6b 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -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)
+ }
+}