aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index d78a650c05d..fce3800dc49 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.69 1999/09/26 02:28:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.70 1999/10/07 04:23:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -94,6 +94,37 @@ union_planner(Query *parse)
List *current_pathkeys = NIL;
Index rt_index;
+ /*
+ * A HAVING clause without aggregates is equivalent to a WHERE clause
+ * (except it can only refer to grouped fields). If there are no
+ * aggs anywhere in the query, then we don't want to create an Agg
+ * plan node, so merge the HAVING condition into WHERE. (We used to
+ * consider this an error condition, but it seems to be legal SQL.)
+ */
+ if (parse->havingQual != NULL && ! parse->hasAggs)
+ {
+ if (parse->qual == NULL)
+ parse->qual = parse->havingQual;
+ else
+ parse->qual = (Node *) make_andclause(lappend(lcons(parse->qual,
+ NIL),
+ parse->havingQual));
+ parse->havingQual = NULL;
+ }
+
+ /*
+ * Simplify constant expressions in targetlist and quals.
+ *
+ * Note that at this point the qual has not yet been converted to
+ * implicit-AND form, so we can apply eval_const_expressions directly.
+ * Also note that we need to do this before SS_process_sublinks,
+ * because that routine inserts bogus "Const" nodes.
+ */
+ tlist = (List *) eval_const_expressions((Node *) tlist);
+ parse->qual = eval_const_expressions(parse->qual);
+ parse->havingQual = eval_const_expressions(parse->havingQual);
+
+
if (parse->unionClause)
{
result_plan = (Plan *) plan_union_queries(parse);
@@ -221,7 +252,6 @@ union_planner(Query *parse)
/* Generate the (sub) plan */
result_plan = query_planner(parse,
- parse->commandType,
sub_tlist,
(List *) parse->qual);
@@ -301,25 +331,6 @@ union_planner(Query *parse)
*/
if (parse->havingQual)
{
- /*--------------------
- * Require the havingQual to contain at least one aggregate function
- * (else it could have been done as a WHERE constraint). This check
- * used to be much stricter, requiring an aggregate in each clause of
- * the CNF-ified qual. However, that's probably overly anal-retentive.
- * We now do it first so that we will not complain if there is an
- * aggregate but it gets optimized away by eval_const_expressions().
- * The agg itself is never const, of course, but consider
- * SELECT ... HAVING xyz OR (COUNT(*) > 1)
- * where xyz reduces to constant true in a particular query.
- * We probably should not refuse this query.
- *--------------------
- */
- if (pull_agg_clause(parse->havingQual) == NIL)
- elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
-
- /* Simplify constant expressions in havingQual */
- parse->havingQual = eval_const_expressions(parse->havingQual);
-
/* Convert the havingQual to implicit-AND normal form */
parse->havingQual = (Node *)
canonicalize_qual((Expr *) parse->havingQual, true);