*** a/src/backend/nodes/outfuncs.c --- b/src/backend/nodes/outfuncs.c *************** *** 1479,1484 **** _outPlannerInfo(StringInfo str, PlannerInfo *node) --- 1479,1485 ---- WRITE_NODE_FIELD(group_pathkeys); WRITE_NODE_FIELD(distinct_pathkeys); WRITE_NODE_FIELD(sort_pathkeys); + WRITE_NODE_FIELD(window_pathkeys); WRITE_FLOAT_FIELD(total_table_pages, "%.0f"); WRITE_FLOAT_FIELD(tuple_fraction, "%.4f"); WRITE_BOOL_FIELD(hasJoinRTEs); *** a/src/backend/optimizer/plan/planmain.c --- b/src/backend/optimizer/plan/planmain.c *************** *** 233,238 **** query_planner(PlannerInfo *root, List *tlist, --- 233,239 ---- */ root->query_pathkeys = canonicalize_pathkeys(root, root->query_pathkeys); root->group_pathkeys = canonicalize_pathkeys(root, root->group_pathkeys); + root->window_pathkeys = canonicalize_pathkeys(root, root->window_pathkeys); root->distinct_pathkeys = canonicalize_pathkeys(root, root->distinct_pathkeys); root->sort_pathkeys = canonicalize_pathkeys(root, root->sort_pathkeys); *** a/src/backend/optimizer/plan/planner.c --- b/src/backend/optimizer/plan/planner.c *************** *** 902,907 **** grouping_planner(PlannerInfo *root, double tuple_fraction) --- 902,948 ---- else root->group_pathkeys = NIL; + /* + * Currently we don't relocate each Window node based on + * cost estimation; it'd be better to think about the order + * of each node execution. But for now we only think about + * the bottom node pathkeys. This should be fixed. + */ + if (parse->windowList) + { + ListCell *l; + + foreach(l, parse->windowList) + { + List *partition_pathkeys = NIL; + List *order_pathkeys = NIL; + WindowClause *wc = (WindowClause *) lfirst(l); + + if (wc->partitionClause && + grouping_is_sortable(wc->partitionClause)) + partition_pathkeys = + make_pathkeys_for_sortclauses(root, + wc->partitionClause, + tlist, + false); + + if (wc->orderClause && + grouping_is_sortable(wc->orderClause)) + order_pathkeys = + make_pathkeys_for_sortclauses(root, + wc->orderClause, + tlist, + false); + + root->window_pathkeys = list_concat(partition_pathkeys, order_pathkeys); + /* + * Window node may be stacked more than one, but + * what is effective to query_planner() is only the bottom pathkeys. + */ + break; + } + } + if (parse->distinctClause && grouping_is_sortable(parse->distinctClause)) root->distinct_pathkeys = *************** *** 954,959 **** grouping_planner(PlannerInfo *root, double tuple_fraction) --- 995,1002 ---- */ if (root->group_pathkeys) root->query_pathkeys = root->group_pathkeys; + else if (root->window_pathkeys) + root->query_pathkeys = root->window_pathkeys; else if (list_length(root->distinct_pathkeys) > list_length(root->sort_pathkeys)) root->query_pathkeys = root->distinct_pathkeys; *************** *** 1277,1283 **** grouping_planner(PlannerInfo *root, double tuple_fraction) continue; /* ! * Currently, Window Partitioning strategy is only by Sort. * So just join partitionClause and orderClause * to match Grouping. Hashing algorithm will be considered later. */ --- 1320,1326 ---- continue; /* ! * Currently, Window partitioning is only by Sort. * So just join partitionClause and orderClause * to match Grouping. Hashing algorithm will be considered later. */ *** a/src/include/nodes/relation.h --- b/src/include/nodes/relation.h *************** *** 174,179 **** typedef struct PlannerInfo --- 174,181 ---- List *distinct_pathkeys; /* distinctClause pathkeys, if any */ List *sort_pathkeys; /* sortClause pathkeys, if any */ + List *window_pathkeys; /* pathkeys of bottom Window, if any */ + List *initial_rels; /* RelOptInfos we are now trying to join */ MemoryContext planner_cxt; /* context holding PlannerInfo */