From 61be68ba0ac7df3fc308410e8f7aaea8739ac051 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
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)

