sqlc-dev / sqlc

Generate type-safe code from SQL
https://sqlc.dev
MIT License
13.37k stars 803 forks source link

Enum array gets output as []interface{} #3511

Open knpwrs opened 3 months ago

knpwrs commented 3 months ago

Version

1.26.0

What happened?

When I select an enum array column in Postgres (pgx) with sqlc the generated type for that column is []interface{}. For some reason this doesn't reproduce in the playground.

I came across this issue but I am new to Go and I'm not quite sure what to do with this code, or if it is even relevant to the issue I am seeing: https://github.com/sqlc-dev/sqlc/issues/2116#issuecomment-1493299852

This is the output:

type UploadDataRow struct {
    ID       pgtype.UUID
    Variants []interface{}
}

Relevant log output

No response

Database schema

CREATE TYPE upload_variant AS ENUM (
    'VIDEO_4K',
    'VIDEO_4K_DOWNLOAD',
    'VIDEO_1080P',
    'VIDEO_1080P_DOWNLOAD',
    'VIDEO_720P',
    'VIDEO_720P_DOWNLOAD',
    'VIDEO_480P',
    'VIDEO_480P_DOWNLOAD',
    'VIDEO_360P',
    'VIDEO_360P_DOWNLOAD',
    'AUDIO',
    'AUDIO_DOWNLOAD'
);

CREATE TABLE upload (
  id   BIGSERIAL PRIMARY KEY,
  variants upload_variant[]
);

SQL queries

-- name: GetUploads :many
SELECT * FROM upload;

Configuration

version: "2"
sql:
  - engine: "postgresql"
    queries: "./app/data"
    database:
      uri: ${DATABASE_URL}
    gen:
      go:
        package: "data"
        out: "./app/data"
        sql_package: "pgx/v5"

Playground URL

https://play.sqlc.dev/p/e60a8ebfe202c5a91bdaaee9b3aef12b085f188ceec8e62b4503c59c6f1d553c

What operating system are you using?

Linux, macOS

What database engines are you using?

PostgreSQL

What type of code are you generating?

Go

knpwrs commented 3 months ago

It seems like this might be related to not specifying a schema.sql file. Does that sound right?

knpwrs commented 3 months ago

I got everything generating correctly and now I understand the purpose of that code in the linked issue. Any custom types need to be registered with pgx or else there will be a runtime failure when pgx tries to read the value into the struct.

I did this as such:

func getDbConn(ctx context.Context) *pgx.Conn {
    conn, err := pgx.Connect(ctx, os.Getenv("DATABASE_URL"))
    if err != nil {
        log.Fatalln(err)
    }

    dataTypeNames := []string{
        "upload_variant",
        "_upload_variant",
    }

    for _, typeName := range dataTypeNames {
        dataType, err := conn.LoadType(ctx, typeName)
        if err != nil {
            log.Fatalln(err)
        }
        conn.TypeMap().RegisterType(dataType)
    }

    return conn
}