*** a/src/backend/optimizer/plan/planner.c --- b/src/backend/optimizer/plan/planner.c *************** *** 104,109 **** static void get_column_info_for_window(PlannerInfo *root, WindowClause *wc, --- 104,110 ---- int *ordNumCols, AttrNumber **ordColIdx, Oid **ordOperators); + static List *adjust_targetlist(PlannerInfo *root, List *tlist); /***************************************************************************** *************** *** 1008,1013 **** grouping_planner(PlannerInfo *root, double tuple_fraction) --- 1009,1015 ---- double dNumGroups = 0; bool use_hashed_distinct = false; bool tested_hashed_distinct = false; + bool tlist_is_adjustable; /* Tweak caller-supplied tuple_fraction if have LIMIT/OFFSET */ if (parse->limitCount || parse->limitOffset) *************** *** 1680,1685 **** grouping_planner(PlannerInfo *root, double tuple_fraction) --- 1682,1690 ---- } } /* end of if (setOperations) */ + /* Check whether we can remove rejunk sort entries safely */ + tlist_is_adjustable = is_projection_capable_plan(result_plan); + /* * If there is a DISTINCT clause, add the necessary node(s). */ *************** *** 1779,1784 **** grouping_planner(PlannerInfo *root, double tuple_fraction) --- 1784,1792 ---- result_plan, current_pathkeys, -1.0); + + /* We can't remove rejunk sort entries safely */ + tlist_is_adjustable = false; } result_plan = (Plan *) make_unique(result_plan, *************** *** 1802,1807 **** grouping_planner(PlannerInfo *root, double tuple_fraction) --- 1810,1821 ---- limit_tuples); current_pathkeys = root->sort_pathkeys; } + else + { + if (tlist_is_adjustable) + result_plan->targetlist = adjust_targetlist(root, + result_plan->targetlist); + } } /* *************** *** 3372,3377 **** get_column_info_for_window(PlannerInfo *root, WindowClause *wc, List *tlist, --- 3386,3484 ---- } } + /* + * adjust_targetlist + * Remove resjunk sort entries used only for ORDER BY clause if any. + */ + static List * + adjust_targetlist(PlannerInfo *root, List *tlist) + { + List *new_tlist; + Query *parse = root->parse; + Bitmapset *srefs; + Bitmapset *grefs; + ListCell *lc; + bool found; + ListCell *curr; + ListCell *prev; + ListCell *next; + + /* Collect the sortgroupref numbers of ORDER BY clause. */ + srefs = NULL; + foreach(lc, parse->sortClause) + { + SortGroupClause *scl = (SortGroupClause *) lfirst(lc); + + srefs = bms_add_member(srefs, scl->tleSortGroupRef); + } + + /* Collect the sortgroupref numbers of GROUP BY/DISTINCT ON clause. */ + grefs = NULL; + if (parse->groupClause) + { + foreach(lc, parse->groupClause) + { + SortGroupClause *gcl = (SortGroupClause *) lfirst(lc); + + grefs = bms_add_member(grefs, gcl->tleSortGroupRef); + } + } + if (parse->hasDistinctOn) + { + foreach(lc, parse->distinctClause) + { + SortGroupClause *gcl = (SortGroupClause *) lfirst(lc); + + grefs = bms_add_member(grefs, gcl->tleSortGroupRef); + } + } + + /* Find the sortgroupref numbers used only for ORDER BY clause. */ + srefs = bms_difference(srefs, grefs); + if(bms_is_empty(srefs)) + return tlist; + + /* Remove resjunk sort entries used only for ORDER BY clause if any. */ + curr = list_head(tlist); + prev = NULL; + found = false; + while(curr) + { + TargetEntry *tle = (TargetEntry *) lfirst(curr); + + next = lnext(curr); + + if (tle->resjunk && tle->ressortgroupref != 0 && + bms_is_member(tle->ressortgroupref, srefs)) + { + tlist = list_delete_cell(tlist, curr, prev); + found = true; + } + else + prev = curr; + + curr = next; + } + if (found) + { + int resno = 1; + + foreach(lc, tlist) + { + TargetEntry *tle = (TargetEntry *) lfirst(lc); + + if (tle->resno != resno) + { + tle = flatCopyTargetEntry(tle); + tle->resno = resno; + } + resno++; + } + } + + return tlist; + } + /* * expression_planner