"failed to build any N-way joins" from a five-relation query

From: Richard Guo <guofenglinux(at)gmail(dot)com>
To: Pg Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: "failed to build any N-way joins" from a five-relation query
Date: 2026-10-08 06:12:12
Message-ID: CAMbWs4_p6iWbsjNcYpd6-6mWFnog3UJ2fZKrxWAQTsyNoyeQTw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

The following query fails on v14 to master:

create table t (a int);

select 1 from t t1 left join t t2 on true,
lateral (select t2.a offset 0) s1 left join t t3 on s1.a = t3.a,
lateral (select t3.a offset 0) s2
where s2.a > t1.a;
ERROR: failed to build any 5-way joins

The dependencies between the rels form a chain:

t1 --LJ--> t2 <--lateral-- s1 --LJ--> t3 <--lateral-- s2

so the only possible join order is t1, t2, s1, t3, s2.

The problem is that at level 2 join_is_legal() accepts {t1, s2}, which
are linked by the clause "s2.a > t1.a". And that misleads the
clauseless-join heuristics into thinking that legality of t1/s2 means
that the clauseless join t1/t2 need not be formed.

But {t1, s2} is a dead end. s2 needs t3 as a lateral parameter, so
{t1, s2} must end up on the inner side of some nestloop that has t3
on its outer side. Now consider which side of that nestloop the
remaining rels can go:

t2 must be on the inner side, because it is the RHS of "t1 LJ t2"
and t1 is there.
s1 must be on the inner side, because it laterally references t2.
t3 must be on the inner side, because it is the RHS of "s1 LJ t3".

So t3 would have to be on both sides. How would that be possible?

join_is_legal() already has a check for this sort of dead end. It
collects the rels that must end up on the inner side of an outer join
with the proposed join (join_plus_rhs), and rejects the join if its
lateral parameters come from any of them. However, that search only
follows outer joins from min_lefthand to min_righthand. Here it adds
t2 and stops, because the LHS of "s1 LJ t3" is s1, not t2. It misses
that s1 has to come along with t2 because of the lateral reference.

So I think we can fix it by teaching that search to also include any
rel that laterally references a rel already in the set. Hench, the
attached.

- Richard

Attachment Content-Type Size
v1-0001-Disallow-joins-whose-lateral-references-can-never.patch application/octet-stream 6.1 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message shveta malik 2026-10-08 06:12:27 Re: Proposal: Conflict log history table for Logical Replication
Previous Message vignesh C 2026-10-08 06:00:16 Incorrect CONTEXT reported for errors from parallel apply worker in logical replication