diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 53c43db011..ab0fa77ec4 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -98,6 +98,8 @@ typedef struct
 	char		max_hazard;		/* worst proparallel hazard found so far */
 	char		max_interesting;	/* worst proparallel hazard of interest */
 	List	   *safe_param_ids; /* PARAM_EXEC Param IDs to treat as safe */
+	RangeTblEntry *targetRTE;	/* query's target relation if any */
+	CmdType		commandType;
 } max_parallel_hazard_context;
 
 static bool contain_agg_clause_walker(Node *node, void *context);
@@ -108,6 +110,15 @@ static bool contain_volatile_functions_walker(Node *node, void *context);
 static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context);
 static bool max_parallel_hazard_walker(Node *node,
 									   max_parallel_hazard_context *context);
+static bool target_rel_max_parallel_hazard(max_parallel_hazard_context *context);
+static bool target_rel_max_parallel_hazard_recurse(Relation relation,
+									   CmdType command_type,
+									   max_parallel_hazard_context *context);
+static bool target_rel_trigger_max_parallel_hazard(TriggerDesc *trigdesc,
+									   max_parallel_hazard_context *context);
+static bool target_rel_index_expr_max_parallel_hazard(Relation rel,
+										  max_parallel_hazard_context *context);
+static bool target_rel_domain_max_parallel_hazard(Oid typid, max_parallel_hazard_context *context);
 static bool contain_nonstrict_functions_walker(Node *node, void *context);
 static bool contain_exec_param_walker(Node *node, List *param_ids);
 static bool contain_context_dependent_node(Node *clause);
@@ -158,15 +169,6 @@ static Query *substitute_actual_srf_parameters(Query *expr,
 static Node *substitute_actual_srf_parameters_mutator(Node *node,
 													  substitute_actual_srf_parameters_context *context);
 
-static bool trigger_max_parallel_hazard_for_modify(TriggerDesc *trigdesc,
-												   max_parallel_hazard_context *context);
-static bool index_expr_max_parallel_hazard_for_modify(Relation rel,
-													  max_parallel_hazard_context *context);
-static bool domain_max_parallel_hazard_for_modify(Oid typid, max_parallel_hazard_context *context);
-static bool rel_max_parallel_hazard_for_modify(Relation rel,
-											   CmdType command_type,
-											   max_parallel_hazard_context *context);
-
 /*****************************************************************************
  *		Aggregate-function clause manipulation
  *****************************************************************************/
@@ -570,19 +572,11 @@ max_parallel_hazard(Query *parse)
 	context.max_hazard = PROPARALLEL_SAFE;
 	context.max_interesting = PROPARALLEL_UNSAFE;
 	context.safe_param_ids = NIL;
+	context.targetRTE = parse->resultRelation > 0 ?
+			rt_fetch(parse->resultRelation, parse->rtable) : NULL;
+	context.commandType = parse->commandType;
 	(void) max_parallel_hazard_walker((Node *) parse, &context);
 
-	/*
-	 * Additional parallel-mode safety checks are required in order to
-	 * allow an underlying parallel query to be used for a
-	 * table-modification command that is supported in parallel-mode.
-	 */
-
-	if (context.max_hazard != PROPARALLEL_UNSAFE &&
-		IsModifySupportedInParallelMode(parse->commandType))
-	{
-		context.max_hazard = max_parallel_hazard_for_modify(parse, context.max_hazard);
-	}
 	return context.max_hazard;
 }
 
@@ -787,6 +781,19 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
 		}
 		return false;			/* nothing to recurse to */
 	}
+	else if (IsA(node, RangeTblEntry))
+	{
+		RangeTblEntry *rte = (RangeTblEntry *) node;
+
+		/* Nothing interesting to check for SELECTs */
+		if (context->targetRTE == NULL)
+			return false;
+
+		if (rte == context->targetRTE)
+			return target_rel_max_parallel_hazard(context);
+
+		return false;
+	}
 
 	/*
 	 * When we're first invoked on a completely unplanned tree, we must
@@ -804,10 +811,28 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
 			return true;
 		}
 
+		/*
+		 * UPDATE is not currently supported in parallel-mode, so prohibit
+		 * INSERT...ON CONFLICT...DO UPDATE...
+		 * In order to support update, even if only in the leader, some
+		 * further work would need to be done. A mechanism would be needed
+		 * for sharing combo-cids between leader and workers during
+		 * parallel-mode, since for example, the leader might generate a
+		 * combo-cid and it needs to be propagated to the workers.
+		 */
+		if (query->onConflict != NULL &&
+			query->onConflict->action == ONCONFLICT_UPDATE)
+		{
+			context->max_hazard = PROPARALLEL_UNSAFE;
+			return true;
+		}
+
 		/* Recurse into subselects */
 		return query_tree_walker(query,
 								 max_parallel_hazard_walker,
-								 context, 0);
+								 context,
+								 context->targetRTE != NULL ?
+								 QTW_EXAMINE_RTES_BEFORE: 0);
 	}
 
 	/* Recurse to check arguments */
@@ -817,12 +842,12 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
 }
 
 /*
- * trigger_max_parallel_hazard_for_modify
+ * target_rel_trigger_max_parallel_hazard
  *
  * Finds the maximum parallel-mode hazard level for the specified trigger data.
  */
 static bool
-trigger_max_parallel_hazard_for_modify(TriggerDesc *trigdesc,
+target_rel_trigger_max_parallel_hazard(TriggerDesc *trigdesc,
 									   max_parallel_hazard_context *context)
 {
 	int			i;
@@ -853,13 +878,13 @@ trigger_max_parallel_hazard_for_modify(TriggerDesc *trigdesc,
 }
 
 /*
- * index_expr_max_parallel_hazard_for_modify
+ * target_rel_index_expr_max_parallel_hazard
  *
  * Finds the maximum parallel-mode hazard level for any existing index
  * expressions of a specified relation.
  */
 static bool
-index_expr_max_parallel_hazard_for_modify(Relation rel,
+target_rel_index_expr_max_parallel_hazard(Relation rel,
 										  max_parallel_hazard_context *context)
 {
 	List		*index_oid_list;
@@ -924,7 +949,7 @@ index_expr_max_parallel_hazard_for_modify(Relation rel,
 }
 
 /*
- * domain_max_parallel_hazard_for_modify
+ * target_rel_domain_max_parallel_hazard
  *
  * Finds the maximum parallel-mode hazard level for the specified DOMAIN type.
  * Only any CHECK expressions are examined for parallel safety.
@@ -934,7 +959,7 @@ index_expr_max_parallel_hazard_for_modify(Relation rel,
  *
  */
 static bool
-domain_max_parallel_hazard_for_modify(Oid typid, max_parallel_hazard_context *context)
+target_rel_domain_max_parallel_hazard(Oid typid, max_parallel_hazard_context *context)
 {
 	Relation	con_rel;
 	ScanKeyData key[1];
@@ -994,15 +1019,31 @@ domain_max_parallel_hazard_for_modify(Oid typid, max_parallel_hazard_context *co
 }
 
 /*
- * rel_max_parallel_hazard_for_modify
+ * target_rel_max_parallel_hazard
  *
  * Determines the maximum parallel-mode hazard level for modification
  * of a specified relation.
  */
 static bool
-rel_max_parallel_hazard_for_modify(Relation rel,
-								   CmdType command_type,
-								   max_parallel_hazard_context *context)
+target_rel_max_parallel_hazard(max_parallel_hazard_context *context)
+{
+	Relation	targetRel = table_open(context->targetRTE->relid,
+									   context->targetRTE->rellockmode);
+	bool	max_hazard_found;
+
+	max_hazard_found = target_rel_max_parallel_hazard_recurse(targetRel,
+															  context->commandType,
+															  context);
+
+	table_close(targetRel, NoLock);
+
+	return max_hazard_found;
+}
+
+static bool
+target_rel_max_parallel_hazard_recurse(Relation rel,
+									   CmdType command_type,
+									   max_parallel_hazard_context *context)
 {
 	TupleDesc	tupdesc;
 	int			attnum;
@@ -1076,9 +1117,9 @@ rel_max_parallel_hazard_for_modify(Relation rel,
 			Relation	part_rel;
 
 			part_rel = table_open(pdesc->oids[i], AccessShareLock);
-			max_hazard_found = rel_max_parallel_hazard_for_modify(part_rel,
-														command_type,
-														context);
+			max_hazard_found = target_rel_max_parallel_hazard_recurse(part_rel,
+																	  command_type,
+																	  context);
 			table_close(part_rel, AccessShareLock);
 			if (max_hazard_found)
 			{
@@ -1091,7 +1132,7 @@ rel_max_parallel_hazard_for_modify(Relation rel,
 	 * If there are any index expressions, check that they are parallel-mode
 	 * safe.
 	 */
-	if (index_expr_max_parallel_hazard_for_modify(rel, context))
+	if (target_rel_index_expr_max_parallel_hazard(rel, context))
 	{
 		return true;
 	}
@@ -1101,7 +1142,7 @@ rel_max_parallel_hazard_for_modify(Relation rel,
 	 */
 	if (rel->trigdesc != NULL)
 	{
-		if (trigger_max_parallel_hazard_for_modify(rel->trigdesc, context))
+		if (target_rel_trigger_max_parallel_hazard(rel->trigdesc, context))
 		{
 			return true;
 		}
@@ -1136,7 +1177,7 @@ rel_max_parallel_hazard_for_modify(Relation rel,
 			 */
 			if (get_typtype(att->atttypid) == TYPTYPE_DOMAIN)
 			{
-				if (domain_max_parallel_hazard_for_modify(att->atttypid, context))
+				if (target_rel_domain_max_parallel_hazard(att->atttypid, context))
 				{
 					return true;
 				}
@@ -1168,77 +1209,6 @@ rel_max_parallel_hazard_for_modify(Relation rel,
 	return false;
 }
 
-/*
- * max_parallel_hazard_for_modify
- *
- * Determines the worst parallel-mode hazard level for the specified
- * table-modification statement, based on the statement attributes and
- * target table. An initial max parallel hazard level may optionally be
- * supplied. The search returns the earliest in the following list:
- * PROPARALLEL_UNSAFE, PROPARALLEL_RESTRICTED, PROPARALLEL_SAFE
- */
-char
-max_parallel_hazard_for_modify(Query *parse, char initial_max_parallel_hazard)
-{
-	RangeTblEntry *rte;
-	ListCell *lc;
-	bool hasSubQuery;
-	max_parallel_hazard_context context;
-	Relation rel;
-
-
-	/*
-	 * UPDATE is not currently supported in parallel-mode, so prohibit
-	 * INSERT...ON CONFLICT...DO UPDATE...
-	 * In order to support update, even if only in the leader, some
-	 * further work would need to be done. A mechanism would be needed
-	 * for sharing combo-cids between leader and workers during
-	 * parallel-mode, since for example, the leader might generate a
-	 * combo-cid and it needs to be propagated to the workers.
-	 */
-	if (parse->onConflict != NULL && parse->onConflict->action == ONCONFLICT_UPDATE)
-		return PROPARALLEL_UNSAFE;
-
-	/*
-	 * If there is no underlying SELECT, a parallel table-modification
-	 * operation is not possible (nor desirable).
-	 */
-	hasSubQuery = false;
-	foreach(lc, parse->rtable)
-	{
-		rte = lfirst_node(RangeTblEntry, lc);
-		if (rte->rtekind == RTE_SUBQUERY)
-		{
-			hasSubQuery = true;
-			break;
-		}
-	}
-	if (!hasSubQuery)
-		return PROPARALLEL_UNSAFE;
-
-	/*
-	 * Setup the context used in finding the max parallel-mode hazard.
-	 */
-	Assert(initial_max_parallel_hazard == 0 ||
-		   initial_max_parallel_hazard == PROPARALLEL_SAFE ||
-		   initial_max_parallel_hazard == PROPARALLEL_RESTRICTED);
-	context.max_hazard = initial_max_parallel_hazard == 0 ?
-		PROPARALLEL_SAFE : initial_max_parallel_hazard;
-	context.max_interesting = PROPARALLEL_UNSAFE;
-	context.safe_param_ids = NIL;
-
-	rte = rt_fetch(parse->resultRelation, parse->rtable);
-
-	/*
-	 * The target table is already locked by the caller (this is done in the
-	 * parse/analyze phase).
-	 */
-	rel = table_open(rte->relid, NoLock);
-	(void) rel_max_parallel_hazard_for_modify(rel, parse->commandType, &context);
-	table_close(rel, NoLock);
-	return context.max_hazard;
-}
-
 /*****************************************************************************
  *		Check clauses for nonstrict functions
  *****************************************************************************/
