1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Rethink the GetForeignUpperPaths API (again).

In the previous design, the GetForeignUpperPaths FDW callback hook was
called before we got around to labeling upper relations with the proper
consider_parallel flag; this meant that any upper paths created by an FDW
would be marked not-parallel-safe.  While that's probably just as well
right now, we aren't going to want it to be true forever.  Hence, abandon
the idea that FDWs should be allowed to inject upper paths before the core
code has gotten around to creating the relevant upper relation.  (Well,
actually they still can, but it's on their own heads how well it works.)
Instead, adopt the same API already designed for create_upper_paths_hook:
we call GetForeignUpperPaths after each upperrel has been created and
populated with the paths the core planner knows how to make.
This commit is contained in:
Tom Lane
2016-07-01 13:12:34 -04:00
parent 5ce5e4a12e
commit 9e703987a8
6 changed files with 135 additions and 54 deletions

View File

@ -1291,6 +1291,12 @@ inheritance_planner(PlannerInfo *root)
/* Result path must go into outer query's FINAL upperrel */
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.
@ -1788,21 +1794,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
root->upper_targets[UPPERREL_WINDOW] = sort_input_target;
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
@ -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,
@ -3268,6 +3274,13 @@ create_grouping_paths(PlannerInfo *root,
!has_parallel_hazard((Node *) parse->havingQual, false))
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.
*/
@ -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,
@ -3820,6 +3842,13 @@ create_window_paths(PlannerInfo *root,
!has_parallel_hazard((Node *) activeWindows, false))
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
@ -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,