aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-01-10 13:36:34 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2024-01-10 13:36:34 -0500
commitee955321869e46289d11b0c77255c74d62caf3a5 (patch)
treef9d50341a0ad6754465d5d6cfd75d7885511b525
parent65ee2ed0d0da6dd45853b050b4d59634d64479bd (diff)
downloadpostgresql-ee955321869e46289d11b0c77255c74d62caf3a5.tar.gz
postgresql-ee955321869e46289d11b0c77255c74d62caf3a5.zip
Handle WindowClause.runCondition in tree walker/mutator functions.
Commit 9d9c02ccd, which added the notion of a "run condition" for window functions, neglected to teach nodeFuncs.c to process the new field. Remarkably, that doesn't seem to have had any ill effects before we invented Var.varnullingrels, but now it can cause visible failures in join-removal scenarios. I have no faith that there's not reachable problems in v15 too, so back-patch the code change to v15 where 9d9c02ccd came in. The test case seems irrelevant to v15, though. Per bug #18277 from Zuming Jiang. Diagnosis and patch by Richard Guo. Discussion: https://postgr.es/m/18277-089ead83b329a2fd@postgresql.org
-rw-r--r--src/backend/nodes/nodeFuncs.c6
-rw-r--r--src/test/regress/expected/window.out26
-rw-r--r--src/test/regress/sql/window.sql9
3 files changed, 41 insertions, 0 deletions
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 503d76aae07..9cb70b6d1e0 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -2283,6 +2283,8 @@ expression_tree_walker_impl(Node *node,
return true;
if (WALK(wc->endOffset))
return true;
+ if (WALK(wc->runCondition))
+ return true;
}
break;
case T_CTECycleClause:
@@ -2627,6 +2629,8 @@ query_tree_walker_impl(Query *query,
return true;
if (WALK(wc->endOffset))
return true;
+ if (WALK(wc->runCondition))
+ return true;
}
}
@@ -3312,6 +3316,7 @@ expression_tree_mutator_impl(Node *node,
MUTATE(newnode->orderClause, wc->orderClause, List *);
MUTATE(newnode->startOffset, wc->startOffset, Node *);
MUTATE(newnode->endOffset, wc->endOffset, Node *);
+ MUTATE(newnode->runCondition, wc->runCondition, List *);
return (Node *) newnode;
}
break;
@@ -3641,6 +3646,7 @@ query_tree_mutator_impl(Query *query,
FLATCOPY(newnode, wc, WindowClause);
MUTATE(newnode->startOffset, wc->startOffset, Node *);
MUTATE(newnode->endOffset, wc->endOffset, Node *);
+ MUTATE(newnode->runCondition, wc->runCondition, List *);
resultlist = lappend(resultlist, (Node *) newnode);
}
diff --git a/src/test/regress/expected/window.out b/src/test/regress/expected/window.out
index 1d4b78b9b27..86127887022 100644
--- a/src/test/regress/expected/window.out
+++ b/src/test/regress/expected/window.out
@@ -3804,6 +3804,32 @@ SELECT * FROM
sales | 3 | 4800 | 08-01-2007 | 3 | 1 | 3 | 3 | 1
(2 rows)
+-- Ensure we remove references to reduced outer joins as nulling rels in run
+-- conditions
+EXPLAIN (COSTS OFF)
+SELECT 1 FROM
+ (SELECT ntile(e2.salary) OVER (PARTITION BY e1.depname) AS c
+ FROM empsalary e1 LEFT JOIN empsalary e2 ON TRUE
+ WHERE e1.empno = e2.empno) s
+WHERE s.c = 1;
+ QUERY PLAN
+---------------------------------------------------------
+ Subquery Scan on s
+ Filter: (s.c = 1)
+ -> WindowAgg
+ Run Condition: (ntile(e2.salary) OVER (?) <= 1)
+ -> Sort
+ Sort Key: e1.depname
+ -> Merge Join
+ Merge Cond: (e1.empno = e2.empno)
+ -> Sort
+ Sort Key: e1.empno
+ -> Seq Scan on empsalary e1
+ -> Sort
+ Sort Key: e2.empno
+ -> Seq Scan on empsalary e2
+(14 rows)
+
-- Tests to ensure we don't push down the run condition when it's not valid to
-- do so.
-- Ensure we don't push down when the frame options show that the window
diff --git a/src/test/regress/sql/window.sql b/src/test/regress/sql/window.sql
index 3ab6ac715d0..c0ad51ca544 100644
--- a/src/test/regress/sql/window.sql
+++ b/src/test/regress/sql/window.sql
@@ -1236,6 +1236,15 @@ SELECT * FROM
FROM empsalary
) e WHERE rn <= 1 AND c1 <= 3 AND nt < 2;
+-- Ensure we remove references to reduced outer joins as nulling rels in run
+-- conditions
+EXPLAIN (COSTS OFF)
+SELECT 1 FROM
+ (SELECT ntile(e2.salary) OVER (PARTITION BY e1.depname) AS c
+ FROM empsalary e1 LEFT JOIN empsalary e2 ON TRUE
+ WHERE e1.empno = e2.empno) s
+WHERE s.c = 1;
+
-- Tests to ensure we don't push down the run condition when it's not valid to
-- do so.