sqlc-dev/sqlc

Type overrides not honoured for nullable fields with pgx5

lucianonooijen opened this issue · 5 comments

Version

1.27.0

What happened?

With the following config:

        emit_pointers_for_null_types: true
        overrides:
          - db_type: "uuid"
            go_type:
              import: "github.com/google/uuid"
              type: "UUID"

The generated Go type is

type User struct {
	ID           int32       `json:"id"`
	UserUuid     uuid.UUID   `json:"userUuid"`
	PasswordHash *string     `json:"passwordHash"`
	PasswordUuid pgtype.UUID `json:"passwordUuid"`
	Email        string      `json:"email"`
	FirstName    string      `json:"firstName"`
	LastName     string      `json:"lastName"`
	CreatedAt    time.Time   `json:"createdAt"`
}

where I would expect

PasswordUuid *uuid.UUID `json:"passwordUuid"`

Relevant log output

No response

Database schema

-- Users table
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    user_uuid uuid UNIQUE NOT NULL DEFAULT (uuid_generate_v4()),
    password_hash varchar,
    password_uuid uuid UNIQUE,
    email varchar UNIQUE NOT NULL,
    first_name varchar NOT NULL,
    last_name varchar NOT NULL,
    created_at timestamp NOT NULL DEFAULT (now())
);

SQL queries

n/a

Configuration

version: "2"
sql:
  - engine: "postgresql"
    queries: "sql/"
    schema: "migrations/"
    gen:
      go:
        package: "database"
        out: "internal/data/database"
        sql_package: "pgx/v5"
        emit_json_tags: true
        json_tags_case_style: "camel"
        emit_pointers_for_null_types: true
        overrides:
          - db_type: "uuid"
            go_type:
              import: "github.com/google/uuid"
              type: "UUID"
          - db_type: "pg_catalog.timestamp"
            go_type: "time.Time"

Playground URL

No response

What operating system are you using?

Linux

What database engines are you using?

PostgreSQL

What type of code are you generating?

Go

Another example, but with timestamps:

-- Logs chunks table
CREATE TABLE logs_chunks (
    chunk SERIAL PRIMARY KEY,
    log bigint NOT NULL REFERENCES logs(id),
    created_on timestamp NOT NULL DEFAULT now(),
    blob_path varchar UNIQUE NOT NULL,
    chunk_start timestamp,
    chunk_end timestamp,
    line_count int NOT NULL,
    category_counts jsonb NOT NULL,
    severity_counts jsonb NOT NULL,

    CONSTRAINT log_chunks_category_counts_object CHECK (jsonb_typeof(category_counts) = 'object'),
    CONSTRAINT log_chunks_severity_counts_object CHECK (jsonb_typeof(severity_counts) = 'object')
);

With

-- name: AddLogChunk :exec
-- Adds data for an uploaded log chunk
INSERT INTO logs_chunks(log, blob_path, chunk_start, chunk_end, line_count, category_counts, severity_counts)
VALUES ($1, $2, $3, $4, $5, $6, $7);

Generating

type AddLogChunkParams struct {
	Log            int64            `json:"log"`
	BlobPath       string           `json:"blobPath"`
	ChunkStart     pgtype.Timestamp `json:"chunkStart"`
	ChunkEnd       pgtype.Timestamp `json:"chunkEnd"`
	LineCount      int32            `json:"lineCount"`
	CategoryCounts []byte           `json:"categoryCounts"`
	SeverityCounts []byte           `json:"severityCounts"`
}

You need 2 configs. One for non pointer version and another for pointer version.
try something like this

- db_type: "uuid"
  go_type:
    import: "github.com/google/uuid"
    type: "UUID"
- db_type: "uuid"
  go_type:
    import: "github.com/google/uuid"
    type: "UUID"
    pointer: true
  nullable: true

Same goes for timestamptz

Ah thank you very much, this indeed solves it!

@lucianonooijen please close the issue

Done! It might be worth adding the nullable/pointer logic into the documentation as well, in case others encounter the same issue