Commit 3487c4e0 authored by Cyrill Schumacher's avatar Cyrill Schumacher Committed by Daniel Theophanes

database/sql: convertAssign string and time.Time into RawBytes

A new switch case for converting the source string type into a
destination RawBytes type avoids the reflection based conversion.
Speed up from old ~61.7ns/op down to ~49ns/op.

A second new switch case allows to convert and assign a source time.Time
type into a destination sql.RawBytes type. This switch case appends
the time to the reset RawBytes slice. This allows the reuse of RawBytes
and avoids allocations.

Fixes #20746

Change-Id: Ib0563fd5c5c7cb6d9d0acaa1d9aa7b2927f1329c
Reviewed-on: https://go-review.googlesource.com/66830
Run-TryBot: Daniel Theophanes <kardianos@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDaniel Theophanes <kardianos@gmail.com>
parent a82ee9c7
......@@ -234,6 +234,12 @@ func convertAssign(dest, src interface{}) error {
}
*d = []byte(s)
return nil
case *RawBytes:
if d == nil {
return errNilPtr
}
*d = append((*d)[:0], s...)
return nil
}
case []byte:
switch d := dest.(type) {
......@@ -273,6 +279,12 @@ func convertAssign(dest, src interface{}) error {
}
*d = []byte(s.Format(time.RFC3339Nano))
return nil
case *RawBytes:
if d == nil {
return errNilPtr
}
*d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
return nil
}
case nil:
switch d := dest.(type) {
......
......@@ -106,6 +106,7 @@ var conversionTests = []conversionTest{
// To RawBytes
{s: nil, d: &scanraw, wantraw: nil},
{s: []byte("byteslice"), d: &scanraw, wantraw: RawBytes("byteslice")},
{s: "string", d: &scanraw, wantraw: RawBytes("string")},
{s: 123, d: &scanraw, wantraw: RawBytes("123")},
{s: int8(123), d: &scanraw, wantraw: RawBytes("123")},
{s: int64(123), d: &scanraw, wantraw: RawBytes("123")},
......@@ -114,6 +115,9 @@ var conversionTests = []conversionTest{
{s: uint32(123), d: &scanraw, wantraw: RawBytes("123")},
{s: uint64(123), d: &scanraw, wantraw: RawBytes("123")},
{s: 1.5, d: &scanraw, wantraw: RawBytes("1.5")},
// time.Time has been placed here to check that the RawBytes slice gets
// correctly reset when calling time.Time.AppendFormat.
{s: time.Unix(2, 5).UTC(), d: &scanraw, wantraw: RawBytes("1970-01-01T00:00:02.000000005Z")},
// Strings to integers
{s: "255", d: &scanuint8, wantuint: 255},
......@@ -347,6 +351,7 @@ func TestRawBytesAllocs(t *testing.T) {
{"float32", float32(1.5), "1.5"},
{"float64", float64(64), "64"},
{"bool", false, "false"},
{"time", time.Unix(2, 5).UTC(), "1970-01-01T00:00:02.000000005Z"},
}
buf := make(RawBytes, 10)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment