aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1998-03-30 16:36:43 +0000
committerBruce Momjian <bruce@momjian.us>1998-03-30 16:36:43 +0000
commitc579ce0fb03aaf92d184adf369cf13be013adf1b (patch)
tree679a8e287af5009d916fd4936483322d22375614 /src/backend/optimizer/plan/planner.c
parent9c93fa2e4af9bb67261ecdedef2b5a97a9283f34 (diff)
downloadpostgresql-c579ce0fb03aaf92d184adf369cf13be013adf1b.tar.gz
postgresql-c579ce0fb03aaf92d184adf369cf13be013adf1b.zip
I started adding the Having Clause and it works quite fine for
sequential scans! (I think it will also work with hash, index, etc but I did not check it out! I made some High level changes which should work for all access methods, but maybe I'm wrong. Please let me know.) Now it is possible to make queries like: select s.sname, max(p.pid), min(p.pid) from part p, supplier s where s.sid=p.sid group by s.sname having max(pid)=6 and min(pid)=1 or avg(pid)=4; Having does not work yet for queries that contain a subselect statement in the Having clause, I'll try to fix this in the next days. If there are some bugs, please let me know, I'll start to read the mailinglists now! Now here is the patch against the original 6.3 version (no snapshot!!): Stefan
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c131
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;
}
+
+
+