LoadTypes always returning empty slice
- Dominant language
- Go
- Stars
- 14.3k
- Forks
- 1.1k
- Avg merge
- 6d 9h
- Merged PRs (30d)
- 11
Description
**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:
```go
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.
Contributor guide
Research direction
Start with the reported main.go reproduction and run it with the race detector using go run -race main.go. Trace the LoadTypes and LoadType entry points and compare their returned registrations; done means LoadTypes returns both requested types and the enum array scans successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, postgresql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100