]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: rewrite Null[T].Value method, update doc for Null[T]
authorJes Cok <xigua67damn@gmail.com>
Mon, 21 Oct 2024 04:42:51 +0000 (04:42 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 21 Oct 2024 18:42:47 +0000 (18:42 +0000)
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>
src/database/sql/sql.go
src/database/sql/sql_test.go

index b7cf3d12fa8d26321180a84002173714bec35882..eddb647ed0cd8b987d1ddbc14a3deba57ac8ffa6 100644 (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].
index 110a2bae5bd2473ec708923f651f1265d4744cc5..db1d8b3c6b65efade75e31b7f594ee772bb36294 100644 (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)
+       }
+}