Fix GroupBY func broken by HAVING.
authorVadim B. Mikheev
Tue, 8 Sep 1998 02:50:20 +0000 (02:50 +0000)
committerVadim B. Mikheev
Tue, 8 Sep 1998 02:50:20 +0000 (02:50 +0000)
src/backend/optimizer/plan/planner.c

index e513b4f368094c8d3b56ae9a78c497ecfc3c59fa..4fa4a11b7b4354da177211f12e95d615567c6da5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.33 1998/09/03 02:34:30 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.34 1998/09/08 02:50:20 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -95,17 +95,9 @@ Plan *
 union_planner(Query *parse)
 {
    List       *tlist = parse->targetList;
-
-   /*
-    * copy the original tlist, we will need the original one for the AGG
-    * node later on
-    */
-   List       *new_tlist = new_unsorted_tlist(tlist);
-
+   int         tlist_len = length(tlist);
    List       *rangetable = parse->rtable;
-
    Plan       *result_plan = (Plan *) NULL;
-
    Index       rt_index;
 
 
@@ -133,36 +125,18 @@ union_planner(Query *parse)
        List      **vpm = NULL;
 
        /*
-        * This is only necessary if aggregates are in use in queries
-        * like: SELECT sid FROM part GROUP BY sid HAVING MIN(pid) > 1;
-        * (pid is used but never selected for!!!) because the function
-        * 'query_planner' creates the plan for the lefttree of the
-        * 'GROUP' node and returns only those attributes contained in
-        * 'tlist'. The original 'tlist' contains only 'sid' here and
-        * that's why we have to to extend it to attributes which are not
-        * selected but are used in the havingQual.
-        */
-
-       /*
-        * 'check_having_qual_for_vars' takes the havingQual and the
-        * actual 'tlist' as arguments and recursively scans the
-        * havingQual for attributes (VAR nodes) that are not contained in
-        * 'tlist' yet. If so, it creates a new entry and attaches it to
-        * the list 'new_tlist' (consisting of the VAR node and the RESDOM
-        * node as usual with tlists :-)  )
+        * check_having_qual_for_vars takes the havingQual and the tlist
+        * as arguments and recursively scans the havingQual for VAR nodes 
+        * that are not contained in tlist yet. If so, it creates a new entry 
+        * and attaches it to the tlist. Latter, we use tlist_len to 
+        * truncate tlist - ie restore actual tlist...
         */
        if (parse->hasAggs)
        {
            if (parse->havingQual != NULL)
-               new_tlist = check_having_qual_for_vars(parse->havingQual, new_tlist);
+               tlist = check_having_qual_for_vars(parse->havingQual, tlist);
        }
 
-       new_tlist = preprocess_targetlist(new_tlist,
-                                         parse->commandType,
-                                         parse->resultRelation,
-                                         parse->rtable);
-
-       /* Here starts the original (pre having) code */
        tlist = preprocess_targetlist(tlist,
                                      parse->commandType,
                                      parse->resultRelation,
@@ -176,7 +150,7 @@ union_planner(Query *parse)
        PlannerVarParam = lcons(vpm, PlannerVarParam);
        result_plan = query_planner(parse,
                                    parse->commandType,
-                                   new_tlist,
+                                   tlist,
                                    (List *) parse->qual);
        PlannerVarParam = lnext(PlannerVarParam);
        if (vpm != NULL)
@@ -199,9 +173,8 @@ union_planner(Query *parse)
         */
        tuplePerGroup = parse->hasAggs;
 
-       /* Use 'new_tlist' instead of 'tlist' */
        result_plan =
-           make_groupPlan(&new_tlist,
+           make_groupPlan(&tlist,
                           tuplePerGroup,
                           parse->groupClause,
                           result_plan);
@@ -215,11 +188,6 @@ union_planner(Query *parse)
        int         old_length = 0,
                    new_length = 0;
 
-       /*
-        * Create the AGG node but use 'tlist' not 'new_tlist' as target
-        * list because we don't want the additional attributes (only used
-        * for the havingQual, see above) to show up in the result
-        */
        result_plan = (Plan *) make_agg(tlist, result_plan);
 
        /*
@@ -235,7 +203,22 @@ union_planner(Query *parse)
            List       *clause;
            List      **vpm = NULL;
 
-
+           /* 
+            * Restore target list: get rid of Vars added for havingQual.
+            * Assumption: tlist_len > 0...
+            */
+           {
+               List   *l;
+               int     tlen = 0;
+           
+               foreach (l, ((Agg *) result_plan)->plan.targetlist)
+               {
+                   if (++tlen == tlist_len)
+                       break;
+               }
+               lnext(l) = NIL;
+           }
+           
            /*
             * stuff copied from above to handle the use of attributes
             * from outside in subselects