From 61be68ba0ac7df3fc308410e8f7aaea8739ac051 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 12 Mar 2018 12:36:57 -0400 Subject: [PATCH 1/7] Teach create_projection_plan to omit projection where possible. We sometimes insert a ProjectionPath into a plan tree when it isn't actually needed. The existing code already provides for the case where the ProjectionPath's subpath can perform the projection itself instead of needing a Result node to do it, but previously it didn't consider the possibility that the parent node might not actually require the projection. This optimization also allows the "physical tlist" optimization to be preserved in some cases where it would not otherwise happen. Patch by me, reviewed by Amit Kapila. --- src/backend/optimizer/plan/createplan.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 8b4f031d96..997d032939 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -87,7 +87,9 @@ static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags); static Gather *create_gather_plan(PlannerInfo *root, GatherPath *best_path); -static Plan *create_projection_plan(PlannerInfo *root, ProjectionPath *best_path); +static Plan *create_projection_plan(PlannerInfo *root, + ProjectionPath *best_path, + int flags); static Plan *inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe); static Sort *create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags); static Group *create_group_plan(PlannerInfo *root, GroupPath *best_path); @@ -400,7 +402,8 @@ create_plan_recurse(PlannerInfo *root, Path *best_path, int flags) if (IsA(best_path, ProjectionPath)) { plan = create_projection_plan(root, - (ProjectionPath *) best_path); + (ProjectionPath *) best_path, + flags); } else if (IsA(best_path, MinMaxAggPath)) { @@ -1567,7 +1570,7 @@ create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path) * but sometimes we can just let the subplan do the work. */ static Plan * -create_projection_plan(PlannerInfo *root, ProjectionPath *best_path) +create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags) { Plan *plan; Plan *subplan; @@ -1576,7 +1579,22 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path) /* Since we intend to project, we don't need to constrain child tlist */ subplan = create_plan_recurse(root, best_path->subpath, 0); - tlist = build_path_tlist(root, &best_path->path); + /* + * If our caller doesn't really care what tlist we return, then we might + * not really need to project. If use_physical_tlist returns false, then + * we're obliged to project. If it returns true, we can skip actually + * projecting but must still correctly label the input path's tlist with + * the sortgroupref information if the caller has so requested. + */ + if (!use_physical_tlist(root, &best_path->path, flags)) + tlist = build_path_tlist(root, &best_path->path); + else if ((flags & CP_LABEL_TLIST) != 0) + { + tlist = copyObject(subplan->targetlist); + apply_pathtarget_labeling_to_tlist(tlist, best_path->path.pathtarget); + } + else + return subplan; /* * We might not really need a Result node here, either because the subplan -- 2.14.3 (Apple Git-98)