From 71e1e5a8ee56877f0ade8575f2f28aa83ba27f66 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Mon, 20 Mar 2023 02:16:42 +0000 Subject: [PATCH] Avoid some copies. --- driver/driver.go | 3 +-- driver/driver_test.go | 2 +- stmt.go | 54 ++++++++++++++++++++++++++++--------------- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/driver/driver.go b/driver/driver.go index be551de..24e28c1 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -386,8 +386,7 @@ func (r rows) Next(dest []driver.Value) error { case sqlite3.TEXT: dest[i] = maybeTime(r.stmt.ColumnText(i)) case sqlite3.BLOB: - buf, _ := dest[i].([]byte) - dest[i] = r.stmt.ColumnBlob(i, buf) + dest[i] = r.stmt.ColumnRawBlob(i) case sqlite3.NULL: if buf, ok := dest[i].([]byte); ok { dest[i] = buf[0:0] diff --git a/driver/driver_test.go b/driver/driver_test.go index 1995578..0b3c5ba 100644 --- a/driver/driver_test.go +++ b/driver/driver_test.go @@ -308,7 +308,7 @@ func Test_QueryRow_blob_null(t *testing.T) { want := [][]byte{nil, {0xca, 0xfe}, {0xba, 0xbe}, nil} for i := 0; rows.Next(); i++ { - var buf []byte + var buf sql.RawBytes err = rows.Scan(&buf) if err != nil { t.Fatal(err) diff --git a/stmt.go b/stmt.go index bc71650..067331d 100644 --- a/stmt.go +++ b/stmt.go @@ -334,21 +334,7 @@ func (s *Stmt) ColumnTime(col int, format TimeFormat) time.Time { // // https://www.sqlite.org/c3ref/column_blob.html func (s *Stmt) ColumnText(col int) string { - r := s.c.call(s.c.api.columnText, - uint64(s.handle), uint64(col)) - - ptr := uint32(r[0]) - if ptr == 0 { - r = s.c.call(s.c.api.errcode, uint64(s.c.handle)) - s.err = s.c.error(r[0]) - return "" - } - - r = s.c.call(s.c.api.columnBytes, - uint64(s.handle), uint64(col)) - - mem := s.c.mem.view(ptr, r[0]) - return string(mem) + return string(s.ColumnRawText(col)) } // ColumnBlob appends to buf and returns @@ -357,6 +343,39 @@ func (s *Stmt) ColumnText(col int) string { // // https://www.sqlite.org/c3ref/column_blob.html func (s *Stmt) ColumnBlob(col int, buf []byte) []byte { + return append(buf, s.ColumnRawBlob(col)...) +} + +// ColumnRawText returns the value of the result column as a []byte. +// The []byte is owned by SQLite and may be invalidated by +// subsequent calls to [Stmt] methods. +// The leftmost column of the result set has the index 0. +// +// https://www.sqlite.org/c3ref/column_blob.html +func (s *Stmt) ColumnRawText(col int) []byte { + r := s.c.call(s.c.api.columnText, + uint64(s.handle), uint64(col)) + + ptr := uint32(r[0]) + if ptr == 0 { + r = s.c.call(s.c.api.errcode, uint64(s.c.handle)) + s.err = s.c.error(r[0]) + return nil + } + + r = s.c.call(s.c.api.columnBytes, + uint64(s.handle), uint64(col)) + + return s.c.mem.view(ptr, r[0]) +} + +// ColumnRawBlob returns the value of the result column as a []byte. +// The []byte is owned by SQLite and may be invalidated by +// subsequent calls to [Stmt] methods. +// The leftmost column of the result set has the index 0. +// +// https://www.sqlite.org/c3ref/column_blob.html +func (s *Stmt) ColumnRawBlob(col int) []byte { r := s.c.call(s.c.api.columnBlob, uint64(s.handle), uint64(col)) @@ -364,14 +383,13 @@ func (s *Stmt) ColumnBlob(col int, buf []byte) []byte { if ptr == 0 { r = s.c.call(s.c.api.errcode, uint64(s.c.handle)) s.err = s.c.error(r[0]) - return buf[0:0] + return nil } r = s.c.call(s.c.api.columnBytes, uint64(s.handle), uint64(col)) - mem := s.c.mem.view(ptr, r[0]) - return append(buf[0:0], mem...) + return s.c.mem.view(ptr, r[0]) } // Return true if stmt is an empty SQL statement.