From d7407c41a72e7db954da6ce3e0a8f55a4c1747bc Mon Sep 17 00:00:00 2001
From: Richard Guo <riguo@pivotal.io>
Date: Thu, 16 Apr 2020 15:53:33 +0000
Subject: [PATCH] Fix incremental sort crash.

---
 src/backend/optimizer/plan/planner.c   | 31 +++++++++++++++++++++++++++++++
 src/backend/optimizer/prep/prepunion.c |  6 +++---
 src/include/optimizer/planner.h        |  4 ++++
 3 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index b31c524..fa57133 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -5422,6 +5422,37 @@ mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
 	}
 }
 
+/* select_pathkeys_for_union_unique
+ *	  Choose the pathkeys in right order for Sort and Unique.
+ *
+ * Since 'Sort and Unique' is to unique-ify the result of a UNION by sorting
+ * on all columns, we adjust the sort order to match with result ordering
+ * requirements. Thus we can avoid the final Sort node.
+ */
+List *
+select_pathkeys_for_union_unique(PlannerInfo *root,
+								 List *groupList,
+								 List *tlist)
+{
+	List *processed_tlist;
+	List *sort_pathkeys;
+	List *pathkeys;
+
+	processed_tlist =
+		postprocess_setop_tlist(copyObject(tlist), root->parse->targetList);
+
+	sort_pathkeys = make_pathkeys_for_sortclauses(root,
+												  root->parse->sortClause,
+												  processed_tlist);
+
+	pathkeys = make_pathkeys_for_sortclauses(root, groupList, tlist);
+
+	pathkeys = list_concat(sort_pathkeys,
+						   list_difference_ptr(pathkeys, sort_pathkeys));
+
+	return pathkeys;
+}
+
 /*
  * postprocess_setop_tlist
  *	  Fix up targetlist returned by plan_set_operations().
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 951aed8..c31cee8 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -977,9 +977,9 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
 				create_sort_path(root,
 								 result_rel,
 								 path,
-								 make_pathkeys_for_sortclauses(root,
-															   groupList,
-															   tlist),
+								 select_pathkeys_for_union_unique(root,
+																  groupList,
+																  tlist),
 								 -1.0);
 		path = (Path *) create_upper_unique_path(root,
 												 result_rel,
diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h
index beb7dbb..159698a 100644
--- a/src/include/optimizer/planner.h
+++ b/src/include/optimizer/planner.h
@@ -53,6 +53,10 @@ extern bool limit_needed(Query *parse);
 
 extern void mark_partial_aggref(Aggref *agg, AggSplit aggsplit);
 
+extern List *select_pathkeys_for_union_unique(PlannerInfo *root,
+											  List *groupList,
+											  List *tlist);
+
 extern Path *get_cheapest_fractional_path(RelOptInfo *rel,
 										  double tuple_fraction);
 
-- 
2.7.4

