mirror of
https://github.com/postgres/postgres.git
synced 2026-03-27 21:03:14 -04:00
Fix self-join removal to update bare Var references in join clauses
Self-join removal failed to update Var nodes when the join clause was a bare Var (e.g., ON t1.bool_col) rather than an expression containing Vars. ChangeVarNodesWalkExpression() used expression_tree_walker(), which descends into child nodes but does not process the top-level node itself. When a bare Var referencing the removed relation appeared as the clause, its varno was left unchanged, leading to "no relation entry for relid N" errors. Fix by calling ChangeVarNodes_walker() directly instead of expression_tree_walker(), so the top-level node is also processed. Bug: #19435 Reported-by: Hang Ammmkilo <ammmkilo@163.com> Author: Andrei Lepikhov <lepihov@gmail.com> Co-authored-by: Tender Wang <tndrwang@gmail.com> Co-authored-by: Alexander Korotkov <aekorotkov@gmail.com> Reviewed-by: Kirill Reshke <reshkekirill@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/19435-3cc1a87f291129f1%40postgresql.org Backpatch-through: 18
This commit is contained in:
parent
e7975f1c06
commit
07b7a964d3
3 changed files with 23 additions and 3 deletions
|
|
@ -744,9 +744,7 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
|
|||
bool
|
||||
ChangeVarNodesWalkExpression(Node *node, ChangeVarNodes_context *context)
|
||||
{
|
||||
return expression_tree_walker(node,
|
||||
ChangeVarNodes_walker,
|
||||
(void *) context);
|
||||
return ChangeVarNodes_walker(node, context);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -8092,6 +8092,22 @@ WHERE q0.a = 1;
|
|||
-> Seq Scan on sj n1
|
||||
(7 rows)
|
||||
|
||||
-- Do not forget to replace relid in bare Var join clause (bug #19435)
|
||||
ALTER TABLE sl ADD COLUMN bool_col boolean;
|
||||
EXPLAIN (COSTS OFF)
|
||||
SELECT 1 AS c1 FROM sl sl1 LEFT JOIN (sl AS sl2 NATURAL JOIN sl AS sl3)
|
||||
ON sl2.bool_col LEFT JOIN sl AS sl4 ON sl2.bool_col;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop Left Join
|
||||
-> Seq Scan on sl sl1
|
||||
-> Nested Loop Left Join
|
||||
Join Filter: sl3.bool_col
|
||||
-> Seq Scan on sl sl3
|
||||
Filter: (bool_col AND (a IS NOT NULL) AND (b IS NOT NULL) AND (c IS NOT NULL) AND (bool_col IS NOT NULL))
|
||||
-> Seq Scan on sl sl4
|
||||
(7 rows)
|
||||
|
||||
-- Check optimization disabling if it will violate special join conditions.
|
||||
-- Two identical joined relations satisfies self join removal conditions but
|
||||
-- stay in different special join infos.
|
||||
|
|
|
|||
|
|
@ -3156,6 +3156,12 @@ SELECT * FROM
|
|||
(SELECT n2.a FROM sj n1, sj n2 WHERE n1.a <> n2.a) q0, sl
|
||||
WHERE q0.a = 1;
|
||||
|
||||
-- Do not forget to replace relid in bare Var join clause (bug #19435)
|
||||
ALTER TABLE sl ADD COLUMN bool_col boolean;
|
||||
EXPLAIN (COSTS OFF)
|
||||
SELECT 1 AS c1 FROM sl sl1 LEFT JOIN (sl AS sl2 NATURAL JOIN sl AS sl3)
|
||||
ON sl2.bool_col LEFT JOIN sl AS sl4 ON sl2.bool_col;
|
||||
|
||||
-- Check optimization disabling if it will violate special join conditions.
|
||||
-- Two identical joined relations satisfies self join removal conditions but
|
||||
-- stay in different special join infos.
|
||||
|
|
|
|||
Loading…
Reference in a new issue