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

sqlc Code Generation Errors with UPDATE Query: Star Expansion Failure and Non-Existent 'sqlc' Schema #3897

Open
sunmery opened this issue Mar 25, 2025 · 1 comment
Labels

Comments

@sunmery
Copy link

sunmery commented Mar 25, 2025

Version

1.28.0

What happened?

When attempting to generate code for an UPDATE query using sqlc, I encountered two different errors depending on the syntax used:

  1. Error 1 :
    When using $1 and $2 as positional placeholders in the query:
UPDATE products.products
SET name        = coalesce(sqlc.narg(name), name),
    updated_at  = now()
WHERE id = $1
  AND merchant_id = $2
RETURNING *;

The error reported by sqlc is:

internal/data/queries/product.sql:42:1: star expansion failed for query
  1. Error 2 :
    When using sqlc.arg() for named parameters:
-- name: UpdateProduct :one
UPDATE products.products
SET name        = coalesce(sqlc.narg(name), name),
    updated_at  = now()
WHERE id = sqlc.arg(id)
  AND merchant_id = sqlc.arg(merchant_id)
RETURNING *;

The error reported by sqlc is:

internal/data/queries/product.sql:46:12: schema "sqlc" does not exist

Both queries execute successfully when run directly in the database, indicating that the issue lies with sqlc's parsing or code generation.

Image

Relevant log output

error1: internal/data/queries/product.sql:42:1: star expansion failed for query

error2: internal/data/queries/product.sql:46:12: schema "sqlc" does not exist

Database schema

CREATE SCHEMA IF NOT EXISTS merchant;
SET SEARCH_PATH TO merchant, products;

CREATE FUNCTION uuidv7_sub_ms() RETURNS uuid
AS
$$
select encode(
               substring(int8send(floor(t_ms)::int8) from 3) ||
               int2send((7 << 12)::int2 | ((t_ms - floor(t_ms)) * 4096)::int2) ||
               substring(uuid_send(gen_random_uuid()) from 9 for 8)
           , 'hex')::uuid
from (select extract(epoch from clock_timestamp()) * 1000 as t_ms) s
$$ LANGUAGE sql volatile;

CREATE TABLE merchant.stock_alerts
(
    id          UUID                 DEFAULT uuidv7_sub_ms() PRIMARY KEY,
    product_id  UUID        NOT NULL,
    merchant_id UUID        NOT NULL,
    threshold   INT         NOT NULL CHECK (threshold > 0),
    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (product_id, merchant_id)
);

CREATE TABLE products.products
(
    id               UUID                  DEFAULT uuidv7_sub_ms(),
    merchant_id      UUID         NOT NULL,
    name             VARCHAR(255) NOT NULL,
    description      TEXT,
    price            NUMERIC(15, 2) CHECK (price >= 0),
    status           SMALLINT     NOT NULL DEFAULT 1,
    current_audit_id UUID,
    category_id      int8         NOT NULL,
    created_at       TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    updated_at       TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    deleted_at       TIMESTAMPTZ,
    PRIMARY KEY (merchant_id, id)
);

SQL queries

-- name: UpdateProduct :one
UPDATE products.products
SET name        = coalesce(sqlc.narg(name), name),
    updated_at  = now()
WHERE id = sqlc.arg(id)
  AND merchant_id = sqlc.arg(merchant_id)
RETURNING *;

-- name: UpdateProduct2 :one
UPDATE products.products
SET name        = $3,
    updated_at  = now()
WHERE id = $1
  AND merchant_id = $2
RETURNING *;

Configuration

version: "2"
sql:
  - schema: "internal/data/migrate"
    queries: "internal/data/queries"
    engine: "postgresql"
    database:
      uri: ${DB_SOURCE}
      # uri: postgresql://postgres:postgres@localhost:5432/database?sslmode=disable
    gen:
      go:
        package: "models"
        out: "internal/data/models"
        sql_package: "pgx/v5"
        emit_db_tags: false
        emit_prepared_queries: true
        emit_interface: true
        emit_exact_table_names: true
        emit_empty_slices: false
        emit_exported_queries: true
        emit_json_tags: false
        emit_result_struct_pointers: false
        emit_params_struct_pointers: false
        emit_methods_with_db_argument: false
        emit_pointers_for_null_types: true
        emit_enum_valid_method: true
        emit_all_enum_values: true
        emit_sql_as_comment: true
        json_tags_id_uppercase: true
        json_tags_case_style: snake
        omit_unused_structs: false
        output_batch_file_name: batch.go
        output_db_file_name: db.go
        output_models_file_name: models.go
        output_querier_file_name: querier.go
        output_copyfrom_file_name: copyfrom.go
        query_parameter_limit: 1
        overrides:
          - db_type: "pg_catalog.timestamptz"
            go_type: "time.Time"
          - db_type: "uuid"
            go_type: "github.com/google/uuid.UUID"
          - db_type: "pg_catalog.int4"
            go_type: "uint32"
          - db_type: "pg_catalog.int8"
            go_type: "uint64"

Playground URL

No response

What operating system are you using?

macOS

What database engines are you using?

PostgreSQL

What type of code are you generating?

Go

@sunmery sunmery added the bug Something isn't working label Mar 25, 2025
@sunmery
Copy link
Author

sunmery commented Mar 25, 2025

When I use :exec and remove RETURNING *, it works correctly.

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

1 participant