| From: | Tender Wang <tndrwang(at)gmail(dot)com> |
|---|---|
| To: | Richard Guo <guofenglinux(at)gmail(dot)com> |
| Cc: | Pg Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: "failed to build any N-way joins" from a five-relation query |
| Date: | 2026-10-10 02:37:44 |
| Message-ID: | CAHewXNkO8SM87_CnVZTXrosRHMruxawEaGk4v0yYG6c3ktyf1g@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Tender Wang <tndrwang(at)gmail(dot)com> 于2026年10月9日周五 16:08写道:
>
> Richard Guo <guofenglinux(at)gmail(dot)com> 于2026年10月8日周四 14:12写道:
> CREATE TABLE t (a int);
>
> SELECT 1
> FROM t t1 LEFT JOIN t t2 ON true,
> LATERAL (SELECT t2.a OFFSET 0) s1
> FULL JOIN t t3 ON s1.a = t3.a,
> LATERAL (SELECT t3.a OFFSET 0) s2
> WHERE s2.a > t1.a;
>
> This gives:
>
> ERROR: failed to build any 4-way joins
>
> It fails both with and without v1.
>
> I haven't traced the exact cause yet, but wanted to flag this case.
>
I investigated the cause of the failure reported yesterday.
The FULL JOIN is planned as a separate joinlist subproblem, and its
resulting joinrel becomes an input to the outer join search.
The loop over simple_rel_array does not account for this composite
input's lateral dependencies.
The proposed fix is to also scan joinrel entries in root->initial_rels
when expanding join_plus_rhs:
diff --git a/src/backend/optimizer/path/joinrels.c
b/src/backend/optimizer/path/joinrels.c
index 1278d958fb7..b53edefa8ca 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -655,6 +655,21 @@ join_is_legal(PlannerInfo *root, RelOptInfo
*rel1, RelOptInfo *rel2,
more = true;
}
}
+ /* Add composite inputs that laterally
reference any rel found so far. */
+ foreach (l, root->initial_rels)
+ {
+ RelOptInfo *jrel =
lfirst_node(RelOptInfo, l);
+
+ if (jrel->reloptkind != RELOPT_JOINREL)
+ continue;
+
+ if
(!bms_is_subset(jrel->relids, join_plus_rhs) &&
+
bms_overlap(jrel->lateral_relids, join_plus_rhs))
+ {
+ join_plus_rhs =
bms_add_members(join_plus_rhs, jrel->relids);
+ more = true;
+ }
+ }
} while (more);
if (bms_overlap(join_plus_rhs, join_lateral_rels))
return false; /* will not be able to
join to some RHS rel */
This loop goes inside the existing more loop, alongside the baserel loop.
Using initial_rels limits the additional checks to composite inputs of
the current join search, avoiding ordinary candidate joinrels in
join_rel_list.
Your existing loop still covers baserels.
--
Thanks,
Tender Wang
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Chao Li | 2026-10-10 03:40:15 | Re: pg_walinspect: add functions to locate and list WAL by time and LSN |
| Previous Message | lin teletele | 2026-10-10 02:20:04 | [PATCH] Fix pg_dump --clean with inherited partition constraints |