summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/createplan.c1
-rw-r--r--src/backend/optimizer/util/pathnode.c19
-rw-r--r--src/test/regress/expected/select_parallel.out23
-rw-r--r--src/test/regress/sql/select_parallel.sql4
4 files changed, 46 insertions, 1 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index f7cd738eeac..7bf1751e938 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1858,6 +1858,7 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
*/
subplan = create_plan_recurse(root, best_path->subpath,
CP_IGNORE_TLIST);
+ Assert(is_projection_capable_plan(subplan));
tlist = build_path_tlist(root, &best_path->path);
}
else
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 5778f80c01e..d54de06a3df 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -2556,7 +2556,23 @@ create_projection_path(PlannerInfo *root,
PathTarget *target)
{
ProjectionPath *pathnode = makeNode(ProjectionPath);
- PathTarget *oldtarget = subpath->pathtarget;
+ PathTarget *oldtarget;
+
+ /*
+ * We mustn't put a ProjectionPath directly above another; it's useless
+ * and will confuse create_projection_plan. Rather than making sure all
+ * callers handle that, let's implement it here, by stripping off any
+ * ProjectionPath in what we're given. Given this rule, there won't be
+ * more than one.
+ */
+ if (IsA(subpath, ProjectionPath))
+ {
+ ProjectionPath *subpp = (ProjectionPath *) subpath;
+
+ Assert(subpp->path.parent == rel);
+ subpath = subpp->subpath;
+ Assert(!IsA(subpath, ProjectionPath));
+ }
pathnode->path.pathtype = T_Result;
pathnode->path.parent = rel;
@@ -2582,6 +2598,7 @@ create_projection_path(PlannerInfo *root,
* Note: in the latter case, create_projection_plan has to recheck our
* conclusion; see comments therein.
*/
+ oldtarget = subpath->pathtarget;
if (is_projection_capable_path(subpath) ||
equal(oldtarget->exprs, target->exprs))
{
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index 9b0c418db71..51514421a28 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -1128,6 +1128,29 @@ ORDER BY 1, 2, 3;
------------------------------+---------------------------+-------------+--------------
(0 rows)
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT generate_series(1, two), array(select generate_series(1, two))
+ FROM tenk1 ORDER BY tenthous;
+ QUERY PLAN
+----------------------------------------------------------------------
+ ProjectSet
+ Output: generate_series(1, tenk1.two), (SubPlan 1), tenk1.tenthous
+ -> Gather Merge
+ Output: tenk1.two, tenk1.tenthous
+ Workers Planned: 4
+ -> Result
+ Output: tenk1.two, tenk1.tenthous
+ -> Sort
+ Output: tenk1.tenthous, tenk1.two
+ Sort Key: tenk1.tenthous
+ -> Parallel Seq Scan on public.tenk1
+ Output: tenk1.tenthous, tenk1.two
+ SubPlan 1
+ -> ProjectSet
+ Output: generate_series(1, tenk1.two)
+ -> Result
+(16 rows)
+
-- test passing expanded-value representations to workers
CREATE FUNCTION make_some_array(int,int) returns int[] as
$$declare x int[];
diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql
index 5a01a98b268..7853ae80d2e 100644
--- a/src/test/regress/sql/select_parallel.sql
+++ b/src/test/regress/sql/select_parallel.sql
@@ -431,6 +431,10 @@ ORDER BY 1;
SELECT * FROM information_schema.foreign_data_wrapper_options
ORDER BY 1, 2, 3;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT generate_series(1, two), array(select generate_series(1, two))
+ FROM tenk1 ORDER BY tenthous;
+
-- test passing expanded-value representations to workers
CREATE FUNCTION make_some_array(int,int) returns int[] as
$$declare x int[];