mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Fix EquivalenceClass processing for nested append relations.
The original coding of EquivalenceClasses didn't foresee that appendrel child relations might themselves be appendrels; but this is possible for example when a UNION ALL subquery scans a table with inheritance children. The oversight led to failure to optimize ordering-related issues very well for the grandchild tables. After some false starts involving explicitly flattening the appendrel representation, we found that this could be fixed easily by removing a few implicit assumptions about appendrel parent rels not being children themselves. Kyotaro Horiguchi and Tom Lane, reviewed by Noah Misch
This commit is contained in:
@ -1021,10 +1021,15 @@ get_cheapest_parameterized_child_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
* accumulate_append_subpath
|
||||
* Add a subpath to the list being built for an Append or MergeAppend
|
||||
*
|
||||
* It's possible that the child is itself an Append path, in which case
|
||||
* we can "cut out the middleman" and just add its child paths to our
|
||||
* own list. (We don't try to do this earlier because we need to
|
||||
* apply both levels of transformation to the quals.)
|
||||
* It's possible that the child is itself an Append or MergeAppend path, in
|
||||
* which case we can "cut out the middleman" and just add its child paths to
|
||||
* our own list. (We don't try to do this earlier because we need to apply
|
||||
* both levels of transformation to the quals.)
|
||||
*
|
||||
* Note that if we omit a child MergeAppend in this way, we are effectively
|
||||
* omitting a sort step, which seems fine: if the parent is to be an Append,
|
||||
* its result would be unsorted anyway, while if the parent is to be a
|
||||
* MergeAppend, there's no point in a separate sort on a child.
|
||||
*/
|
||||
static List *
|
||||
accumulate_append_subpath(List *subpaths, Path *path)
|
||||
@ -1036,6 +1041,13 @@ accumulate_append_subpath(List *subpaths, Path *path)
|
||||
/* list_copy is important here to avoid sharing list substructure */
|
||||
return list_concat(subpaths, list_copy(apath->subpaths));
|
||||
}
|
||||
else if (IsA(path, MergeAppendPath))
|
||||
{
|
||||
MergeAppendPath *mpath = (MergeAppendPath *) path;
|
||||
|
||||
/* list_copy is important here to avoid sharing list substructure */
|
||||
return list_concat(subpaths, list_copy(mpath->subpaths));
|
||||
}
|
||||
else
|
||||
return lappend(subpaths, path);
|
||||
}
|
||||
|
Reference in New Issue
Block a user