Skip to content

Commit 6668164

Browse files
Detects nullable fields with LEFT_JOIN, OUTER_JOIN, or RIGHT_JOIN (#983)
- Builds on top of #733 - Properly detects left, right, full joins - Uses proper enum ordering Co-authored-by: Ryad El-Dajani <ryad.eldajani@posteo.de>
1 parent 7761663 commit 6668164

File tree

37 files changed

+859
-6
lines changed

37 files changed

+859
-6
lines changed

examples/booktest/postgresql/db_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func TestBooks(t *testing.T) {
139139
t.Fatal(err)
140140
}
141141
for _, ab := range res {
142-
t.Logf("Book %d: '%s', Author: '%s', ISBN: '%s' Tags: '%v'\n", ab.BookID, ab.Title, ab.Name, ab.Isbn, ab.Tags)
142+
t.Logf("Book %d: '%s', Author: '%s', ISBN: '%s' Tags: '%v'\n", ab.BookID, ab.Title, ab.Name.String, ab.Isbn, ab.Tags)
143143
}
144144

145145
// TODO: call say_hello(varchar)

examples/booktest/postgresql/query.sql.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/kotlin/src/main/kotlin/com/example/booktest/postgresql/QueriesImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ WHERE tags && ?::varchar[]
2323
data class BooksByTagsRow (
2424
val bookId: Int,
2525
val title: String,
26-
val name: String,
26+
val name: String?,
2727
val isbn: String,
2828
val tags: List<String>
2929
)

examples/python/src/booktest/query.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
class BooksByTagsRow:
2828
book_id: int
2929
title: str
30-
name: str
30+
name: Optional[str]
3131
isbn: str
3232
tags: List[str]
3333

internal/compiler/output_columns.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,57 @@ func outputColumns(qc *QueryCatalog, node ast.Node) ([]*Column, error) {
206206
}
207207
}
208208

209+
if n, ok := node.(*ast.SelectStmt); ok {
210+
for _, col := range cols {
211+
if !col.NotNull || col.Table == nil {
212+
continue
213+
}
214+
for _, f := range n.FromClause.Items {
215+
if res := isTableRequired(f, col.Table.Name, tableRequired); res != tableNotFound {
216+
col.NotNull = res == tableRequired
217+
break
218+
}
219+
}
220+
}
221+
}
222+
209223
return cols, nil
210224
}
211225

226+
const (
227+
tableNotFound = iota
228+
tableRequired
229+
tableOptional
230+
)
231+
232+
func isTableRequired(n ast.Node, tableName string, prior int) int {
233+
switch n := n.(type) {
234+
case *ast.RangeVar:
235+
if *n.Relname == tableName {
236+
return prior
237+
}
238+
case *ast.JoinExpr:
239+
helper := func(l, r int) int {
240+
if res := isTableRequired(n.Larg, tableName, l); res != tableNotFound {
241+
return res
242+
}
243+
if res := isTableRequired(n.Rarg, tableName, r); res != tableNotFound {
244+
return res
245+
}
246+
return tableNotFound
247+
}
248+
switch n.Jointype {
249+
case ast.JoinTypeLeft:
250+
return helper(tableRequired, tableOptional)
251+
case ast.JoinTypeRight:
252+
return helper(tableOptional, tableRequired)
253+
case ast.JoinTypeFull:
254+
return helper(tableOptional, tableOptional)
255+
}
256+
}
257+
return tableNotFound
258+
}
259+
212260
// Compute the output columns for a statement.
213261
//
214262
// Return an error if column references are ambiguous

internal/endtoend/testdata/join_full/mysql/go/db.go

Lines changed: 29 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_full/mysql/go/models.go

Lines changed: 16 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_full/mysql/go/query.sql.go

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CREATE TABLE foo (id serial not null, bar_id int references bar(id));
2+
CREATE TABLE bar (id serial not null);
3+
4+
-- name: FullJoin :many
5+
SELECT f.id, f.bar_id, b.id
6+
FROM foo f
7+
FULL OUTER JOIN bar b ON b.id = f.bar_id
8+
WHERE f.id = $1;
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": "query.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}

internal/endtoend/testdata/join_full/postgresql/go/db.go

Lines changed: 29 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_full/postgresql/go/models.go

Lines changed: 16 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_full/postgresql/go/query.sql.go

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CREATE TABLE foo (id serial not null, bar_id int references bar(id));
2+
CREATE TABLE bar (id serial not null);
3+
4+
-- name: FullJoin :many
5+
SELECT f.id, f.bar_id, b.id
6+
FROM foo f
7+
FULL OUTER JOIN bar b ON b.id = f.bar_id
8+
WHERE f.id = $1;
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": "query.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}

internal/endtoend/testdata/join_left/mysql/go/db.go

Lines changed: 29 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/mysql/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.

0 commit comments

Comments
 (0)