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

Reply via email to