Sorry about the delay in replying. On 2016/09/15 21:58, Ashutosh Bapat wrote: > Hi Amit, > > It looks like there is some problem while creating paramterized paths > for multi-level partitioned tables. Here's a longish testcase > > [ ... ] > > Please check if you are able to reproduce these errors in your > repository. I made sure that I cleaned up all partition-wise join code > before testing this, but ... .
Thanks for the test case. I can reproduce the same. > I tried to debug the problem somewhat. In set_append_rel_pathlist(), > it finds that at least one child has a parameterized path as the > cheapest path, so it doesn't create an unparameterized path for append > rel. At the same time there is a parameterization common to all the > children, so it doesn't create any path. There seem to be two problems > here > 1. The children from second level onwards may not be getting > parameterized for lateral references. That seems unlikely but > possible. > 2. Reparameterization should have corrected this, but > reparameterize_path() does not support AppendPaths. Hmm, 0005-Refactor-optimizer-s-inheritance-set-expansion-code-5.patch is certainly to be blamed here; if I revert the patch, the problem goes away. Based on 2 above, I attempted to add logic for AppendPath in reparameterize_path() as in the attached. It fixes the reported problem and does not break any regression tests. If it's sane to do things this way, I will incorporate the attached into patch 0005 mentioned above. Thoughts? Thanks, Amit
commit 86c8fc2c268d17fb598bf6879cfef2b2a2f42417 Author: amit <amitlangot...@gmail.com> Date: Tue Sep 27 16:02:54 2016 +0900 Handle AppendPath in reparameterize_path(). diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 2a49639..750f0ea 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -1570,6 +1570,40 @@ cost_sort(Path *path, PlannerInfo *root, } /* + * cost_append + * Determines and returns the cost of a Append node + * + * Compute rows and costs as sums of subplan rows and costs. We charge + * nothing extra for the Append itself, which perhaps is too optimistic, + * but since it doesn't do any selection or projection, it is a pretty + * cheap node. + */ +void +cost_append(AppendPath *apath, Relids required_outer) +{ + ListCell *l; + + apath->path.rows = 0; + apath->path.startup_cost = 0; + apath->path.total_cost = 0; + foreach(l, apath->subpaths) + { + Path *subpath = (Path *) lfirst(l); + + apath->path.rows += subpath->rows; + + if (l == list_head(apath->subpaths)) /* first node? */ + apath->path.startup_cost = subpath->startup_cost; + apath->path.total_cost += subpath->total_cost; + apath->path.parallel_safe = apath->path.parallel_safe && + subpath->parallel_safe; + + /* All child paths must have same parameterization */ + Assert(bms_equal(PATH_REQ_OUTER(subpath), required_outer)); + } +} + +/* * cost_merge_append * Determines and returns the cost of a MergeAppend node. * diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index abb7507..bf8fb55 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -1206,7 +1206,6 @@ create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer, int parallel_workers) { AppendPath *pathnode = makeNode(AppendPath); - ListCell *l; pathnode->path.pathtype = T_Append; pathnode->path.parent = rel; @@ -1220,32 +1219,7 @@ create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer, * unsorted */ pathnode->subpaths = subpaths; - /* - * We don't bother with inventing a cost_append(), but just do it here. - * - * Compute rows and costs as sums of subplan rows and costs. We charge - * nothing extra for the Append itself, which perhaps is too optimistic, - * but since it doesn't do any selection or projection, it is a pretty - * cheap node. - */ - pathnode->path.rows = 0; - pathnode->path.startup_cost = 0; - pathnode->path.total_cost = 0; - foreach(l, subpaths) - { - Path *subpath = (Path *) lfirst(l); - - pathnode->path.rows += subpath->rows; - - if (l == list_head(subpaths)) /* first node? */ - pathnode->path.startup_cost = subpath->startup_cost; - pathnode->path.total_cost += subpath->total_cost; - pathnode->path.parallel_safe = pathnode->path.parallel_safe && - subpath->parallel_safe; - - /* All child paths must have same parameterization */ - Assert(bms_equal(PATH_REQ_OUTER(subpath), required_outer)); - } + cost_append(pathnode, required_outer); return pathnode; } @@ -3204,6 +3178,41 @@ reparameterize_path(PlannerInfo *root, Path *path, spath->path.pathkeys, required_outer); } + case T_Append: + { + AppendPath *apath = (AppendPath *) path; + AppendPath *newpath; + List *new_subpaths = NIL; + ListCell *lc; + + foreach(lc, apath->subpaths) + { + Path *subpath = lfirst(lc); + Path *new_subpath; + + new_subpath = reparameterize_path(root, subpath, + required_outer, + loop_count); + if (new_subpath) + new_subpaths = lappend(new_subpaths, new_subpath); + else + return NULL; + } + + /* + * Like IndexPath, we flat-copy the path node, and revise + * its param_info, and redo the cost estimate (costs of + * subpaths may have changed due to parameterization). + */ + newpath = makeNode(AppendPath); + memcpy(newpath, apath, sizeof(AppendPath)); + newpath->path.param_info = + get_appendrel_parampathinfo(rel, required_outer); + newpath->subpaths = new_subpaths; + cost_append(newpath, required_outer); + + return (Path *) newpath; + } default: break; } diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 2a4df2f..ec1d6f2 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -98,6 +98,7 @@ extern void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples); +extern void cost_append(AppendPath *apath, Relids required_outer); extern void cost_merge_append(Path *path, PlannerInfo *root, List *pathkeys, int n_streams, Cost input_startup_cost, Cost input_total_cost,
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers