diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 2119db4..41a7067 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2826,52 +2826,24 @@ CopyFrom(CopyState cstate)
 	/*
 	 * It's generally more efficient to prepare a bunch of tuples for
 	 * insertion, and insert them in bulk, for example, with one
-	 * table_multi_insert() call than call table_tuple_insert() separately
-	 * for every tuple. However, there are a number of reasons why we might
-	 * not be able to do this.  We check some conditions below while some
-	 * other target relation properties are checked in InitResultRelInfo().
-	 * Partition initialization will use result of this check implicitly as
-	 * the ri_usesMultiInsert value of the parent relation.
+	 * table_multi_insert() call than call table_tuple_insert() separately for
+	 * every tuple. However, there are a number of reasons why we might not be
+	 * able to do this.  For example, if there any volatile expressions in the
+	 * table's default values or in the statement's WHERE clause, which may
+	 * query the table we are inserting into, buffering tuples might produce
+	 * wrong results.  Also, the relation we are trying to insert into itself
+	 * may not be amenable to buffered inserts.
+	 *
+	 * Note: For partitions, this flag is set considering the target table's
+	 * flag that is being set here and partition's own properties which are
+	 * checked by calling ExecRelationAllowsMultiInsert().  It does not matter
+	 * whether partitions have any volatile default expressions as we use the
+	 * defaults from the target of the COPY command.
 	 */
-	if (!checkMultiInsertMode(target_resultRelInfo, NULL))
-	{
-		/*
-		 * Do nothing. Can't allow multi-insert mode if previous conditions
-		 * checking disallow this.
-		 */
-	}
-	else if (cstate->volatile_defexprs || list_length(cstate->attnumlist) == 0)
-	{
-		/*
-		 * Can't support bufferization of copy into foreign tables without any
-		 * defined columns or if there are any volatile default expressions in the
-		 * table. Similarly to the trigger case above, such expressions may query
-		 * the table we're inserting into.
-		 *
-		 * Note: It does not matter if any partitions have any volatile
-		 * default expressions as we use the defaults from the target of the
-		 * COPY command.
-		 */
-	}
-	else if (contain_volatile_functions(cstate->whereClause))
-	{
-		/*
-		 * Can't support multi-inserts if there are any volatile function
-		 * expressions in WHERE clause.  Similarly to the trigger case above,
-		 * such expressions may query the table we're inserting into.
-		 */
-	}
-	else
-	{
-		/*
-		 * Looks okay to try multi-insert.
-		 *
-		 * For partitioned tables, whether or not to use multi-insert depends
-		 * on the individual parition's properties which are also checked in
-		 * InitResultRelInfo().
-		 */
+	if (!cstate->volatile_defexprs &&
+		!contain_volatile_functions(cstate->whereClause) &&
+		ExecRelationAllowsMultiInsert(target_resultRelInfo, NULL))
 		target_resultRelInfo->ri_usesMultiInsert = true;
-	}
 
 	/* Verify the named relation is a valid target for INSERT */
 	CheckValidResultRel(resultRelInfo, CMD_INSERT);
@@ -2898,10 +2870,10 @@ CopyFrom(CopyState cstate)
 	 * Init COPY into foreign table. Initialization of copying into foreign
 	 * partitions will be done later.
 	 */
-	if (target_resultRelInfo->ri_FdwRoutine != NULL &&
-		target_resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
-		target_resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
-																resultRelInfo);
+	if (resultRelInfo->ri_FdwRoutine != NULL &&
+		resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)
+		resultRelInfo->ri_FdwRoutine->BeginForeignInsert(mtstate,
+														 resultRelInfo);
 
 	/* Prepare to catch AFTER triggers. */
 	AfterTriggerBeginQuery();
@@ -3302,7 +3274,7 @@ CopyFrom(CopyState cstate)
 	if (target_resultRelInfo->ri_FdwRoutine != NULL &&
 		target_resultRelInfo->ri_FdwRoutine->EndForeignInsert != NULL)
 		target_resultRelInfo->ri_FdwRoutine->EndForeignInsert(estate,
-														target_resultRelInfo);
+															  target_resultRelInfo);
 
 	/* Tear down the multi-insert buffer data */
 	CopyMultiInsertInfoCleanup(&multiInsertInfo);
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 12ee7f2..4999474 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1351,6 +1351,55 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
 }
 
 /*
+ * ExecRelationAllowsMultiInsert
+ *		Does this relation allow caller to use multi-insert mode when
+ *		inserting rows into it?
+ */
+bool
+ExecRelationAllowsMultiInsert(const ResultRelInfo *rri,
+							  const ResultRelInfo *partition_root)
+{
+	Assert(rri->ri_usesMultiInsert == false);
+
+	/*
+	 * If a partition's root parent isn't allowed to use it, neither is the
+	 * partition.
+	 */
+	if (partition_root && !partition_root->ri_usesMultiInsert)
+		return false;
+
+	/*
+	 * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
+	 * triggers on the table. Such triggers might query the table we're
+	 * inserting into and act differently if the tuples that have already
+	 * been processed and prepared for insertion are not there.
+	 */
+	if (rri->ri_TrigDesc != NULL &&
+		(rri->ri_TrigDesc->trig_insert_before_row ||
+		 rri->ri_TrigDesc->trig_insert_instead_row))
+		return false;
+
+	/*
+	 * For partitioned tables we can't support multi-inserts when there are
+	 * any statement level insert triggers. It might be possible to allow
+	 * partitioned tables with such triggers in the future, but for now,
+	 * CopyMultiInsertInfoFlush expects that any before row insert and
+	 * statement level insert triggers are on the same relation.
+	 */
+	if (rri->ri_RelationDesc->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
+		rri->ri_TrigDesc != NULL &&
+		rri->ri_TrigDesc->trig_insert_new_table)
+		return false;
+
+	/* Foreign tables don't support multi-inserts. */
+	if (rri->ri_FdwRoutine != NULL)
+		return false;
+
+	/* OK, caller can use multi-insert on this relation. */
+	return true;
+}
+
+/*
  * ExecGetTriggerResultRel
  *		Get a ResultRelInfo for a trigger target relation.
  *
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index baaa0f6..d752fe3 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -548,46 +548,6 @@ ExecHashSubPlanResultRelsByOid(ModifyTableState *mtstate,
 	}
 }
 
-bool
-checkMultiInsertMode(const ResultRelInfo *rri, const ResultRelInfo *parent)
-{
-	Assert(rri->ri_usesMultiInsert == false);
-
-	if (parent && !parent->ri_usesMultiInsert)
-		return false;
-
-	/* Check if the relation allows to use "multi-insert" mode. */
-	if (rri->ri_TrigDesc != NULL &&
-		(rri->ri_TrigDesc->trig_insert_before_row ||
-		 rri->ri_TrigDesc->trig_insert_instead_row))
-		/*
-		 * Can't support multi-inserts when there are any BEFORE/INSTEAD OF
-		 * triggers on the table. Such triggers might query the table we're
-		 * inserting into and act differently if the tuples that have already
-		 * been processed and prepared for insertion are not there.
-		 */
-		return false;
-
-	if (rri->ri_RelationDesc->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
-		rri->ri_TrigDesc != NULL &&
-		rri->ri_TrigDesc->trig_insert_new_table)
-		/*
-		 * For partitioned tables we can't support multi-inserts when there
-		 * are any statement level insert triggers. It might be possible to
-		 * allow partitioned tables with such triggers in the future, but for
-		 * now, CopyMultiInsertInfoFlush expects that any before row insert
-		 * and statement level insert triggers are on the same relation.
-		 */
-		return false;
-
-	if (rri->ri_FdwRoutine != NULL)
-		/* Foreign tables don't support multi-inserts. */
-		return false;
-
-	/* OK, caller can use multi-insert on this relation. */
-	return true;
-}
-
 /*
  * ExecInitPartitionInfo
  *		Lock the partition and initialize ResultRelInfo.  Also setup other
@@ -628,7 +588,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
 	 * parent and its child.
 	 */
 	leaf_part_rri->ri_usesMultiInsert =
-						checkMultiInsertMode(leaf_part_rri, rootResultRelInfo);
+		ExecRelationAllowsMultiInsert(leaf_part_rri, rootResultRelInfo);
 
 	/*
 	 * Verify result relation is a valid target for an INSERT.  An UPDATE of a
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 415e117..1146685 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -190,6 +190,8 @@ extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
 							  Index resultRelationIndex,
 							  Relation partition_root,
 							  int instrument_options);
+extern bool ExecRelationAllowsMultiInsert(const ResultRelInfo *rri,
+							  const ResultRelInfo *partition_root);
 extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
 extern void ExecCleanUpTriggerState(EState *estate);
 extern void ExecConstraints(ResultRelInfo *resultRelInfo,
