aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/createplan.c1
-rw-r--r--src/backend/optimizer/util/pathnode.c19
2 files changed, 19 insertions, 1 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 83e8b34b1bc..66c5e3ee80f 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1845,6 +1845,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 056f7422c19..ffc03238c56 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -2579,7 +2579,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;
@@ -2605,6 +2621,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))
{