aboutsummaryrefslogtreecommitdiff
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 b02f7809c96..439e6b6426c 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1976,6 +1976,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 b248b038e03..9ce5f95e3b1 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -2632,7 +2632,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;
@@ -2658,6 +2674,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 05ebcb284a5..4ea1aa7dfd4 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -1126,6 +1126,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 d31e290ec22..f9247312484 100644
--- a/src/test/regress/sql/select_parallel.sql
+++ b/src/test/regress/sql/select_parallel.sql
@@ -429,6 +429,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[];