diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 1999-10-07 04:23:24 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 1999-10-07 04:23:24 +0000 |
commit | 3eb1c8227751aecede58e742a13b07127a7e2652 (patch) | |
tree | c2f606088b1536e385811667c7f032552b89afa6 /src/backend/optimizer/plan/planner.c | |
parent | 4040fcfa78065882aa16895906ff8398aaaf1c23 (diff) |
Fix planner and rewriter to follow SQL semantics for tables that are
mentioned in FROM but not elsewhere in the query: such tables should be
joined over anyway. Aside from being more standards-compliant, this allows
removal of some very ugly hacks for COUNT(*) processing. Also, allow
HAVING clause without aggregate functions, since SQL does. Clean up
CREATE RULE statement-list syntax the same way Bruce just fixed the
main stmtmulti production.
CAUTION: addition of a field to RangeTblEntry nodes breaks stored rules;
you will have to initdb if you have any rules.
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 53 |
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); |