sqlc-dev / sqlc

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

Non-nullable parameters generated when using overridden type + sqlc.narg + COALESCE #3494

Open bbkane opened 1 month ago

bbkane commented 1 month ago

Version

1.26.0

What happened?

I've got a SQLite table with a TEXT data type called create_time . I update create_time with the following update query:

-- See https://docs.sqlc.dev/en/latest/howto/named_parameters.html#nullable-parameters
-- name: EnvUpdate :exec
UPDATE env SET
    create_time = COALESCE(sqlc.narg('create_time'), create_time)
WHERE id = sqlc.arg('id');

This works fine and generates an update query parameter with a string pointer as I expect when using sqlc.narg:

type EnvUpdateParams struct {
    CreateTime *string
    ID         int64
}

However, if I create the type type SQLiteTime string and set create_time to use this type in sqlc.yaml (which I would like to do so I can attach methods to the type), the generated update code does NOT use a pointer as I expect:

type EnvUpdateParams struct {
    CreateTime sqlite.SQLiteTime
    ID         int64
}

I would expect it to look like:

type EnvUpdateParams struct {
    CreateTime *sqlite.SQLiteTime
    ID         int64
}

Not having it be a pointer means I can't assign nil to it, which breaks my COALESCE SQL update query.

As a full reproducible demo of this bug, I've made https://github.com/bbkane/sqlc-override-nullable . It has a using-text package that demos the correct codegen, and a using-overrides that demos the incorrect codegen.

Some more context about WHY I'd like to be able to to this:

I'm writing an environment variable manager CLI that needs to store times. Instead of the "sqlc-native" format as a stringified time.Time, I want to store times in the "sqlite-native" format as a text column so I can run datetime queries on the columns.

Finally, thank you so much for writing sqlc! I've started GitHub sponsoring you because this tool removes a lot of the drudgery of working with SQL from Go, and I really appreciate that.

Relevant log output

No response

Database schema

CREATE TABLE env (
    id INTEGER PRIMARY KEY,
    create_time TEXT NOT NULL
) STRICT;

SQL queries

-- See https://docs.sqlc.dev/en/latest/howto/named_parameters.html#nullable-parameters
-- name: EnvUpdate :exec
UPDATE env SET
    create_time = COALESCE(sqlc.narg('create_time'), create_time)
WHERE id = sqlc.arg('id');

Configuration

sql:
  - engine: sqlite
    gen:
      go:
        emit_pointers_for_null_types: true
        out: sqlcgen
        package: sqlcgen
        overrides:
          - column: "env.create_time"
            go_type: "go.bbkane.com/sqlc-override-nullable/using-override/sqlite.SQLiteTime"
    queries: queries
    schema: migrations
# yq wants to double quote "2", but yamllint wants it single-quoted
# yamllint disable-line rule:quoted-strings
version: "2"

Playground URL

No response

What operating system are you using?

Linux, macOS

What database engines are you using?

SQLite

What type of code are you generating?

Go

bbkane commented 1 month ago

Also see https://github.com/sqlc-dev/sqlc/issues/2800