diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 3cda8ac481..cf9e589872 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -1942,94 +1942,64 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo)
 			/*
 			 * Initialize the subplan_map and subpart_map.
 			 *
-			 * Because we request detached partitions to be included, and
-			 * detaching waits for old transactions, it is safe to assume that
-			 * no partitions have disappeared since this query was planned.
+			 * The set of partitions that exist now might not be the same that
+			 * existed when the plan was made.  The normal case is that it is;
+			 * optimize for that case with a quick comparison, and just copy
+			 * the subplan_map and make subpart_map point to the one in
+			 * PruneInfo.
 			 *
-			 * However, new partitions may have been added.
+			 * For the case where they aren't identical, we could have more
+			 * partitions on either side; or even exactly the same number of
+			 * them on both but the set of OIDs doesn't match fully.  Handle
+			 * this by creating new subplan_map and subpart_map arrays that
+			 * corresponds to the ones in the PruneInfo where the new
+			 * partition descriptor's OIDs match.  Any that don't match can be
+			 * set to -1, as if they were pruned.  Both arrays must be in
+			 * numerical OID order.
 			 */
-			Assert(partdesc->nparts >= pinfo->nparts);
 			pprune->nparts = partdesc->nparts;
 			pprune->subplan_map = palloc(sizeof(int) * partdesc->nparts);
-			if (partdesc->nparts == pinfo->nparts)
+
+			if (partdesc->nparts == pinfo->nparts &&
+				memcmp(partdesc->oids, pinfo->relid_map,
+					   sizeof(int) * partdesc->nparts) == 0)
 			{
-				/*
-				 * There are no new partitions, so this is simple.  We can
-				 * simply point to the subpart_map from the plan, but we must
-				 * copy the subplan_map since we may change it later.
-				 */
 				pprune->subpart_map = pinfo->subpart_map;
 				memcpy(pprune->subplan_map, pinfo->subplan_map,
 					   sizeof(int) * pinfo->nparts);
-
-				/*
-				 * Double-check that the list of unpruned relations has not
-				 * changed.  (Pruned partitions are not in relid_map[].)
-				 */
-#ifdef USE_ASSERT_CHECKING
-				for (int k = 0; k < pinfo->nparts; k++)
-				{
-					Assert(partdesc->oids[k] == pinfo->relid_map[k] ||
-						   pinfo->subplan_map[k] == -1);
-				}
-#endif
 			}
 			else
 			{
 				int			pd_idx = 0;
-				int			pp_idx;
 
 				/*
-				 * Some new partitions have appeared since plan time, and
-				 * those are reflected in our PartitionDesc but were not
-				 * present in the one used to construct subplan_map and
-				 * subpart_map.  So we must construct new and longer arrays
-				 * where the partitions that were originally present map to
-				 * the same sub-structures, and any added partitions map to
-				 * -1, as if the new partitions had been pruned.
-				 *
-				 * Note: pinfo->relid_map[] may contain InvalidOid entries for
-				 * partitions pruned by the planner.  We cannot tell exactly
-				 * which of the partdesc entries these correspond to, but we
-				 * don't have to; just skip over them.  The non-pruned
-				 * relid_map entries, however, had better be a subset of the
-				 * partdesc entries and in the same order.
+				 * If the number of partitions on both sides is the same, it's
+				 * possible that a partition has been detached and another
+				 * attached.  Cope with that by creating a map that skips any
+				 * partitions that don't match.
 				 */
 				pprune->subpart_map = palloc(sizeof(int) * partdesc->nparts);
-				for (pp_idx = 0; pp_idx < partdesc->nparts; pp_idx++)
-				{
-					/* Skip any InvalidOid relid_map entries */
-					while (pd_idx < pinfo->nparts &&
-						   !OidIsValid(pinfo->relid_map[pd_idx]))
-						pd_idx++;
 
-					if (pd_idx < pinfo->nparts &&
-						pinfo->relid_map[pd_idx] == partdesc->oids[pp_idx])
+				for (int pp_idx = 0; pp_idx < partdesc->nparts;)
+				{
+					if (partdesc->oids[pp_idx] == pinfo->relid_map[pd_idx])
+					{
+						pprune->subpart_map[pp_idx] = pinfo->subpart_map[pd_idx];
+						pprune->subplan_map[pp_idx] = pinfo->subplan_map[pd_idx];
+						pp_idx++;
+						pd_idx++;
+					}
+					else if (pinfo->relid_map[pd_idx] < partdesc->oids[pp_idx])
 					{
-						/* match... */
-						pprune->subplan_map[pp_idx] =
-							pinfo->subplan_map[pd_idx];
-						pprune->subpart_map[pp_idx] =
-							pinfo->subpart_map[pd_idx];
 						pd_idx++;
 					}
 					else
 					{
-						/* this partdesc entry is not in the plan */
-						pprune->subplan_map[pp_idx] = -1;
 						pprune->subpart_map[pp_idx] = -1;
+						pprune->subplan_map[pp_idx] = -1;
+						pp_idx++;
 					}
 				}
-
-				/*
-				 * It might seem that we need to skip any trailing InvalidOid
-				 * entries in pinfo->relid_map before checking that we scanned
-				 * all of the relid_map.  But we will have skipped them above,
-				 * because they must correspond to some partdesc->oids
-				 * entries; we just couldn't tell which.
-				 */
-				if (pd_idx != pinfo->nparts)
-					elog(ERROR, "could not match partition child tables to plan elements");
 			}
 
 			/* present_parts is also subject to later modification */
-- 
2.39.2
