Skip to content
Snippets Groups Projects
Commit 7fd47825 authored by Bruce Momjian's avatar Bruce Momjian
Browse files

Fix aggregates on inherited tables.

parent 1783963c
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.11 1997/12/18 12:54:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.12 1997/12/20 07:59:25 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
static Plan *subplanner(Query *root, List *flat_tlist, List *qual); static Plan *subplanner(Query *root, List *flat_tlist, List *qual);
static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan); static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
static Plan * extern Plan *
make_groupPlan(List **tlist, bool tuplePerGroup, make_groupPlan(List **tlist, bool tuplePerGroup,
List *groupClause, Plan *subplan); List *groupClause, Plan *subplan);
...@@ -72,7 +72,6 @@ query_planner(Query *root, ...@@ -72,7 +72,6 @@ query_planner(Query *root,
List *flattened_tlist = NIL; List *flattened_tlist = NIL;
List *level_tlist = NIL; List *level_tlist = NIL;
Plan *subplan = (Plan *) NULL; Plan *subplan = (Plan *) NULL;
Agg *aggplan = NULL;
/* /*
* A command without a target list or qualification is an error, * A command without a target list or qualification is an error,
...@@ -174,49 +173,6 @@ query_planner(Query *root, ...@@ -174,49 +173,6 @@ query_planner(Query *root,
set_tlist_references(subplan); set_tlist_references(subplan);
/*
* If we have a GROUP BY clause, insert a group node (with the
* appropriate sort node.)
*/
if (root->groupClause != NULL)
{
bool tuplePerGroup;
/*
* decide whether how many tuples per group the Group node needs
* to return. (Needs only one tuple per group if no aggregate is
* present. Otherwise, need every tuple from the group to do the
* aggregation.)
*/
tuplePerGroup = (root->qry_aggs) ? TRUE : FALSE;
subplan =
make_groupPlan(&tlist, tuplePerGroup, root->groupClause, subplan);
}
/*
* If aggregate is present, insert the agg node
*/
if (root->qry_aggs)
{
aggplan = make_agg(tlist, root->qry_numAgg, root->qry_aggs, subplan);
/*
* set the varno/attno entries to the appropriate references to
* the result tuple of the subplans. (We need to set those in the
* array of aggreg's in the Agg node also. Even though they're
* pointers, after a few dozen's of copying, they're not the same
* as those in the target list.)
*/
set_agg_tlist_references(aggplan);
set_agg_agglist_references(aggplan);
subplan = (Plan *) aggplan;
tlist = aggplan->plan.targetlist;
}
/* /*
* Build a result node linking the plan if we have constant quals * Build a result node linking the plan if we have constant quals
*/ */
...@@ -236,25 +192,6 @@ query_planner(Query *root, ...@@ -236,25 +192,6 @@ query_planner(Query *root,
return (plan); return (plan);
} }
/*
* fix up the flattened target list of the plan root node so that
* expressions are evaluated. this forces expression evaluations that
* may involve expensive function calls to be delayed to the very last
* stage of query execution. this could be bad. but it is joey's
* responsibility to optimally push these expressions down the plan
* tree. -- Wei
*
* But now nothing to do if there are GroupBy and/or Aggregates: 1.
* make_groupPlan fixes tlist; 2. flatten_tlist_vars does nothing with
* aggregates fixing only other entries (i.e. - GroupBy-ed and so
* fixed by make_groupPlan). - vadim 04/05/97
*/
if (root->groupClause == NULL && aggplan == NULL)
{
subplan->targetlist = flatten_tlist_vars(tlist,
subplan->targetlist);
}
/* /*
* Destructively modify the query plan's targetlist to add fjoin lists * Destructively modify the query plan's targetlist to add fjoin lists
* to flatten functions that return sets of base types * to flatten functions that return sets of base types
...@@ -380,7 +317,7 @@ make_result(List *tlist, ...@@ -380,7 +317,7 @@ make_result(List *tlist,
* *
*****************************************************************************/ *****************************************************************************/
static Plan * Plan *
make_groupPlan(List **tlist, make_groupPlan(List **tlist,
bool tuplePerGroup, bool tuplePerGroup,
List *groupClause, List *groupClause,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.13 1997/12/18 19:41:44 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.14 1997/12/20 07:59:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#include "executor/executor.h" #include "executor/executor.h"
static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode); static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
extern Plan *make_groupPlan(List **tlist, bool tuplePerGroup,
List *groupClause, Plan *subplan);
/***************************************************************************** /*****************************************************************************
* *
...@@ -72,30 +74,32 @@ planner(Query *parse) ...@@ -72,30 +74,32 @@ planner(Query *parse)
List *rangetable = parse->rtable; List *rangetable = parse->rtable;
char *uniqueflag = parse->uniqueFlag; char *uniqueflag = parse->uniqueFlag;
List *sortclause = parse->sortClause; List *sortclause = parse->sortClause;
Plan *special_plans = (Plan *) NULL; Agg *aggplan = NULL;
Plan *result_plan = (Plan *) NULL; Plan *result_plan = (Plan *) NULL;
List *preprocessed_tlist = NIL;
List *primary_qual; List *primary_qual;
int rt_index; int rt_index;
/* /*
* plan inheritance * plan inheritance
*/ */
rt_index = first_matching_rt_entry(rangetable, INHERITS_FLAG); rt_index = first_matching_rt_entry(rangetable, INHERITS_FLAG);
if (rt_index != -1) if (rt_index != -1)
{ {
special_plans = (Plan *) plan_union_queries((Index) rt_index, result_plan = (Plan *) plan_union_queries((Index) rt_index,
parse, parse,
INHERITS_FLAG); INHERITS_FLAG);
/* XXX do we need to do this? bjm 12/19/97 */
tlist = preprocess_targetlist(tlist,
parse->commandType,
parse->resultRelation,
parse->rtable);
} }
if (special_plans)
result_plan = special_plans;
else else
{ {
preprocessed_tlist = preprocess_targetlist(tlist, tlist = preprocess_targetlist(tlist,
parse->commandType, parse->commandType,
parse->resultRelation, parse->resultRelation,
parse->rtable); parse->rtable);
...@@ -104,10 +108,76 @@ planner(Query *parse) ...@@ -104,10 +108,76 @@ planner(Query *parse)
result_plan = query_planner(parse, result_plan = query_planner(parse,
parse->commandType, parse->commandType,
preprocessed_tlist, tlist,
primary_qual); primary_qual);
} }
/*
* If we have a GROUP BY clause, insert a group node (with the
* appropriate sort node.)
*/
if (parse->groupClause != NULL)
{
bool tuplePerGroup;
/*
* decide whether how many tuples per group the Group node needs
* to return. (Needs only one tuple per group if no aggregate is
* present. Otherwise, need every tuple from the group to do the
* aggregation.)
*/
tuplePerGroup = (parse->qry_aggs) ? TRUE : FALSE;
result_plan =
make_groupPlan( &tlist,
tuplePerGroup,
parse->groupClause,
result_plan);
}
/*
* If aggregate is present, insert the agg node
*/
if (parse->qry_aggs)
{
aggplan = make_agg(tlist,
parse->qry_numAgg,
parse->qry_aggs,
result_plan);
/*
* set the varno/attno entries to the appropriate references to
* the result tuple of the subplans. (We need to set those in the
* array of aggreg's in the Agg node also. Even though they're
* pointers, after a few dozen's of copying, they're not the same
* as those in the target list.)
*/
set_agg_tlist_references(aggplan);
set_agg_agglist_references(aggplan);
result_plan = (Plan *) aggplan;
}
/*
* fix up the flattened target list of the plan root node so that
* expressions are evaluated. this forces expression evaluations that
* may involve expensive function calls to be delayed to the very last
* stage of query execution. this could be bad. but it is joey's
* responsibility to optimally push these expressions down the plan
* tree. -- Wei
*
* But now nothing to do if there are GroupBy and/or Aggregates: 1.
* make_groupPlan fixes tlist; 2. flatten_tlist_vars does nothing with
* aggregates fixing only other entries (i.e. - GroupBy-ed and so
* fixed by make_groupPlan). - vadim 04/05/97
*/
if (parse->groupClause == NULL && aggplan == NULL)
{
result_plan->targetlist = flatten_tlist_vars(tlist,
result_plan->targetlist);
}
/* /*
* For now, before we hand back the plan, check to see if there is a * For now, before we hand back the plan, check to see if there is a
* user-specified sort that needs to be done. Eventually, this will * user-specified sort that needs to be done. Eventually, this will
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.8 1997/09/08 21:45:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.9 1997/12/20 07:59:28 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -47,6 +47,7 @@ static List *tlist_temp_references(Oid tempid, List *tlist); ...@@ -47,6 +47,7 @@ static List *tlist_temp_references(Oid tempid, List *tlist);
static void replace_result_clause(List *clause, List *subplanTargetList); static void replace_result_clause(List *clause, List *subplanTargetList);
static bool OperandIsInner(Node *opnd, int inner_relid); static bool OperandIsInner(Node *opnd, int inner_relid);
static void replace_agg_clause(Node *expr, List *targetlist); static void replace_agg_clause(Node *expr, List *targetlist);
static Node *del_agg_clause(Node *clause);
/***************************************************************************** /*****************************************************************************
* *
...@@ -803,3 +804,96 @@ replace_agg_clause(Node *clause, List *subplanTargetList) ...@@ -803,3 +804,96 @@ replace_agg_clause(Node *clause, List *subplanTargetList)
} }
} }
/*
* del_agg_tlist_references
* Remove the Agg nodes from the target list
* We do this so inheritance only does aggregates in the upper node
*/
void del_agg_tlist_references(List *tlist)
{
List *tl;
foreach(tl, tlist)
{
TargetEntry *tle = lfirst(tl);
tle->expr = del_agg_clause(tle->expr);
}
}
static Node *
del_agg_clause(Node *clause)
{
List *t;
if (IsA(clause, Var))
{
return clause;
}
else if (is_funcclause(clause))
{
/*
* This is a function. Recursively call this routine for its
* arguments...
*/
foreach(t, ((Expr *) clause)->args)
{
lfirst(t) = del_agg_clause(lfirst(t));
}
}
else if (IsA(clause, Aggreg))
{
/* here is the real action, to remove the Agg node */
return del_agg_clause(((Aggreg *) clause)->target);
}
else if (IsA(clause, ArrayRef))
{
ArrayRef *aref = (ArrayRef *) clause;
/*
* This is an arrayref. Recursively call this routine for its
* expression and its index expression...
*/
foreach(t, aref->refupperindexpr)
{
lfirst(t) = del_agg_clause(lfirst(t));
}
foreach(t, aref->reflowerindexpr)
{
lfirst(t) = del_agg_clause(lfirst(t));
}
aref->refexpr = del_agg_clause(aref->refexpr);
aref->refassgnexpr = del_agg_clause(aref->refassgnexpr);
}
else if (is_opclause(clause))
{
/*
* This is an operator. Recursively call this routine for both its
* left and right operands
*/
Node *left = (Node *) get_leftop((Expr *) clause);
Node *right = (Node *) get_rightop((Expr *) clause);
if (left != (Node *) NULL)
left = del_agg_clause(left);
if (right != (Node *) NULL)
right = del_agg_clause(right);
}
else if (IsA(clause, Param) ||IsA(clause, Const))
{
return clause;
}
else
{
/*
* Ooops! we can not handle that!
*/
elog(WARN, "del_agg_clause: Can not handle this tlist!\n");
}
return NULL;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.10 1997/12/18 03:03:41 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.11 1997/12/20 07:59:33 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,21 +33,16 @@ ...@@ -33,21 +33,16 @@
#include "optimizer/planner.h" #include "optimizer/planner.h"
#include "optimizer/prep.h" #include "optimizer/prep.h"
static List * static List *plan_union_query(List *relids, Index rt_index,
plan_union_query(List *relids, Index rt_index,
RangeTblEntry *rt_entry, Query *parse, UnionFlag flag, RangeTblEntry *rt_entry, Query *parse, UnionFlag flag,
List **union_rtentriesPtr); List **union_rtentriesPtr);
static RangeTblEntry * static RangeTblEntry *new_rangetable_entry(Oid new_relid,
new_rangetable_entry(Oid new_relid,
RangeTblEntry *old_entry); RangeTblEntry *old_entry);
static Query * static Query *subst_rangetable(Query *root, Index index,
subst_rangetable(Query *root, Index index,
RangeTblEntry *new_entry); RangeTblEntry *new_entry);
static void static void fix_parsetree_attnums(Index rt_index, Oid old_relid,
fix_parsetree_attnums(Index rt_index, Oid old_relid,
Oid new_relid, Query *parsetree); Oid new_relid, Query *parsetree);
static Append * static Append *make_append(List *unionplans, Index rt_index,
make_append(List *unionplans, Index rt_index,
List *union_rt_entries, List *tlist); List *union_rt_entries, List *tlist);
...@@ -238,12 +233,12 @@ plan_union_query(List *relids, ...@@ -238,12 +233,12 @@ plan_union_query(List *relids,
* reset the uniqueflag and sortclause in parse tree root, so that * reset the uniqueflag and sortclause in parse tree root, so that
* sorting will only be done once after append * sorting will only be done once after append
*/ */
/* new_root->uniqueFlag = false; */
new_root->uniqueFlag = NULL; new_root->uniqueFlag = NULL;
new_root->sortClause = NULL; new_root->sortClause = NULL;
new_root->groupClause = NULL; new_root->groupClause = NULL;
new_root->qry_numAgg = 0; new_root->qry_numAgg = 0;
new_root->qry_aggs = NULL; new_root->qry_aggs = NULL;
del_agg_tlist_references(new_root->targetList);
fix_parsetree_attnums(rt_index, fix_parsetree_attnums(rt_index,
rt_entry->relid, rt_entry->relid,
relid, relid,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: planmain.h,v 1.8 1997/12/18 12:54:41 momjian Exp $ * $Id: planmain.h,v 1.9 1997/12/20 07:59:43 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -57,6 +57,7 @@ extern List *index_outerjoin_references(List *inner_indxqual, ...@@ -57,6 +57,7 @@ extern List *index_outerjoin_references(List *inner_indxqual,
extern void set_result_tlist_references(Result *resultNode); extern void set_result_tlist_references(Result *resultNode);
extern void set_agg_tlist_references(Agg *aggNode); extern void set_agg_tlist_references(Agg *aggNode);
extern void set_agg_agglist_references(Agg *aggNode); extern void set_agg_agglist_references(Agg *aggNode);
extern void del_agg_tlist_references(List *tlist);
#endif /* PLANMAIN_H */ #endif /* PLANMAIN_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: prep.h,v 1.8 1997/12/18 12:54:45 momjian Exp $ * $Id: prep.h,v 1.9 1997/12/20 07:59:44 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,8 +24,7 @@ extern List *cnfify(Expr *qual, bool removeAndFlag); ...@@ -24,8 +24,7 @@ extern List *cnfify(Expr *qual, bool removeAndFlag);
/* /*
* prototypes for preptlist.h * prototypes for preptlist.h
*/ */
extern List * extern List *preprocess_targetlist(List *tlist, int command_type,
preprocess_targetlist(List *tlist, int command_type,
Index result_relation, List *range_table); Index result_relation, List *range_table);
/* /*
...@@ -36,12 +35,10 @@ typedef enum UnionFlag ...@@ -36,12 +35,10 @@ typedef enum UnionFlag
INHERITS_FLAG, VERSION_FLAG INHERITS_FLAG, VERSION_FLAG
} UnionFlag; } UnionFlag;
extern List * extern List *find_all_inheritors(List *unexamined_relids,
find_all_inheritors(List *unexamined_relids,
List *examined_relids); List *examined_relids);
extern int first_matching_rt_entry(List *rangetable, UnionFlag flag); extern int first_matching_rt_entry(List *rangetable, UnionFlag flag);
extern Append * extern Append *plan_union_queries(Index rt_index, Query *parse,
plan_union_queries(Index rt_index, Query *parse,
UnionFlag flag); UnionFlag flag);
#endif /* PREP_H */ #endif /* PREP_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment