diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc41625..587ee9bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# Unreleased + +## Fixes + +* Fix Rows.Values returning same value for multiple columns of same complex type + # 3.1.0 (January 15, 2018) ## Features diff --git a/query.go b/query.go index 3576091f..c014cacd 100644 --- a/query.go +++ b/query.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "reflect" "time" "github.com/pkg/errors" @@ -287,7 +288,7 @@ func (rows *Rows) Values() ([]interface{}, error) { } if dt, ok := rows.conn.ConnInfo.DataTypeForOID(fd.DataType); ok { - value := dt.Value + value := reflect.New(reflect.ValueOf(dt.Value).Elem().Type()).Interface().(pgtype.Value) switch fd.FormatCode { case TextFormatCode: diff --git a/query_test.go b/query_test.go index 24285175..6b6b5fac 100644 --- a/query_test.go +++ b/query_test.go @@ -5,6 +5,7 @@ import ( "context" "database/sql" "fmt" + "reflect" "strings" "testing" "time" @@ -155,6 +156,68 @@ func TestConnQueryValues(t *testing.T) { } } +// https://github.com/jackc/pgx/issues/386 +func TestConnQueryValuesWithMultipleComplexColumnsOfSameType(t *testing.T) { + t.Parallel() + + conn := mustConnect(t, *defaultConnConfig) + defer closeConn(t, conn) + + expected0 := &pgtype.Int8Array{ + Elements: []pgtype.Int8{ + {Int: 1, Status: pgtype.Present}, + {Int: 2, Status: pgtype.Present}, + {Int: 3, Status: pgtype.Present}, + }, + Dimensions: []pgtype.ArrayDimension{{Length: 3, LowerBound: 1}}, + Status: pgtype.Present, + } + + expected1 := &pgtype.Int8Array{ + Elements: []pgtype.Int8{ + {Int: 4, Status: pgtype.Present}, + {Int: 5, Status: pgtype.Present}, + {Int: 6, Status: pgtype.Present}, + }, + Dimensions: []pgtype.ArrayDimension{{Length: 3, LowerBound: 1}}, + Status: pgtype.Present, + } + + var rowCount int32 + + rows, err := conn.Query("select '{1,2,3}'::bigint[], '{4,5,6}'::bigint[] from generate_series(1,$1) n", 10) + if err != nil { + t.Fatalf("conn.Query failed: %v", err) + } + defer rows.Close() + + for rows.Next() { + rowCount++ + + values, err := rows.Values() + if err != nil { + t.Fatalf("rows.Values failed: %v", err) + } + if len(values) != 2 { + t.Errorf("Expected rows.Values to return 2 values, but it returned %d", len(values)) + } + if !reflect.DeepEqual(values[0], expected0) { + t.Errorf(`Expected values[0] to be %v, but it was %v`, expected0, values[0]) + } + if !reflect.DeepEqual(values[1], expected1) { + t.Errorf(`Expected values[1] to be %v, but it was %v`, expected1, values[1]) + } + } + + if rows.Err() != nil { + t.Fatalf("conn.Query failed: %v", err) + } + + if rowCount != 10 { + t.Error("Select called onDataRow wrong number of times") + } +} + // https://github.com/jackc/pgx/issues/228 func TestRowsScanDoesNotAllowScanningBinaryFormatValuesIntoString(t *testing.T) { t.Parallel()