diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 39 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 51 |
2 files changed, 64 insertions, 26 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 816a2b2a576..75e2b0b9036 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -285,12 +285,9 @@ static Memoize *make_memoize(Plan *lefttree, Oid *hashoperators, Oid *collations, List *param_exprs, bool singlerow, bool binary_mode, uint32 est_entries, Bitmapset *keyparamids); -static WindowAgg *make_windowagg(List *tlist, Index winref, +static WindowAgg *make_windowagg(List *tlist, WindowClause *wc, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, - int frameOptions, Node *startOffset, Node *endOffset, - Oid startInRangeFunc, Oid endInRangeFunc, - Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition, List *qual, bool topWindow, Plan *lefttree); static Group *make_group(List *tlist, List *qual, int numGroupCols, @@ -2683,7 +2680,7 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path) /* And finally we can make the WindowAgg node */ plan = make_windowagg(tlist, - wc->winref, + wc, partNumCols, partColIdx, partOperators, @@ -2692,14 +2689,6 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path) ordColIdx, ordOperators, ordCollations, - wc->frameOptions, - wc->startOffset, - wc->endOffset, - wc->startInRangeFunc, - wc->endInRangeFunc, - wc->inRangeColl, - wc->inRangeAsc, - wc->inRangeNullsFirst, best_path->runCondition, best_path->qual, best_path->topwindow, @@ -6704,18 +6693,16 @@ make_agg(List *tlist, List *qual, } static WindowAgg * -make_windowagg(List *tlist, Index winref, +make_windowagg(List *tlist, WindowClause *wc, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, - int frameOptions, Node *startOffset, Node *endOffset, - Oid startInRangeFunc, Oid endInRangeFunc, - Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition, List *qual, bool topWindow, Plan *lefttree) { WindowAgg *node = makeNode(WindowAgg); Plan *plan = &node->plan; - node->winref = winref; + node->winname = wc->name; + node->winref = wc->winref; node->partNumCols = partNumCols; node->partColIdx = partColIdx; node->partOperators = partOperators; @@ -6724,17 +6711,17 @@ make_windowagg(List *tlist, Index winref, node->ordColIdx = ordColIdx; node->ordOperators = ordOperators; node->ordCollations = ordCollations; - node->frameOptions = frameOptions; - node->startOffset = startOffset; - node->endOffset = endOffset; + node->frameOptions = wc->frameOptions; + node->startOffset = wc->startOffset; + node->endOffset = wc->endOffset; node->runCondition = runCondition; /* a duplicate of the above for EXPLAIN */ node->runConditionOrig = runCondition; - node->startInRangeFunc = startInRangeFunc; - node->endInRangeFunc = endInRangeFunc; - node->inRangeColl = inRangeColl; - node->inRangeAsc = inRangeAsc; - node->inRangeNullsFirst = inRangeNullsFirst; + node->startInRangeFunc = wc->startInRangeFunc; + node->endInRangeFunc = wc->endInRangeFunc; + node->inRangeColl = wc->inRangeColl; + node->inRangeAsc = wc->inRangeAsc; + node->inRangeNullsFirst = wc->inRangeNullsFirst; node->topWindow = topWindow; plan->targetlist = tlist; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 014e80c30e6..a4d523dcb0f 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -214,6 +214,7 @@ static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist); static void optimize_window_clauses(PlannerInfo *root, WindowFuncLists *wflists); static List *select_active_windows(PlannerInfo *root, WindowFuncLists *wflists); +static void name_active_windows(List *activeWindows); static PathTarget *make_window_input_target(PlannerInfo *root, PathTarget *final_target, List *activeWindows); @@ -1539,7 +1540,11 @@ grouping_planner(PlannerInfo *root, double tuple_fraction, */ optimize_window_clauses(root, wflists); + /* Extract the list of windows actually in use. */ activeWindows = select_active_windows(root, wflists); + + /* Make sure they all have names, for EXPLAIN's use. */ + name_active_windows(activeWindows); } else parse->hasWindowFuncs = false; @@ -5915,6 +5920,52 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists) } /* + * name_active_windows + * Ensure all active windows have unique names. + * + * The parser will have checked that user-assigned window names are unique + * within the Query. Here we assign made-up names to any unnamed + * WindowClauses for the benefit of EXPLAIN. (We don't want to do this + * at parse time, because it'd mess up decompilation of views.) + * + * activeWindows: result of select_active_windows + */ +static void +name_active_windows(List *activeWindows) +{ + int next_n = 1; + char newname[16]; + ListCell *lc; + + foreach(lc, activeWindows) + { + WindowClause *wc = lfirst_node(WindowClause, lc); + + /* Nothing to do if it has a name already. */ + if (wc->name) + continue; + + /* Select a name not currently present in the list. */ + for (;;) + { + ListCell *lc2; + + snprintf(newname, sizeof(newname), "w%d", next_n++); + foreach(lc2, activeWindows) + { + WindowClause *wc2 = lfirst_node(WindowClause, lc2); + + if (wc2->name && strcmp(wc2->name, newname) == 0) + break; /* matched */ + } + if (lc2 == NULL) + break; /* reached the end with no match */ + } + wc->name = pstrdup(newname); + } +} + +/* * common_prefix_cmp * QSort comparison function for WindowClauseSortData * |