From: Tom Lane Date: Thu, 3 Apr 2003 18:04:17 +0000 (+0000) Subject: Repair incorrect checking of grouped/ungrouped variables in the presence X-Git-Tag: REL7_3_3~40 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a880697f097b26c196d3e0cd079a03821deac95b;p=postgresql Repair incorrect checking of grouped/ungrouped variables in the presence of unnamed joins; per pghackers discussion 31-Mar-03. --- diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 127abdc2de..6a4f01c77f 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.50 2002/06/20 20:29:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.50.2.1 2003/04/03 18:04:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "optimizer/clauses.h" #include "optimizer/tlist.h" +#include "optimizer/var.h" #include "parser/parse_agg.h" #include "parser/parsetree.h" @@ -133,7 +134,9 @@ void parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual) { List *groupClauses = NIL; - List *tl; + List *lst; + bool hasJoinRTEs; + Node *clause; /* This should only be called if we found aggregates, GROUP, or HAVING */ Assert(pstate->p_hasAggs || qry->groupClause || qry->havingQual); @@ -158,9 +161,9 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual) * expressions for use by check_ungrouped_columns() (this avoids * repeated scans of the targetlist within the recursive routine...) */ - foreach(tl, qry->groupClause) + foreach(lst, qry->groupClause) { - GroupClause *grpcl = lfirst(tl); + GroupClause *grpcl = lfirst(lst); Node *expr; expr = get_sortgroupclause_expr(grpcl, qry->targetList); @@ -170,11 +173,38 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual) } /* - * Check the targetlist and HAVING clause for ungrouped variables. + * If there are join alias vars involved, we have to flatten them + * to the underlying vars, so that aliased and unaliased vars will be + * correctly taken as equal. We can skip the expense of doing this + * if no rangetable entries are RTE_JOIN kind. */ - check_ungrouped_columns((Node *) qry->targetList, pstate, groupClauses); - check_ungrouped_columns((Node *) qry->havingQual, pstate, groupClauses); + hasJoinRTEs = false; + foreach(lst, pstate->p_rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lst); + + if (rte->rtekind == RTE_JOIN) + { + hasJoinRTEs = true; + break; + } + } - /* Release the list storage (but not the pointed-to expressions!) */ - freeList(groupClauses); + if (hasJoinRTEs) + groupClauses = (List *) flatten_join_alias_vars((Node *) groupClauses, + pstate->p_rtable, + true); + + /* + * Check the targetlist and HAVING clause for ungrouped variables. + */ + clause = (Node *) qry->targetList; + if (hasJoinRTEs) + clause = flatten_join_alias_vars(clause, pstate->p_rtable, true); + check_ungrouped_columns(clause, pstate, groupClauses); + + clause = (Node *) qry->havingQual; + if (hasJoinRTEs) + clause = flatten_join_alias_vars(clause, pstate->p_rtable, true); + check_ungrouped_columns(clause, pstate, groupClauses); }