Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit49635d7

Browse files
committed
Minor additional refactoring of planner.c's PathTarget handling.
Teach make_group_input_target() and make_window_input_target() to workentirely with the PathTarget representation of tlists, rather thanconstructing a tlist and immediately deconstructing it into PathTargetformat. In itself this only saves a few palloc's; the bigger picture isthat it opens the door for sharing cost_qual_eval work across all ofplanner.c's constructions of PathTargets. I'll come back to that later.In support of this, flesh out tlist.c's infrastructure for PathTargetsa bit more.
1 parent92f03fe commit49635d7

File tree

3 files changed

+111
-64
lines changed

3 files changed

+111
-64
lines changed

‎src/backend/optimizer/plan/planner.c

Lines changed: 62 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,13 @@ static RelOptInfo *create_distinct_paths(PlannerInfo *root,
128128
staticRelOptInfo*create_ordered_paths(PlannerInfo*root,
129129
RelOptInfo*input_rel,
130130
doublelimit_tuples);
131-
staticPathTarget*make_group_input_target(PlannerInfo*root,List*tlist);
131+
staticPathTarget*make_group_input_target(PlannerInfo*root,
132+
PathTarget*final_target);
132133
staticList*postprocess_setop_tlist(List*new_tlist,List*orig_tlist);
133134
staticList*select_active_windows(PlannerInfo*root,WindowFuncLists*wflists);
134135
staticPathTarget*make_window_input_target(PlannerInfo*root,
135-
List*tlist,List*activeWindows);
136+
PathTarget*final_target,
137+
List*activeWindows);
136138
staticList*make_pathkeys_for_window(PlannerInfo*root,WindowClause*wc,
137139
List*tlist);
138140

@@ -1664,7 +1666,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
16641666
*/
16651667
if (activeWindows)
16661668
grouping_target=make_window_input_target(root,
1667-
tlist,
1669+
final_target,
16681670
activeWindows);
16691671
else
16701672
grouping_target=final_target;
@@ -1678,7 +1680,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
16781680
have_grouping= (parse->groupClause||parse->groupingSets||
16791681
parse->hasAggs||root->hasHavingQual);
16801682
if (have_grouping)
1681-
scanjoin_target=make_group_input_target(root,tlist);
1683+
scanjoin_target=make_group_input_target(root,final_target);
16821684
else
16831685
scanjoin_target=grouping_target;
16841686

@@ -3758,10 +3760,10 @@ create_ordered_paths(PlannerInfo *root,
37583760
*
37593761
* If there is grouping or aggregation, the scan/join subplan cannot emit
37603762
* the query's final targetlist; for example, it certainly can't emit any
3761-
* aggregate function calls. This routine generates the correct target list
3763+
* aggregate function calls. This routine generates the correct target
37623764
* for the scan/join subplan.
37633765
*
3764-
* Theinitial target list passed from the parser already contains entries
3766+
* Thequery target list passed from the parser already contains entries
37653767
* for all ORDER BY and GROUP BY expressions, but it will not have entries
37663768
* for variables used only in HAVING clauses; so we need to add those
37673769
* variables to the subplan target list. Also, we flatten all expressions
@@ -3774,56 +3776,52 @@ create_ordered_paths(PlannerInfo *root,
37743776
* where the a+b target will be used by the Sort/Group steps, and the
37753777
* other targets will be used for computing the final results.
37763778
*
3777-
* 'tlist' is the query's final target list.
3779+
* 'final_target' is the query's final target list (in PathTarget form)
37783780
*
37793781
* The result is the PathTarget to be computed by the Paths returned from
37803782
* query_planner().
37813783
*/
37823784
staticPathTarget*
3783-
make_group_input_target(PlannerInfo*root,List*tlist)
3785+
make_group_input_target(PlannerInfo*root,PathTarget*final_target)
37843786
{
37853787
Query*parse=root->parse;
3786-
List*sub_tlist;
3788+
PathTarget*input_target;
37873789
List*non_group_cols;
37883790
List*non_group_vars;
3789-
ListCell*tl;
3791+
inti;
3792+
ListCell*lc;
37903793

37913794
/*
3792-
* We must build atlist containing all grouping columns, plus any other
3793-
* Vars mentioned in the targetlist and HAVING qual.
3795+
* We must build atarget containing all grouping columns, plus any other
3796+
* Vars mentioned in thequery'stargetlist and HAVING qual.
37943797
*/
3795-
sub_tlist=NIL;
3798+
input_target=create_empty_pathtarget();
37963799
non_group_cols=NIL;
37973800

3798-
foreach(tl,tlist)
3801+
i=0;
3802+
foreach(lc,final_target->exprs)
37993803
{
3800-
TargetEntry*tle= (TargetEntry*)lfirst(tl);
3804+
Expr*expr= (Expr*)lfirst(lc);
3805+
Indexsgref=final_target->sortgrouprefs[i];
38013806

3802-
if (tle->ressortgroupref&&parse->groupClause&&
3803-
get_sortgroupref_clause_noerr(tle->ressortgroupref,
3804-
parse->groupClause)!=NULL)
3807+
if (sgref&&parse->groupClause&&
3808+
get_sortgroupref_clause_noerr(sgref,parse->groupClause)!=NULL)
38053809
{
38063810
/*
3807-
* It's a grouping column, so add it to theresult tlist as-is.
3811+
* It's a grouping column, so add it to theinput target as-is.
38083812
*/
3809-
TargetEntry*newtle;
3810-
3811-
newtle=makeTargetEntry(tle->expr,
3812-
list_length(sub_tlist)+1,
3813-
NULL,
3814-
false);
3815-
newtle->ressortgroupref=tle->ressortgroupref;
3816-
sub_tlist=lappend(sub_tlist,newtle);
3813+
add_column_to_pathtarget(input_target,expr,sgref);
38173814
}
38183815
else
38193816
{
38203817
/*
38213818
* Non-grouping column, so just remember the expression for later
3822-
* call to pull_var_clause. There's no need for pull_var_clause
3823-
* to examine the TargetEntry node itself.
3819+
* call to pull_var_clause.
38243820
*/
3825-
non_group_cols=lappend(non_group_cols,tle->expr);
3821+
non_group_cols=lappend(non_group_cols,expr);
38263822
}
3823+
3824+
i++;
38273825
}
38283826

38293827
/*
@@ -3834,7 +3832,7 @@ make_group_input_target(PlannerInfo *root, List *tlist)
38343832

38353833
/*
38363834
* Pull out all the Vars mentioned in non-group cols (plus HAVING), and
3837-
* add them to theresult tlist if not already present. (A Var used
3835+
* add them to theinput target if not already present. (A Var used
38383836
* directly as a GROUP BY item will be present already.) Note this
38393837
* includes Vars used in resjunk items, so we are covering the needs of
38403838
* ORDER BY and window specifications. Vars used within Aggrefs and
@@ -3844,13 +3842,14 @@ make_group_input_target(PlannerInfo *root, List *tlist)
38443842
PVC_RECURSE_AGGREGATES |
38453843
PVC_RECURSE_WINDOWFUNCS |
38463844
PVC_INCLUDE_PLACEHOLDERS);
3847-
sub_tlist=add_to_flat_tlist(sub_tlist,non_group_vars);
3845+
add_new_columns_to_pathtarget(input_target,non_group_vars);
38483846

38493847
/* clean up cruft */
38503848
list_free(non_group_vars);
38513849
list_free(non_group_cols);
38523850

3853-
returncreate_pathtarget(root,sub_tlist);
3851+
/* XXX this causes some redundant cost calculation ... */
3852+
returnset_pathtarget_cost_width(root,input_target);
38543853
}
38553854

38563855
/*
@@ -3964,13 +3963,13 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
39643963
* make_window_input_target
39653964
* Generate appropriate PathTarget for initial input to WindowAgg nodes.
39663965
*
3967-
* When the query has window functions, this function computes theinitial
3968-
* targetlistto be computed by the node just below the first WindowAgg.
3966+
* When the query has window functions, this function computes thedesired
3967+
* target to be computed by the node just below the first WindowAgg.
39693968
* This tlist must contain all values needed to evaluate the window functions,
39703969
* compute the final target list, and perform any required final sort step.
39713970
* If multiple WindowAggs are needed, each intermediate one adds its window
3972-
* function results onto this tlist; only the topmost WindowAgg computes the
3973-
* actual desired target list.
3971+
* function results onto thisbasetlist; only the topmost WindowAgg computes
3972+
*theactual desired target list.
39743973
*
39753974
* This function is much like make_group_input_target, though not quite enough
39763975
* like it to share code. As in that function, we flatten most expressions
@@ -3986,7 +3985,7 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
39863985
* flatten Aggref expressions, since those are to be computed below the
39873986
* window functions and just referenced like Vars above that.
39883987
*
3989-
* 'tlist' is the query's final target list.
3988+
* 'final_target' is the query's final target list (in PathTarget form)
39903989
* 'activeWindows' is the list of active windows previously identified by
39913990
*select_active_windows.
39923991
*
@@ -3995,14 +3994,15 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
39953994
*/
39963995
staticPathTarget*
39973996
make_window_input_target(PlannerInfo*root,
3998-
List*tlist,
3997+
PathTarget*final_target,
39993998
List*activeWindows)
40003999
{
40014000
Query*parse=root->parse;
4001+
PathTarget*input_target;
40024002
Bitmapset*sgrefs;
4003-
List*new_tlist;
40044003
List*flattenable_cols;
40054004
List*flattenable_vars;
4005+
inti;
40064006
ListCell*lc;
40074007

40084008
Assert(parse->hasWindowFuncs);
@@ -4040,52 +4040,49 @@ make_window_input_target(PlannerInfo *root,
40404040
}
40414041

40424042
/*
4043-
* Construct atlist containing all the non-flattenabletlist items, and
4044-
* save aside the others for a moment.
4043+
* Construct atarget containing all the non-flattenabletargetlist items,
4044+
*andsave aside the others for a moment.
40454045
*/
4046-
new_tlist=NIL;
4046+
input_target=create_empty_pathtarget();
40474047
flattenable_cols=NIL;
40484048

4049-
foreach(lc,tlist)
4049+
i=0;
4050+
foreach(lc,final_target->exprs)
40504051
{
4051-
TargetEntry*tle= (TargetEntry*)lfirst(lc);
4052+
Expr*expr= (Expr*)lfirst(lc);
4053+
Indexsgref=final_target->sortgrouprefs[i];
40524054

40534055
/*
40544056
* Don't want to deconstruct window clauses or GROUP BY items. (Note
40554057
* that such items can't contain window functions, so it's okay to
40564058
* compute them below the WindowAgg nodes.)
40574059
*/
4058-
if (tle->ressortgroupref!=0&&
4059-
bms_is_member(tle->ressortgroupref,sgrefs))
4060+
if (sgref!=0&&bms_is_member(sgref,sgrefs))
40604061
{
4061-
/* Don't want to deconstruct this value, so add to new_tlist */
4062-
TargetEntry*newtle;
4063-
4064-
newtle=makeTargetEntry(tle->expr,
4065-
list_length(new_tlist)+1,
4066-
NULL,
4067-
false);
4068-
/* Preserve its sortgroupref marking, in case it's volatile */
4069-
newtle->ressortgroupref=tle->ressortgroupref;
4070-
new_tlist=lappend(new_tlist,newtle);
4062+
/*
4063+
* Don't want to deconstruct this value, so add it to the input
4064+
* target as-is.
4065+
*/
4066+
add_column_to_pathtarget(input_target,expr,sgref);
40714067
}
40724068
else
40734069
{
40744070
/*
40754071
* Column is to be flattened, so just remember the expression for
4076-
* later call to pull_var_clause. There's no need for
4077-
* pull_var_clause to examine the TargetEntry node itself.
4072+
* later call to pull_var_clause.
40784073
*/
4079-
flattenable_cols=lappend(flattenable_cols,tle->expr);
4074+
flattenable_cols=lappend(flattenable_cols,expr);
40804075
}
4076+
4077+
i++;
40814078
}
40824079

40834080
/*
40844081
* Pull out all the Vars and Aggrefs mentioned in flattenable columns, and
4085-
* add them to theresult tlist if not already present. (Some might be
4082+
* add them to theinput target if not already present. (Some might be
40864083
* there already because they're used directly as window/group clauses.)
40874084
*
4088-
* Note: it's essential to use PVC_INCLUDE_AGGREGATES here, so thatthe
4085+
* Note: it's essential to use PVC_INCLUDE_AGGREGATES here, so thatany
40894086
* Aggrefs are placed in the Agg node's tlist and not left to be computed
40904087
* at higher levels. On the other hand, we should recurse into
40914088
* WindowFuncs to make sure their input expressions are available.
@@ -4094,13 +4091,14 @@ make_window_input_target(PlannerInfo *root,
40944091
PVC_INCLUDE_AGGREGATES |
40954092
PVC_RECURSE_WINDOWFUNCS |
40964093
PVC_INCLUDE_PLACEHOLDERS);
4097-
new_tlist=add_to_flat_tlist(new_tlist,flattenable_vars);
4094+
add_new_columns_to_pathtarget(input_target,flattenable_vars);
40984095

40994096
/* clean up cruft */
41004097
list_free(flattenable_vars);
41014098
list_free(flattenable_cols);
41024099

4103-
returncreate_pathtarget(root,new_tlist);
4100+
/* XXX this causes some redundant cost calculation ... */
4101+
returnset_pathtarget_cost_width(root,input_target);
41044102
}
41054103

41064104
/*

‎src/backend/optimizer/util/tlist.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,17 @@ copy_pathtarget(PathTarget *src)
623623
returndst;
624624
}
625625

626+
/*
627+
* create_empty_pathtarget
628+
* Create an empty (zero columns, zero cost) PathTarget.
629+
*/
630+
PathTarget*
631+
create_empty_pathtarget(void)
632+
{
633+
/* This is easy, but we don't want callers to hard-wire this ... */
634+
return (PathTarget*)palloc0(sizeof(PathTarget));
635+
}
636+
626637
/*
627638
* add_column_to_pathtarget
628639
*Append a target column to the PathTarget.
@@ -655,6 +666,41 @@ add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
655666
}
656667
}
657668

669+
/*
670+
* add_new_column_to_pathtarget
671+
*Append a target column to the PathTarget, but only if it's not
672+
*equal() to any pre-existing target expression.
673+
*
674+
* The caller cannot specify a sortgroupref, since it would be unclear how
675+
* to merge that with a pre-existing column.
676+
*
677+
* As with make_pathtarget_from_tlist, we leave it to the caller to update
678+
* the cost and width fields.
679+
*/
680+
void
681+
add_new_column_to_pathtarget(PathTarget*target,Expr*expr)
682+
{
683+
if (!list_member(target->exprs,expr))
684+
add_column_to_pathtarget(target,expr,0);
685+
}
686+
687+
/*
688+
* add_new_columns_to_pathtarget
689+
*Apply add_new_column_to_pathtarget() for each element of the list.
690+
*/
691+
void
692+
add_new_columns_to_pathtarget(PathTarget*target,List*exprs)
693+
{
694+
ListCell*lc;
695+
696+
foreach(lc,exprs)
697+
{
698+
Expr*expr= (Expr*)lfirst(lc);
699+
700+
add_new_column_to_pathtarget(target,expr);
701+
}
702+
}
703+
658704
/*
659705
* apply_pathtarget_labeling_to_tlist
660706
*Apply any sortgrouprefs in the PathTarget to matching tlist entries

‎src/include/optimizer/tlist.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@ extern bool grouping_is_hashable(List *groupClause);
5555
externPathTarget*make_pathtarget_from_tlist(List*tlist);
5656
externList*make_tlist_from_pathtarget(PathTarget*target);
5757
externPathTarget*copy_pathtarget(PathTarget*src);
58+
externPathTarget*create_empty_pathtarget(void);
5859
externvoidadd_column_to_pathtarget(PathTarget*target,
5960
Expr*expr,Indexsortgroupref);
61+
externvoidadd_new_column_to_pathtarget(PathTarget*target,Expr*expr);
62+
externvoidadd_new_columns_to_pathtarget(PathTarget*target,List*exprs);
6063
externvoidapply_pathtarget_labeling_to_tlist(List*tlist,PathTarget*target);
6164

6265
/* Convenience macro to get a PathTarget with valid cost/width fields */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp