diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/optimizer/README | 13 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planagg.c | 5 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 108 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 4 | ||||
-rw-r--r-- | src/include/foreign/fdwapi.h | 4 |
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, |