aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/allpaths.c
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2024-05-05 12:54:46 +1200
committerDavid Rowley <drowley@postgresql.org>2024-05-05 12:54:46 +1200
commit7d2c7f08d9c5ad02101c0fb47cd8e859dd89083b (patch)
treea84db7d521410918fab94680bff9bdce1ae7643d /src/backend/optimizer/path/allpaths.c
parent01df14763431df1506cbae206945cd165c66d1d3 (diff)
downloadpostgresql-7d2c7f08d9c5ad02101c0fb47cd8e859dd89083b.tar.gz
postgresql-7d2c7f08d9c5ad02101c0fb47cd8e859dd89083b.zip
Fix query pullup issue with WindowClause runCondition
94985c210 added code to detect when WindowFuncs were monotonic and allowed additional quals to be "pushed down" into the subquery to be used as WindowClause runConditions in order to short-circuit execution in nodeWindowAgg.c. The Node representation of runConditions wasn't well selected and because we do qual pushdown before planning the subquery, the planning of the subquery could perform subquery pull-up of nested subqueries. For WindowFuncs with args, the arguments could be changed after pushing the qual down to the subquery. This was made more difficult by the fact that the code duplicated the WindowFunc inside an OpExpr to include in the WindowClauses runCondition field. This could result in duplication of subqueries and a pull-up of such a subquery could result in another initplan parameter being issued for the 2nd version of the subplan. This could result in errors such as: ERROR: WindowFunc not found in subplan target lists To fix this, we change the node representation of these run conditions and instead of storing an OpExpr containing the WindowFunc in a list inside WindowClause, we now store a new node type named WindowFuncRunCondition within a new field in the WindowFunc. These get transformed into OpExprs later in planning once subquery pull-up has been performed. This problem did exist in v15 and v16, but that was fixed by 9d36b883b and e5d20bbd. Cat version bump due to new node type and modifying WindowFunc struct. Bug: #18305 Reported-by: Zuming Jiang Discussion: https://postgr.es/m/18305-33c49b4c830b37b3%40postgresql.org
Diffstat (limited to 'src/backend/optimizer/path/allpaths.c')
-rw-r--r--src/backend/optimizer/path/allpaths.c36
1 files changed, 12 insertions, 24 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