jackc / jackc/pgx

LoadTypes always returning empty slice

Open
#2,254 5 comments 1 reaction 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.