Fixes for ChangeVarNodes_walker()
This commit fixes two bug in ChangeVarNodes_walker() function. * When considering RestrictInfo, walk down to its clauses based on the presense of relid to be deleted not just in clause_relids but also in required_relids. * Incrementally adjust num_base_rels based on the change of clause_relids instead of recalculating it using clause_relids, which could contain outer-join relids. Reported-by: Richard Guo <guofenglinux@gmail.com> Discussion: https://postgr.es/m/CAMbWs49PE3CvnV8vrQ0Dr%3DHqgZZmX0tdNbzVNJxqc8yg-8kDQQ%40mail.gmail.com Author: Andrei Lepikhov <lepihov@gmail.com> Reviewed-by: Alexander Korotkov <aekorotkov@gmail.com>
This commit is contained in:
parent
15b1b4dd3f
commit
2260c7f6d9
@ -644,14 +644,34 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
|
|||||||
bool clause_relids_is_multiple =
|
bool clause_relids_is_multiple =
|
||||||
(bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
|
(bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
|
||||||
|
|
||||||
if (bms_is_member(context->rt_index, rinfo->clause_relids))
|
/*
|
||||||
|
* Recurse down into clauses if the target relation is present in
|
||||||
|
* clause_relids or required_relids. We must check required_relids
|
||||||
|
* because the relation not present in clause_relids might still be
|
||||||
|
* present somewhere in orclause.
|
||||||
|
*/
|
||||||
|
if (bms_is_member(context->rt_index, rinfo->clause_relids) ||
|
||||||
|
bms_is_member(context->rt_index, rinfo->required_relids))
|
||||||
{
|
{
|
||||||
|
Relids new_clause_relids;
|
||||||
|
|
||||||
expression_tree_walker((Node *) rinfo->clause, ChangeVarNodes_walker, (void *) context);
|
expression_tree_walker((Node *) rinfo->clause, ChangeVarNodes_walker, (void *) context);
|
||||||
expression_tree_walker((Node *) rinfo->orclause, ChangeVarNodes_walker, (void *) context);
|
expression_tree_walker((Node *) rinfo->orclause, ChangeVarNodes_walker, (void *) context);
|
||||||
|
|
||||||
rinfo->clause_relids =
|
new_clause_relids = adjust_relid_set(rinfo->clause_relids,
|
||||||
adjust_relid_set(rinfo->clause_relids, context->rt_index, context->new_index);
|
context->rt_index,
|
||||||
rinfo->num_base_rels = bms_num_members(rinfo->clause_relids);
|
context->new_index);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Incrementally adjust num_base_rels based on the change of
|
||||||
|
* clause_relids, which could contain both base relids and
|
||||||
|
* outer-join relids. This operation is legal until we remove
|
||||||
|
* only baserels.
|
||||||
|
*/
|
||||||
|
rinfo->num_base_rels -= bms_num_members(rinfo->clause_relids) -
|
||||||
|
bms_num_members(new_clause_relids);
|
||||||
|
|
||||||
|
rinfo->clause_relids = new_clause_relids;
|
||||||
rinfo->left_relids =
|
rinfo->left_relids =
|
||||||
adjust_relid_set(rinfo->left_relids, context->rt_index, context->new_index);
|
adjust_relid_set(rinfo->left_relids, context->rt_index, context->new_index);
|
||||||
rinfo->right_relids =
|
rinfo->right_relids =
|
||||||
|
@ -7260,6 +7260,20 @@ WHERE t1.id = emp1.id RETURNING emp1.id, emp1.code, t1.code;
|
|||||||
Index Cond: (id = emp1.id)
|
Index Cond: (id = emp1.id)
|
||||||
(5 rows)
|
(5 rows)
|
||||||
|
|
||||||
|
-- Check that SJE correctly replaces relations in OR-clauses
|
||||||
|
EXPLAIN (COSTS OFF)
|
||||||
|
SELECT * FROM emp1 t1
|
||||||
|
INNER JOIN emp1 t2 ON t1.id = t2.id
|
||||||
|
LEFT JOIN emp1 t3 ON t1.code = 1 AND (t2.code = t3.code OR t2.code = 1);
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Nested Loop Left Join
|
||||||
|
Join Filter: ((t2.code = 1) AND ((t2.code = t3.code) OR (t2.code = 1)))
|
||||||
|
-> Seq Scan on emp1 t2
|
||||||
|
-> Materialize
|
||||||
|
-> Seq Scan on emp1 t3
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
INSERT INTO emp1 VALUES (1, 1), (2, 1);
|
INSERT INTO emp1 VALUES (1, 1), (2, 1);
|
||||||
WITH t1 AS (SELECT * FROM emp1)
|
WITH t1 AS (SELECT * FROM emp1)
|
||||||
UPDATE emp1 SET code = t1.code + 1 FROM t1
|
UPDATE emp1 SET code = t1.code + 1 FROM t1
|
||||||
|
@ -2807,6 +2807,12 @@ WITH t1 AS (SELECT * FROM emp1)
|
|||||||
UPDATE emp1 SET code = t1.code + 1 FROM t1
|
UPDATE emp1 SET code = t1.code + 1 FROM t1
|
||||||
WHERE t1.id = emp1.id RETURNING emp1.id, emp1.code, t1.code;
|
WHERE t1.id = emp1.id RETURNING emp1.id, emp1.code, t1.code;
|
||||||
|
|
||||||
|
-- Check that SJE correctly replaces relations in OR-clauses
|
||||||
|
EXPLAIN (COSTS OFF)
|
||||||
|
SELECT * FROM emp1 t1
|
||||||
|
INNER JOIN emp1 t2 ON t1.id = t2.id
|
||||||
|
LEFT JOIN emp1 t3 ON t1.code = 1 AND (t2.code = t3.code OR t2.code = 1);
|
||||||
|
|
||||||
INSERT INTO emp1 VALUES (1, 1), (2, 1);
|
INSERT INTO emp1 VALUES (1, 1), (2, 1);
|
||||||
|
|
||||||
WITH t1 AS (SELECT * FROM emp1)
|
WITH t1 AS (SELECT * FROM emp1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user