From c3258b7f52a3144ecee26228491d7513cd673715 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sat, 30 Jul 2022 09:10:50 -0500 Subject: [PATCH] Fix scan pointer to pointer to nil slice https://github.com/jackc/pgx/issues/1263 --- pgtype/array_codec.go | 7 +++++++ pgtype/pgtype_test.go | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/pgtype/array_codec.go b/pgtype/array_codec.go index 8ed45da5..dae12039 100644 --- a/pgtype/array_codec.go +++ b/pgtype/array_codec.go @@ -6,6 +6,7 @@ import ( "fmt" "reflect" + "github.com/jackc/pgx/v5/internal/anynil" "github.com/jackc/pgx/v5/internal/pgio" ) @@ -216,6 +217,12 @@ func (c *ArrayCodec) PlanScan(m *Map, oid uint32, format int16, target any) Scan return nil } + // target / arrayScanner might be a pointer to a nil. If it is create one so we can call ScanIndexType to plan the + // scan of the elements. + if anynil.Is(target) { + arrayScanner = reflect.New(reflect.TypeOf(target).Elem()).Interface().(ArraySetter) + } + elementType := arrayScanner.ScanIndexType() elementScanPlan := m.PlanScan(c.ElementType.OID, format, elementType) diff --git a/pgtype/pgtype_test.go b/pgtype/pgtype_test.go index 685cbb62..6325829e 100644 --- a/pgtype/pgtype_test.go +++ b/pgtype/pgtype_test.go @@ -254,6 +254,17 @@ func TestScanPlanInterface(t *testing.T) { assert.Error(t, err) } +// https://github.com/jackc/pgx/issues/1263 +func TestMapScanPtrToPtrToSlice(t *testing.T) { + m := pgtype.NewMap() + src := []byte("{foo,bar}") + var v *[]string + plan := m.PlanScan(pgtype.TextArrayOID, pgtype.TextFormatCode, &v) + err := plan.Scan(src, &v) + require.NoError(t, err) + require.Equal(t, []string{"foo", "bar"}, *v) +} + func BenchmarkTypeMapScanInt4IntoBinaryDecoder(b *testing.B) { m := pgtype.NewMap() src := []byte{0, 0, 0, 42}