88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.98 2000/12/14 22:30:43 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.99 2001/01/18 07:12:37 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -132,6 +132,7 @@ subquery_planner(Query *parse, double tuple_fraction)
132132List * saved_initplan = PlannerInitPlan ;
133133int saved_planid = PlannerPlanId ;
134134Plan * plan ;
135+ List * newHaving ;
135136List * lst ;
136137
137138/* Set up for a new level of subquery */
@@ -155,20 +156,6 @@ subquery_planner(Query *parse, double tuple_fraction)
155156parse -> jointree = (FromExpr * )
156157preprocess_jointree (parse , (Node * )parse -> jointree );
157158
158- /*
159- * A HAVING clause without aggregates is equivalent to a WHERE clause
160- * (except it can only refer to grouped fields). If there are no aggs
161- * anywhere in the query, then we don't want to create an Agg plan
162- * node, so merge the HAVING condition into WHERE.(We used to
163- * consider this an error condition, but it seems to be legal SQL.)
164- */
165- if (parse -> havingQual != NULL && !parse -> hasAggs )
166- {
167- parse -> jointree -> quals = make_and_qual (parse -> jointree -> quals ,
168- parse -> havingQual );
169- parse -> havingQual = NULL ;
170- }
171-
172159/*
173160 * Do expression preprocessing on targetlist and quals.
174161 */
@@ -181,6 +168,37 @@ subquery_planner(Query *parse, double tuple_fraction)
181168parse -> havingQual = preprocess_expression (parse ,parse -> havingQual ,
182169EXPRKIND_HAVING );
183170
171+ /*
172+ * A HAVING clause without aggregates is equivalent to a WHERE clause
173+ * (except it can only refer to grouped fields). Transfer any agg-free
174+ * clauses of the HAVING qual into WHERE. This may seem like wasting
175+ * cycles to cater to stupidly-written queries, but there are other
176+ * reasons for doing it. Firstly, if the query contains no aggs at all,
177+ * then we aren't going to generate an Agg plan node, and so there'll be
178+ * no place to execute HAVING conditions; without this transfer, we'd
179+ * lose the HAVING condition entirely, which is wrong. Secondly, when
180+ * we push down a qual condition into a sub-query, it's easiest to push
181+ * the qual into HAVING always, in case it contains aggs, and then let
182+ * this code sort it out.
183+ *
184+ * Note that both havingQual and parse->jointree->quals are in
185+ * implicitly-ANDed-list form at this point, even though they are
186+ * declared as Node *. Also note that contain_agg_clause does not
187+ * recurse into sub-selects, which is exactly what we need here.
188+ */
189+ newHaving = NIL ;
190+ foreach (lst , (List * )parse -> havingQual )
191+ {
192+ Node * havingclause = (Node * )lfirst (lst );
193+
194+ if (contain_agg_clause (havingclause ))
195+ newHaving = lappend (newHaving ,havingclause );
196+ else
197+ parse -> jointree -> quals = (Node * )
198+ lappend ((List * )parse -> jointree -> quals ,havingclause );
199+ }
200+ parse -> havingQual = (Node * )newHaving ;
201+
184202/*
185203 * Do the main planning. If we have an inherited target relation,
186204 * that needs special processing, else go straight to grouping_planner.
@@ -554,12 +572,6 @@ preprocess_expression(Query *parse, Node *expr, int kind)
554572 * Check for ungrouped variables passed to subplans. Note we
555573 * do NOT do this for subplans in WHERE (or JOIN/ON); it's legal
556574 * there because WHERE is evaluated pre-GROUP.
557- *
558- * An interesting fine point: if subquery_planner reassigned a
559- * HAVING qual into WHERE, then we will accept references to
560- * ungrouped vars from subplans in the HAVING qual. This is not
561- * entirely consistent, but it doesn't seem particularly
562- * harmful...
563575 */
564576check_subplans_for_ungrouped_vars (expr ,parse );
565577}
@@ -1049,6 +1061,11 @@ grouping_planner(Query *parse, double tuple_fraction)
10491061result_plan );
10501062/* Note: Agg does not affect any existing sort order of the tuples */
10511063}
1064+ else
1065+ {
1066+ /* If there are no Aggs, we shouldn't have any HAVING qual anymore */
1067+ Assert (parse -> havingQual == NULL );
1068+ }
10521069
10531070/*
10541071 * If we were not able to make the plan come out in the right order,