The query below gives wrong results with mergejoin:

create table t1 (a int);
create table t2 (a int);
create table t3 (a int);
insert into t1 values (1);
insert into t2 values (2);
insert into t3 values (100);
analyze t1, t2, t3;

set enable_hashjoin to off;
set enable_nestloop to off;

select * from t1
  left join lateral (select t1.a from t3) s(x) on true
  join t2 on s.x + 1 = t2.a;
 a | x | a
---+---+---
(0 rows)

This should return one row: (1, 1, 2).

The problem is in prepare_sort_from_pathkeys().  When the sort key is
not in the input plan's targetlist, it adds a resjunk entry for it by
copying the EC member's expression as-is, without replacing lateral
references with nestloop Params.  Here the sort key is "PHV(t1.a) +
1", and the t1.a inside the PHV is left as a plain Var in the
targetlist of the scan on t3.  The executor then fetches it from the
t3 tuple, so the merge join ends up comparing t3.a + 1 with t2.a.

If the sort sits atop a join rather than a scan, setrefs.c notices the
stray Var and we get an error instead:

select 1 from t1
  left join lateral (select t1.a, t3.a from t3, t3 t4) s(x, y) on true
  join t2 on s.x + 1 = t2.a
where s.y is not null;
ERROR:  variable not found in subplan target lists

The fix seems straightforward: run replace_nestloop_params() on the
expression before adding it to the targetlist.  The annoying part is
that prepare_sort_from_pathkeys() doesn't have 'root', so we have to
pass it in from all its callers.

- Richard

Attachment: v1-0001-Fix-lateral-references-in-sort-keys-added-by-crea.patch
Description: Binary data

Reply via email to