mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Fix aggregates on inherited tables.
This commit is contained in:
parent
1783963cab
commit
7fd4782504
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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 @@
|
||||
static Plan *subplanner(Query *root, List *flat_tlist, List *qual);
|
||||
static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
|
||||
|
||||
static Plan *
|
||||
extern Plan *
|
||||
make_groupPlan(List **tlist, bool tuplePerGroup,
|
||||
List *groupClause, Plan *subplan);
|
||||
|
||||
@ -72,7 +72,6 @@ query_planner(Query *root,
|
||||
List *flattened_tlist = NIL;
|
||||
List *level_tlist = NIL;
|
||||
Plan *subplan = (Plan *) NULL;
|
||||
Agg *aggplan = NULL;
|
||||
|
||||
/*
|
||||
* A command without a target list or qualification is an error,
|
||||
@ -174,49 +173,6 @@ query_planner(Query *root,
|
||||
|
||||
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
|
||||
*/
|
||||
@ -236,25 +192,6 @@ query_planner(Query *root,
|
||||
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
|
||||
* to flatten functions that return sets of base types
|
||||
@ -380,7 +317,7 @@ make_result(List *tlist,
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static Plan *
|
||||
Plan *
|
||||
make_groupPlan(List **tlist,
|
||||
bool tuplePerGroup,
|
||||
List *groupClause,
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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 @@
|
||||
#include "executor/executor.h"
|
||||
|
||||
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)
|
||||
List *rangetable = parse->rtable;
|
||||
char *uniqueflag = parse->uniqueFlag;
|
||||
List *sortclause = parse->sortClause;
|
||||
Plan *special_plans = (Plan *) NULL;
|
||||
Agg *aggplan = NULL;
|
||||
|
||||
Plan *result_plan = (Plan *) NULL;
|
||||
|
||||
List *preprocessed_tlist = NIL;
|
||||
List *primary_qual;
|
||||
int rt_index;
|
||||
|
||||
|
||||
/*
|
||||
* plan inheritance
|
||||
*/
|
||||
rt_index = first_matching_rt_entry(rangetable, INHERITS_FLAG);
|
||||
if (rt_index != -1)
|
||||
{
|
||||
special_plans = (Plan *) plan_union_queries((Index) rt_index,
|
||||
result_plan = (Plan *) plan_union_queries((Index) rt_index,
|
||||
parse,
|
||||
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
|
||||
{
|
||||
preprocessed_tlist = preprocess_targetlist(tlist,
|
||||
tlist = preprocess_targetlist(tlist,
|
||||
parse->commandType,
|
||||
parse->resultRelation,
|
||||
parse->rtable);
|
||||
@ -104,10 +108,76 @@ planner(Query *parse)
|
||||
|
||||
result_plan = query_planner(parse,
|
||||
parse->commandType,
|
||||
preprocessed_tlist,
|
||||
tlist,
|
||||
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
|
||||
* user-specified sort that needs to be done. Eventually, this will
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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);
|
||||
static void replace_result_clause(List *clause, List *subplanTargetList);
|
||||
static bool OperandIsInner(Node *opnd, int inner_relid);
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 @@
|
||||
*
|
||||
*
|
||||
* 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 @@
|
||||
#include "optimizer/planner.h"
|
||||
#include "optimizer/prep.h"
|
||||
|
||||
static List *
|
||||
plan_union_query(List *relids, Index rt_index,
|
||||
static List *plan_union_query(List *relids, Index rt_index,
|
||||
RangeTblEntry *rt_entry, Query *parse, UnionFlag flag,
|
||||
List **union_rtentriesPtr);
|
||||
static RangeTblEntry *
|
||||
new_rangetable_entry(Oid new_relid,
|
||||
static RangeTblEntry *new_rangetable_entry(Oid new_relid,
|
||||
RangeTblEntry *old_entry);
|
||||
static Query *
|
||||
subst_rangetable(Query *root, Index index,
|
||||
static Query *subst_rangetable(Query *root, Index index,
|
||||
RangeTblEntry *new_entry);
|
||||
static void
|
||||
fix_parsetree_attnums(Index rt_index, Oid old_relid,
|
||||
static void fix_parsetree_attnums(Index rt_index, Oid old_relid,
|
||||
Oid new_relid, Query *parsetree);
|
||||
static Append *
|
||||
make_append(List *unionplans, Index rt_index,
|
||||
static Append *make_append(List *unionplans, Index rt_index,
|
||||
List *union_rt_entries, List *tlist);
|
||||
|
||||
|
||||
@ -238,12 +233,12 @@ plan_union_query(List *relids,
|
||||
* reset the uniqueflag and sortclause in parse tree root, so that
|
||||
* sorting will only be done once after append
|
||||
*/
|
||||
/* new_root->uniqueFlag = false; */
|
||||
new_root->uniqueFlag = NULL;
|
||||
new_root->sortClause = NULL;
|
||||
new_root->groupClause = NULL;
|
||||
new_root->qry_numAgg = 0;
|
||||
new_root->qry_aggs = NULL;
|
||||
del_agg_tlist_references(new_root->targetList);
|
||||
fix_parsetree_attnums(rt_index,
|
||||
rt_entry->relid,
|
||||
relid,
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* 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,
|
||||
extern void set_result_tlist_references(Result *resultNode);
|
||||
extern void set_agg_tlist_references(Agg *aggNode);
|
||||
extern void set_agg_agglist_references(Agg *aggNode);
|
||||
extern void del_agg_tlist_references(List *tlist);
|
||||
|
||||
|
||||
#endif /* PLANMAIN_H */
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* 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);
|
||||
/*
|
||||
* prototypes for preptlist.h
|
||||
*/
|
||||
extern List *
|
||||
preprocess_targetlist(List *tlist, int command_type,
|
||||
extern List *preprocess_targetlist(List *tlist, int command_type,
|
||||
Index result_relation, List *range_table);
|
||||
|
||||
/*
|
||||
@ -36,12 +35,10 @@ typedef enum UnionFlag
|
||||
INHERITS_FLAG, VERSION_FLAG
|
||||
} UnionFlag;
|
||||
|
||||
extern List *
|
||||
find_all_inheritors(List *unexamined_relids,
|
||||
extern List *find_all_inheritors(List *unexamined_relids,
|
||||
List *examined_relids);
|
||||
extern int first_matching_rt_entry(List *rangetable, UnionFlag flag);
|
||||
extern Append *
|
||||
plan_union_queries(Index rt_index, Query *parse,
|
||||
extern Append *plan_union_queries(Index rt_index, Query *parse,
|
||||
UnionFlag flag);
|
||||
|
||||
#endif /* PREP_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user