aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/allpaths.c36
-rw-r--r--src/backend/optimizer/plan/createplan.c2
-rw-r--r--src/backend/optimizer/plan/planner.c54
-rw-r--r--src/backend/optimizer/prep/prepjointree.c8
-rw-r--r--src/backend/optimizer/util/clauses.c1
-rw-r--r--src/backend/optimizer/util/pathnode.c3
6 files changed, 61 insertions, 43 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index cc51ae17575..4895cee9944 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -2205,7 +2205,7 @@ set_dummy_rel_pathlist(RelOptInfo *rel)
* the run condition will handle all of the required filtering.
*
* Returns true if 'opexpr' was found to be useful and was added to the
- * WindowClauses runCondition. We also set *keep_original accordingly and add
+ * WindowFunc's runCondition. We also set *keep_original accordingly and add
* 'attno' to *run_cond_attrs offset by FirstLowInvalidHeapAttributeNumber.
* If the 'opexpr' cannot be used then we set *keep_original to true and
* return false.
@@ -2358,7 +2358,7 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti,
*keep_original = true;
runopexpr = opexpr;
- /* determine the operator to use for the runCondition qual */
+ /* determine the operator to use for the WindowFuncRunCondition */
runoperator = get_opfamily_member(opinfo->opfamily_id,
opinfo->oplefttype,
opinfo->oprighttype,
@@ -2369,27 +2369,15 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti,
if (runopexpr != NULL)
{
- Expr *newexpr;
+ WindowFuncRunCondition *wfuncrc;
- /*
- * Build the qual required for the run condition keeping the
- * WindowFunc on the same side as it was originally.
- */
- if (wfunc_left)
- newexpr = make_opclause(runoperator,
- runopexpr->opresulttype,
- runopexpr->opretset, (Expr *) wfunc,
- otherexpr, runopexpr->opcollid,
- runopexpr->inputcollid);
- else
- newexpr = make_opclause(runoperator,
- runopexpr->opresulttype,
- runopexpr->opretset,
- otherexpr, (Expr *) wfunc,
- runopexpr->opcollid,
- runopexpr->inputcollid);
+ wfuncrc = makeNode(WindowFuncRunCondition);
+ wfuncrc->opno = runoperator;
+ wfuncrc->inputcollid = runopexpr->inputcollid;
+ wfuncrc->wfunc_left = wfunc_left;
+ wfuncrc->arg = copyObject(otherexpr);
- wclause->runCondition = lappend(wclause->runCondition, newexpr);
+ wfunc->runCondition = lappend(wfunc->runCondition, wfuncrc);
/* record that this attno was used in a run condition */
*run_cond_attrs = bms_add_member(*run_cond_attrs,
@@ -2403,9 +2391,9 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti,
/*
* check_and_push_window_quals
- * Check if 'clause' is a qual that can be pushed into a WindowFunc's
- * WindowClause as a 'runCondition' qual. These, when present, allow
- * some unnecessary work to be skipped during execution.
+ * Check if 'clause' is a qual that can be pushed into a WindowFunc
+ * as a 'runCondition' qual. These, when present, allow some unnecessary
+ * work to be skipped during execution.
*
* 'run_cond_attrs' will be populated with all targetlist resnos of subquery
* targets (offset by FirstLowInvalidHeapAttributeNumber) that we pushed
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 3b778865674..6b64c4a362d 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2699,7 +2699,7 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
wc->inRangeColl,
wc->inRangeAsc,
wc->inRangeNullsFirst,
- wc->runCondition,
+ best_path->runCondition,
best_path->qual,
best_path->topwindow,
subplan);
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 5320da51a06..032818423f6 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -870,9 +870,6 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
EXPRKIND_LIMIT);
wc->endOffset = preprocess_expression(root, wc->endOffset,
EXPRKIND_LIMIT);
- wc->runCondition = (List *) preprocess_expression(root,
- (Node *) wc->runCondition,
- EXPRKIND_TARGET);
}
parse->limitOffset = preprocess_expression(root, parse->limitOffset,
@@ -4527,9 +4524,11 @@ create_one_window_path(PlannerInfo *root,
{
WindowClause *wc = lfirst_node(WindowClause, l);
List *window_pathkeys;
+ List *runcondition = NIL;
int presorted_keys;
bool is_sorted;
bool topwindow;
+ ListCell *lc2;
window_pathkeys = make_pathkeys_for_window(root,
wc,
@@ -4577,7 +4576,6 @@ create_one_window_path(PlannerInfo *root,
* we do need to account for the increase in tlist width.
*/
int64 tuple_width = window_target->width;
- ListCell *lc2;
window_target = copy_pathtarget(window_target);
foreach(lc2, wflists->windowFuncs[wc->winref])
@@ -4599,17 +4597,53 @@ create_one_window_path(PlannerInfo *root,
topwindow = foreach_current_index(l) == list_length(activeWindows) - 1;
/*
- * Accumulate all of the runConditions from each intermediate
- * WindowClause. The top-level WindowAgg must pass these as a qual so
- * that it filters out unwanted tuples correctly.
+ * Collect the WindowFuncRunConditions from each WindowFunc and
+ * convert them into OpExprs
*/
- if (!topwindow)
- topqual = list_concat(topqual, wc->runCondition);
+ foreach(lc2, wflists->windowFuncs[wc->winref])
+ {
+ ListCell *lc3;
+ WindowFunc *wfunc = lfirst_node(WindowFunc, lc2);
+
+ foreach(lc3, wfunc->runCondition)
+ {
+ WindowFuncRunCondition *wfuncrc =
+ lfirst_node(WindowFuncRunCondition, lc3);
+ Expr *opexpr;
+ Expr *leftop;
+ Expr *rightop;
+
+ if (wfuncrc->wfunc_left)
+ {
+ leftop = (Expr *) copyObject(wfunc);
+ rightop = copyObject(wfuncrc->arg);
+ }
+ else
+ {
+ leftop = copyObject(wfuncrc->arg);
+ rightop = (Expr *) copyObject(wfunc);
+ }
+
+ opexpr = make_opclause(wfuncrc->opno,
+ BOOLOID,
+ false,
+ leftop,
+ rightop,
+ InvalidOid,
+ wfuncrc->inputcollid);
+
+ runcondition = lappend(runcondition, opexpr);
+
+ if (!topwindow)
+ topqual = lappend(topqual, opexpr);
+ }
+ }
path = (Path *)
create_windowagg_path(root, window_rel, path, window_target,
wflists->windowFuncs[wc->winref],
- wc, topwindow ? topqual : NIL, topwindow);
+ runcondition, wc,
+ topwindow ? topqual : NIL, topwindow);
}
add_path(window_rel, path);
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 41da670f150..5482ab85a76 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2175,14 +2175,6 @@ perform_pullup_replace_vars(PlannerInfo *root,
parse->returningList = (List *)
pullup_replace_vars((Node *) parse->returningList, rvcontext);
- foreach(lc, parse->windowClause)
- {
- WindowClause *wc = lfirst_node(WindowClause, lc);
-
- if (wc->runCondition != NIL)
- wc->runCondition = (List *)
- pullup_replace_vars((Node *) wc->runCondition, rvcontext);
- }
if (parse->onConflict)
{
parse->onConflict->onConflictSet = (List *)
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 59487cbd795..b4e085e9d4b 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -2566,6 +2566,7 @@ eval_const_expressions_mutator(Node *node,
newexpr->inputcollid = expr->inputcollid;
newexpr->args = args;
newexpr->aggfilter = aggfilter;
+ newexpr->runCondition = expr->runCondition;
newexpr->winref = expr->winref;
newexpr->winstar = expr->winstar;
newexpr->winagg = expr->winagg;
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 3cf1dac0873..3491c3af1c9 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -3471,6 +3471,7 @@ create_minmaxagg_path(PlannerInfo *root,
* 'subpath' is the path representing the source of data
* 'target' is the PathTarget to be computed
* 'windowFuncs' is a list of WindowFunc structs
+ * 'runCondition' is a list of OpExprs to short-circuit WindowAgg execution
* 'winclause' is a WindowClause that is common to all the WindowFuncs
* 'qual' WindowClause.runconditions from lower-level WindowAggPaths.
* Must always be NIL when topwindow == false
@@ -3486,6 +3487,7 @@ create_windowagg_path(PlannerInfo *root,
Path *subpath,
PathTarget *target,
List *windowFuncs,
+ List *runCondition,
WindowClause *winclause,
List *qual,
bool topwindow)
@@ -3510,6 +3512,7 @@ create_windowagg_path(PlannerInfo *root,
pathnode->subpath = subpath;
pathnode->winclause = winclause;
pathnode->qual = qual;
+ pathnode->runCondition = runCondition;
pathnode->topwindow = topwindow;
/*