{
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
- if (bms_is_subset(phinfo->ph_needed, joinrelids))
- continue; /* PHV is not used above the join */
if (bms_overlap(phinfo->ph_lateral, innerrel->relids))
return false; /* it references innerrel laterally */
+ if (bms_is_subset(phinfo->ph_needed, joinrelids))
+ continue; /* PHV is not used above the join */
if (!bms_overlap(phinfo->ph_eval_at, innerrel->relids))
continue; /* it definitely doesn't reference innerrel */
if (bms_is_subset(phinfo->ph_eval_at, innerrel->relids))
sjinfo->syn_righthand = bms_del_member(sjinfo->syn_righthand, relid);
}
- /*
- * Likewise remove references from LateralJoinInfo data structures.
- *
- * If we are deleting a LATERAL subquery, we can forget its
- * LateralJoinInfos altogether. Otherwise, make sure the target is not
- * included in any lateral_lhs set. (It probably can't be, since that
- * should have precluded deciding to remove it; but let's cope anyway.)
- */
- for (l = list_head(root->lateral_info_list); l != NULL; l = nextl)
- {
- LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l);
-
- nextl = lnext(l);
- ljinfo->lateral_rhs = bms_del_member(ljinfo->lateral_rhs, relid);
- if (bms_is_empty(ljinfo->lateral_rhs))
- root->lateral_info_list = list_delete_ptr(root->lateral_info_list,
- ljinfo);
- else
- {
- ljinfo->lateral_lhs = bms_del_member(ljinfo->lateral_lhs, relid);
- Assert(!bms_is_empty(ljinfo->lateral_lhs));
- }
- }
+ /* There shouldn't be any LATERAL info to translate, as yet */
+ Assert(root->lateral_info_list == NIL);
/*
* Likewise remove references from PlaceHolderVar data structures,
* removing any no-longer-needed placeholders entirely.
+ *
+ * Removal is a bit tricker than it might seem: we can remove PHVs that
+ * are used at the target rel and/or in the join qual, but not those that
+ * are used at join partner rels or above the join. It's not that easy to
+ * distinguish PHVs used at partner rels from those used in the join qual,
+ * since they will both have ph_needed sets that are subsets of
+ * joinrelids. However, a PHV used at a partner rel could not have the
+ * target rel in ph_eval_at, so we check that while deciding whether to
+ * remove or just update the PHV. There is no corresponding test in
+ * join_is_removable because it doesn't need to distinguish those cases.
*/
for (l = list_head(root->placeholder_list); l != NULL; l = nextl)
{
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
nextl = lnext(l);
- if (bms_is_subset(phinfo->ph_needed, joinrelids))
+ Assert(!bms_is_member(relid, phinfo->ph_lateral));
+ if (bms_is_subset(phinfo->ph_needed, joinrelids) &&
+ bms_is_member(relid, phinfo->ph_eval_at))
root->placeholder_list = list_delete_ptr(root->placeholder_list,
phinfo);
else
{
phinfo->ph_eval_at = bms_del_member(phinfo->ph_eval_at, relid);
Assert(!bms_is_empty(phinfo->ph_eval_at));
- Assert(!bms_is_member(relid, phinfo->ph_lateral));
phinfo->ph_needed = bms_del_member(phinfo->ph_needed, relid);
}
}
Seq Scan on uniquetbl t1
(1 row)
+explain (costs off)
+select t0.*
+from
+ text_tbl t0
+ left join
+ (select case t1.ten when 0 then 'doh!'::text else null::text end as case1,
+ t1.stringu2
+ from tenk1 t1
+ join int4_tbl i4 ON i4.f1 = t1.unique2
+ left join uniquetbl u1 ON u1.f1 = t1.string4) ss
+ on t0.f1 = ss.case1
+where ss.stringu2 !~* ss.case1;
+ QUERY PLAN
+--------------------------------------------------------------------------------------------
+ Nested Loop
+ Join Filter: (CASE t1.ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END = t0.f1)
+ -> Nested Loop
+ -> Seq Scan on int4_tbl i4
+ -> Index Scan using tenk1_unique2 on tenk1 t1
+ Index Cond: (unique2 = i4.f1)
+ Filter: (stringu2 !~* CASE ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END)
+ -> Materialize
+ -> Seq Scan on text_tbl t0
+(9 rows)
+
+select t0.*
+from
+ text_tbl t0
+ left join
+ (select case t1.ten when 0 then 'doh!'::text else null::text end as case1,
+ t1.stringu2
+ from tenk1 t1
+ join int4_tbl i4 ON i4.f1 = t1.unique2
+ left join uniquetbl u1 ON u1.f1 = t1.string4) ss
+ on t0.f1 = ss.case1
+where ss.stringu2 !~* ss.case1;
+ f1
+------
+ doh!
+(1 row)
+
rollback;
-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs
select * from