From: Cyrill Schumacher Date: Thu, 28 Sep 2017 08:23:12 +0000 (+0200) Subject: database/sql: convertAssign string and time.Time into RawBytes X-Git-Tag: go1.10beta1~928 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=3487c4e02199b68d71df1868326e1b0a872a89a2;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Daniel Theophanes --- diff --git a/src/database/sql/convert.go b/src/database/sql/convert.go index 3c387fb25c..c349a96edf 100644 --- a/src/database/sql/convert.go +++ b/src/database/sql/convert.go @@ -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) { diff --git a/src/database/sql/convert_test.go b/src/database/sql/convert_test.go index 169ecaed6f..35dbab3339 100644 --- a/src/database/sql/convert_test.go +++ b/src/database/sql/convert_test.go @@ -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)