Further tighten nullingrel marking rules in build_joinrel_tlist().
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 8 Feb 2023 19:45:36 +0000 (14:45 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 8 Feb 2023 19:45:36 +0000 (14:45 -0500)
The code I added in fee7b77b9 could misbehave if commute_above_r
contains multiple relids.  While adding too many relids here is
probably harmless (pre-fee7b77b9, we did it all the time), it's
not very expensive to be accurate: we just have to intersect
commute_above_r with the join's relids.

Discussion: https://postgr.es/m/17781-c0405c8b3cd5e072@postgresql.org

src/backend/optimizer/util/relnode.c

index 29da78b62ef89943c18181ac0fd366f136bac61f..a70a16238a8526b5a306053beb874543301aa08f 100644 (file)
@@ -1051,9 +1051,9 @@ min_join_parameterization(PlannerInfo *root,
  *             A leftjoin (B leftjoin C on (Pbc)) on (Pab)
  * Here the now-upper A/B join must not mark C columns as nulled by itself.
  *
- * Second, if sjinfo->commute_above_r is already part of the joinrel then
- * it is added to the nulling bitmaps of nullable Vars.  This takes care of
- * the reverse case where we implement
+ * Second, any relid in sjinfo->commute_above_r that is already part of
+ * the joinrel is added to the nulling bitmaps of nullable Vars and PHVs.
+ * This takes care of the reverse case where we implement
  *             A leftjoin (B leftjoin C on (Pbc)) on (Pab)
  * as
  *             (A leftjoin B on (Pab)) leftjoin C on (Pbc)
@@ -1100,9 +1100,10 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
                                                  bms_is_subset(phv->phrels, sjinfo->syn_lefthand))))
                                                phv->phnullingrels = bms_add_member(phv->phnullingrels,
                                                                                                                        sjinfo->ojrelid);
-                                       if (bms_overlap(sjinfo->commute_above_r, joinrel->relids))
-                                               phv->phnullingrels = bms_add_members(phv->phnullingrels,
-                                                                                                                        sjinfo->commute_above_r);
+                                       phv->phnullingrels =
+                                               bms_join(phv->phnullingrels,
+                                                                bms_intersect(sjinfo->commute_above_r,
+                                                                                          relids));
                                }
 
                                joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
@@ -1164,9 +1165,10 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
                                  bms_is_member(var->varno, sjinfo->syn_lefthand))))
                                var->varnullingrels = bms_add_member(var->varnullingrels,
                                                                                                         sjinfo->ojrelid);
-                       if (bms_overlap(sjinfo->commute_above_r, joinrel->relids))
-                               var->varnullingrels = bms_add_members(var->varnullingrels,
-                                                                                                         sjinfo->commute_above_r);
+                       var->varnullingrels =
+                               bms_join(var->varnullingrels,
+                                                bms_intersect(sjinfo->commute_above_r,
+                                                                          relids));
                }
 
                joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,