Skip to content

Commit 027ca2c

Browse files
fix: support PostgreSQL 18 RETURNING OLD/NEW syntax
The pg_query_go parser already parses RETURNING OLD.* and RETURNING NEW.* correctly, but sqlc's compiler rejected these queries because the star expansion and column resolution logic tried to match "old"/"new" against actual table names and found no match. This caused star expansion to produce empty column lists (resulting in invalid SQL like "RETURNING ;") and column refs like OLD.bar to fail with "column does not exist". The fix recognizes "old" and "new" as special scope/alias values in three places and lets them match the target table's columns instead of being filtered out. Fixes #3600 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4bf2159 commit 027ca2c

File tree

8 files changed

+151
-3
lines changed

8 files changed

+151
-3
lines changed

internal/compiler/expand.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ func (c *Compiler) expandStmt(qc *QueryCatalog, raw *ast.RawStmt, node ast.Node)
132132
}
133133
}
134134
for _, t := range tables {
135-
if scope != "" && scope != t.Rel.Name {
135+
isOldNew := strings.EqualFold(scope, "old") || strings.EqualFold(scope, "new")
136+
if scope != "" && !isOldNew && scope != t.Rel.Name {
136137
continue
137138
}
138139
tableName := c.quoteIdent(t.Rel.Name)

internal/compiler/output_columns.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package compiler
33
import (
44
"errors"
55
"fmt"
6+
"strings"
67

78
"github.com/sqlc-dev/sqlc/internal/sql/ast"
89
"github.com/sqlc-dev/sqlc/internal/sql/astutils"
@@ -269,7 +270,8 @@ func (c *Compiler) outputColumns(qc *QueryCatalog, node ast.Node) ([]*Column, er
269270
// TODO: This code is copied in func expand()
270271
for _, t := range tables {
271272
scope := astutils.Join(n.Fields, ".")
272-
if scope != "" && scope != t.Rel.Name {
273+
isOldNew := strings.EqualFold(scope, "old") || strings.EqualFold(scope, "new")
274+
if scope != "" && !isOldNew && scope != t.Rel.Name {
273275
continue
274276
}
275277
for _, c := range t.Columns {
@@ -669,7 +671,8 @@ func outputColumnRefs(res *ast.ResTarget, tables []*Table, node *ast.ColumnRef)
669671
if schema != "" && t.Rel.Schema != schema {
670672
continue
671673
}
672-
if alias != "" && t.Rel.Name != alias {
674+
isOldNew := strings.EqualFold(alias, "old") || strings.EqualFold(alias, "new")
675+
if alias != "" && !isOldNew && t.Rel.Name != alias {
673676
continue
674677
}
675678
for _, c := range t.Columns {

internal/endtoend/testdata/returning_old_new/postgresql/stdlib/go/db.go

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/returning_old_new/postgresql/stdlib/go/models.go

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/returning_old_new/postgresql/stdlib/go/query.sql.go

Lines changed: 74 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- name: UpdateReturningOldStar :one
2+
UPDATE foo SET bar = $1 WHERE id = $2 RETURNING OLD.*;
3+
4+
-- name: UpdateReturningNewStar :one
5+
UPDATE foo SET bar = $1 WHERE id = $2 RETURNING NEW.*;
6+
7+
-- name: UpdateReturningOldNewCols :one
8+
UPDATE foo SET bar = $1 WHERE id = $2 RETURNING OLD.bar, NEW.bar;
9+
10+
-- name: DeleteReturningOldStar :one
11+
DELETE FROM foo WHERE id = $1 RETURNING OLD.*;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE TABLE foo (
2+
id serial primary key,
3+
bar text not null,
4+
baz int not null default 0
5+
);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"path": "go",
6+
"engine": "postgresql",
7+
"name": "querytest",
8+
"schema": "schema.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}

0 commit comments

Comments
 (0)