diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 68b2204..7ed8279 100644
*** a/src/backend/optimizer/path/pathkeys.c
--- b/src/backend/optimizer/path/pathkeys.c
*************** build_expression_pathkey(PlannerInfo *ro
*** 771,779 ****
   * 'subquery_pathkeys': the subquery's output pathkeys, in its terms.
   * 'subquery_tlist': the subquery's output targetlist, in its terms.
   *
!  * It is not necessary for caller to do truncate_useless_pathkeys(),
!  * because we select keys in a way that takes usefulness of the keys into
!  * account.
   */
  List *
  convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
--- 771,781 ----
   * 'subquery_pathkeys': the subquery's output pathkeys, in its terms.
   * 'subquery_tlist': the subquery's output targetlist, in its terms.
   *
!  * We intentionally don't do truncate_useless_pathkeys() here, because there
!  * are situations where seeing the raw ordering of the subquery is helpful.
!  * For example, if it returns ORDER BY x DESC, that may prompt us to
!  * construct a mergejoin using DESC order rather than ASC order; but the
!  * right_merge_direction heuristic would have us throw the knowledge away.
   */
  List *
  convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index efe073a..270c119 100644
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
*************** static List *get_gating_quals(PlannerInf
*** 81,88 ****
  static Plan *create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
  				   List *gating_quals);
  static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path);
! static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path);
! static Plan *create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path);
  static Result *create_group_result_plan(PlannerInfo *root,
  						 GroupResultPath *best_path);
  static ProjectSet *create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path);
--- 81,90 ----
  static Plan *create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
  				   List *gating_quals);
  static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path);
! static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path,
! 				   int flags);
! static Plan *create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
! 						 int flags);
  static Result *create_group_result_plan(PlannerInfo *root,
  						 GroupResultPath *best_path);
  static ProjectSet *create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path);
*************** create_plan_recurse(PlannerInfo *root, P
*** 390,400 ****
  			break;
  		case T_Append:
  			plan = create_append_plan(root,
! 									  (AppendPath *) best_path);
  			break;
  		case T_MergeAppend:
  			plan = create_merge_append_plan(root,
! 											(MergeAppendPath *) best_path);
  			break;
  		case T_Result:
  			if (IsA(best_path, ProjectionPath))
--- 392,404 ----
  			break;
  		case T_Append:
  			plan = create_append_plan(root,
! 									  (AppendPath *) best_path,
! 									  flags);
  			break;
  		case T_MergeAppend:
  			plan = create_merge_append_plan(root,
! 											(MergeAppendPath *) best_path,
! 											flags);
  			break;
  		case T_Result:
  			if (IsA(best_path, ProjectionPath))
*************** create_join_plan(PlannerInfo *root, Join
*** 1054,1063 ****
   *	  Returns a Plan node.
   */
  static Plan *
! create_append_plan(PlannerInfo *root, AppendPath *best_path)
  {
  	Append	   *plan;
  	List	   *tlist = build_path_tlist(root, &best_path->path);
  	List	   *pathkeys = best_path->path.pathkeys;
  	List	   *subplans = NIL;
  	ListCell   *subpaths;
--- 1058,1069 ----
   *	  Returns a Plan node.
   */
  static Plan *
! create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
  {
  	Append	   *plan;
  	List	   *tlist = build_path_tlist(root, &best_path->path);
+ 	int			orig_tlist_length = list_length(tlist);
+ 	bool		tlist_was_changed = false;
  	List	   *pathkeys = best_path->path.pathkeys;
  	List	   *subplans = NIL;
  	ListCell   *subpaths;
*************** create_append_plan(PlannerInfo *root, Ap
*** 1112,1118 ****
  
  	if (pathkeys != NIL)
  	{
! 		/* Compute sort column info, and adjust the Append's tlist as needed */
  		(void) prepare_sort_from_pathkeys((Plan *) plan, pathkeys,
  										  best_path->path.parent->relids,
  										  NULL,
--- 1118,1129 ----
  
  	if (pathkeys != NIL)
  	{
! 		/*
! 		 * Compute sort column info, and adjust the Append's tlist as needed.
! 		 * Because we pass adjust_tlist_in_place = true, we may ignore the
! 		 * function result; it must be the same plan node.  However, we then
! 		 * need to detect whether any tlist entries were added.
! 		 */
  		(void) prepare_sort_from_pathkeys((Plan *) plan, pathkeys,
  										  best_path->path.parent->relids,
  										  NULL,
*************** create_append_plan(PlannerInfo *root, Ap
*** 1122,1127 ****
--- 1133,1139 ----
  										  &nodeSortOperators,
  										  &nodeCollations,
  										  &nodeNullsFirst);
+ 		tlist_was_changed = (orig_tlist_length != list_length(plan->plan.targetlist));
  	}
  
  	/* Build the plan for each child */
*************** create_append_plan(PlannerInfo *root, Ap
*** 1231,1237 ****
  
  	copy_generic_path_info(&plan->plan, (Path *) best_path);
  
! 	return (Plan *) plan;
  }
  
  /*
--- 1243,1262 ----
  
  	copy_generic_path_info(&plan->plan, (Path *) best_path);
  
! 	/*
! 	 * If prepare_sort_from_pathkeys added sort columns, but we were told to
! 	 * produce either the exact tlist or a narrow tlist, we should get rid of
! 	 * the sort columns again.  We must inject a projection node to do so.
! 	 */
! 	if (tlist_was_changed && (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST)))
! 	{
! 		tlist = list_truncate(list_copy(plan->plan.targetlist),
! 							  orig_tlist_length);
! 		return inject_projection_plan((Plan *) plan, tlist,
! 									  plan->plan.parallel_safe);
! 	}
! 	else
! 		return (Plan *) plan;
  }
  
  /*
*************** create_append_plan(PlannerInfo *root, Ap
*** 1242,1252 ****
   *	  Returns a Plan node.
   */
  static Plan *
! create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
  {
  	MergeAppend *node = makeNode(MergeAppend);
  	Plan	   *plan = &node->plan;
  	List	   *tlist = build_path_tlist(root, &best_path->path);
  	List	   *pathkeys = best_path->path.pathkeys;
  	List	   *subplans = NIL;
  	ListCell   *subpaths;
--- 1267,1280 ----
   *	  Returns a Plan node.
   */
  static Plan *
! create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
! 						 int flags)
  {
  	MergeAppend *node = makeNode(MergeAppend);
  	Plan	   *plan = &node->plan;
  	List	   *tlist = build_path_tlist(root, &best_path->path);
+ 	int			orig_tlist_length = list_length(tlist);
+ 	bool		tlist_was_changed;
  	List	   *pathkeys = best_path->path.pathkeys;
  	List	   *subplans = NIL;
  	ListCell   *subpaths;
*************** create_merge_append_plan(PlannerInfo *ro
*** 1265,1271 ****
  	plan->lefttree = NULL;
  	plan->righttree = NULL;
  
! 	/* Compute sort column info, and adjust MergeAppend's tlist as needed */
  	(void) prepare_sort_from_pathkeys(plan, pathkeys,
  									  best_path->path.parent->relids,
  									  NULL,
--- 1293,1304 ----
  	plan->lefttree = NULL;
  	plan->righttree = NULL;
  
! 	/*
! 	 * Compute sort column info, and adjust MergeAppend's tlist as needed.
! 	 * Because we pass adjust_tlist_in_place = true, we may ignore the
! 	 * function result; it must be the same plan node.  However, we then need
! 	 * to detect whether any tlist entries were added.
! 	 */
  	(void) prepare_sort_from_pathkeys(plan, pathkeys,
  									  best_path->path.parent->relids,
  									  NULL,
*************** create_merge_append_plan(PlannerInfo *ro
*** 1275,1280 ****
--- 1308,1314 ----
  									  &node->sortOperators,
  									  &node->collations,
  									  &node->nullsFirst);
+ 	tlist_was_changed = (orig_tlist_length != list_length(plan->targetlist));
  
  	/*
  	 * Now prepare the child plans.  We must apply prepare_sort_from_pathkeys
*************** create_merge_append_plan(PlannerInfo *ro
*** 1371,1377 ****
  	node->mergeplans = subplans;
  	node->part_prune_info = partpruneinfo;
  
! 	return (Plan *) node;
  }
  
  /*
--- 1405,1422 ----
  	node->mergeplans = subplans;
  	node->part_prune_info = partpruneinfo;
  
! 	/*
! 	 * If prepare_sort_from_pathkeys added sort columns, but we were told to
! 	 * produce either the exact tlist or a narrow tlist, we should get rid of
! 	 * the sort columns again.  We must inject a projection node to do so.
! 	 */
! 	if (tlist_was_changed && (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST)))
! 	{
! 		tlist = list_truncate(list_copy(plan->targetlist), orig_tlist_length);
! 		return inject_projection_plan(plan, tlist, plan->parallel_safe);
! 	}
! 	else
! 		return plan;
  }
  
  /*
diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out
index da70438..c4405ca 100644
*** a/src/test/regress/expected/union.out
--- b/src/test/regress/expected/union.out
*************** ORDER BY x;
*** 915,920 ****
--- 915,994 ----
   2 | 4
  (1 row)
  
+ -- Test cases where the native ordering of a sub-select has more pathkeys
+ -- than the outer query cares about
+ explain (costs off)
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where q2 = q2;
+                         QUERY PLAN                        
+ ----------------------------------------------------------
+  Unique
+    ->  Merge Append
+          Sort Key: "*SELECT* 1".q1
+          ->  Subquery Scan on "*SELECT* 1"
+                ->  Unique
+                      ->  Sort
+                            Sort Key: i81.q1, i81.q2
+                            ->  Seq Scan on int8_tbl i81
+                                  Filter: (q2 IS NOT NULL)
+          ->  Subquery Scan on "*SELECT* 2"
+                ->  Unique
+                      ->  Sort
+                            Sort Key: i82.q1, i82.q2
+                            ->  Seq Scan on int8_tbl i82
+                                  Filter: (q2 IS NOT NULL)
+ (15 rows)
+ 
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where q2 = q2;
+         q1        
+ ------------------
+               123
+  4567890123456789
+ (2 rows)
+ 
+ explain (costs off)
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where -q1 = q2;
+                            QUERY PLAN                           
+ ----------------------------------------------------------------
+  Unique
+    ->  Result
+          ->  Merge Append
+                Sort Key: "*SELECT* 1".q1, ((- "*SELECT* 1".q1))
+                ->  Subquery Scan on "*SELECT* 1"
+                      ->  Unique
+                            ->  Sort
+                                  Sort Key: i81.q1, i81.q2
+                                  ->  Seq Scan on int8_tbl i81
+                                        Filter: ((- q1) = q2)
+                ->  Subquery Scan on "*SELECT* 2"
+                      ->  Unique
+                            ->  Sort
+                                  Sort Key: i82.q1, i82.q2
+                                  ->  Seq Scan on int8_tbl i82
+                                        Filter: ((- q1) = q2)
+ (16 rows)
+ 
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where -q1 = q2;
+         q1        
+ ------------------
+  4567890123456789
+ (1 row)
+ 
  -- Test proper handling of parameterized appendrel paths when the
  -- potential join qual is expensive
  create function expensivefunc(int) returns int
diff --git a/src/test/regress/sql/union.sql b/src/test/regress/sql/union.sql
index eed7c8d..5f4881d 100644
*** a/src/test/regress/sql/union.sql
--- b/src/test/regress/sql/union.sql
*************** SELECT * FROM
*** 379,384 ****
--- 379,412 ----
  WHERE x > 3
  ORDER BY x;
  
+ -- Test cases where the native ordering of a sub-select has more pathkeys
+ -- than the outer query cares about
+ explain (costs off)
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where q2 = q2;
+ 
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where q2 = q2;
+ 
+ explain (costs off)
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where -q1 = q2;
+ 
+ select distinct q1 from
+   (select distinct * from int8_tbl i81
+    union all
+    select distinct * from int8_tbl i82) ss
+ where -q1 = q2;
+ 
  -- Test proper handling of parameterized appendrel paths when the
  -- potential join qual is expensive
  create function expensivefunc(int) returns int
