aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/README13
-rw-r--r--src/backend/optimizer/plan/planagg.c5
-rw-r--r--src/backend/optimizer/plan/planner.c108
-rw-r--r--src/backend/optimizer/prep/prepunion.c4
-rw-r--r--src/include/foreign/fdwapi.h4
5 files changed, 100 insertions, 34 deletions
diff --git a/src/backend/optimizer/README b/src/backend/optimizer/README
index 799e0ebe810..775bcc3b73b 100644
--- a/src/backend/optimizer/README
+++ b/src/backend/optimizer/README
@@ -919,19 +919,6 @@ The result of subquery_planner() is always returned as a set of Paths
stored in the UPPERREL_FINAL rel with NULL relids. The other types of
upperrels are created only if needed for the particular query.
-The upper-relation infrastructure is designed so that things will work
-properly if a particular upper relation is created and Paths are added
-to it sooner than would normally happen. This allows, for example,
-for an FDW's GetForeignPaths function to insert a Path representing
-remote aggregation into the UPPERREL_GROUP_AGG upperrel, if it notices
-that the query represents an aggregation that could be done entirely on
-the foreign server. That Path will then compete with Paths representing
-local aggregation on a regular scan of the foreign table, once the core
-planner reaches the point of considering aggregation. (In practice,
-it will usually be more convenient for FDWs to detect such cases in a
-GetForeignUpperPaths callback; but that still represents injecting a
-Path before the core code has touched the corresponding upperrel.)
-
Parallel Query and Partial Paths
--------------------------------
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index cefec7bdf10..805aae7ee7a 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -205,7 +205,10 @@ preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
* will likely always win, but we need not assume that here.)
*
* Note: grouping_planner won't have created this upperrel yet, but it's
- * fine for us to create it first.
+ * fine for us to create it first. We will not have inserted the correct
+ * consider_parallel value in it, but MinMaxAggPath paths are currently
+ * never parallel-safe anyway, so that doesn't matter. Likewise, it
+ * doesn't matter that we haven't filled FDW-related fields in the rel.
*/
grouped_rel = fetch_upper_rel(root, UPPERREL_GROUP_AGG, NULL);
add_path(grouped_rel, (Path *)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 747a14d71c3..0ece4f2aace 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1292,6 +1292,12 @@ inheritance_planner(PlannerInfo *root)
final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
/*
+ * We don't currently worry about setting final_rel's consider_parallel
+ * flag in this case, nor about allowing FDWs or create_upper_paths_hook
+ * to get control here.
+ */
+
+ /*
* If we managed to exclude every child rel, return a dummy plan; it
* doesn't even need a ModifyTable node.
*/
@@ -1789,21 +1795,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
root->upper_targets[UPPERREL_GROUP_AGG] = grouping_target;
/*
- * If there is an FDW that's responsible for the final scan/join rel,
- * let it consider injecting extension Paths into the query's
- * upperrels, where they will compete with the Paths we create below.
- * We pass the final scan/join rel because that's not so easily
- * findable from the PlannerInfo struct; anything else the FDW wants
- * to know should be obtainable via "root".
- *
- * Note: CustomScan providers, as well as FDWs that don't want to use
- * this hook, can use the create_upper_paths_hook; see below.
- */
- if (current_rel->fdwroutine &&
- current_rel->fdwroutine->GetForeignUpperPaths)
- current_rel->fdwroutine->GetForeignUpperPaths(root, current_rel);
-
- /*
* If we have grouping and/or aggregation, consider ways to implement
* that. We build a new upperrel representing the output of this
* phase.
@@ -1891,9 +1882,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
}
/*
- * Now we are prepared to build the final-output upperrel. Insert all
- * surviving paths, with LockRows, Limit, and/or ModifyTable steps added
- * if needed.
+ * Now we are prepared to build the final-output upperrel.
*/
final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
@@ -1910,7 +1899,15 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
final_rel->consider_parallel = true;
/*
- * Generate paths for the final rel.
+ * If the current_rel belongs to a single FDW, so does the final_rel.
+ */
+ final_rel->serverid = current_rel->serverid;
+ final_rel->umid = current_rel->umid;
+ final_rel->fdwroutine = current_rel->fdwroutine;
+
+ /*
+ * Generate paths for the final_rel. Insert all surviving paths, with
+ * LockRows, Limit, and/or ModifyTable steps added if needed.
*/
foreach(lc, current_rel->pathlist)
{
@@ -1994,6 +1991,15 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
add_path(final_rel, path);
}
+ /*
+ * If there is an FDW that's responsible for all baserels of the query,
+ * let it consider adding ForeignPaths.
+ */
+ if (final_rel->fdwroutine &&
+ final_rel->fdwroutine->GetForeignUpperPaths)
+ final_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_FINAL,
+ current_rel, final_rel);
+
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_FINAL,
@@ -3269,6 +3275,13 @@ create_grouping_paths(PlannerInfo *root,
grouped_rel->consider_parallel = true;
/*
+ * If the input rel belongs to a single FDW, so does the grouped rel.
+ */
+ grouped_rel->serverid = input_rel->serverid;
+ grouped_rel->umid = input_rel->umid;
+ grouped_rel->fdwroutine = input_rel->fdwroutine;
+
+ /*
* Check for degenerate grouping.
*/
if ((root->hasHavingQual || parse->groupingSets) &&
@@ -3770,6 +3783,15 @@ create_grouping_paths(PlannerInfo *root,
errmsg("could not implement GROUP BY"),
errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
+ /*
+ * If there is an FDW that's responsible for all baserels of the query,
+ * let it consider adding ForeignPaths.
+ */
+ if (grouped_rel->fdwroutine &&
+ grouped_rel->fdwroutine->GetForeignUpperPaths)
+ grouped_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_GROUP_AGG,
+ input_rel, grouped_rel);
+
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_GROUP_AGG,
@@ -3821,6 +3843,13 @@ create_window_paths(PlannerInfo *root,
window_rel->consider_parallel = true;
/*
+ * If the input rel belongs to a single FDW, so does the window rel.
+ */
+ window_rel->serverid = input_rel->serverid;
+ window_rel->umid = input_rel->umid;
+ window_rel->fdwroutine = input_rel->fdwroutine;
+
+ /*
* Consider computing window functions starting from the existing
* cheapest-total path (which will likely require a sort) as well as any
* existing paths that satisfy root->window_pathkeys (which won't).
@@ -3841,6 +3870,15 @@ create_window_paths(PlannerInfo *root,
activeWindows);
}
+ /*
+ * If there is an FDW that's responsible for all baserels of the query,
+ * let it consider adding ForeignPaths.
+ */
+ if (window_rel->fdwroutine &&
+ window_rel->fdwroutine->GetForeignUpperPaths)
+ window_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_WINDOW,
+ input_rel, window_rel);
+
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_WINDOW,
@@ -3984,6 +4022,13 @@ create_distinct_paths(PlannerInfo *root,
*/
distinct_rel->consider_parallel = input_rel->consider_parallel;
+ /*
+ * If the input rel belongs to a single FDW, so does the distinct_rel.
+ */
+ distinct_rel->serverid = input_rel->serverid;
+ distinct_rel->umid = input_rel->umid;
+ distinct_rel->fdwroutine = input_rel->fdwroutine;
+
/* Estimate number of distinct rows there will be */
if (parse->groupClause || parse->groupingSets || parse->hasAggs ||
root->hasHavingQual)
@@ -4129,6 +4174,15 @@ create_distinct_paths(PlannerInfo *root,
errmsg("could not implement DISTINCT"),
errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
+ /*
+ * If there is an FDW that's responsible for all baserels of the query,
+ * let it consider adding ForeignPaths.
+ */
+ if (distinct_rel->fdwroutine &&
+ distinct_rel->fdwroutine->GetForeignUpperPaths)
+ distinct_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_DISTINCT,
+ input_rel, distinct_rel);
+
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_DISTINCT,
@@ -4176,6 +4230,13 @@ create_ordered_paths(PlannerInfo *root,
!has_parallel_hazard((Node *) target->exprs, false))
ordered_rel->consider_parallel = true;
+ /*
+ * If the input rel belongs to a single FDW, so does the ordered_rel.
+ */
+ ordered_rel->serverid = input_rel->serverid;
+ ordered_rel->umid = input_rel->umid;
+ ordered_rel->fdwroutine = input_rel->fdwroutine;
+
foreach(lc, input_rel->pathlist)
{
Path *path = (Path *) lfirst(lc);
@@ -4204,6 +4265,15 @@ create_ordered_paths(PlannerInfo *root,
}
}
+ /*
+ * If there is an FDW that's responsible for all baserels of the query,
+ * let it consider adding ForeignPaths.
+ */
+ if (ordered_rel->fdwroutine &&
+ ordered_rel->fdwroutine->GetForeignUpperPaths)
+ ordered_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_ORDERED,
+ input_rel, ordered_rel);
+
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_ORDERED,
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index ca01238c7f2..b7147832e0f 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -174,6 +174,10 @@ plan_set_operations(PlannerInfo *root)
*/
setop_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
+ /*
+ * We don't currently worry about setting setop_rel's consider_parallel
+ * flag, nor about allowing FDWs to contribute paths to it.
+ */
/*
* If the topmost node is a recursive union, it needs special processing.
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h
index d5c1df26987..e1b0d0da7df 100644
--- a/src/include/foreign/fdwapi.h
+++ b/src/include/foreign/fdwapi.h
@@ -60,7 +60,9 @@ typedef void (*GetForeignJoinPaths_function) (PlannerInfo *root,
JoinPathExtraData *extra);
typedef void (*GetForeignUpperPaths_function) (PlannerInfo *root,
- RelOptInfo *scan_join_rel);
+ UpperRelationKind stage,
+ RelOptInfo *input_rel,
+ RelOptInfo *output_rel);
typedef void (*AddForeignUpdateTargets_function) (Query *parsetree,
RangeTblEntry *target_rte,