Skip to content

duckdb: a result column without a name is called ?column?, which is not valid Go #4657

Open

Description

@xen0l

Version

main at commit 3ad8b20 (2026-10-23), built with CGO_ENABLED=0 go install github.com/sqlc-dev/sqlc/cmd/sqlc@3ad8b20fb02b5bea81591b673da0758b8685d951.
sqlc version prints v1.31.1 because internal/info/facts.go hard-codes it.
The DuckDB engine was added in #4621 and is not in a tagged release.

What happened?

A result column with no alias, that is not a plain column and not a function call, gets the name ?column?.
For a query with such a column, sqlc writes var ?column? ... in the generated Go.
The code does not format, and sqlc generate fails with illegal character U+003F '?'.
The same expression with an alias works. Affected: CAST(...) and a || b.

The PostgreSQL and SQLite engines name such a column column_1 (by position). DuckDB should do the same.

What DuckDB v1.5.6 reports (DESCRIBE): CAST(age AS BIGINT) BIGINT and ("name" || '!') VARCHAR.

Expected: a valid Go name (column_1), and code that compiles.

Cause

targetName in internal/core/analyzer/projection.go (lines 108–120) returns the string "?column?" when a target has
no name, no column name and no function name. The Go generator already falls back to column_N
(internal/codegen/golang/result.go, columnName), but only for an empty name. No other non-test Go file contains ?column?.

Reproduction

repro3.sh
#!/usr/bin/env bash
rm -rf repro3 && mkdir repro3 && cd repro3
cat > sqlc.yaml <<'EOF'
version: "2"
sql:
  - engine: "duckdb"
    schema: "schema.sql"
    queries: "query.sql"
    gen:
      go:
        package: "repro"
        out: "out"
EOF
cat > schema.sql <<'EOF'
CREATE TABLE people (id INTEGER NOT NULL, name VARCHAR NOT NULL, age INTEGER);
EOF
while IFS= read -r q; do
  printf -- '-- name: Q :many\n%s\n' "$q" > query.sql; rm -rf out
  echo "== $q"
  sqlc generate 2>&1 | grep -E 'error generating code|var \?column\?' | head -3
  [ -f out/query.sql.go ] && echo "generated OK: $(grep -E '^func \(q \*Queries\) Q' out/query.sql.go | sed 's/^func (q \*Queries) //')"
done <<'EOF'
SELECT CAST(age AS BIGINT) AS age FROM people;
SELECT CAST(age AS BIGINT) FROM people;
SELECT name || '!' FROM people;
SELECT id + 1, age * 2 FROM people;
SELECT upper(name) FROM people;
EOF
echo
echo "== the name that sqlc analyze reports"
printf -- "-- name: Q :many\nSELECT CAST(age AS BIGINT) FROM people;\n" > query.sql
sqlc analyze --dialect duckdb --schema schema.sql query.sql | grep -E '"name"' | grep -v '"name": "Q"'

Fix

I have a patch with an end-to-end test case, and I will open a pull request.

Related

With this change, SELECT * EXCLUDE (...) generates []any and fails at run time instead of failing at generate time. That is the subject of the separate issue about * EXCLUDE and * REPLACE.

Relevant log output

== SELECT CAST(age AS BIGINT) AS age FROM people;
generated OK: Q(ctx context.Context) ([]sql.NullInt64, error) {
== SELECT CAST(age AS BIGINT) FROM people;
        var ?column? sql.NullInt64
error generating code: source error: 43:13: illegal character U+003F '?' (and 10 more errors)
== SELECT name || '!' FROM people;
        var ?column? string
error generating code: source error: 42:13: illegal character U+003F '?' (and 10 more errors)
== SELECT id + 1, age * 2 FROM people;
generated OK: Q(ctx context.Context) ([]QRow, error) {
== SELECT upper(name) FROM people;
generated OK: Q(ctx context.Context) ([]string, error) {

== the name that sqlc analyze reports
        "name": "?column?",
          "name": "bigint",

Database schema

CREATE TABLE people (id INTEGER NOT NULL, name VARCHAR NOT NULL, age INTEGER);

SQL queries

SELECT CAST(age AS BIGINT) AS age FROM people;      -- works
SELECT CAST(age AS BIGINT) FROM people;             -- fails
SELECT name || '!' FROM people;                     -- fails
SELECT id + 1, age * 2 FROM people;                 -- works
SELECT upper(name) FROM people;                     -- works

Configuration

version: "2"
sql:
  - engine: "duckdb"
    schema: "schema.sql"
    queries: "query.sql"
    gen:
      go:
        package: "repro"
        out: "out"

Playground URL

Not available. play.sqlc.dev runs only v1.18.0–v1.25.0, and the DuckDB engine is not in a release (v1.25.0 answers unknown engine: duckdb; main, a commit and every later release return HTTP 500). The report has a script that needs only go install github.com/sqlc-dev/sqlc/cmd/sqlc@3ad8b20fb02b5bea81591b673da0758b8685d951.

What operating system are you using?

Linux

What database engines are you using?

(none of the listed options; the engine is duckdb)

What type of code are you generating?

Go

Related

Related: #4660 (SELECT * EXCLUDE (...) and * REPLACE (...)).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions