From dc4b6235a0150de2a1e15f315dee550cc4ccdd92 Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Wed, 31 May 2023 14:17:11 +0800 Subject: [PATCH v1] Fix nulling bitmap for nestloop parameters --- src/backend/optimizer/util/paramassign.c | 12 ++++++++++++ src/test/regress/expected/join.out | 16 ++++++++++++++++ src/test/regress/sql/join.sql | 5 +++++ 3 files changed, 33 insertions(+) diff --git a/src/backend/optimizer/util/paramassign.c b/src/backend/optimizer/util/paramassign.c index 66534c0a78..192e1752e9 100644 --- a/src/backend/optimizer/util/paramassign.c +++ b/src/backend/optimizer/util/paramassign.c @@ -503,6 +503,14 @@ process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params) * Identify any NestLoopParams that should be supplied by a NestLoop plan * node with the specified lefthand rels. Remove them from the active * root->curOuterParams list and return them as the result list. + * + * We also need to adjust the nulling bitmap for them, for the case that we + * have transformed the first form of identity 3 to the second form. In such + * case, the selected params should not have the A/B join in their nulling + * bitmap. (Note there is no problem when identity 3 is applied in the other + * direction, because setrefs.c only checks that the nullingrels in + * NestLoopParams are just a subset of those in the Vars actually available + * from the outer.) */ List * identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids) @@ -524,6 +532,8 @@ identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids) { root->curOuterParams = foreach_delete_current(root->curOuterParams, cell); + nlp->paramval->varnullingrels = + bms_intersect(nlp->paramval->varnullingrels, leftrelids); result = lappend(result, nlp); } else if (IsA(nlp->paramval, PlaceHolderVar) && @@ -533,6 +543,8 @@ identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids) { root->curOuterParams = foreach_delete_current(root->curOuterParams, cell); + ((PlaceHolderVar *) nlp->paramval)->phnullingrels = + bms_intersect(((PlaceHolderVar *) nlp->paramval)->phnullingrels, leftrelids); result = lappend(result, nlp); } } diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 4c278b2fa3..681d30c608 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -2589,6 +2589,22 @@ on t2.q2 = 123; -> Seq Scan on int8_tbl t5 (12 rows) +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral (select * from int8_tbl t3 where t3.q1 = t2.q1 offset 0) s on t2.q1 = 1; + QUERY PLAN +------------------------------------------- + Nested Loop Left Join + -> Seq Scan on int8_tbl t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t2.q1 = 1) + -> Seq Scan on int8_tbl t2 + -> Seq Scan on int8_tbl t3 + Filter: (q1 = t2.q1) +(8 rows) + -- -- check a case where we formerly got confused by conflicting sort orders -- in redundant merge join path keys diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 4baf5ebc13..862335bda9 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -514,6 +514,11 @@ select * from int8_tbl t1 left join left join int8_tbl t5 on t2.q1 = t5.q1 on t2.q2 = 123; +explain (costs off) +select * from int8_tbl t1 + left join int8_tbl t2 on true + left join lateral (select * from int8_tbl t3 where t3.q1 = t2.q1 offset 0) s on t2.q1 = 1; + -- -- check a case where we formerly got confused by conflicting sort orders -- in redundant merge join path keys -- 2.31.0