summaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/plan/createplan.c39
-rw-r--r--src/backend/optimizer/plan/planner.c51
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
*