mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-02 19:26:51 +02:00
Fix using GroupBy/non-GroupBy expressions in HAVING.
This commit is contained in:
parent
04abb54197
commit
9a2949e5dd
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.34 1998/09/08 02:50:20 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.35 1998/09/09 03:48:01 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -185,9 +185,6 @@ union_planner(Query *parse)
|
|||||||
*/
|
*/
|
||||||
if (parse->hasAggs)
|
if (parse->hasAggs)
|
||||||
{
|
{
|
||||||
int old_length = 0,
|
|
||||||
new_length = 0;
|
|
||||||
|
|
||||||
result_plan = (Plan *) make_agg(tlist, result_plan);
|
result_plan = (Plan *) make_agg(tlist, result_plan);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -256,31 +253,10 @@ union_planner(Query *parse)
|
|||||||
*/
|
*/
|
||||||
foreach(clause, ((Agg *) result_plan)->plan.qual)
|
foreach(clause, ((Agg *) result_plan)->plan.qual)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure there are aggregates in the havingQual if so,
|
|
||||||
* the list must be longer after
|
|
||||||
* check_having_qual_for_aggs
|
|
||||||
*/
|
|
||||||
old_length = length(((Agg *) result_plan)->aggs);
|
|
||||||
|
|
||||||
((Agg *) result_plan)->aggs = nconc(((Agg *) result_plan)->aggs,
|
((Agg *) result_plan)->aggs = nconc(((Agg *) result_plan)->aggs,
|
||||||
check_having_qual_for_aggs((Node *) lfirst(clause),
|
check_having_qual_for_aggs((Node *) lfirst(clause),
|
||||||
((Agg *) result_plan)->plan.lefttree->targetlist,
|
((Agg *) result_plan)->plan.lefttree->targetlist,
|
||||||
((List *) parse->groupClause)));
|
((List *) parse->groupClause)));
|
||||||
|
|
||||||
/*
|
|
||||||
* Have a look at the length of the returned list. If
|
|
||||||
* there is no difference, no aggregates have been found
|
|
||||||
* and that means, that the Qual belongs to the where
|
|
||||||
* clause
|
|
||||||
*/
|
|
||||||
if (((new_length = length(((Agg *) result_plan)->aggs)) == old_length) ||
|
|
||||||
(new_length == 0))
|
|
||||||
{
|
|
||||||
elog(ERROR, "This could have been done in a where clause!!");
|
|
||||||
return (Plan *) NIL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PlannerVarParam = lnext(PlannerVarParam);
|
PlannerVarParam = lnext(PlannerVarParam);
|
||||||
if (vpm != NULL)
|
if (vpm != NULL)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.26 1998/09/01 04:29:54 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.27 1998/09/09 03:48:02 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1045,36 +1045,15 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla
|
|||||||
else if (is_funcclause(clause) || not_clause(clause) ||
|
else if (is_funcclause(clause) || not_clause(clause) ||
|
||||||
or_clause(clause) || and_clause(clause))
|
or_clause(clause) || and_clause(clause))
|
||||||
{
|
{
|
||||||
int new_length = 0,
|
|
||||||
old_length = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a function. Recursively call this routine for its
|
* This is a function. Recursively call this routine for its
|
||||||
* arguments... (i.e. for AND, OR, ... clauses!)
|
* arguments... (i.e. for AND, OR, ... clauses!)
|
||||||
*/
|
*/
|
||||||
foreach(t, ((Expr *) clause)->args)
|
foreach(t, ((Expr *) clause)->args)
|
||||||
{
|
{
|
||||||
old_length = length((List *) agg_list);
|
|
||||||
|
|
||||||
agg_list = nconc(agg_list,
|
agg_list = nconc(agg_list,
|
||||||
check_having_qual_for_aggs(lfirst(t), subplanTargetList,
|
check_having_qual_for_aggs(lfirst(t), subplanTargetList,
|
||||||
groupClause));
|
groupClause));
|
||||||
|
|
||||||
/*
|
|
||||||
* The arguments of OR or AND clauses are comparisons or
|
|
||||||
* relations and because we are in the havingQual there must
|
|
||||||
* be at least one operand using an aggregate function. If so,
|
|
||||||
* we will find it and the lenght of the agg_list will be
|
|
||||||
* increased after the above call to
|
|
||||||
* check_having_qual_for_aggs. If there are no aggregates
|
|
||||||
* used, the query could have been formulated using the
|
|
||||||
* 'where' clause
|
|
||||||
*/
|
|
||||||
if (((new_length = length((List *) agg_list)) == old_length) || (new_length == 0))
|
|
||||||
{
|
|
||||||
elog(ERROR, "This could have been done in a where clause!!");
|
|
||||||
return NIL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return agg_list;
|
return agg_list;
|
||||||
}
|
}
|
||||||
@ -1199,7 +1178,6 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ooops! we can not handle that!
|
* Ooops! we can not handle that!
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.13 1998/09/01 04:30:26 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.14 1998/09/09 03:48:17 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -104,7 +104,8 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
|
|||||||
List *gl;
|
List *gl;
|
||||||
|
|
||||||
if (expr == NULL || IsA(expr, Const) ||
|
if (expr == NULL || IsA(expr, Const) ||
|
||||||
IsA(expr, Param) ||IsA(expr, Aggreg))
|
IsA(expr, Param) || IsA(expr, Aggreg) ||
|
||||||
|
IsA(expr, SubLink)) /* can't handle currently !!! */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
foreach(gl, groupClause)
|
foreach(gl, groupClause)
|
||||||
@ -207,13 +208,10 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
|||||||
* the expression specified in the HAVING clause has the same
|
* the expression specified in the HAVING clause has the same
|
||||||
* restriction as those in the target list.
|
* restriction as those in the target list.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* Need to change here when we get HAVING works. Currently
|
|
||||||
* qry->havingQual is NULL. - vadim 04/05/97
|
|
||||||
if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
|
if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"parser: illegal use of aggregates or non-group column in HAVING clause");
|
"parser: illegal use of aggregates or non-group column in HAVING clause");
|
||||||
*/
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user