1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

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.
This commit is contained in:
Tom Lane
1999-10-07 04:23:24 +00:00
parent 4040fcfa78
commit 3eb1c82277
21 changed files with 408 additions and 390 deletions

View File

@ -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);