@@ -1291,6 +1291,12 @@ inheritance_planner(PlannerInfo *root)
12911291/* Result path must go into outer query's FINAL upperrel */
12921292final_rel = fetch_upper_rel (root ,UPPERREL_FINAL ,NULL );
12931293
1294+ /*
1295+ * We don't currently worry about setting final_rel's consider_parallel
1296+ * flag in this case, nor about allowing FDWs or create_upper_paths_hook
1297+ * to get control here.
1298+ */
1299+
12941300/*
12951301 * If we managed to exclude every child rel, return a dummy plan; it
12961302 * doesn't even need a ModifyTable node.
@@ -1788,21 +1794,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
17881794root -> upper_targets [UPPERREL_WINDOW ]= sort_input_target ;
17891795root -> upper_targets [UPPERREL_GROUP_AGG ]= grouping_target ;
17901796
1791- /*
1792- * If there is an FDW that's responsible for the final scan/join rel,
1793- * let it consider injecting extension Paths into the query's
1794- * upperrels, where they will compete with the Paths we create below.
1795- * We pass the final scan/join rel because that's not so easily
1796- * findable from the PlannerInfo struct; anything else the FDW wants
1797- * to know should be obtainable via "root".
1798- *
1799- * Note: CustomScan providers, as well as FDWs that don't want to use
1800- * this hook, can use the create_upper_paths_hook; see below.
1801- */
1802- if (current_rel -> fdwroutine &&
1803- current_rel -> fdwroutine -> GetForeignUpperPaths )
1804- current_rel -> fdwroutine -> GetForeignUpperPaths (root ,current_rel );
1805-
18061797/*
18071798 * If we have grouping and/or aggregation, consider ways to implement
18081799 * that. We build a new upperrel representing the output of this
@@ -1891,9 +1882,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
18911882}
18921883
18931884/*
1894- * Now we are prepared to build the final-output upperrel. Insert all
1895- * surviving paths, with LockRows, Limit, and/or ModifyTable steps added
1896- * if needed.
1885+ * Now we are prepared to build the final-output upperrel.
18971886 */
18981887final_rel = fetch_upper_rel (root ,UPPERREL_FINAL ,NULL );
18991888
@@ -1910,7 +1899,15 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
19101899final_rel -> consider_parallel = true;
19111900
19121901/*
1913- * Generate paths for the final rel.
1902+ * If the current_rel belongs to a single FDW, so does the final_rel.
1903+ */
1904+ final_rel -> serverid = current_rel -> serverid ;
1905+ final_rel -> umid = current_rel -> umid ;
1906+ final_rel -> fdwroutine = current_rel -> fdwroutine ;
1907+
1908+ /*
1909+ * Generate paths for the final_rel. Insert all surviving paths, with
1910+ * LockRows, Limit, and/or ModifyTable steps added if needed.
19141911 */
19151912foreach (lc ,current_rel -> pathlist )
19161913{
@@ -1994,6 +1991,15 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
19941991add_path (final_rel ,path );
19951992}
19961993
1994+ /*
1995+ * If there is an FDW that's responsible for all baserels of the query,
1996+ * let it consider adding ForeignPaths.
1997+ */
1998+ if (final_rel -> fdwroutine &&
1999+ final_rel -> fdwroutine -> GetForeignUpperPaths )
2000+ final_rel -> fdwroutine -> GetForeignUpperPaths (root ,UPPERREL_FINAL ,
2001+ current_rel ,final_rel );
2002+
19972003/* Let extensions possibly add some more paths */
19982004if (create_upper_paths_hook )
19992005(* create_upper_paths_hook ) (root ,UPPERREL_FINAL ,
@@ -3268,6 +3274,13 @@ create_grouping_paths(PlannerInfo *root,
32683274!has_parallel_hazard ((Node * )parse -> havingQual , false))
32693275grouped_rel -> consider_parallel = true;
32703276
3277+ /*
3278+ * If the input rel belongs to a single FDW, so does the grouped rel.
3279+ */
3280+ grouped_rel -> serverid = input_rel -> serverid ;
3281+ grouped_rel -> umid = input_rel -> umid ;
3282+ grouped_rel -> fdwroutine = input_rel -> fdwroutine ;
3283+
32713284/*
32723285 * Check for degenerate grouping.
32733286 */
@@ -3770,6 +3783,15 @@ create_grouping_paths(PlannerInfo *root,
37703783errmsg ("could not implement GROUP BY" ),
37713784errdetail ("Some of the datatypes only support hashing, while others only support sorting." )));
37723785
3786+ /*
3787+ * If there is an FDW that's responsible for all baserels of the query,
3788+ * let it consider adding ForeignPaths.
3789+ */
3790+ if (grouped_rel -> fdwroutine &&
3791+ grouped_rel -> fdwroutine -> GetForeignUpperPaths )
3792+ grouped_rel -> fdwroutine -> GetForeignUpperPaths (root ,UPPERREL_GROUP_AGG ,
3793+ input_rel ,grouped_rel );
3794+
37733795/* Let extensions possibly add some more paths */
37743796if (create_upper_paths_hook )
37753797(* create_upper_paths_hook ) (root ,UPPERREL_GROUP_AGG ,
@@ -3820,6 +3842,13 @@ create_window_paths(PlannerInfo *root,
38203842!has_parallel_hazard ((Node * )activeWindows , false))
38213843window_rel -> consider_parallel = true;
38223844
3845+ /*
3846+ * If the input rel belongs to a single FDW, so does the window rel.
3847+ */
3848+ window_rel -> serverid = input_rel -> serverid ;
3849+ window_rel -> umid = input_rel -> umid ;
3850+ window_rel -> fdwroutine = input_rel -> fdwroutine ;
3851+
38233852/*
38243853 * Consider computing window functions starting from the existing
38253854 * cheapest-total path (which will likely require a sort) as well as any
@@ -3841,6 +3870,15 @@ create_window_paths(PlannerInfo *root,
38413870activeWindows );
38423871}
38433872
3873+ /*
3874+ * If there is an FDW that's responsible for all baserels of the query,
3875+ * let it consider adding ForeignPaths.
3876+ */
3877+ if (window_rel -> fdwroutine &&
3878+ window_rel -> fdwroutine -> GetForeignUpperPaths )
3879+ window_rel -> fdwroutine -> GetForeignUpperPaths (root ,UPPERREL_WINDOW ,
3880+ input_rel ,window_rel );
3881+
38443882/* Let extensions possibly add some more paths */
38453883if (create_upper_paths_hook )
38463884(* create_upper_paths_hook ) (root ,UPPERREL_WINDOW ,
@@ -3984,6 +4022,13 @@ create_distinct_paths(PlannerInfo *root,
39844022 */
39854023distinct_rel -> consider_parallel = input_rel -> consider_parallel ;
39864024
4025+ /*
4026+ * If the input rel belongs to a single FDW, so does the distinct_rel.
4027+ */
4028+ distinct_rel -> serverid = input_rel -> serverid ;
4029+ distinct_rel -> umid = input_rel -> umid ;
4030+ distinct_rel -> fdwroutine = input_rel -> fdwroutine ;
4031+
39874032/* Estimate number of distinct rows there will be */
39884033if (parse -> groupClause || parse -> groupingSets || parse -> hasAggs ||
39894034root -> hasHavingQual )
@@ -4129,6 +4174,15 @@ create_distinct_paths(PlannerInfo *root,
41294174errmsg ("could not implement DISTINCT" ),
41304175errdetail ("Some of the datatypes only support hashing, while others only support sorting." )));
41314176
4177+ /*
4178+ * If there is an FDW that's responsible for all baserels of the query,
4179+ * let it consider adding ForeignPaths.
4180+ */
4181+ if (distinct_rel -> fdwroutine &&
4182+ distinct_rel -> fdwroutine -> GetForeignUpperPaths )
4183+ distinct_rel -> fdwroutine -> GetForeignUpperPaths (root ,UPPERREL_DISTINCT ,
4184+ input_rel ,distinct_rel );
4185+
41324186/* Let extensions possibly add some more paths */
41334187if (create_upper_paths_hook )
41344188(* create_upper_paths_hook ) (root ,UPPERREL_DISTINCT ,
@@ -4176,6 +4230,13 @@ create_ordered_paths(PlannerInfo *root,
41764230!has_parallel_hazard ((Node * )target -> exprs , false))
41774231ordered_rel -> consider_parallel = true;
41784232
4233+ /*
4234+ * If the input rel belongs to a single FDW, so does the ordered_rel.
4235+ */
4236+ ordered_rel -> serverid = input_rel -> serverid ;
4237+ ordered_rel -> umid = input_rel -> umid ;
4238+ ordered_rel -> fdwroutine = input_rel -> fdwroutine ;
4239+
41794240foreach (lc ,input_rel -> pathlist )
41804241{
41814242Path * path = (Path * )lfirst (lc );
@@ -4204,6 +4265,15 @@ create_ordered_paths(PlannerInfo *root,
42044265}
42054266}
42064267
4268+ /*
4269+ * If there is an FDW that's responsible for all baserels of the query,
4270+ * let it consider adding ForeignPaths.
4271+ */
4272+ if (ordered_rel -> fdwroutine &&
4273+ ordered_rel -> fdwroutine -> GetForeignUpperPaths )
4274+ ordered_rel -> fdwroutine -> GetForeignUpperPaths (root ,UPPERREL_ORDERED ,
4275+ input_rel ,ordered_rel );
4276+
42074277/* Let extensions possibly add some more paths */
42084278if (create_upper_paths_hook )
42094279(* create_upper_paths_hook ) (root ,UPPERREL_ORDERED ,