diff options
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 131 |
1 files changed, 129 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 824c0d29b35..35c19d6c44f 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.23 1998/02/26 04:32:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.24 1998/03/30 16:36:04 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -59,6 +59,115 @@ make_groupPlan(List **tlist, bool tuplePerGroup, * *****************************************************************************/ + +/***S*H***/ /* Anfang */ + +static List * +check_having_qual_for_aggs(Node *clause, List *subplanTargetList) +{ + List *t; + List *agg_list = NIL; + + if (IsA(clause, Var)) + { + TargetEntry *subplanVar; + + /* + * Ha! A Var node! + */ + subplanVar = match_varid((Var *) clause, subplanTargetList); + + /* + * Change the varno & varattno fields of the var node. + * + */ + ((Var *) clause)->varattno = subplanVar->resdom->resno; + return NIL; + } + /***S*H***/ + else if (is_funcclause(clause) || not_clause(clause) || + or_clause(clause) || and_clause(clause)) + { + + /* + * This is a function. Recursively call this routine for its + * arguments... + */ + foreach(t, ((Expr *) clause)->args) + { + agg_list = nconc(agg_list, + check_having_qual_for_aggs(lfirst(t), subplanTargetList)); + } + return agg_list; + } + else if (IsA(clause, Aggreg)) + { + return lcons(clause, + check_having_qual_for_aggs(((Aggreg *) clause)->target, subplanTargetList)); + + } + 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) + { + agg_list = nconc(agg_list, + check_having_qual_for_aggs(lfirst(t), subplanTargetList)); + } + foreach(t, aref->reflowerindexpr) + { + agg_list = nconc(agg_list, + check_having_qual_for_aggs(lfirst(t), subplanTargetList)); + } + agg_list = nconc(agg_list, + check_having_qual_for_aggs(aref->refexpr, subplanTargetList)); + agg_list = nconc(agg_list, + check_having_qual_for_aggs(aref->refassgnexpr, subplanTargetList)); + + return agg_list; + } + 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) + agg_list = nconc(agg_list, + check_having_qual_for_aggs(left, subplanTargetList)); + if (right != (Node *) NULL) + agg_list = nconc(agg_list, + check_having_qual_for_aggs(right, subplanTargetList)); + + return agg_list; + } + else if (IsA(clause, Param) ||IsA(clause, Const)) + { + /* do nothing! */ + return NIL; + } + else + { + + /* + * Ooops! we can not handle that! + */ + elog(ERROR, "check_having_qual_for_aggs: Can not handle this having_qual!\n"); + return NIL; + } +} +/***S*H***/ /* Ende */ + + Plan * planner(Query *parse) { @@ -181,7 +290,22 @@ union_planner(Query *parse) * the result tuple of the subplans. */ ((Agg *) result_plan)->aggs = - set_agg_tlist_references((Agg *) result_plan); + set_agg_tlist_references((Agg *) result_plan); + + /***S*H***/ + if(parse->havingQual!=NULL) { + List *clause; + + /***S*H***/ /* set qpqual of having clause */ + ((Agg *) result_plan)->plan.qual=cnfify((Expr *)parse->havingQual,true); + + foreach(clause, ((Agg *) result_plan)->plan.qual) + { + ((Agg *) result_plan)->aggs = nconc(((Agg *) result_plan)->aggs, + check_having_qual_for_aggs((Node *) lfirst(clause), + ((Agg *) result_plan)->plan.lefttree->targetlist)); + } + } } /* @@ -429,3 +553,6 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList) /* success */ return; } + + + |