diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 36 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 54 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepjointree.c | 8 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 1 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 3 |
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; /* |