diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c new file mode 100644 index 34d4f40..298f5b5 *** a/src/backend/nodes/copyfuncs.c --- b/src/backend/nodes/copyfuncs.c *************** _copyTargetEntry(const TargetEntry *from *** 1753,1758 **** --- 1753,1759 ---- COPY_SCALAR_FIELD(resorigtbl); COPY_SCALAR_FIELD(resorigcol); COPY_SCALAR_FIELD(resjunk); + COPY_SCALAR_FIELD(resorderbyonly); return newnode; } diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c new file mode 100644 index bb5cdae..65f7058 *** a/src/backend/nodes/makefuncs.c --- b/src/backend/nodes/makefuncs.c *************** makeTargetEntry(Expr *expr, *** 230,235 **** --- 230,236 ---- tle->resorigcol = 0; tle->resjunk = resjunk; + tle->resorderbyonly = false; return tle; } diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c new file mode 100644 index b61005f..96add12 *** a/src/backend/optimizer/plan/planner.c --- b/src/backend/optimizer/plan/planner.c *************** grouping_planner(PlannerInfo *root, doub *** 1794,1799 **** --- 1794,1826 ---- limit_tuples); current_pathkeys = root->sort_pathkeys; } + else + { + /* + * Plan come out in the right order, we can remove attributes which + * are used only for ORDER BY clause because there is no need to + * calculate them. + */ + ListCell *tl, *tl_prev, *tl_next; + tl_prev = NULL; + tl = list_head(result_plan->targetlist); + while (tl) + { + TargetEntry *tle = (TargetEntry *)lfirst(tl); + tl_next = lnext(tl); + if (tle->resorderbyonly && tle->resjunk) + { + result_plan->targetlist = + list_delete_cell(result_plan->targetlist, tl, tl_prev); + } + else + { + tl_prev = tl; + } + + tl = tl_next; + } + } } /* diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c new file mode 100644 index ee40b55..842cf11 *** a/src/backend/parser/parse_clause.c --- b/src/backend/parser/parse_clause.c *************** findTargetlistEntrySQL99(ParseState *pst *** 1501,1507 **** --- 1501,1512 ---- texpr = strip_implicit_coercions((Node *) tle->expr); if (equal(expr, texpr)) + { + /* Update resorderbyonly flag */ + if (exprKind != EXPR_KIND_ORDER_BY) + tle->resorderbyonly = false; return tle; + } } /* *************** findTargetlistEntrySQL99(ParseState *pst *** 1512,1517 **** --- 1517,1526 ---- target_result = transformTargetEntry(pstate, node, expr, exprKind, NULL, true); + /* Set resorderbyonly flag if needed */ + if (exprKind == EXPR_KIND_ORDER_BY) + target_result->resorderbyonly = true; + *tlist = lappend(*tlist, target_result); return target_result; diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h new file mode 100644 index cd4561d..129755e *** a/src/include/nodes/primnodes.h --- b/src/include/nodes/primnodes.h *************** typedef struct TargetEntry *** 1172,1177 **** --- 1172,1178 ---- AttrNumber resorigcol; /* column's number in source table */ bool resjunk; /* set to true to eliminate the attribute from * final target list */ + bool resorderbyonly; /* attribute is used only in ORDER BY clause */ } TargetEntry; diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out new file mode 100644 index 906a928..4e2e9fa *** a/src/test/regress/expected/inherit.out --- b/src/test/regress/expected/inherit.out *************** explain (verbose, costs off) select * fr *** 1213,1219 **** QUERY PLAN ------------------------------------------------------------------------ Result ! Output: matest0.id, matest0.name, ((1 - matest0.id)) -> Merge Append Sort Key: ((1 - matest0.id)) -> Index Scan using matest0i on public.matest0 --- 1213,1219 ---- QUERY PLAN ------------------------------------------------------------------------ Result ! Output: matest0.id, matest0.name -> Merge Append Sort Key: ((1 - matest0.id)) -> Index Scan using matest0i on public.matest0