pgx icon indicating copy to clipboard operation
pgx copied to clipboard

panic on scanning to slice of custom types

Open mr-tron opened this issue 1 year ago • 2 comments

Describe the bug Library panics on scanning to []CustomType

To Reproduce

package main

import (
	"context"

	"github.com/jackc/pgx/v4/pgxpool"
)

type Int64 int64
func main() {
	conn,err := pgxpool.Connect(context.Background(), "postgres://user:qwert1@localhost/tests?port=5432&application_name=subbotin_pidor")
	if err !=nil {
		panic(err)
	}
	_, err = conn.Exec(context.Background(), "CREATE TABLE IF NOT EXISTS test (id serial PRIMARY KEY, ids bigint[])")
	if err != nil {
		panic(err)
	}
	_, err = conn.Exec(context.Background(), "INSERT INTO test (ids) VALUES ($1)", []Int64{1,2,3})
	if err != nil {
		panic(err)
	}
	var ids []Int64
	err = conn.QueryRow(context.Background(), "SELECT ids FROM test WHERE id = 1").Scan(&ids)
	if err != nil {
		panic(err)
	}
	print(ids)
}

Expected behavior Printing 1, 2, 3

Actual behavior

panic: reflect.Value.Convert: value of type *[]main.Int64 cannot be converted to type *[]int64

goroutine 1 [running]:
reflect.Value.Convert({0x727320?, 0xc0002020a8?, 0x3?}, {0x81cde8, 0x7276e0})
        /home/user/sdk/go1.22.0/src/reflect/value.go:3368 +0x12c
github.com/jackc/pgtype.toInterface({0x727320?, 0xc0002020a8?, 0x6?}, {0x81cde8?, 0x7276e0?})
        /home/user/go/pkg/mod/github.com/jackc/[email protected]/convert.go:397 +0x46
github.com/jackc/pgtype.GetAssignToDstType({0x727320?, 0xc0002020a8?})
        /home/user/go/pkg/mod/github.com/jackc/[email protected]/convert.go:431 +0x2a6
github.com/jackc/pgtype.(*Int8Array).AssignTo(0xc000072e80, {0x727320, 0xc0002020a8})
        /home/user/go/pkg/mod/github.com/jackc/[email protected]/int8_array.go:613 +0x885
github.com/jackc/pgtype.(*scanPlanDataTypeAssignTo).Scan(0xc00007e5a0, 0xc00010abd0, 0x3f8, 0x1, {0xc0001b2336, 0x38, 0x38}, {0x727320, 0xc0002020a8})
        /home/user/go/pkg/mod/github.com/jackc/[email protected]/pgtype.go:590 +0x130
github.com/jackc/pgx/v4.(*connRows).Scan(0xc00021a000, {0xc000210020?, 0x1, 0xc000210020?})
        /home/user/go/pkg/mod/github.com/jackc/pgx/[email protected]/rows.go:225 +0x3fd
github.com/jackc/pgx/v4.(*connRow).Scan(0xc00021a000, {0xc000210020, 0x1, 0x1})
        /home/user/go/pkg/mod/github.com/jackc/pgx/[email protected]/rows.go:88 +0x8e
github.com/jackc/pgx/v4/pgxpool.(*poolRow).Scan(0xc0000e69e0, {0xc000210020?, 0xa87f40?, 0x796afb?})
        /home/user/go/pkg/mod/github.com/jackc/pgx/[email protected]/pgxpool/rows.go:100 +0x31
main.main()

Version

  • Go: v2.21
  • PostgreSQL: 14
  • pgx: github.com/jackc/pgx/v4 v4.17.2

mr-tron avatar May 28 '24 19:05 mr-tron

There is a workarround:

type Int64s []Int64

func (ids *Int64s) Scan(src interface{}) error {
	var dest pgtype.Int8Array
	err := dest.Scan(src)
	*ids = make(Int64s, len(dest.Elements))
	for i := range dest.Elements {
		(*ids)[i] = Int64(dest.Elements[i].Int)
	}
	return err
}

but I don't sure what library should panic in any cases

mr-tron avatar May 28 '24 20:05 mr-tron

It works on v5.

jackc avatar May 28 '24 22:05 jackc