Fuzzing with LLM found $subject in v16 to master branches. create table t (a int, b int); insert into t values (1, 1), (2, 2);
select * from t t1
left join (t t2 join t t3 using (a) as x) on t1.a = x.a + 1
where x is null;
a | b | a | b | b
---+---+---+---+---
1 | 1 | | |
2 | 2 | | |
(2 rows)
The second row should not be there. A similar query fails instead:
select * from t t1
left join (t t2 join t t3 using (a) as x) on true
left join t t4 on x is null;
ERROR: wrong varnullingrels (b) (expected (b 5)) for Var 2/1
The problem is in transformWholeRowRef(), which expands "x" into a
RowExpr over the join's merged columns. It builds the fields with
expandRTE(), so the Vars are not marked as nullable by the outer join
above, and the planner pushes "x is null" down below that join. There
is even an XXX comment there:
/* XXX we ought to mark the row as possibly nullable */
To fix, I think we can build the fields with expandNSItemVars()
instead. It yields the same Vars, but also marks them with
markNullableIfNeeded(), as scanNSItemForColumn() does for a plain
reference such as x.a.
The annoying thing is that stored views containing such a reference
would need to be recreated.
- Richard
v1-0001-Fix-nullingrels-of-whole-row-references-to-JOIN-U.patch
Description: Binary data
