mirror of
https://github.com/postgres/postgres.git
synced 2025-09-03 15:22:11 +03:00
Make the behavior of HAVING without GROUP BY conform to the SQL spec.
Formerly, if such a clause contained no aggregate functions we mistakenly treated it as equivalent to WHERE. Per spec it must cause the query to be treated as a grouped query of a single group, the same as appearance of aggregate functions would do. Also, the HAVING filter must execute after aggregate function computation even if it itself contains no aggregate functions.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.147 2004/12/31 22:00:45 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.148 2005/03/10 23:21:24 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -181,18 +181,6 @@ rewriteRuleAction(Query *parsetree,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We copy the qualifications of the parsetree to the action and vice
|
||||
* versa. So force hasSubLinks if one of them has it. If this is not
|
||||
* right, the flag will get cleared later, but we mustn't risk having
|
||||
* it not set when it needs to be. (XXX this should probably be
|
||||
* handled by AddQual and friends, not here...)
|
||||
*/
|
||||
if (parsetree->hasSubLinks)
|
||||
sub_action->hasSubLinks = TRUE;
|
||||
else if (sub_action->hasSubLinks)
|
||||
parsetree->hasSubLinks = TRUE;
|
||||
|
||||
/*
|
||||
* Event Qualification forces copying of parsetree and splitting into
|
||||
* two queries one w/rule_qual, one w/NOT rule_qual. Also add user
|
||||
@@ -996,23 +984,6 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
|
||||
query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
|
||||
QTW_IGNORE_RT_SUBQUERIES);
|
||||
|
||||
/*
|
||||
* If the query was marked having aggregates, check if this is still
|
||||
* true after rewriting. Ditto for sublinks. Note there should be no
|
||||
* aggs in the qual at this point. (Does this code still do anything
|
||||
* useful? The view-becomes-subselect-in-FROM approach doesn't look
|
||||
* like it could remove aggs or sublinks...)
|
||||
*/
|
||||
if (parsetree->hasAggs)
|
||||
{
|
||||
parsetree->hasAggs = checkExprHasAggs((Node *) parsetree);
|
||||
if (parsetree->hasAggs)
|
||||
if (checkExprHasAggs((Node *) parsetree->jointree))
|
||||
elog(ERROR, "failed to remove aggregates from qual");
|
||||
}
|
||||
if (parsetree->hasSubLinks)
|
||||
parsetree->hasSubLinks = checkExprHasSubLink((Node *) parsetree);
|
||||
|
||||
return parsetree;
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.89 2004/12/31 22:00:46 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.90 2005/03/10 23:21:24 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -37,8 +37,7 @@ static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid);
|
||||
|
||||
/*
|
||||
* checkExprHasAggs -
|
||||
* Queries marked hasAggs might not have them any longer after
|
||||
* rewriting. Check it.
|
||||
* Check if an expression contains an aggregate function call.
|
||||
*
|
||||
* The objective of this routine is to detect whether there are aggregates
|
||||
* belonging to the initial query level. Aggregates belonging to subqueries
|
||||
@@ -93,8 +92,7 @@ checkExprHasAggs_walker(Node *node, checkExprHasAggs_context *context)
|
||||
|
||||
/*
|
||||
* checkExprHasSubLink -
|
||||
* Queries marked hasSubLinks might not have them any longer after
|
||||
* rewriting. Check it.
|
||||
* Check if an expression contains a SubLink.
|
||||
*/
|
||||
bool
|
||||
checkExprHasSubLink(Node *node)
|
||||
@@ -756,68 +754,14 @@ AddQual(Query *parsetree, Node *qual)
|
||||
copy);
|
||||
|
||||
/*
|
||||
* Make sure query is marked correctly if added qual has sublinks or
|
||||
* aggregates (not sure it can ever have aggs, but sublinks
|
||||
* definitely). Need not search qual when query is already marked.
|
||||
* We had better not have stuck an aggregate into the WHERE clause.
|
||||
*/
|
||||
if (!parsetree->hasAggs)
|
||||
parsetree->hasAggs = checkExprHasAggs(copy);
|
||||
if (!parsetree->hasSubLinks)
|
||||
parsetree->hasSubLinks = checkExprHasSubLink(copy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the given havingQual to the one already contained in the parsetree
|
||||
* just as AddQual does for the normal 'where' qual
|
||||
*/
|
||||
void
|
||||
AddHavingQual(Query *parsetree, Node *havingQual)
|
||||
{
|
||||
Node *copy;
|
||||
|
||||
if (havingQual == NULL)
|
||||
return;
|
||||
|
||||
if (parsetree->commandType == CMD_UTILITY)
|
||||
{
|
||||
/*
|
||||
* There's noplace to put the qual on a utility statement.
|
||||
*
|
||||
* See comments in AddQual for motivation.
|
||||
*/
|
||||
if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
|
||||
return;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("conditional utility statements are not implemented")));
|
||||
}
|
||||
|
||||
if (parsetree->setOperations != NULL)
|
||||
{
|
||||
/*
|
||||
* There's noplace to put the qual on a setop statement, either.
|
||||
* (This could be fixed, but right now the planner simply ignores
|
||||
* any qual condition on a setop query.)
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
|
||||
}
|
||||
|
||||
/* INTERSECT want's the original, but we need to copy - Jan */
|
||||
copy = copyObject(havingQual);
|
||||
|
||||
parsetree->havingQual = make_and_qual(parsetree->havingQual,
|
||||
copy);
|
||||
Assert(!checkExprHasAggs(copy));
|
||||
|
||||
/*
|
||||
* Make sure query is marked correctly if added qual has sublinks or
|
||||
* aggregates (not sure it can ever have aggs, but sublinks
|
||||
* definitely). Need not search qual when query is already marked.
|
||||
* Make sure query is marked correctly if added qual has sublinks.
|
||||
* Need not search qual when query is already marked.
|
||||
*/
|
||||
if (!parsetree->hasAggs)
|
||||
parsetree->hasAggs = checkExprHasAggs(copy);
|
||||
if (!parsetree->hasSubLinks)
|
||||
parsetree->hasSubLinks = checkExprHasSubLink(copy);
|
||||
}
|
||||
|
Reference in New Issue
Block a user