Fix LEFT JOIN subqueries reusing stale right-side values

This commit is contained in:
Duy Dang
2025-11-01 01:24:31 +07:00
parent 331ba14e7c
commit 3ee47a2c3c
2 changed files with 26 additions and 1 deletions

View File

@@ -1240,6 +1240,20 @@ pub fn close_loop(
cursor_id: *cursor_id,
});
});
if let Table::FromClauseSubquery(from_clause_subquery) = &table.table {
if let Some(start_reg) = from_clause_subquery.result_columns_start_reg {
let column_count = from_clause_subquery.columns.len();
if column_count > 0 {
// Subqueries materialize their row into registers rather than being read back
// through a cursor. NullRow only affects cursor reads, so we also have to
// explicitly null out the cached registers or stale values would be re-emitted.
program.emit_insn(Insn::Null {
dest: start_reg,
dest_end: Some(start_reg + column_count - 1),
});
}
}
}
// Then we jump to setting the left join match flag to 1 again,
// but this time the right table cursor will set everything to null.
// This leads to emitting a row with cols from the left + nulls from the right,

View File

@@ -340,6 +340,17 @@ do_execsql_test_on_specific_db {:memory:} left-join-column-crash {
} {1|1|3|3
1|1|4|4}
# regression test for ignoring ON clause when LEFT JOIN uses a FROM clause subquery
do_execsql_test_on_specific_db {:memory:} left-join-subquery-on {
CREATE TABLE t1(a INTEGER);
INSERT INTO t1 VALUES (1),(2),(3);
CREATE TABLE t2(b INTEGER);
INSERT INTO t2 VALUES (2),(4);
SELECT a, b FROM t1 LEFT JOIN (SELECT * FROM t2 WHERE b > 2) ON t1.a = b ORDER BY a;
} {1|
2|
3|}
# Test that column names in USING clause are not ambiguous since they are deduplicated.
# The column 'a' appears in both tables but can be referenced unqualified in the SELECT
# since it's in the USING clause.
@@ -390,4 +401,4 @@ do_execsql_test_on_specific_db {:memory:} redundant-join-condition {
create table t(x);
insert into t values ('lol');
select t1.x from t t1 join t t2 on t1.x=t2.x where t1.x=t2.x;
} {lol}
} {lol}