Skip to content

Commit be44a57

Browse files
committed
fix(compiler): handle subqueries in JOIN nullability inference
Fixed incorrect nullability inference when using subqueries with LEFT/RIGHT/FULL OUTER JOINs. When using subqueries in JOINs like: SELECT * FROM a LEFT JOIN (SELECT * FROM b) si ON si.a_id = a.id Columns from subquery 'si' were incorrectly treated as NOT NULL. Root cause: The isTableRequired() function did not handle *ast.RangeSubselect (subquery ranges). Solution: - Added *ast.RangeSubselect case to isTableRequired() - Match subqueries by their alias names - Verified all JOIN types (LEFT/RIGHT/FULL OUTER) work correctly Test coverage: - Added internal/endtoend/testdata/join_left_subquery/postgresql/ - Covers LEFT JOIN, RIGHT JOIN, and FULL OUTER JOIN patterns Fixes #4117
1 parent 2e0435c commit be44a57

File tree

7 files changed

+337
-0
lines changed

7 files changed

+337
-0
lines changed

internal/compiler/output_columns.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,13 @@ func isTableRequired(n ast.Node, col *Column, prior int) int {
424424
if aliasMatch && tableMatch {
425425
return prior
426426
}
427+
case *ast.RangeSubselect:
428+
// For subqueries, match only by alias since there's no table name
429+
if n.Alias != nil && col.TableAlias != "" {
430+
if *n.Alias.Aliasname == col.TableAlias {
431+
return prior
432+
}
433+
}
427434
case *ast.JoinExpr:
428435
helper := func(l, r int) int {
429436
if res := isTableRequired(n.Larg, col, l); res != tableNotFound {

internal/endtoend/testdata/join_left_subquery/postgresql/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/join_left_subquery/postgresql/go/models.go

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

internal/endtoend/testdata/join_left_subquery/postgresql/go/query.sql.go

Lines changed: 229 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-- name: LeftJoinSubquery :many
2+
SELECT * FROM a AS table_a
3+
LEFT JOIN (SELECT * FROM b WHERE b.name IS NOT NULL) si ON si.a_id = table_a.id;
4+
5+
-- name: LeftJoinSubqueryExplicitColumns :many
6+
SELECT
7+
table_a.id,
8+
table_a.name,
9+
si.id,
10+
si.a_id,
11+
si.name
12+
FROM a AS table_a
13+
LEFT JOIN (SELECT id, a_id, name FROM b WHERE b.name IS NOT NULL) si ON si.a_id = table_a.id;
14+
15+
-- name: LeftJoinSubqueryNoAlias :many
16+
SELECT * FROM a
17+
LEFT JOIN (SELECT * FROM b) subquery ON subquery.a_id = a.id;
18+
19+
-- name: RightJoinSubquery :many
20+
SELECT * FROM a AS table_a
21+
RIGHT JOIN (SELECT * FROM b WHERE b.name IS NOT NULL) si ON si.a_id = table_a.id;
22+
23+
-- name: FullOuterJoinSubquery :many
24+
SELECT * FROM a AS table_a
25+
FULL OUTER JOIN (SELECT * FROM b WHERE b.name IS NOT NULL) si ON si.a_id = table_a.id;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- https://github.com/sqlc-dev/sqlc/issues/4117
2+
CREATE TABLE a (
3+
id uuid PRIMARY KEY,
4+
name TEXT
5+
);
6+
7+
CREATE TABLE b (
8+
id uuid PRIMARY KEY,
9+
a_id uuid NOT NULL REFERENCES a (id),
10+
name TEXT
11+
);
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)