Skip to content

SQLite: non-ASCII character (em-dash) in SQL comment corrupts generated queries #4372

@exploded

Description

@exploded

Version

1.30.0

What happened?

When a SQL comment between two named queries contains an em-dash (—, U+2014), sqlc corrupts the generated Go code. The trailing ? parameter placeholder is stripped from the query, and the comment text leaks into the Go source as a misplaced comment.

In our production codebase this caused ~15 queries to silently fail at runtime. The corruption went unnoticed because the Go code compiles — sqlc generates the correct number of params in the struct/function, but the SQL string is truncated.

Expected generated output

const updateItem = `-- name: UpdateItem :exec
UPDATE items SET name = ? WHERE id = ?
`

func (q *Queries) UpdateItem(ctx context.Context, arg UpdateItemParams) error {
	_, err := q.db.ExecContext(ctx, updateItem, arg.Name, arg.ID)
	return err
}

Actual generated output

const updateItem = `-- name: UpdateItem :exec

UPDATE items SET name = ? WHERE id =
`

// section — divider
func (q *Queries) UpdateItem(ctx context.Context, arg UpdateItemParams) error {
	_, err := q.db.ExecContext(ctx, updateItem, arg.Name, arg.ID)
	return err
}

Note:

WHERE id = is missing the trailing ? — runtime SQL syntax error
The comment // section — divider leaked into the Go code
Two args are passed to ExecContext but the SQL only has one ? placeholder
The bug cascades: in a file with many queries after the offending comment, every query loses its last ? and gets ?; prepended from the previous query.

Replacing the em-dash (—) with a regular hyphen (-) fixes the issue.

Relevant log output

const updateItem = `-- name: UpdateItem :exec

UPDATE items SET name = ? WHERE id =
`

// section — divider
func (q *Queries) UpdateItem(ctx context.Context, arg UpdateItemParams) error {
	_, err := q.db.ExecContext(ctx, updateItem, arg.Name, arg.ID)
	return err
}

Database schema

CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT NOT NULL);

SQL queries

-- name: GetItem :one
SELECT id, name FROM items WHERE id = ?;

-- section — divider

-- name: UpdateItem :exec
UPDATE items SET name = ? WHERE id = ?;

Configuration

version: "2"
sql:
  - engine: "sqlite"
    queries: "query.sql"
    schema: "schema.sql"
    gen:
      go:
        package: "db"
        out: "db"

Playground URL

(https://play.sqlc.dev/p/effb23cebb0f3c49e956dc7b28f962735b871a5f6feb5d3e3114e9f9b841cb28)

What operating system are you using?

Windows

What database engines are you using?

SQLite

What type of code are you generating?

Go

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions