]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: convertAssign string and time.Time into RawBytes
authorCyrill Schumacher <cyrill@schumacher.fm>
Thu, 28 Sep 2017 08:23:12 +0000 (10:23 +0200)
committerDaniel Theophanes <kardianos@gmail.com>
Sun, 1 Oct 2017 16:41:57 +0000 (16:41 +0000)
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: Daniel Theophanes <kardianos@gmail.com>
src/database/sql/convert.go
src/database/sql/convert_test.go

index 3c387fb25c1ab6e0f2f158daed04500967308983..c349a96edf0d8dbcfa893ed317856f74a357cc72 100644 (file)
@@ -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) {
index 169ecaed6f864c28018fb3954fd50215ad9bab88..35dbab3339ebdf28a23e16f0f8cdf01f6206dcf3 100644 (file)
@@ -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)