From ef7114a8ceec41043c2006dc7f4032962269b770 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Mon, 31 Jan 2022 20:39:50 -0600 Subject: [PATCH] Add DecodeValue and DecodeDatabaseSQLValue for ArrayCodec --- pgtype/array_codec.go | 27 +++++++++++++++------------ pgtype/array_codec_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/pgtype/array_codec.go b/pgtype/array_codec.go index 5d847fae..901ea5f7 100644 --- a/pgtype/array_codec.go +++ b/pgtype/array_codec.go @@ -332,26 +332,29 @@ func (spac *scanPlanArrayCodec) Scan(src []byte, dst interface{}) error { } } -func (c ArrayCodec) DecodeDatabaseSQLValue(ci *ConnInfo, oid uint32, format int16, src []byte) (driver.Value, error) { +func (c *ArrayCodec) DecodeDatabaseSQLValue(ci *ConnInfo, oid uint32, format int16, src []byte) (driver.Value, error) { if src == nil { return nil, nil } - // var n int64 - // err := c.PlanScan(ci, oid, format, &n, true).Scan(ci, oid, format, src, &n) - // return n, err - - return nil, fmt.Errorf("not implemented") + switch format { + case TextFormatCode: + return string(src), nil + case BinaryFormatCode: + buf := make([]byte, len(src)) + copy(buf, src) + return buf, nil + default: + return nil, fmt.Errorf("unknown format code %d", format) + } } -func (c ArrayCodec) DecodeValue(ci *ConnInfo, oid uint32, format int16, src []byte) (interface{}, error) { +func (c *ArrayCodec) DecodeValue(ci *ConnInfo, oid uint32, format int16, src []byte) (interface{}, error) { if src == nil { return nil, nil } - // var n int16 - // err := c.PlanScan(ci, oid, format, &n, true).Scan(ci, oid, format, src, &n) - // return n, err - - return nil, fmt.Errorf("not implemented") + var slice []interface{} + err := ci.PlanScan(oid, format, &slice).Scan(src, &slice) + return slice, err } diff --git a/pgtype/array_codec_test.go b/pgtype/array_codec_test.go index c358586e..0c31dcee 100644 --- a/pgtype/array_codec_test.go +++ b/pgtype/array_codec_test.go @@ -6,6 +6,7 @@ import ( "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestArrayCodec(t *testing.T) { @@ -70,3 +71,40 @@ func TestArrayCodecAnySlice(t *testing.T) { assert.Equalf(t, tt.expected, actual, "%d", i) } } + +func TestArrayCodecDecodeValue(t *testing.T) { + conn := testutil.MustConnectPgx(t) + defer testutil.MustCloseContext(t, conn) + + for _, tt := range []struct { + sql string + expected interface{} + }{ + { + sql: `select '{}'::int4[]`, + expected: []interface{}{}, + }, + { + sql: `select '{1,2}'::int8[]`, + expected: []interface{}{int64(1), int64(2)}, + }, + { + sql: `select '{foo,bar}'::text[]`, + expected: []interface{}{"foo", "bar"}, + }, + } { + t.Run(tt.sql, func(t *testing.T) { + rows, err := conn.Query(context.Background(), tt.sql) + require.NoError(t, err) + + for rows.Next() { + values, err := rows.Values() + require.NoError(t, err) + require.Len(t, values, 1) + require.Equal(t, tt.expected, values[0]) + } + + require.NoError(t, rows.Err()) + }) + } +}