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
This commit is contained in:
Tom Lane 2024-01-10 13:36:33 -05:00
parent 5b2da240e0
commit d641b827af
3 changed files with 41 additions and 0 deletions

View File

@ -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);
}

View File

@ -4181,6 +4181,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

View File

@ -1368,6 +1368,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.