Skip to content

Commit db805db

Browse files
authored
Merge pull request #3201 from dolthub/elian/9807
dolthub/dolt#9807 - FULL OUTER JOIN with empty left subquery rets unmatched right rows
2 parents e787e8e + 5d96f23 commit db805db

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

enginetest/join_op_tests.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,61 @@ var EngineOnlyJoinOpTests = []joinOpTest{
105105
}
106106

107107
var DefaultJoinOpTests = []joinOpTest{
108+
{
109+
// https://github.com/dolthub/dolt/issues/9807
110+
name: "FULL OUTER JOIN fails with empty subquery",
111+
setup: [][]string{
112+
{
113+
"CREATE TABLE t(c BOOLEAN);",
114+
"INSERT INTO t VALUES (FALSE);",
115+
},
116+
},
117+
tests: []JoinOpTests{
118+
{
119+
Query: "SELECT * FROM ( SELECT c FROM t WHERE c ) sub1 FULL OUTER JOIN ( SELECT 1 AS c ) sub2 ON 1=1;",
120+
Expected: []sql.Row{
121+
{nil, 1},
122+
},
123+
},
124+
},
125+
},
126+
{
127+
// https://github.com/dolthub/dolt/issues/9807
128+
name: "FULL OUTER JOIN with empty tables",
129+
setup: [][]string{
130+
{
131+
"CREATE TABLE t1 (i INT);",
132+
"CREATE TABLE t2 (j INT);",
133+
"INSERT INTO t2 VALUES (1);",
134+
},
135+
},
136+
tests: []JoinOpTests{
137+
{
138+
Query: "SELECT i, j FROM t1 FULL OUTER JOIN t2 ON 1=1;",
139+
Expected: []sql.Row{
140+
{nil, 1},
141+
},
142+
},
143+
{
144+
Query: "SELECT j, i FROM t2 FULL OUTER JOIN t1 ON 1=1;",
145+
Expected: []sql.Row{
146+
{1, nil},
147+
},
148+
},
149+
{
150+
Query: "SELECT i, j FROM t1 FULL OUTER JOIN t2 ON 1=0;",
151+
Expected: []sql.Row{
152+
{nil, 1},
153+
},
154+
},
155+
{
156+
Query: "SELECT j, i FROM t2 FULL OUTER JOIN t1 ON 1=0;",
157+
Expected: []sql.Row{
158+
{1, nil},
159+
},
160+
},
161+
},
162+
},
108163
{
109164
name: "bug where transitive join edge drops filters",
110165
setup: [][]string{

sql/rowexec/join_iters.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,10 @@ func (i *fullJoinIter) Next(ctx *sql.Context) (sql.Row, error) {
487487
}
488488
i.r = nil
489489
i.leftRow = nil
490+
continue
491+
}
492+
if err != nil {
493+
return nil, err
490494
}
491495

492496
row := i.buildRow(i.leftRow, rightRow)
@@ -512,7 +516,9 @@ func (i *fullJoinIter) Next(ctx *sql.Context) (sql.Row, error) {
512516

513517
for {
514518
if i.r == nil {
515-
iter, err := i.b.Build(ctx, i.rp, i.leftRow)
519+
// Phase 2 of FULL OUTER JOIN: return unmatched right rows as (null, rightRow).
520+
// Use parentRow instead of leftRow since leftRow is nil when left side is empty.
521+
iter, err := i.b.Build(ctx, i.rp, i.parentRow)
516522
if err != nil {
517523
return nil, err
518524
}

0 commit comments

Comments
 (0)