From 30d1e78ce73e07c463b5c946b571ee964caeb3eb Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Tue, 15 Dec 2020 07:14:58 -0500
Subject: [PATCH 2/2] support pctas in append tuple cost adjustment

---
 src/backend/optimizer/path/allpaths.c | 29 +++++++++++++++++++++++++++++
 src/backend/optimizer/plan/planner.c  |  9 +++++++--
 src/include/commands/createas.h       |  3 ++-
 3 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 84a69b0..82f85b8 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -23,6 +23,7 @@
 #include "catalog/pg_class.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
+#include "commands/createas.h"
 #include "foreign/fdwapi.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
@@ -1104,10 +1105,38 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 			set_rel_consider_parallel(root, childrel, childRTE);
 
 		/*
+		 * When subplan is subquery, It's possible to do parallel insert
+		 * if top-node of subquery is Gather, so we set the flag to
+		 * ignore parallel tuple cost by the Gather path in cost_gather
+		 * if the SELECT is for CTAS.
+		 */ 
+		if(childrel->rtekind == RTE_SUBQUERY)
+		{
+			if((root->query_level == 1 ||
+				root->parent_root->parse->CTASParallelInsInfo &
+				CTAS_PARALLEL_INS_IGN_TUP_COST_APPEND)
+				&&
+				!(root->parse->rowMarks ||
+				limit_needed(root->parse) ||
+				root->parse->sortClause ||
+				root->parse->distinctClause ||
+				root->parse->hasWindowFuncs ||
+				root->parse->groupClause ||
+				root->parse->groupingSets ||
+				root->parse->hasAggs ||
+				root->hasHavingQual))
+				root->parse->CTASParallelInsInfo |=
+										CTAS_PARALLEL_INS_IGN_TUP_COST_APPEND;
+		}
+
+		/*
 		 * Compute the child's size.
 		 */
 		set_rel_size(root, childrel, childRTindex, childRTE);
 
+		if(root->parse->CTASParallelInsInfo & CTAS_PARALLEL_INS_IGN_TUP_COST_APPEND)
+			root->parse->CTASParallelInsInfo &= ~CTAS_PARALLEL_INS_IGN_TUP_COST_APPEND;
+
 		/*
 		 * It is possible that constraint exclusion detected a contradiction
 		 * within a child subquery, even though we didn't prove one above. If
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index d287b6b..86d42e1 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -7350,8 +7350,13 @@ can_partial_agg(PlannerInfo *root)
 static bool
 ignore_parallel_tuple_cost(PlannerInfo *root)
 {
-	if (root->query_level == 1 &&
-		(root->parse->CTASParallelInsInfo & CTAS_PARALLEL_INS_SELECT))
+	if(root->query_level != 1 &&
+	  (root->parent_root->parse->CTASParallelInsInfo & CTAS_PARALLEL_INS_IGN_TUP_COST_APPEND))
+	{
+		root->parse->CTASParallelInsInfo |= CTAS_PARALLEL_INS_SELECT;
+	}
+
+	if (root->parse->CTASParallelInsInfo & CTAS_PARALLEL_INS_SELECT)
 	{
 		/*
 		 * In each of following cases, a parent path will be generated for the
diff --git a/src/include/commands/createas.h b/src/include/commands/createas.h
index e01a615..7a50b18 100644
--- a/src/include/commands/createas.h
+++ b/src/include/commands/createas.h
@@ -54,7 +54,8 @@ typedef enum CTASParallelInsertOpt
 	 */
 	CTAS_PARALLEL_INS_TUP_COST_CAN_IGN = 1 << 1,
 
-	CTAS_PARALLEL_INS_TUP_COST_IGNORED = 1 << 2
+	CTAS_PARALLEL_INS_TUP_COST_IGNORED = 1 << 2,
+	CTAS_PARALLEL_INS_IGN_TUP_COST_APPEND = 1 << 3
 } CTASParallelInsertOpt;
 
 #define IS_CTAS(intoclause) (intoclause && IsA(intoclause, IntoClause))
-- 
1.8.3.1

