return nil
}
+ // The following conversions use a string value as an intermediate representation
+ // to convert between various numeric types.
+ //
+ // This also allows scanning into user defined types such as "type Int int64".
+ // For symmetry, also check for string destination types.
switch dv.Kind() {
case reflect.Ptr:
if src == nil {
}
dv.SetFloat(f64)
return nil
+ case reflect.String:
+ switch v := src.(type) {
+ case string:
+ dv.SetString(v)
+ return nil
+ case []byte:
+ dv.SetString(string(v))
+ return nil
+ }
}
return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
var someTime = time.Unix(123, 0)
var answer int64 = 42
-type userDefined float64
-
-type userDefinedSlice []int
+type (
+ userDefined float64
+ userDefinedSlice []int
+ userDefinedString string
+)
type conversionTest struct {
s, d interface{} // source and destination
wantptr *int64 // if non-nil, *d's pointed value must be equal to *wantptr
wantnil bool // if true, *d must be *int64(nil)
wantusrdef userDefined
+ wantusrstr userDefinedString
}
// Target variables for scanning into.
{s: int64(123), d: new(userDefined), wantusrdef: 123},
{s: "1.5", d: new(userDefined), wantusrdef: 1.5},
{s: []byte{1, 2, 3}, d: new(userDefinedSlice), wanterr: `unsupported Scan, storing driver.Value type []uint8 into type *sql.userDefinedSlice`},
+ {s: "str", d: new(userDefinedString), wantusrstr: "str"},
// Other errors
{s: complex(1, 2), d: &scanstr, wanterr: `unsupported Scan, storing driver.Value type complex128 into type *string`},
if ct.wantusrdef != 0 && ct.wantusrdef != *ct.d.(*userDefined) {
errf("want userDefined %f, got %f", ct.wantusrdef, *ct.d.(*userDefined))
}
+ if len(ct.wantusrstr) != 0 && ct.wantusrstr != *ct.d.(*userDefinedString) {
+ errf("want userDefined %q, got %q", ct.wantusrstr, *ct.d.(*userDefinedString))
+ }
}
}
}
}
+// Issue 18101.
+func TestTypedString(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ type Str string
+ var scanned Str
+
+ err := db.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expected := Str("Alice")
+ if scanned != expected {
+ t.Errorf("expected %+v, got %+v", expected, scanned)
+ }
+}
+
func BenchmarkConcurrentDBExec(b *testing.B) {
b.ReportAllocs()
ct := new(concurrentDBExecTest)