Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoadTypes always returning empty slice #2254

Open
kosmoz opened this issue Feb 11, 2025 · 2 comments
Open

LoadTypes always returning empty slice #2254

kosmoz opened this issue Feb 11, 2025 · 2 comments
Labels

Comments

@kosmoz
Copy link

kosmoz commented Feb 11, 2025

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.

@jackc
Copy link
Owner

jackc commented Feb 17, 2025

@kosmoz Can you check out #2183? @felix-roehrich has been doing some work on LoadTypes and it's possible his changes have fixed this.

@kosmoz
Copy link
Author

kosmoz commented Feb 18, 2025

Yes, the same code as above works in https://github.com/felix-roehrich/pgx/tree/fr/load-types

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants