From 192605e8056f4e5833295673eb6c193ff7b05bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6ne?= Date: Wed, 11 Nov 2026 15:55:40 +0100 Subject: [PATCH 1/2] fix(sqlite): Keep RETURNING alias as column name --- internal/engine/sqlite/convert.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go index dad36d4d1e..b3865a2aa6 100644 --- a/internal/engine/sqlite/convert.go +++ b/internal/engine/sqlite/convert.go @@ -535,11 +535,16 @@ func (c *cc) convertUpdateStmt(n *meyer.UpdateStmt) ast.Node { func (c *cc) convertReturning(cols []*meyer.ResultColumn) *ast.List { list := &ast.List{Items: []ast.Node{}} for _, col := range cols { - list.Items = append(list.Items, &ast.ResTarget{ + target := &ast.ResTarget{ Indirection: &ast.List{}, Val: c.convertExpr(col.Expr), Location: col.Pos(), - }) + } + if col.Alias != nil { + name := identifier(col.Alias) + target.Name = &name + } + list.Items = append(list.Items, target) } return list } From 98cb55b145132a13d7ad6efdacf2c0cc9c7f6456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6ne?= Date: Wed, 11 Nov 2026 15:57:10 +0100 Subject: [PATCH 2/2] test(sqlite): Added RETURNING alias end-to-end test --- .../testdata/returning_alias/sqlite/go/db.go | 31 +++ .../returning_alias/sqlite/go/models.go | 16 ++ .../returning_alias/sqlite/go/query.sql.go | 241 ++++++++++++++++++ .../testdata/returning_alias/sqlite/query.sql | 36 +++ .../returning_alias/sqlite/schema.sql | 8 + .../testdata/returning_alias/sqlite/sqlc.json | 16 ++ 6 files changed, 348 insertions(+) create mode 100644 internal/endtoend/testdata/returning_alias/sqlite/go/db.go create mode 100644 internal/endtoend/testdata/returning_alias/sqlite/go/models.go create mode 100644 internal/endtoend/testdata/returning_alias/sqlite/go/query.sql.go create mode 100644 internal/endtoend/testdata/returning_alias/sqlite/query.sql create mode 100644 internal/endtoend/testdata/returning_alias/sqlite/schema.sql create mode 100644 internal/endtoend/testdata/returning_alias/sqlite/sqlc.json diff --git a/internal/endtoend/testdata/returning_alias/sqlite/go/db.go b/internal/endtoend/testdata/returning_alias/sqlite/go/db.go new file mode 100644 index 0000000000..32faa9f2b8 --- /dev/null +++ b/internal/endtoend/testdata/returning_alias/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.31.1 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...any) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...any) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...any) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/returning_alias/sqlite/go/models.go b/internal/endtoend/testdata/returning_alias/sqlite/go/models.go new file mode 100644 index 0000000000..0b10664563 --- /dev/null +++ b/internal/endtoend/testdata/returning_alias/sqlite/go/models.go @@ -0,0 +1,16 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.31.1 + +package querytest + +import ( + "database/sql" +) + +type T struct { + ID int64 + Name string + Score int64 + Created sql.NullString +} diff --git a/internal/endtoend/testdata/returning_alias/sqlite/go/query.sql.go b/internal/endtoend/testdata/returning_alias/sqlite/go/query.sql.go new file mode 100644 index 0000000000..b113bfc362 --- /dev/null +++ b/internal/endtoend/testdata/returning_alias/sqlite/go/query.sql.go @@ -0,0 +1,241 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.31.1 +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const deleteReturningAlias = `-- name: DeleteReturningAlias :many +DELETE FROM t WHERE score < ? +RETURNING id AS deleted_id, upper(name) AS shout +` + +type DeleteReturningAliasRow struct { + DeletedID int64 + Shout string +} + +func (q *Queries) DeleteReturningAlias(ctx context.Context, score int64) ([]DeleteReturningAliasRow, error) { + rows, err := q.db.QueryContext(ctx, deleteReturningAlias, score) + if err != nil { + return nil, err + } + defer rows.Close() + var items []DeleteReturningAliasRow + for rows.Next() { + var i DeleteReturningAliasRow + if err := rows.Scan(&i.DeletedID, &i.Shout); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const insertReturningAlias = `-- name: InsertReturningAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS new_id, score * 2 AS doubled +` + +type InsertReturningAliasParams struct { + Name string + Score int64 +} + +type InsertReturningAliasRow struct { + NewID int64 + Doubled int64 +} + +func (q *Queries) InsertReturningAlias(ctx context.Context, arg InsertReturningAliasParams) (InsertReturningAliasRow, error) { + row := q.db.QueryRowContext(ctx, insertReturningAlias, arg.Name, arg.Score) + var i InsertReturningAliasRow + err := row.Scan(&i.NewID, &i.Doubled) + return i, err +} + +const insertReturningAliasNoAs = `-- name: InsertReturningAliasNoAs :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id new_id, score * 2 doubled +` + +type InsertReturningAliasNoAsParams struct { + Name string + Score int64 +} + +type InsertReturningAliasNoAsRow struct { + NewID int64 + Doubled int64 +} + +func (q *Queries) InsertReturningAliasNoAs(ctx context.Context, arg InsertReturningAliasNoAsParams) (InsertReturningAliasNoAsRow, error) { + row := q.db.QueryRowContext(ctx, insertReturningAliasNoAs, arg.Name, arg.Score) + var i InsertReturningAliasNoAsRow + err := row.Scan(&i.NewID, &i.Doubled) + return i, err +} + +const insertReturningQuotedAlias = `-- name: InsertReturningQuotedAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS "newId", name AS [label] +` + +type InsertReturningQuotedAliasParams struct { + Name string + Score int64 +} + +type InsertReturningQuotedAliasRow struct { + NewId int64 + Label string +} + +func (q *Queries) InsertReturningQuotedAlias(ctx context.Context, arg InsertReturningQuotedAliasParams) (InsertReturningQuotedAliasRow, error) { + row := q.db.QueryRowContext(ctx, insertReturningQuotedAlias, arg.Name, arg.Score) + var i InsertReturningQuotedAliasRow + err := row.Scan(&i.NewId, &i.Label) + return i, err +} + +const insertReturningSameColumnTwice = `-- name: InsertReturningSameColumnTwice :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS old_id, id AS row_id +` + +type InsertReturningSameColumnTwiceParams struct { + Name string + Score int64 +} + +type InsertReturningSameColumnTwiceRow struct { + OldID int64 + RowID int64 +} + +func (q *Queries) InsertReturningSameColumnTwice(ctx context.Context, arg InsertReturningSameColumnTwiceParams) (InsertReturningSameColumnTwiceRow, error) { + row := q.db.QueryRowContext(ctx, insertReturningSameColumnTwice, arg.Name, arg.Score) + var i InsertReturningSameColumnTwiceRow + err := row.Scan(&i.OldID, &i.RowID) + return i, err +} + +const insertReturningSingleAlias = `-- name: InsertReturningSingleAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS new_id +` + +type InsertReturningSingleAliasParams struct { + Name string + Score int64 +} + +func (q *Queries) InsertReturningSingleAlias(ctx context.Context, arg InsertReturningSingleAliasParams) (int64, error) { + row := q.db.QueryRowContext(ctx, insertReturningSingleAlias, arg.Name, arg.Score) + var new_id int64 + err := row.Scan(&new_id) + return new_id, err +} + +const insertReturningStarAndAlias = `-- name: InsertReturningStarAndAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id, name, score, created, score * 2 AS doubled +` + +type InsertReturningStarAndAliasParams struct { + Name string + Score int64 +} + +type InsertReturningStarAndAliasRow struct { + ID int64 + Name string + Score int64 + Created sql.NullString + Doubled int64 +} + +func (q *Queries) InsertReturningStarAndAlias(ctx context.Context, arg InsertReturningStarAndAliasParams) (InsertReturningStarAndAliasRow, error) { + row := q.db.QueryRowContext(ctx, insertReturningStarAndAlias, arg.Name, arg.Score) + var i InsertReturningStarAndAliasRow + err := row.Scan( + &i.ID, + &i.Name, + &i.Score, + &i.Created, + &i.Doubled, + ) + return i, err +} + +const updateReturningAlias = `-- name: UpdateReturningAlias :many +UPDATE t SET score = ? WHERE name = ? +RETURNING id AS updated_id, score - 1 AS previous +` + +type UpdateReturningAliasParams struct { + Score int64 + Name string +} + +type UpdateReturningAliasRow struct { + UpdatedID int64 + Previous int64 +} + +func (q *Queries) UpdateReturningAlias(ctx context.Context, arg UpdateReturningAliasParams) ([]UpdateReturningAliasRow, error) { + rows, err := q.db.QueryContext(ctx, updateReturningAlias, arg.Score, arg.Name) + if err != nil { + return nil, err + } + defer rows.Close() + var items []UpdateReturningAliasRow + for rows.Next() { + var i UpdateReturningAliasRow + if err := rows.Scan(&i.UpdatedID, &i.Previous); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const upsertReturningAlias = `-- name: UpsertReturningAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +ON CONFLICT (name) DO UPDATE SET score = score + excluded.score +RETURNING id AS new_id, score AS total +` + +type UpsertReturningAliasParams struct { + Name string + Score int64 +} + +type UpsertReturningAliasRow struct { + NewID int64 + Total int64 +} + +func (q *Queries) UpsertReturningAlias(ctx context.Context, arg UpsertReturningAliasParams) (UpsertReturningAliasRow, error) { + row := q.db.QueryRowContext(ctx, upsertReturningAlias, arg.Name, arg.Score) + var i UpsertReturningAliasRow + err := row.Scan(&i.NewID, &i.Total) + return i, err +} diff --git a/internal/endtoend/testdata/returning_alias/sqlite/query.sql b/internal/endtoend/testdata/returning_alias/sqlite/query.sql new file mode 100644 index 0000000000..fe404281f7 --- /dev/null +++ b/internal/endtoend/testdata/returning_alias/sqlite/query.sql @@ -0,0 +1,36 @@ +-- name: InsertReturningAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS new_id, score * 2 AS doubled; + +-- name: InsertReturningAliasNoAs :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id new_id, score * 2 doubled; + +-- name: InsertReturningQuotedAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS "newId", name AS [label]; + +-- name: InsertReturningSingleAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS new_id; + +-- name: InsertReturningStarAndAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING *, score * 2 AS doubled; + +-- name: InsertReturningSameColumnTwice :one +INSERT INTO t (name, score) VALUES (?, ?) +RETURNING id AS old_id, id AS row_id; + +-- name: UpsertReturningAlias :one +INSERT INTO t (name, score) VALUES (?, ?) +ON CONFLICT (name) DO UPDATE SET score = score + excluded.score +RETURNING id AS new_id, score AS total; + +-- name: UpdateReturningAlias :many +UPDATE t SET score = ? WHERE name = ? +RETURNING id AS updated_id, score - 1 AS previous; + +-- name: DeleteReturningAlias :many +DELETE FROM t WHERE score < ? +RETURNING id AS deleted_id, upper(name) AS shout; diff --git a/internal/endtoend/testdata/returning_alias/sqlite/schema.sql b/internal/endtoend/testdata/returning_alias/sqlite/schema.sql new file mode 100644 index 0000000000..7303461a30 --- /dev/null +++ b/internal/endtoend/testdata/returning_alias/sqlite/schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE t ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + score INTEGER NOT NULL, + created TEXT +); + +CREATE UNIQUE INDEX t_name ON t (name); diff --git a/internal/endtoend/testdata/returning_alias/sqlite/sqlc.json b/internal/endtoend/testdata/returning_alias/sqlite/sqlc.json new file mode 100644 index 0000000000..e63bc00cf9 --- /dev/null +++ b/internal/endtoend/testdata/returning_alias/sqlite/sqlc.json @@ -0,0 +1,16 @@ +{ + "version": "2", + "sql": [ + { + "engine": "sqlite", + "schema": "schema.sql", + "queries": "query.sql", + "gen": { + "go": { + "package": "querytest", + "out": "go" + } + } + } + ] +}