summaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-06-26 10:41:10 -0700
committerTom Lane <tgl@sss.pgh.pa.us>2014-06-26 10:42:08 -0700
commit555d0b2000e33fd1ad2721015996a66c43bbb3cd (patch)
tree5fd992cd25c52f5b33634250dbfa21a5652e71a4 /src/backend/optimizer
parent865868043af0f23cd72d4450ca4410828b016cea (diff)
Back-patch "Fix EquivalenceClass processing for nested append relations".
When we committed a87c729153e372f3731689a7be007bc2b53f1410, we somehow failed to notice that it didn't merely improve plan quality for expression indexes; there were very closely related cases that failed outright with "could not find pathkey item to sort". The failing cases seem to be those where the planner was already capable of selecting a MergeAppend plan, and there was inheritance involved: the lack of appropriate eclass child members would prevent prepare_sort_from_pathkeys() from succeeding on the MergeAppend's child plan nodes for inheritance child tables. Accordingly, back-patch into 9.1 through 9.3, along with an extra regression test case covering the problem. Per trouble report from Michael Glaesemann.
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/allpaths.c20
-rw-r--r--src/backend/optimizer/path/equivclass.c12
-rw-r--r--src/backend/optimizer/plan/createplan.c2
3 files changed, 25 insertions, 9 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 715f44675f8..59b72339163 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -635,10 +635,15 @@ set_append_rel_pathlist(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)
@@ -650,6 +655,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);
}
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 2a3826cfa5e..d89feb34b32 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1850,16 +1850,20 @@ add_child_rel_equivalences(PlannerInfo *root,
if (cur_ec->ec_has_volatile)
continue;
- /* No point in searching if parent rel not mentioned in eclass */
- if (!bms_is_subset(parent_rel->relids, cur_ec->ec_relids))
+ /*
+ * No point in searching if parent rel not mentioned in eclass; but
+ * we can't tell that for sure if parent rel is itself a child.
+ */
+ if (parent_rel->reloptkind == RELOPT_BASEREL &&
+ !bms_is_subset(parent_rel->relids, cur_ec->ec_relids))
continue;
foreach(lc2, cur_ec->ec_members)
{
EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
- if (cur_em->em_is_child)
- continue; /* ignore children here */
+ if (cur_em->em_is_const)
+ continue; /* ignore consts here */
/* Does it reference (only) parent_rel? */
if (bms_equal(cur_em->em_relids, parent_rel->relids))
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index c246468c929..682217d1503 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -700,7 +700,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
/* Compute sort column info, and adjust MergeAppend's tlist as needed */
(void) prepare_sort_from_pathkeys(root, plan, pathkeys,
- NULL,
+ best_path->path.parent->relids,
NULL,
true,
&node->numCols,