LoadTypes always returning empty slice
Describe the bug It appears that LoadTypes always returns an empty slice of pgtype.Types, even if err is nil. Loading the same types individually works.
This leads to some errors when using arrays with enum types.
To Reproduce Steps to reproduce the behavior:
package main
import (
"context"
"fmt"
"github.com/jackc/pgx/v5"
)
type Color string
type HasColor struct {
Color Color `db:"color"`
Colors []Color `db:"colors"`
}
func main() {
Works()
DoesntWork()
}
func Works() {
conn := InitConn()
defer conn.Close(context.Background())
InitDB(conn)
for _, s := range []string{"COLOR", "_COLOR"} {
t, err := conn.LoadType(context.Background(), s)
if err != nil {
panic(err)
} else {
fmt.Println(t)
}
conn.TypeMap().RegisterType(t)
}
RunTest(conn)
}
func DoesntWork() {
conn := InitConn()
defer conn.Close(context.Background())
InitDB(conn)
types, err := conn.LoadTypes(context.Background(), []string{"COLOR", "_COLOR"})
if err != nil {
panic(err)
} else {
// types is empty!
fmt.Println(types)
}
conn.TypeMap().RegisterTypes(types)
// Doesn't work:
// can't scan into dest[0]: cannot scan unknown type (OID 16389) in text format into *[]main.Color
RunTest(conn)
}
func InitConn() *pgx.Conn {
conn, err := pgx.Connect(context.Background(), "postgres://local:local@localhost:5432/local")
if err != nil {
panic(err)
}
return conn
}
func InitDB(conn *pgx.Conn) {
_, err := conn.Exec(context.Background(), `
CREATE TYPE COLOR AS ENUM ('red', 'green', 'blue');
CREATE TABLE HasColor (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), color COLOR, colors COLOR[]);
INSERT INTO HasColor (color, colors) VALUES ('red', '{green}')
`)
if err != nil {
fmt.Println(err)
}
}
func RunTest(conn *pgx.Conn) {
var result HasColor
err := conn.QueryRow(context.Background(), "select color from HasColor").Scan(&result.Color)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(result)
}
err = conn.QueryRow(context.Background(), "select colors from HasColor").Scan(&result.Colors)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(result)
}
}
Please run your example with the race detector enabled. For example, go run -race main.go or go test -race.
Expected behavior
LoadTypes should work the same as for ... { LoadType ... }
Actual behavior Output of above program:
ERROR: type "color" already exists (SQLSTATE 42710)
&{0xc00007a318 COLOR 16386}
&{0xc00007a320 _COLOR 16385}
{red []}
{red [green]}
ERROR: type "color" already exists (SQLSTATE 42710)
[]
{red []}
can't scan into dest[0]: cannot scan unknown type (OID 16385) in text format into *[]main.Color
Note, that the types array is empty and even though the simple enum can be scanned, the enum array gives an error.
Version
- Go: go version go1.23.6 linux/amd64
- PostgreSQL: PostgreSQL 17.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 14.2.0) 14.2.0, 64-bit
- pgx: github.com/jackc/pgx/v5 v5.7.2
Additional context Add any other context about the problem here.
@kosmoz Can you check out #2183? @felix-roehrich has been doing some work on LoadTypes and it's possible his changes have fixed this.
Yes, the same code as above works in https://github.com/felix-roehrich/pgx/tree/fr/load-types