aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-01-23 16:50:34 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2018-01-23 16:50:34 -0500
commitbb94ce4d26c3b011c01bf44ab200334fea52b600 (patch)
tree0aafab1431e5ce4be722d7471aecffbfdeaf8d20 /src
parent95be5ce1bce3fdcf3ca0638baa12508e5b67ec17 (diff)
downloadpostgresql-bb94ce4d26c3b011c01bf44ab200334fea52b600.tar.gz
postgresql-bb94ce4d26c3b011c01bf44ab200334fea52b600.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/util/pathnode.c34
-rw-r--r--src/test/regress/expected/join.out19
-rw-r--r--src/test/regress/sql/join.sql10
3 files changed, 63 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 91295ebca49..fe3b4582d42 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -3540,6 +3540,40 @@ reparameterize_path(PlannerInfo *root, Path *path,
spath->path.pathkeys,
required_outer);
}
+ case T_Append:
+ {
+ AppendPath *apath = (AppendPath *) path;
+ List *childpaths = NIL;
+ List *partialpaths = NIL;
+ int i;
+ ListCell *lc;
+
+ /* Reparameterize the children */
+ i = 0;
+ foreach(lc, apath->subpaths)
+ {
+ Path *spath = (Path *) lfirst(lc);
+
+ spath = reparameterize_path(root, spath,
+ required_outer,
+ loop_count);
+ if (spath == NULL)
+ return NULL;
+ /* We have to re-split the regular and partial paths */
+ if (i < apath->first_partial_path)
+ childpaths = lappend(childpaths, spath);
+ else
+ partialpaths = lappend(partialpaths, spath);
+ i++;
+ }
+ return (Path *)
+ create_append_path(rel, childpaths, partialpaths,
+ required_outer,
+ apath->path.parallel_workers,
+ apath->path.parallel_aware,
+ apath->partitioned_rels,
+ -1);
+ }
default:
break;
}
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 02e7d56e550..c50a206efb8 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -5188,6 +5188,25 @@ select * from
Output: 3
(11 rows)
+-- check handling of nested appendrels inside LATERAL
+select * from
+ ((select 2 as v) union all (select 3 as v)) as q1
+ cross join lateral
+ ((select * from
+ ((select 4 as v) union all (select 5 as v)) as q3)
+ union all
+ (select q1.v)
+ ) as q2;
+ v | v
+---+---
+ 2 | 4
+ 2 | 5
+ 2 | 2
+ 3 | 4
+ 3 | 5
+ 3 | 3
+(6 rows)
+
-- check we don't try to do a unique-ified semijoin with LATERAL
explain (verbose, costs off)
select * from
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index dd62c38c15e..fc84237ce92 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -1682,6 +1682,16 @@ select * from
select * from (select 3 as z offset 0) z where z.z = x.x
) zz on zz.z = y.y;
+-- check handling of nested appendrels inside LATERAL
+select * from
+ ((select 2 as v) union all (select 3 as v)) as q1
+ cross join lateral
+ ((select * from
+ ((select 4 as v) union all (select 5 as v)) as q3)
+ union all
+ (select q1.v)
+ ) as q2;
+
-- check we don't try to do a unique-ified semijoin with LATERAL
explain (verbose, costs off)
select * from