mirror of
https://github.com/postgres/postgres.git
synced 2025-08-24 09:27:52 +03:00
Fix old oversight in join removal logic.
Commit 9e7e29c75a
introduced an Assert that
join removal didn't reduce the eval_at set of any PlaceHolderVar to empty.
At first glance it looks like join_is_removable ensures that's true --- but
actually, the loop in join_is_removable skips PlaceHolderVars that are not
referenced above the join due to be removed. So, if we don't want any
empty eval_at sets, the right thing to do is to delete any now-unreferenced
PlaceHolderVars from the data structure entirely.
Per fuzz testing by Andreas Seltenreich. Back-patch to 9.3 where the
aforesaid Assert was added.
This commit is contained in:
@@ -382,16 +382,24 @@ remove_rel_from_query(PlannerInfo *root, int relid, Relids joinrelids)
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise remove references from PlaceHolderVar data structures.
|
||||
* Likewise remove references from PlaceHolderVar data structures,
|
||||
* removing any no-longer-needed placeholders entirely.
|
||||
*/
|
||||
foreach(l, root->placeholder_list)
|
||||
for (l = list_head(root->placeholder_list); l != NULL; l = nextl)
|
||||
{
|
||||
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
|
||||
|
||||
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);
|
||||
nextl = lnext(l);
|
||||
if (bms_is_subset(phinfo->ph_needed, joinrelids))
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user