summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/prep/prepjointree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/prep/prepjointree.c')
-rw-r--r--src/backend/optimizer/prep/prepjointree.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 2ebd938f6bd..3fa4d78c3e0 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2598,26 +2598,47 @@ pullup_replace_vars_callback(Var *var,
/*
* Simple Vars always escape being wrapped, unless they are
* lateral references to something outside the subquery being
- * pulled up. (Even then, we could omit the PlaceHolderVar if
- * the referenced rel is under the same lowest outer join, but
- * it doesn't seem worth the trouble to check that.)
+ * pulled up and the referenced rel is not under the same
+ * lowest nulling outer join.
*/
+ wrap = false;
if (rcon->target_rte->lateral &&
!bms_is_member(((Var *) newnode)->varno, rcon->relids))
- wrap = true;
- else
- wrap = false;
+ {
+ nullingrel_info *nullinfo = rcon->nullinfo;
+ int lvarno = ((Var *) newnode)->varno;
+
+ Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
+ if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
+ nullinfo->nullingrels[lvarno]))
+ wrap = true;
+ }
}
else if (newnode && IsA(newnode, PlaceHolderVar) &&
((PlaceHolderVar *) newnode)->phlevelsup == 0)
{
/* The same rules apply for a PlaceHolderVar */
+ wrap = false;
if (rcon->target_rte->lateral &&
!bms_is_subset(((PlaceHolderVar *) newnode)->phrels,
rcon->relids))
- wrap = true;
- else
- wrap = false;
+ {
+ nullingrel_info *nullinfo = rcon->nullinfo;
+ Relids lvarnos = ((PlaceHolderVar *) newnode)->phrels;
+ int lvarno;
+
+ lvarno = -1;
+ while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0)
+ {
+ Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
+ if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
+ nullinfo->nullingrels[lvarno]))
+ {
+ wrap = true;
+ break;
+ }
+ }
+ }
}
else if (rcon->wrap_non_vars)
{