Skip to content

Commit a8691a7

Browse files
committed
Add RawValues to Rows
1 parent 4952a48 commit a8691a7

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

pgxpool/rows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ func (errRows) FieldDescriptions() []pgproto3.FieldDescription { return nil }
1717
func (errRows) Next() bool { return false }
1818
func (e errRows) Scan(dest ...interface{}) error { return e.err }
1919
func (e errRows) Values() ([]interface{}, error) { return nil, e.err }
20+
func (e errRows) RawValues() [][]byte { return nil }
2021

2122
type errRow struct {
2223
err error
@@ -81,6 +82,10 @@ func (rows *poolRows) Values() ([]interface{}, error) {
8182
return values, err
8283
}
8384

85+
func (rows *poolRows) RawValues() [][]byte {
86+
return rows.r.RawValues()
87+
}
88+
8489
type poolRow struct {
8590
r pgx.Row
8691
c *Conn

query_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"os"
99
"reflect"
10+
"strconv"
1011
"strings"
1112
"testing"
1213
"time"
@@ -300,6 +301,39 @@ func TestRowsScanDoesNotAllowScanningBinaryFormatValuesIntoString(t *testing.T)
300301
ensureConnValid(t, conn)
301302
}
302303

304+
func TestConnQueryRawValues(t *testing.T) {
305+
t.Parallel()
306+
307+
conn := mustConnectString(t, os.Getenv("PGX_TEST_DATABASE"))
308+
defer closeConn(t, conn)
309+
310+
var rowCount int32
311+
312+
rows, err := conn.Query(
313+
context.Background(),
314+
"select 'foo'::text, 'bar'::varchar, n, null, n from generate_series(1,$1) n",
315+
pgx.QuerySimpleProtocol(true),
316+
10,
317+
)
318+
require.NoError(t, err)
319+
defer rows.Close()
320+
321+
for rows.Next() {
322+
rowCount++
323+
324+
rawValues := rows.RawValues()
325+
assert.Len(t, rawValues, 5)
326+
assert.Equal(t, "foo", string(rawValues[0]))
327+
assert.Equal(t, "bar", string(rawValues[1]))
328+
assert.Equal(t, strconv.FormatInt(int64(rowCount), 10), string(rawValues[2]))
329+
assert.Nil(t, rawValues[3])
330+
assert.Equal(t, strconv.FormatInt(int64(rowCount), 10), string(rawValues[4]))
331+
}
332+
333+
require.NoError(t, rows.Err())
334+
assert.EqualValues(t, 10, rowCount)
335+
}
336+
303337
// Test that a connection stays valid when query results are closed early
304338
func TestConnQueryCloseEarly(t *testing.T) {
305339
t.Parallel()

rows.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ type Rows interface {
4040
// copy the raw bytes received from PostgreSQL. nil will skip the value entirely.
4141
Scan(dest ...interface{}) error
4242

43-
// Values returns an array of the row values
43+
// Values returns the decoded row values.
4444
Values() ([]interface{}, error)
45+
46+
// RawValues returns the unparsed bytes of the row values. The returned [][]byte is only valid until the next Next
47+
// call or the Rows is closed. However, the underlying byte data is safe to retain a reference to and mutate.
48+
RawValues() [][]byte
4549
}
4650

4751
// Row is a convenience wrapper over Rows that is returned by QueryRow.
@@ -249,6 +253,10 @@ func (rows *connRows) Values() ([]interface{}, error) {
249253
return values, rows.Err()
250254
}
251255

256+
func (rows *connRows) RawValues() [][]byte {
257+
return rows.resultReader.Values()
258+
}
259+
252260
type scanArgError struct {
253261
col int
254262
err error

0 commit comments

Comments
 (0)