diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 8b42e36b6d40cff9c75fa84d92dd44b8d7aa5f84..c97355e8fda8bacf5245f3e958b04d82e7f5621e 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -54,6 +54,9 @@ typedef struct pushdown_safety_info
 bool		enable_geqo = false;	/* just in case GUC doesn't set it */
 int			geqo_threshold;
 
+/* Hook for plugins to get control in set_rel_pathlist() */
+set_rel_pathlist_hook_type set_rel_pathlist_hook = NULL;
+
 /* Hook for plugins to replace standard_join_search() */
 join_search_hook_type join_search_hook = NULL;
 
@@ -355,6 +358,17 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
 		}
 	}
 
+	/*
+	 * Allow a plugin to editorialize on the set of Paths for this base
+	 * relation.  It could add new paths (such as CustomPaths) by calling
+	 * add_path(), or delete or modify paths added by the core code.
+	 */
+	if (set_rel_pathlist_hook)
+		(*set_rel_pathlist_hook) (root, rel, rti, rte);
+
+	/* Now find the cheapest of the paths for this rel */
+	set_cheapest(rel);
+
 #ifdef OPTIMIZER_DEBUG
 	debug_print_rel(root, rel);
 #endif
@@ -401,12 +415,6 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 
 	/* Consider TID scans */
 	create_tidscan_paths(root, rel);
-
-	/* Consider custom scans, if any */
-	create_customscan_paths(root, rel, rte);
-
-	/* Now find the cheapest of the paths for this rel */
-	set_cheapest(rel);
 }
 
 /*
@@ -432,9 +440,6 @@ set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 {
 	/* Call the FDW's GetForeignPaths function to generate path(s) */
 	rel->fdwroutine->GetForeignPaths(root, rel, rte->relid);
-
-	/* Select cheapest path */
-	set_cheapest(rel);
 }
 
 /*
@@ -857,9 +862,6 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
 			add_path(rel, (Path *)
 					 create_append_path(rel, subpaths, required_outer));
 	}
-
-	/* Select cheapest paths */
-	set_cheapest(rel);
 }
 
 /*
@@ -1087,7 +1089,12 @@ set_dummy_rel_pathlist(RelOptInfo *rel)
 
 	add_path(rel, (Path *) create_append_path(rel, NIL, NULL));
 
-	/* Select cheapest path (pretty easy in this case...) */
+	/*
+	 * We set the cheapest path immediately, to ensure that IS_DUMMY_REL()
+	 * will recognize the relation as dummy if anyone asks.  This is redundant
+	 * when we're called from set_rel_size(), but not when called from
+	 * elsewhere, and doing it twice is harmless anyway.
+	 */
 	set_cheapest(rel);
 }
 
@@ -1275,9 +1282,6 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
 
 	/* Generate appropriate path */
 	add_path(rel, create_subqueryscan_path(root, rel, pathkeys, required_outer));
-
-	/* Select cheapest path (pretty easy in this case...) */
-	set_cheapest(rel);
 }
 
 /*
@@ -1346,9 +1350,6 @@ set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 	/* Generate appropriate path */
 	add_path(rel, create_functionscan_path(root, rel,
 										   pathkeys, required_outer));
-
-	/* Select cheapest path (pretty easy in this case...) */
-	set_cheapest(rel);
 }
 
 /*
@@ -1369,9 +1370,6 @@ set_values_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 
 	/* Generate appropriate path */
 	add_path(rel, create_valuesscan_path(root, rel, required_outer));
-
-	/* Select cheapest path (pretty easy in this case...) */
-	set_cheapest(rel);
 }
 
 /*
@@ -1438,9 +1436,6 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 
 	/* Generate appropriate path */
 	add_path(rel, create_ctescan_path(root, rel, required_outer));
-
-	/* Select cheapest path (pretty easy in this case...) */
-	set_cheapest(rel);
 }
 
 /*
@@ -1491,9 +1486,6 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 
 	/* Generate appropriate path */
 	add_path(rel, create_worktablescan_path(root, rel, required_outer));
-
-	/* Select cheapest path (pretty easy in this case...) */
-	set_cheapest(rel);
 }
 
 /*
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 121b9ff3e450a2d651c996de80929c4c6430e13c..319e8b2c37968882cdc70d465e17f9042a572d40 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -27,7 +27,6 @@
 #include "optimizer/var.h"
 #include "parser/parsetree.h"
 #include "utils/lsyscache.h"
-#include "utils/memutils.h"
 #include "utils/selfuncs.h"
 
 
@@ -1927,50 +1926,3 @@ reparameterize_path(PlannerInfo *root, Path *path,
 	}
 	return NULL;
 }
-
-/*****************************************************************************
- *	   creation of custom-plan paths
- *****************************************************************************/
-
-static List *custom_path_providers = NIL;
-
-/*
- * register_custom_path_provider
- *
- * Register a table of callback functions which implements a custom-path
- * provider.  This allows extension to provide additional (hopefully faster)
- * methods of scanning a relation.
- */
-void
-register_custom_path_provider(const CustomPathMethods *cpp_methods)
-{
-	MemoryContext oldcxt;
-
-	oldcxt = MemoryContextSwitchTo(TopMemoryContext);
-	custom_path_providers = lappend(custom_path_providers,
-									(void *) cpp_methods);
-	MemoryContextSwitchTo(oldcxt);
-}
-
-/*
- * create_customscan_paths
- *
- * Invoke custom path provider callbacks.  If the callback determines that
- * the custom-path provider can handle this relation, it can add one or more
- * paths using add_path().
- */
-void
-create_customscan_paths(PlannerInfo *root,
-						RelOptInfo *baserel,
-						RangeTblEntry *rte)
-{
-	ListCell   *cell;
-
-	foreach(cell, custom_path_providers)
-	{
-		const CustomPathMethods *cpp_methods = lfirst(cell);
-
-		if (cpp_methods->CreateCustomScanPath)
-			cpp_methods->CreateCustomScanPath(root, baserel, rte);
-	}
-}
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 7953bf7ed6c808e4dc574fcbcebd1c1f0e5d5c0f..bd5e8ce5c13e203633e9eadce0a4e543e4a6272f 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -906,9 +906,6 @@ typedef struct CustomPathMethods
 {
 	const char *CustomName;
 
-	void		(*CreateCustomScanPath) (PlannerInfo *root,
-													 RelOptInfo *baserel,
-													 RangeTblEntry *rte);
 	struct Plan *(*PlanCustomPath) (PlannerInfo *root,
 												RelOptInfo *rel,
 												struct CustomPath *best_path,
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 0f2882986c0c36d980ccf5833939df9401b8d29d..26b17f5f7afcfcbcaa5c9b9aae4603b37128e2f3 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -128,15 +128,6 @@ extern Path *reparameterize_path(PlannerInfo *root, Path *path,
 					Relids required_outer,
 					double loop_count);
 
-/*
- * Interface definition of custom-scan providers
- */
-extern void register_custom_path_provider(const CustomPathMethods *cpp_methods);
-
-extern void create_customscan_paths(PlannerInfo *root,
-						RelOptInfo *baserel,
-						RangeTblEntry *rte);
-
 /*
  * prototypes for relnode.c
  */
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 9b22fda1ef49c91fd572bb5322ce8c9e07e6fb1c..afa5f9bcd0ecc8ce6d51854f0f22b3bc2d5d861d 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -23,6 +23,13 @@
 extern bool enable_geqo;
 extern int	geqo_threshold;
 
+/* Hook for plugins to get control in set_rel_pathlist() */
+typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
+														RelOptInfo *rel,
+														Index rti,
+														RangeTblEntry *rte);
+extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
+
 /* Hook for plugins to replace standard_join_search() */
 typedef RelOptInfo *(*join_search_hook_type) (PlannerInfo *root,
 														  int levels_needed,