Repository navigation
duckdb: a result column without a name is called ?column?, which is not valid Go #4657
Description
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; -- worksConfiguration
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