From 8540a95c8013a07cd175bab7a8d971663a9a6d09 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Wed, 30 Sep 2015 18:35:40 -0400
Subject: [PATCH 01/14] Test code.

---
 src/backend/access/transam/parallel.c |  2 +
 src/backend/commands/explain.c        | 12 ++++-
 src/backend/optimizer/plan/planner.c  | 87 +++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 29d6ed5..3041dab 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -993,7 +993,9 @@ ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc)
 static void
 ParallelErrorContext(void *arg)
 {
+#if 0
 	errcontext("parallel worker, pid %d", *(int32 *) arg);
+#endif
 }
 
 /*
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7fb8a14..8612430 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -571,6 +571,7 @@ void
 ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
 {
 	Bitmapset  *rels_used = NULL;
+	PlanState *ps;
 
 	Assert(queryDesc->plannedstmt != NULL);
 	es->pstmt = queryDesc->plannedstmt;
@@ -579,7 +580,16 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
 	es->rtable_names = select_rtable_names_for_explain(es->rtable, rels_used);
 	es->deparse_cxt = deparse_context_for_plan_rtable(es->rtable,
 													  es->rtable_names);
-	ExplainNode(queryDesc->planstate, NIL, NULL, NULL, es);
+	/*
+	 * XXX.  Just for testing purposes, suppress the display of a toplevel
+	 * gather node, so that we can run the regression tests with Gather
+	 * nodes forcibly inserted without getting test failures due to different
+	 * EXPLAIN output.
+	 */
+	ps = queryDesc->planstate;
+	if (IsA(ps, GatherState))
+		ps = outerPlanState(ps);
+	ExplainNode(ps, NIL, NULL, NULL, es);
 }
 
 /*
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index e1ee67c..76ad8b3 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -47,6 +47,7 @@
 #include "storage/dsm_impl.h"
 #include "utils/rel.h"
 #include "utils/selfuncs.h"
+#include "utils/syscache.h"
 
 
 /* GUC parameter */
@@ -160,6 +161,40 @@ planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	return result;
 }
 
+/* This code is crap, just for testing.  Don't confuse it with good code. */
+static bool
+rte_check_safety(RangeTblEntry *rte)
+{
+	HeapTuple tp;
+	Form_pg_class reltup;
+	bool retval;
+	ListCell *lc;
+
+	switch (rte->rtekind)
+	{
+		case RTE_RELATION:
+			tp = SearchSysCache1(RELOID, ObjectIdGetDatum(rte->relid));
+			if (!HeapTupleIsValid(tp))
+				elog(ERROR, "cache lookup failed for relation %u",
+					 rte->relid);
+			reltup = (Form_pg_class) GETSTRUCT(tp);
+			retval = (reltup->relpersistence != RELPERSISTENCE_TEMP);
+			ReleaseSysCache(tp);
+			return retval;
+
+		case RTE_SUBQUERY:
+			foreach (lc, rte->subquery->rtable)
+			{
+				RangeTblEntry *rte2 = lfirst(lc);
+				if (!rte_check_safety(rte2))
+					return false;
+			}
+
+		default:
+			return true;
+	}
+}
+
 PlannedStmt *
 standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 {
@@ -284,6 +319,58 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 			top_plan = materialize_finished_plan(top_plan);
 	}
 
+	/* XXX: Force a gather plan for testing purposes. */
+	if (glob->parallelModeOK)
+	{
+		bool		use_gather = true;
+
+		/* We don't copy subplans to workers. */
+		if (glob->subplans != NIL)
+			use_gather = false;
+
+		/* Parallel mode doesn't currently support temporary tables. */
+		if (use_gather)
+		{
+			ListCell   *lc;
+			ListCell   *l;
+
+			foreach(lc, root->parse->rtable)
+			{
+				RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
+				if (!rte_check_safety(rte))
+					use_gather = false;
+			}
+
+			foreach(l, glob->subroots)
+			{
+				PlannerInfo *subroot = (PlannerInfo *) lfirst(l);
+
+				foreach(lc, subroot->parse->rtable)
+				{
+					RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
+
+					if (!rte_check_safety(rte))
+						use_gather = false;
+				}
+			}
+		}
+
+		/* No disqualifying conditions?  Then do it! */
+		if (use_gather)
+		{
+			Gather	   *gather = makeNode(Gather);
+
+			gather->plan.targetlist = top_plan->targetlist;
+			gather->plan.qual = NIL;
+			gather->plan.lefttree = top_plan;
+			gather->plan.righttree = NULL;
+			gather->num_workers = 1;
+			gather->single_copy = true;
+			root->glob->parallelModeNeeded = true;
+			top_plan = &gather->plan;
+		}
+	}
+
 	/*
 	 * If any Params were generated, run through the plan tree and compute
 	 * each plan node's extParam/allParam sets.  Ideally we'd merge this into
-- 
2.3.8 (Apple Git-58)

