8000 Teach reparameterize_path() to handle AppendPaths. · postgres/postgres@ae3699a · GitHub
[go: up one dir, main page]

Skip to content

Commit ae3699a

Browse files
committed
Teach reparameterize_path() to handle AppendPaths.
If we're inside a lateral subquery, there may be no unparameterized paths for a particular child relation of an appendrel, in which case we *must* be able to create similarly-parameterized paths for each other child relation, else the planner will fail with "could not devise a query plan for the given query". This means that there are situations where we'd better be able to reparameterize at least one path for each child. This calls into question the assumption in reparameterize_path() that it can just punt if it feels like it. However, the only case that is known broken right now is where the child is itself an appendrel so that all its paths are AppendPaths. (I think possibly I disregarded that in the original coding on the theory that nested appendrels would get folded together --- but that only happens *after* reparameterize_path(), so it's not excused from handling a child AppendPath.) Given that this code's been like this since 9.3 when LATERAL was introduced, it seems likely we'd have heard of other cases by now if there were a larger problem. Per report from Elvis Pranskevichus. Back-patch to 9.3. Discussion: https://postgr.es/m/5981018.zdth1YWmNy@hammer.magicstack.net
1 parent 2843c01 commit ae3699a

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

src/backend/optimizer/util/pathnode.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3205,6 +3205,29 @@ reparameterize_path(PlannerInfo *root, Path *path,
32053205
spath->path.pathkeys,
32063206
required_outer);
32073207
}
3208+
case T_Append:
3209+
{
3210+
AppendPath *apath = (AppendPath *) path;
3211+
List *childpaths = NIL;
3212+
ListCell *lc;
3213+
3214+
/* Reparameterize the children */
3215+
foreach(lc, apath->subpaths)
3216+
{
3217+
Path *spath = (Path *) lfirst(lc);
3218+
3219+
spath = reparameterize_path(root, spath,
3220+
required_outer,
3221+
loop_count);
3222+
if (spath == NULL)
3223+
return NULL;
3224+
childpaths = lappend(childpaths, spath);
3225+
}
3226+
return (Path *)
3227+
create_append_path(rel, childpaths,
3228+
required_outer,
3229+
apath->path.parallel_workers);
3230+
}
32083231
default:
32093232
break;
32103233
}

src/test/regress/expected/join.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5150,6 +5150,25 @@ select * from
51505150
Output: 3
51515151
(11 rows)
51525152

5153+
-- check handling of nested appendrels inside LATERAL
5154+
select * from
5155+
((select 2 as v) union all (select 3 as v)) as q1
5156+
cross join lateral
5157+
((select * from
5158+
((select 4 as v) union all (select 5 as v)) as q3)
5159+
union all
5160+
(select q1.v)
5161+
) as q2;
5162+
v | v
5163+
---+---
5164+
2 | 4
5165+
2 | 5
5166+
2 | 2
5167+
3 | 4
5168+
3 | 5
5169+
3 | 3
5170+
(6 rows)
5171+
51535172
-- check we don't try to do a unique-ified semijoin with LATERAL
51545173
explain (verbose, costs off)
51555174
select * from

src/test/regress/sql/join.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,16 @@ select * from
16661666
select * from (select 3 as z offset 0) z where z.z = x.x
16671667
) zz on zz.z = y.y;
16681668

1669+
-- check handling of nested appendrels inside LATERAL
1670+
select * from
1671+
((select 2 as v) union all (select 3 as v)) as q1
1672+
cross join lateral
1673+
((select * from
1674+
((select 4 as v) union all (select 5 as v)) as q3)
1675+
union all
1676+
(select q1.v)
1677+
) as q2;
1678+
16691679
-- check we don't try to do a unique-ified semijoin with LATERAL
16701680
explain (verbose, costs off)
16711681
select * from

0 commit comments

Comments
 (0)
0