From 67f2a4158742064399f0c8d382c23a07bf895f4c Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Thu, 20 Apr 2023 20:12:20 -0500 Subject: [PATCH] Fix scanning a table type into a struct Table types have system / hidden columns like tableoid, cmax, xmax, etc. These are not included when sending or receiving composite types. https://github.com/jackc/pgx/issues/1576 --- conn.go | 4 +++- pgtype/composite_test.go | 45 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/conn.go b/conn.go index 92b6f3e4..0bbf3cee 100644 --- a/conn.go +++ b/conn.go @@ -1282,7 +1282,9 @@ func (c *Conn) getCompositeFields(ctx context.Context, oid uint32) ([]pgtype.Com var fieldOID uint32 rows, _ := c.Query(ctx, `select attname, atttypid from pg_attribute -where attrelid=$1 and not attisdropped +where attrelid=$1 + and not attisdropped + and attnum > 0 order by attnum`, typrelid, ) diff --git a/pgtype/composite_test.go b/pgtype/composite_test.go index a6fa8315..a049b448 100644 --- a/pgtype/composite_test.go +++ b/pgtype/composite_test.go @@ -208,3 +208,48 @@ create type point3d as ( } }) } + +// Test for composite type from table instead of create type. Table types have system / hidden columns like tableoid, +// cmax, xmax, etc. These are not included when sending or receiving composite types. +// +// https://github.com/jackc/pgx/issues/1576 +func TestCompositeCodecTranscodeStructWrapperForTable(t *testing.T) { + skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") + + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + + _, err := conn.Exec(ctx, `drop table if exists point3d; + +create table point3d ( + x float8, + y float8, + z float8 +);`) + require.NoError(t, err) + defer conn.Exec(ctx, "drop table point3d") + + dt, err := conn.LoadType(ctx, "point3d") + require.NoError(t, err) + conn.TypeMap().RegisterType(dt) + + formats := []struct { + name string + code int16 + }{ + {name: "TextFormat", code: pgx.TextFormatCode}, + {name: "BinaryFormat", code: pgx.BinaryFormatCode}, + } + + type anotherPoint struct { + X, Y, Z float64 + } + + for _, format := range formats { + input := anotherPoint{X: 1, Y: 2, Z: 3} + var output anotherPoint + err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) + require.NoErrorf(t, err, "%v", format.name) + require.Equalf(t, input, output, "%v", format.name) + } + }) +}