Repair incorrect checking of grouped/ungrouped variables in the presence
authorTom Lane
Thu, 3 Apr 2003 18:04:09 +0000 (18:04 +0000)
committerTom Lane
Thu, 3 Apr 2003 18:04:09 +0000 (18:04 +0000)
of unnamed joins; per pghackers discussion 31-Mar-03.

src/backend/parser/parse_agg.c

index f980d52f2b0e72e2fbee05a4f094227dcc2aa367..92ea3b9bd9e4b54198c802e78cc11fdbb11988f1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.51 2003/01/17 03:25:04 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.52 2003/04/03 18:04:09 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"
 
@@ -179,7 +180,9 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
 {
    List       *groupClauses = NIL;
    bool        have_non_var_grouping = false;
-   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);
@@ -205,9 +208,9 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
     * repeated scans of the targetlist within the recursive routine...).
     * And detect whether any of the expressions aren't simple Vars.
     */
-   foreach(tl, qry->groupClause)
+   foreach(lst, qry->groupClause)
    {
-       GroupClause *grpcl = lfirst(tl);
+       GroupClause *grpcl = (GroupClause *) lfirst(lst);
        Node       *expr;
 
        expr = get_sortgroupclause_expr(grpcl, qry->targetList);
@@ -220,14 +223,40 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
            have_non_var_grouping = true;
    }
 
+   /*
+    * 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.
+    */
+   hasJoinRTEs = false;
+   foreach(lst, pstate->p_rtable)
+   {
+       RangeTblEntry *rte = (RangeTblEntry *) lfirst(lst);
+
+       if (rte->rtekind == RTE_JOIN)
+       {
+           hasJoinRTEs = true;
+           break;
+       }
+   }
+
+   if (hasJoinRTEs)
+       groupClauses = (List *) flatten_join_alias_vars(qry,
+                                                       (Node *) groupClauses);
+
    /*
     * Check the targetlist and HAVING clause for ungrouped variables.
     */
-   check_ungrouped_columns((Node *) qry->targetList, pstate,
-                           groupClauses, have_non_var_grouping);
-   check_ungrouped_columns((Node *) qry->havingQual, pstate,
+   clause = (Node *) qry->targetList;
+   if (hasJoinRTEs)
+       clause = flatten_join_alias_vars(qry, clause);
+   check_ungrouped_columns(clause, pstate,
                            groupClauses, have_non_var_grouping);
 
-   /* Release the list storage (but not the pointed-to expressions!) */
-   freeList(groupClauses);
+   clause = (Node *) qry->havingQual;
+   if (hasJoinRTEs)
+       clause = flatten_join_alias_vars(qry, clause);
+   check_ungrouped_columns(clause, pstate,
+                           groupClauses, have_non_var_grouping);
 }