diff options
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 1 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 19 | ||||
-rw-r--r-- | src/test/regress/expected/select_parallel.out | 23 | ||||
-rw-r--r-- | src/test/regress/sql/select_parallel.sql | 4 |
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[]; |