Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7fd4782

Browse files
committed
Fix aggregates on inherited tables.
1 parent 1783963 commit 7fd4782

File tree

6 files changed

+193
-99
lines changed

6 files changed

+193
-99
lines changed

src/backend/optimizer/plan/planmain.c

+3-66
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.11 1997/12/18 12:54:09 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.12 1997/12/20 07:59:25 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -41,7 +41,7 @@
4141
static Plan *subplanner(Query *root, List *flat_tlist, List *qual);
4242
static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
4343

44-
static Plan *
44+
extern Plan *
4545
make_groupPlan(List **tlist, bool tuplePerGroup,
4646
List *groupClause, Plan *subplan);
4747

@@ -72,7 +72,6 @@ query_planner(Query *root,
7272
List *flattened_tlist = NIL;
7373
List *level_tlist = NIL;
7474
Plan *subplan = (Plan *) NULL;
75-
Agg *aggplan = NULL;
7675

7776
/*
7877
* A command without a target list or qualification is an error,
@@ -174,49 +173,6 @@ query_planner(Query *root,
174173

175174
set_tlist_references(subplan);
176175

177-
/*
178-
* If we have a GROUP BY clause, insert a group node (with the
179-
* appropriate sort node.)
180-
*/
181-
if (root->groupClause != NULL)
182-
{
183-
bool tuplePerGroup;
184-
185-
/*
186-
* decide whether how many tuples per group the Group node needs
187-
* to return. (Needs only one tuple per group if no aggregate is
188-
* present. Otherwise, need every tuple from the group to do the
189-
* aggregation.)
190-
*/
191-
tuplePerGroup = (root->qry_aggs) ? TRUE : FALSE;
192-
193-
subplan =
194-
make_groupPlan(&tlist, tuplePerGroup, root->groupClause, subplan);
195-
196-
}
197-
198-
/*
199-
* If aggregate is present, insert the agg node
200-
*/
201-
if (root->qry_aggs)
202-
{
203-
aggplan = make_agg(tlist, root->qry_numAgg, root->qry_aggs, subplan);
204-
205-
/*
206-
* set the varno/attno entries to the appropriate references to
207-
* the result tuple of the subplans. (We need to set those in the
208-
* array of aggreg's in the Agg node also. Even though they're
209-
* pointers, after a few dozen's of copying, they're not the same
210-
* as those in the target list.)
211-
*/
212-
set_agg_tlist_references(aggplan);
213-
set_agg_agglist_references(aggplan);
214-
215-
subplan = (Plan *) aggplan;
216-
217-
tlist = aggplan->plan.targetlist;
218-
}
219-
220176
/*
221177
* Build a result node linking the plan if we have constant quals
222178
*/
@@ -236,25 +192,6 @@ query_planner(Query *root,
236192
return (plan);
237193
}
238194

239-
/*
240-
* fix up the flattened target list of the plan root node so that
241-
* expressions are evaluated. this forces expression evaluations that
242-
* may involve expensive function calls to be delayed to the very last
243-
* stage of query execution. this could be bad. but it is joey's
244-
* responsibility to optimally push these expressions down the plan
245-
* tree. -- Wei
246-
*
247-
* But now nothing to do if there are GroupBy and/or Aggregates: 1.
248-
* make_groupPlan fixes tlist; 2. flatten_tlist_vars does nothing with
249-
* aggregates fixing only other entries (i.e. - GroupBy-ed and so
250-
* fixed by make_groupPlan). - vadim 04/05/97
251-
*/
252-
if (root->groupClause == NULL && aggplan == NULL)
253-
{
254-
subplan->targetlist = flatten_tlist_vars(tlist,
255-
subplan->targetlist);
256-
}
257-
258195
/*
259196
* Destructively modify the query plan's targetlist to add fjoin lists
260197
* to flatten functions that return sets of base types
@@ -380,7 +317,7 @@ make_result(List *tlist,
380317
*
381318
*****************************************************************************/
382319

383-
static Plan *
320+
Plan *
384321
make_groupPlan(List **tlist,
385322
bool tuplePerGroup,
386323
List *groupClause,

src/backend/optimizer/plan/planner.c

+82-12
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.13 1997/12/18 19:41:44 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.14 1997/12/20 07:59:27 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -47,6 +47,8 @@
4747
#include "executor/executor.h"
4848

4949
static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
50+
extern Plan *make_groupPlan(List **tlist, bool tuplePerGroup,
51+
List *groupClause, Plan *subplan);
5052

5153
/*****************************************************************************
5254
*
@@ -72,42 +74,110 @@ planner(Query *parse)
7274
List *rangetable = parse->rtable;
7375
char *uniqueflag = parse->uniqueFlag;
7476
List *sortclause = parse->sortClause;
75-
Plan *special_plans = (Plan *) NULL;
77+
Agg *aggplan = NULL;
7678

7779
Plan *result_plan = (Plan *) NULL;
7880

79-
List *preprocessed_tlist = NIL;
8081
List *primary_qual;
8182
int rt_index;
83+
8284

8385
/*
8486
* plan inheritance
8587
*/
8688
rt_index = first_matching_rt_entry(rangetable, INHERITS_FLAG);
8789
if (rt_index != -1)
8890
{
89-
special_plans = (Plan *) plan_union_queries((Index) rt_index,
91+
result_plan = (Plan *) plan_union_queries((Index) rt_index,
9092
parse,
9193
INHERITS_FLAG);
94+
/* XXX do we need to do this? bjm 12/19/97 */
95+
tlist = preprocess_targetlist(tlist,
96+
parse->commandType,
97+
parse->resultRelation,
98+
parse->rtable);
9299
}
93-
94-
if (special_plans)
95-
result_plan = special_plans;
96100
else
97101
{
98-
preprocessed_tlist = preprocess_targetlist(tlist,
99-
parse->commandType,
100-
parse->resultRelation,
101-
parse->rtable);
102+
tlist = preprocess_targetlist(tlist,
103+
parse->commandType,
104+
parse->resultRelation,
105+
parse->rtable);
102106

103107
primary_qual = cnfify((Expr *) parse->qual, true);
104108

105109
result_plan = query_planner(parse,
106110
parse->commandType,
107-
preprocessed_tlist,
111+
tlist,
108112
primary_qual);
109113
}
110114

115+
/*
116+
* If we have a GROUP BY clause, insert a group node (with the
117+
* appropriate sort node.)
118+
*/
119+
if (parse->groupClause != NULL)
120+
{
121+
bool tuplePerGroup;
122+
123+
/*
124+
* decide whether how many tuples per group the Group node needs
125+
* to return. (Needs only one tuple per group if no aggregate is
126+
* present. Otherwise, need every tuple from the group to do the
127+
* aggregation.)
128+
*/
129+
tuplePerGroup = (parse->qry_aggs) ? TRUE : FALSE;
130+
131+
result_plan =
132+
make_groupPlan( &tlist,
133+
tuplePerGroup,
134+
parse->groupClause,
135+
result_plan);
136+
137+
}
138+
139+
/*
140+
* If aggregate is present, insert the agg node
141+
*/
142+
if (parse->qry_aggs)
143+
{
144+
aggplan = make_agg(tlist,
145+
parse->qry_numAgg,
146+
parse->qry_aggs,
147+
result_plan);
148+
149+
/*
150+
* set the varno/attno entries to the appropriate references to
151+
* the result tuple of the subplans. (We need to set those in the
152+
* array of aggreg's in the Agg node also. Even though they're
153+
* pointers, after a few dozen's of copying, they're not the same
154+
* as those in the target list.)
155+
*/
156+
set_agg_tlist_references(aggplan);
157+
set_agg_agglist_references(aggplan);
158+
159+
result_plan = (Plan *) aggplan;
160+
}
161+
162+
/*
163+
* fix up the flattened target list of the plan root node so that
164+
* expressions are evaluated. this forces expression evaluations that
165+
* may involve expensive function calls to be delayed to the very last
166+
* stage of query execution. this could be bad. but it is joey's
167+
* responsibility to optimally push these expressions down the plan
168+
* tree. -- Wei
169+
*
170+
* But now nothing to do if there are GroupBy and/or Aggregates: 1.
171+
* make_groupPlan fixes tlist; 2. flatten_tlist_vars does nothing with
172+
* aggregates fixing only other entries (i.e. - GroupBy-ed and so
173+
* fixed by make_groupPlan). - vadim 04/05/97
174+
*/
175+
if (parse->groupClause == NULL && aggplan == NULL)
176+
{
177+
result_plan->targetlist = flatten_tlist_vars(tlist,
178+
result_plan->targetlist);
179+
}
180+
111181
/*
112182
* For now, before we hand back the plan, check to see if there is a
113183
* user-specified sort that needs to be done. Eventually, this will

src/backend/optimizer/plan/setrefs.c

+95-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.8 1997/09/08 21:45:28 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.9 1997/12/20 07:59:28 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -47,6 +47,7 @@ static List *tlist_temp_references(Oid tempid, List *tlist);
4747
static void replace_result_clause(List *clause, List *subplanTargetList);
4848
static bool OperandIsInner(Node *opnd, int inner_relid);
4949
static void replace_agg_clause(Node *expr, List *targetlist);
50+
static Node *del_agg_clause(Node *clause);
5051

5152
/*****************************************************************************
5253
*
@@ -803,3 +804,96 @@ replace_agg_clause(Node *clause, List *subplanTargetList)
803804
}
804805

805806
}
807+
808+
/*
809+
* del_agg_tlist_references
810+
* Remove the Agg nodes from the target list
811+
* We do this so inheritance only does aggregates in the upper node
812+
*/
813+
void del_agg_tlist_references(List *tlist)
814+
{
815+
List *tl;
816+
817+
foreach(tl, tlist)
818+
{
819+
TargetEntry *tle = lfirst(tl);
820+
821+
tle->expr = del_agg_clause(tle->expr);
822+
}
823+
}
824+
825+
static Node *
826+
del_agg_clause(Node *clause)
827+
{
828+
List *t;
829+
830+
if (IsA(clause, Var))
831+
{
832+
return clause;
833+
}
834+
else if (is_funcclause(clause))
835+
{
836+
/*
837+
* This is a function. Recursively call this routine for its
838+
* arguments...
839+
*/
840+
foreach(t, ((Expr *) clause)->args)
841+
{
842+
lfirst(t) = del_agg_clause(lfirst(t));
843+
}
844+
}
845+
else if (IsA(clause, Aggreg))
846+
{
847+
848+
/* here is the real action, to remove the Agg node */
849+
return del_agg_clause(((Aggreg *) clause)->target);
850+
851+
}
852+
else if (IsA(clause, ArrayRef))
853+
{
854+
ArrayRef *aref = (ArrayRef *) clause;
855+
856+
/*
857+
* This is an arrayref. Recursively call this routine for its
858+
* expression and its index expression...
859+
*/
860+
foreach(t, aref->refupperindexpr)
861+
{
862+
lfirst(t) = del_agg_clause(lfirst(t));
863+
}
864+
foreach(t, aref->reflowerindexpr)
865+
{
866+
lfirst(t) = del_agg_clause(lfirst(t));
867+
}
868+
aref->refexpr = del_agg_clause(aref->refexpr);
869+
aref->refassgnexpr = del_agg_clause(aref->refassgnexpr);
870+
}
871+
else if (is_opclause(clause))
872+
{
873+
874+
/*
875+
* This is an operator. Recursively call this routine for both its
876+
* left and right operands
877+
*/
878+
Node *left = (Node *) get_leftop((Expr *) clause);
879+
Node *right = (Node *) get_rightop((Expr *) clause);
880+
881+
if (left != (Node *) NULL)
882+
left = del_agg_clause(left);
883+
if (right != (Node *) NULL)
884+
right = del_agg_clause(right);
885+
}
886+
else if (IsA(clause, Param) ||IsA(clause, Const))
887+
{
888+
return clause;
889+
}
890+
else
891+
{
892+
893+
/*
894+
* Ooops! we can not handle that!
895+
*/
896+
elog(WARN, "del_agg_clause: Can not handle this tlist!\n");
897+
}
898+
return NULL;
899+
}

0 commit comments

Comments
 (0)