mirror of
https://github.com/postgres/postgres.git
synced 2025-05-23 00:02:38 -04:00
Generalize the common code of adding sort before processing of grouping
Extract the repetitive code pattern into a new function make_ordered_path(). Discussion: https://postgr.es/m/CAPpHfdtzaVa7S4onKy3YvttF2rrH5hQNHx9HtcSTLbpjx%2BMJ%2Bw%40mail.gmail.com Author: Andrei Lepikhov
This commit is contained in:
parent
58447e3189
commit
7ab80ac1ca
@ -6809,6 +6809,58 @@ done:
|
|||||||
return parallel_workers;
|
return parallel_workers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_ordered_path
|
||||||
|
* Return a path ordered by 'pathkeys' based on the given 'path'. May
|
||||||
|
* return NULL if it doesn't make sense to generate an ordered path in
|
||||||
|
* this case.
|
||||||
|
*/
|
||||||
|
static Path *
|
||||||
|
make_ordered_path(PlannerInfo *root, RelOptInfo *rel, Path *path,
|
||||||
|
Path *cheapest_path, List *pathkeys)
|
||||||
|
{
|
||||||
|
bool is_sorted;
|
||||||
|
int presorted_keys;
|
||||||
|
|
||||||
|
is_sorted = pathkeys_count_contained_in(pathkeys,
|
||||||
|
path->pathkeys,
|
||||||
|
&presorted_keys);
|
||||||
|
|
||||||
|
if (!is_sorted)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Try at least sorting the cheapest path and also try incrementally
|
||||||
|
* sorting any path which is partially sorted already (no need to deal
|
||||||
|
* with paths which have presorted keys when incremental sort is
|
||||||
|
* disabled unless it's the cheapest input path).
|
||||||
|
*/
|
||||||
|
if (path != cheapest_path &&
|
||||||
|
(presorted_keys == 0 || !enable_incremental_sort))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We've no need to consider both a sort and incremental sort. We'll
|
||||||
|
* just do a sort if there are no presorted keys and an incremental
|
||||||
|
* sort when there are presorted keys.
|
||||||
|
*/
|
||||||
|
if (presorted_keys == 0 || !enable_incremental_sort)
|
||||||
|
path = (Path *) create_sort_path(root,
|
||||||
|
rel,
|
||||||
|
path,
|
||||||
|
pathkeys,
|
||||||
|
-1.0);
|
||||||
|
else
|
||||||
|
path = (Path *) create_incremental_sort_path(root,
|
||||||
|
rel,
|
||||||
|
path,
|
||||||
|
pathkeys,
|
||||||
|
presorted_keys,
|
||||||
|
-1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add_paths_to_grouping_rel
|
* add_paths_to_grouping_rel
|
||||||
*
|
*
|
||||||
@ -6840,46 +6892,16 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
|
|||||||
foreach(lc, input_rel->pathlist)
|
foreach(lc, input_rel->pathlist)
|
||||||
{
|
{
|
||||||
Path *path = (Path *) lfirst(lc);
|
Path *path = (Path *) lfirst(lc);
|
||||||
bool is_sorted;
|
|
||||||
int presorted_keys;
|
|
||||||
|
|
||||||
is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
|
path = make_ordered_path(root,
|
||||||
path->pathkeys,
|
grouped_rel,
|
||||||
&presorted_keys);
|
path,
|
||||||
|
cheapest_path,
|
||||||
|
root->group_pathkeys);
|
||||||
|
|
||||||
if (!is_sorted)
|
if (path == NULL)
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Try at least sorting the cheapest path and also try
|
|
||||||
* incrementally sorting any path which is partially sorted
|
|
||||||
* already (no need to deal with paths which have presorted
|
|
||||||
* keys when incremental sort is disabled unless it's the
|
|
||||||
* cheapest input path).
|
|
||||||
*/
|
|
||||||
if (path != cheapest_path &&
|
|
||||||
(presorted_keys == 0 || !enable_incremental_sort))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
* We've no need to consider both a sort and incremental sort.
|
|
||||||
* We'll just do a sort if there are no presorted keys and an
|
|
||||||
* incremental sort when there are presorted keys.
|
|
||||||
*/
|
|
||||||
if (presorted_keys == 0 || !enable_incremental_sort)
|
|
||||||
path = (Path *) create_sort_path(root,
|
|
||||||
grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
-1.0);
|
|
||||||
else
|
|
||||||
path = (Path *) create_incremental_sort_path(root,
|
|
||||||
grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
presorted_keys,
|
|
||||||
-1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now decide what to stick atop it */
|
/* Now decide what to stick atop it */
|
||||||
if (parse->groupingSets)
|
if (parse->groupingSets)
|
||||||
{
|
{
|
||||||
@ -6935,47 +6957,16 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
|
|||||||
foreach(lc, partially_grouped_rel->pathlist)
|
foreach(lc, partially_grouped_rel->pathlist)
|
||||||
{
|
{
|
||||||
Path *path = (Path *) lfirst(lc);
|
Path *path = (Path *) lfirst(lc);
|
||||||
bool is_sorted;
|
|
||||||
int presorted_keys;
|
|
||||||
|
|
||||||
is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
|
path = make_ordered_path(root,
|
||||||
path->pathkeys,
|
grouped_rel,
|
||||||
&presorted_keys);
|
path,
|
||||||
|
partially_grouped_rel->cheapest_total_path,
|
||||||
|
root->group_pathkeys);
|
||||||
|
|
||||||
if (!is_sorted)
|
if (path == NULL)
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Try at least sorting the cheapest path and also try
|
|
||||||
* incrementally sorting any path which is partially
|
|
||||||
* sorted already (no need to deal with paths which have
|
|
||||||
* presorted keys when incremental sort is disabled unless
|
|
||||||
* it's the cheapest input path).
|
|
||||||
*/
|
|
||||||
if (path != partially_grouped_rel->cheapest_total_path &&
|
|
||||||
(presorted_keys == 0 || !enable_incremental_sort))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
* We've no need to consider both a sort and incremental
|
|
||||||
* sort. We'll just do a sort if there are no pre-sorted
|
|
||||||
* keys and an incremental sort when there are presorted
|
|
||||||
* keys.
|
|
||||||
*/
|
|
||||||
if (presorted_keys == 0 || !enable_incremental_sort)
|
|
||||||
path = (Path *) create_sort_path(root,
|
|
||||||
grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
-1.0);
|
|
||||||
else
|
|
||||||
path = (Path *) create_incremental_sort_path(root,
|
|
||||||
grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
presorted_keys,
|
|
||||||
-1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse->hasAggs)
|
if (parse->hasAggs)
|
||||||
add_path(grouped_rel, (Path *)
|
add_path(grouped_rel, (Path *)
|
||||||
create_agg_path(root,
|
create_agg_path(root,
|
||||||
@ -7200,45 +7191,16 @@ create_partial_grouping_paths(PlannerInfo *root,
|
|||||||
foreach(lc, input_rel->pathlist)
|
foreach(lc, input_rel->pathlist)
|
||||||
{
|
{
|
||||||
Path *path = (Path *) lfirst(lc);
|
Path *path = (Path *) lfirst(lc);
|
||||||
bool is_sorted;
|
|
||||||
int presorted_keys;
|
|
||||||
|
|
||||||
is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
|
path = make_ordered_path(root,
|
||||||
path->pathkeys,
|
partially_grouped_rel,
|
||||||
&presorted_keys);
|
path,
|
||||||
if (!is_sorted)
|
cheapest_total_path,
|
||||||
{
|
root->group_pathkeys);
|
||||||
/*
|
|
||||||
* Try at least sorting the cheapest path and also try
|
if (path == NULL)
|
||||||
* incrementally sorting any path which is partially sorted
|
|
||||||
* already (no need to deal with paths which have presorted
|
|
||||||
* keys when incremental sort is disabled unless it's the
|
|
||||||
* cheapest input path).
|
|
||||||
*/
|
|
||||||
if (path != cheapest_total_path &&
|
|
||||||
(presorted_keys == 0 || !enable_incremental_sort))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
* We've no need to consider both a sort and incremental sort.
|
|
||||||
* We'll just do a sort if there are no presorted keys and an
|
|
||||||
* incremental sort when there are presorted keys.
|
|
||||||
*/
|
|
||||||
if (presorted_keys == 0 || !enable_incremental_sort)
|
|
||||||
path = (Path *) create_sort_path(root,
|
|
||||||
partially_grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
-1.0);
|
|
||||||
else
|
|
||||||
path = (Path *) create_incremental_sort_path(root,
|
|
||||||
partially_grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
presorted_keys,
|
|
||||||
-1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse->hasAggs)
|
if (parse->hasAggs)
|
||||||
add_path(partially_grouped_rel, (Path *)
|
add_path(partially_grouped_rel, (Path *)
|
||||||
create_agg_path(root,
|
create_agg_path(root,
|
||||||
@ -7268,46 +7230,16 @@ create_partial_grouping_paths(PlannerInfo *root,
|
|||||||
foreach(lc, input_rel->partial_pathlist)
|
foreach(lc, input_rel->partial_pathlist)
|
||||||
{
|
{
|
||||||
Path *path = (Path *) lfirst(lc);
|
Path *path = (Path *) lfirst(lc);
|
||||||
bool is_sorted;
|
|
||||||
int presorted_keys;
|
|
||||||
|
|
||||||
is_sorted = pathkeys_count_contained_in(root->group_pathkeys,
|
path = make_ordered_path(root,
|
||||||
path->pathkeys,
|
partially_grouped_rel,
|
||||||
&presorted_keys);
|
path,
|
||||||
|
cheapest_partial_path,
|
||||||
|
root->group_pathkeys);
|
||||||
|
|
||||||
if (!is_sorted)
|
if (path == NULL)
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Try at least sorting the cheapest path and also try
|
|
||||||
* incrementally sorting any path which is partially sorted
|
|
||||||
* already (no need to deal with paths which have presorted
|
|
||||||
* keys when incremental sort is disabled unless it's the
|
|
||||||
* cheapest input path).
|
|
||||||
*/
|
|
||||||
if (path != cheapest_partial_path &&
|
|
||||||
(presorted_keys == 0 || !enable_incremental_sort))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
* We've no need to consider both a sort and incremental sort.
|
|
||||||
* We'll just do a sort if there are no presorted keys and an
|
|
||||||
* incremental sort when there are presorted keys.
|
|
||||||
*/
|
|
||||||
if (presorted_keys == 0 || !enable_incremental_sort)
|
|
||||||
path = (Path *) create_sort_path(root,
|
|
||||||
partially_grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
-1.0);
|
|
||||||
else
|
|
||||||
path = (Path *) create_incremental_sort_path(root,
|
|
||||||
partially_grouped_rel,
|
|
||||||
path,
|
|
||||||
root->group_pathkeys,
|
|
||||||
presorted_keys,
|
|
||||||
-1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse->hasAggs)
|
if (parse->hasAggs)
|
||||||
add_partial_path(partially_grouped_rel, (Path *)
|
add_partial_path(partially_grouped_rel, (Path *)
|
||||||
create_agg_path(root,
|
create_agg_path(root,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user