aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1997-12-20 07:59:44 +0000
committerBruce Momjian <bruce@momjian.us>1997-12-20 07:59:44 +0000
commit7fd4782504c6bb090261b03a3152193cd8e22439 (patch)
tree1aa738bb41f86df6366432dc46b0eb513dca8d0e
parent1783963cab9e938b04b936f61d287384d7f11f2a (diff)
downloadpostgresql-7fd4782504c6bb090261b03a3152193cd8e22439.tar.gz
postgresql-7fd4782504c6bb090261b03a3152193cd8e22439.zip
Fix aggregates on inherited tables.
-rw-r--r--src/backend/optimizer/plan/planmain.c69
-rw-r--r--src/backend/optimizer/plan/planner.c94
-rw-r--r--src/backend/optimizer/plan/setrefs.c96
-rw-r--r--src/backend/optimizer/prep/prepunion.c19
-rw-r--r--src/include/optimizer/planmain.h3
-rw-r--r--src/include/optimizer/prep.h11
6 files changed, 193 insertions, 99 deletions
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index a22c7e6ffc3..d26e3eb8b49 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -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,
@@ -175,49 +174,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
*/
if (constant_qual)
@@ -237,25 +193,6 @@ query_planner(Query *root,
}
/*
- * 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,
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 40e9cc50a63..381c609493b 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -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,13 +74,13 @@ 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
@@ -86,29 +88,97 @@ planner(Query *parse)
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,
- parse->commandType,
- parse->resultRelation,
- parse->rtable);
+ tlist = preprocess_targetlist(tlist,
+ parse->commandType,
+ parse->resultRelation,
+ parse->rtable);
primary_qual = cnfify((Expr *) parse->qual, true);
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
* be moved into the guts of the planner s.t. user specified sorts
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index b6afa5fcb92..1d0f0963c5a 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -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;
+}
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index e5346c388d7..7f9645e0f32 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -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,
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index e2683fc61f7..04363edd03e 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -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 */
diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h
index 5040a32b852..8f63f798cb8 100644
--- a/src/include/optimizer/prep.h
+++ b/src/include/optimizer/prep.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 */