From 4380e23ae1c8c8b983ccabdc570eef807c4f4b8e Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sat, 24 Apr 2021 08:08:34 -0500 Subject: [PATCH] CompositeTextScanner handles backslash escapes fixes https://github.com/jackc/pgx/issues/874 --- composite_type.go | 4 ++++ composite_type_test.go | 43 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/composite_type.go b/composite_type.go index 7c8dbcd5..32e0aa26 100644 --- a/composite_type.go +++ b/composite_type.go @@ -491,6 +491,10 @@ func (cfs *CompositeTextScanner) Next() bool { } else { break } + } else if ch == '\\' { + cfs.rp++ + cfs.fieldBytes = append(cfs.fieldBytes, cfs.src[cfs.rp]) + cfs.rp++ } else { cfs.fieldBytes = append(cfs.fieldBytes, ch) cfs.rp++ diff --git a/composite_type_test.go b/composite_type_test.go index 664fe36e..2349a67d 100644 --- a/composite_type_test.go +++ b/composite_type_test.go @@ -204,6 +204,49 @@ create type ct_test as ( } } +// https://github.com/jackc/pgx/issues/874 +func TestCompositeTypeTextDecodeNested(t *testing.T) { + newCompositeType := func(name string, fieldNames []string, vals ...pgtype.ValueTranscoder) *pgtype.CompositeType { + fields := make([]pgtype.CompositeTypeField, len(fieldNames)) + for i, name := range fieldNames { + fields[i] = pgtype.CompositeTypeField{Name: name} + } + + rowType, err := pgtype.NewCompositeTypeValues(name, fields, vals) + require.NoError(t, err) + return rowType + } + + dimensionsType := func() pgtype.ValueTranscoder { + return newCompositeType( + "dimensions", + []string{"width", "height"}, + &pgtype.Int4{}, + &pgtype.Int4{}, + ) + } + productImageType := func() pgtype.ValueTranscoder { + return newCompositeType( + "product_image_type", + []string{"source", "dimensions"}, + &pgtype.Text{}, + dimensionsType(), + ) + } + productImageSetType := newCompositeType( + "product_image_set_type", + []string{"name", "orig_image", "images"}, + &pgtype.Text{}, + productImageType(), + pgtype.NewArrayType("product_image", 0, func() pgtype.ValueTranscoder { + return productImageType() + }), + ) + + err := productImageSetType.DecodeText(nil, []byte(`(name,"(img1,""(11,11)"")","{""(img2,\\""(22,22)\\"")"",""(img3,\\""(33,33)\\"")""}")`)) + require.NoError(t, err) +} + func Example_composite() { conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE")) if err != nil {