]> granicus.if.org Git - postgresql/commitdiff
Replaced targetlist entry in GroupClause by reference number
authorJan Wieck <JanWieck@Yahoo.com>
Wed, 12 May 1999 15:02:39 +0000 (15:02 +0000)
committerJan Wieck <JanWieck@Yahoo.com>
Wed, 12 May 1999 15:02:39 +0000 (15:02 +0000)
in Resdom and GroupClause so changing of resno's doesn't confuse
the grouping any more.

Jan

22 files changed:
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/freefuncs.c
src/backend/nodes/makefuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/util/tlist.c
src/backend/parser/parse_agg.c
src/backend/parser/parse_clause.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c
src/backend/utils/adt/ruleutils.c
src/include/nodes/parsenodes.h
src/include/nodes/primnodes.h
src/include/nodes/relation.h
src/include/optimizer/planmain.h
src/include/rewrite/rewriteManip.h
src/test/regress/expected/opr_sanity.out
src/test/regress/sql/opr_sanity.sql

index 2ff8d499e8294abd60ca0efb04174871cc71f23e..be70ef33fdf8953fff59ad2b6084a5ae9e11eaa0 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.78 1999/04/27 09:49:36 ishii Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.79 1999/05/12 15:01:31 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -487,8 +487,8 @@ _copyGroupClause(GroupClause *from)
 {
        GroupClause *newnode = makeNode(GroupClause);
 
-       Node_Copy(from, newnode, entry);
        newnode->grpOpoid = from->grpOpoid;
+       newnode->tleGroupref = from->tleGroupref;
 
        return newnode;
 }
@@ -589,6 +589,7 @@ _copyResdom(Resdom *from)
                newnode->resname = pstrdup(from->resname);
        newnode->reskey = from->reskey;
        newnode->reskeyop = from->reskeyop;
+       newnode->resgroupref = from->resgroupref;
        newnode->resjunk = from->resjunk;
 
        return newnode;
index a5d40ef399ddd0caf896453e4ef3da56d099f8d9..45e752f50283c6b515f6951bdaae52bd1c829750 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.35 1999/02/18 00:49:14 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.36 1999/05/12 15:01:33 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,8 @@ _equalResdom(Resdom *a, Resdom *b)
                return false;
        if (a->reskey != b->reskey)
                return false;
+       if (a->resgroupref != b->resgroupref)
+               return false;
        if (a->reskeyop != b->reskeyop)
                return false;
 
index c41c5fb4318d7bacba338d1b6ee9853d87a1e831..3c95dcbe2257b9bf9e14c04a1797170f834e009c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.15 1999/03/01 00:10:31 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.16 1999/05/12 15:01:33 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -396,8 +396,6 @@ _freeAgg(Agg *node)
 static void
 _freeGroupClause(GroupClause *node)
 {
-       freeObject(node->entry);
-
        pfree(node);
 }
 
index efad14195a9e76407ab0364b4c61b1e0a47655a4..fdf689a326edfe9f950932b731876ad81d8fbb8e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.13 1999/02/13 23:15:58 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.14 1999/05/12 15:01:34 wieck Exp $
  *
  * NOTES
  *       Creator functions in POSTGRES 4.2 are generated automatically. Most of
@@ -107,6 +107,7 @@ makeResdom(AttrNumber resno,
        resdom->resname = resname;
        resdom->reskey = reskey;
        resdom->reskeyop = reskeyop;
+       resdom->resgroupref = 0;
        resdom->resjunk = resjunk;
        return resdom;
 }
index 07ea3d868a872d81fa751e558ad4c2a66d832650..c0df063ea06fe01f2b0926ad7b4030b505f9ef36 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *  $Id: outfuncs.c,v 1.80 1999/05/10 00:45:10 momjian Exp $
+ *  $Id: outfuncs.c,v 1.81 1999/05/12 15:01:34 wieck Exp $
  *
  * NOTES
  *       Every (plan) node in POSTGRES has an associated "out" routine which
@@ -255,10 +255,9 @@ _outSortClause(StringInfo str, SortClause *node)
 static void
 _outGroupClause(StringInfo str, GroupClause *node)
 {
-       appendStringInfo(str, " GROUPCLAUSE :entry ");
-       _outNode(str, node->entry);
-
-       appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid);
+       appendStringInfo(str, " GROUPCLAUSE :grpOpoid %u :tleGroupref %d", 
+                       node->grpOpoid,
+                       node->tleGroupref);
 }
 
 /*
@@ -556,15 +555,18 @@ _outHash(StringInfo str, Hash *node)
 static void
 _outResdom(StringInfo str, Resdom *node)
 {
-       appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d ",
+       appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d",
                        node->resno,
                        node->restype,
                        node->restypmod);
 
-       appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d",
+       appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u",
                        stringStringInfo(node->resname),
                        node->reskey,
-                       node->reskeyop,
+                       node->reskeyop);
+
+       appendStringInfo(str, " :resgroupref %d :resjunk %d",
+                       node->resgroupref,
                        node->resjunk);
 }
 
index 3e1dca5a345860cad9c727efb4367fd477d9ed24..0aa0b275fa9d516adfcf17baa87a8c34ab642bf4 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.60 1999/03/01 00:10:31 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.61 1999/05/12 15:01:35 wieck Exp $
  *
  * NOTES
  *       Most of the read functions for plan nodes are tested. (In fact, they
@@ -221,13 +221,14 @@ _readGroupClause()
 
        local_node = makeNode(GroupClause);
 
-       token = lsptok(NULL, &length);          /* skip the :entry */
-       local_node->entry = nodeRead(true);
-
        token = lsptok(NULL, &length);          /* skip :grpOpoid */
        token = lsptok(NULL, &length);          /* get grpOpoid */
        local_node->grpOpoid = strtoul(token, NULL, 10);
 
+       token = lsptok(NULL, &length);          /* skip :tleGroupref */
+       token = lsptok(NULL, &length);          /* get tleGroupref */
+       local_node->tleGroupref = strtoul(token, NULL, 10);
+
        return local_node;
 }
 
@@ -744,6 +745,10 @@ _readResdom()
        token = lsptok(NULL, &length);          /* get reskeyop */
        local_node->reskeyop = (Oid) atol(token);
 
+       token = lsptok(NULL, &length);          /* eat :resgroupref */
+       token = lsptok(NULL, &length);          /* get resgroupref */
+       local_node->resgroupref = strtoul(token, NULL, 10);
+
        token = lsptok(NULL, &length);          /* eat :resjunk */
        token = lsptok(NULL, &length);          /* get resjunk */
        local_node->resjunk = atoi(token);
index 50d93942ec8adc49da7925bff8dc25f3f0d69f7b..a55d444a8b3114a98949b759dc1436b660347910 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.50 1999/05/10 00:45:20 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.51 1999/05/12 15:01:37 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -260,7 +260,8 @@ union_planner(Query *parse)
                         * belong to?)
                         */
                        check_having_for_ungrouped_vars(parse->havingQual,
-                                                                                       parse->groupClause);
+                                                                                       parse->groupClause,
+                                                                                       parse->targetList);
                }
 
                /* Calculate the opfids from the opnos */
@@ -426,8 +427,7 @@ make_subplanTargetList(Query *parse,
                        GroupClause *grpcl = (GroupClause *) lfirst(gl);
 
                        keyno++;                        /* sort key # for this GroupClause */
-                       /* Is it safe to use just resno to match tlist and glist items?? */
-                       if (grpcl->entry->resdom->resno == resdom->resno)
+                       if (grpcl->tleGroupref == resdom->resgroupref)
                        {
                                /* Found a matching groupclause; record info for sorting */
                                foundGroupClause = true;
index cf3c3edfc1f8bd8e91ca2a86dc7f0e02b59b0716..ee3250080ce27102cb654e4cdebe6700ae1a99e9 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.45 1999/05/06 23:07:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.46 1999/05/12 15:01:39 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -961,7 +961,8 @@ del_agg_clause(Node *clause)
  */
 
 void
-check_having_for_ungrouped_vars(Node *clause, List *groupClause)
+check_having_for_ungrouped_vars(Node *clause, List *groupClause,
+                                               List *targetList)
 {
        List       *t;
 
@@ -981,7 +982,7 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
        else if (IsA(clause, Iter))
        {
                check_having_for_ungrouped_vars(((Iter *) clause)->iterexpr,
-                                                                               groupClause);
+                                                                               groupClause, targetList);
        }
        else if (is_subplan(clause))
        {
@@ -997,7 +998,8 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
                        foreach(gl, groupClause)
                        {
                                if (var_equal(lfirst(t),
-                                                         get_expr(((GroupClause *) lfirst(gl))->entry)))
+                                                         get_groupclause_expr((GroupClause *) 
+                                                                                               lfirst(gl), targetList)))
                                {
                                        contained_in_group_clause = true;
                                        break;
@@ -1016,7 +1018,8 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
                 * subplan is a kind of Expr node.
                 */
                foreach(t, ((Expr *) clause)->args)
-                       check_having_for_ungrouped_vars(lfirst(t), groupClause);
+                       check_having_for_ungrouped_vars(lfirst(t), groupClause,
+                                                                                                               targetList);
        }
        else if (IsA(clause, List))
        {
@@ -1024,12 +1027,13 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
                 * Recursively scan AND subclauses (see NOTE above).
                 */
                foreach(t, ((List *) clause))
-                       check_having_for_ungrouped_vars(lfirst(t), groupClause);
+                       check_having_for_ungrouped_vars(lfirst(t), groupClause,
+                                                                                                               targetList);
        }
        else if (IsA(clause, Aggref))
        {
                check_having_for_ungrouped_vars(((Aggref *) clause)->target,
-                                                                               groupClause);
+                                                                               groupClause, targetList);
        }
        else if (IsA(clause, ArrayRef))
        {
@@ -1040,22 +1044,28 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
                 * expression and its index expression...
                 */
                foreach(t, aref->refupperindexpr)
-                       check_having_for_ungrouped_vars(lfirst(t), groupClause);
+                       check_having_for_ungrouped_vars(lfirst(t), groupClause,
+                                                                                                               targetList);
                foreach(t, aref->reflowerindexpr)
-                       check_having_for_ungrouped_vars(lfirst(t), groupClause);
-               check_having_for_ungrouped_vars(aref->refexpr, groupClause);
-               check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause);
+                       check_having_for_ungrouped_vars(lfirst(t), groupClause,
+                                                                                                               targetList);
+               check_having_for_ungrouped_vars(aref->refexpr, groupClause,
+                                                                                                               targetList);
+               check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause,
+                                                                                                               targetList);
        }
        else if (case_clause(clause))
        {
                foreach(t, ((CaseExpr *) clause)->args)
                {
                        CaseWhen   *when = (CaseWhen *) lfirst(t);
-                       check_having_for_ungrouped_vars(when->expr, groupClause);
-                       check_having_for_ungrouped_vars(when->result, groupClause);
+                       check_having_for_ungrouped_vars(when->expr, groupClause,
+                                                                                                               targetList);
+                       check_having_for_ungrouped_vars(when->result, groupClause,
+                                                                                                               targetList);
                }
                check_having_for_ungrouped_vars(((CaseExpr *) clause)->defresult,
-                                                                               groupClause);
+                                                                               groupClause, targetList);
        }
        else
        {
index 084809c9d9e49316ddf98d6fc9b4b67aa56605e8..5b70b368ca90b7ddfc794fbcde24c0c6596a5f22 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.18 1999/02/13 23:16:38 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.19 1999/05/12 15:01:41 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -229,6 +229,49 @@ replace_matching_resname(List *new_tlist, List *old_tlist)
                        new_tl = makeTargetEntry(newresno, old_tle->expr);
                        t_list = lappend(t_list, new_tl);
                }
+
+               /*
+                * Also it is possible that the parser or rewriter added
+                * some junk attributes to hold GROUP BY expressions which
+                * are not part of the result attributes.
+                * We can simply identify them by looking at the resgroupref
+                * in the TLE's resdom, which is a unique number telling which
+                * TLE belongs to which GroupClause.
+                */
+               if (old_tle->resdom->resgroupref > 0)
+               {
+                       bool                    already_there = FALSE;
+                       TargetEntry     *new_tle;
+                       Resdom                  *newresno;
+
+                       /*
+                        * Check if the tle is already in the new list
+                        */
+                       foreach(i, t_list)
+                       {
+                               new_tle = (TargetEntry *)lfirst(i);
+
+                               if (new_tle->resdom->resgroupref == 
+                                                                       old_tle->resdom->resgroupref)
+                               {
+                                       already_there = TRUE;
+                                       break;
+                               }
+
+                       }
+
+                       /*
+                        * If not, add it and make sure it is now a junk attribute
+                        */
+                       if (!already_there)
+                       {
+                               newresno = (Resdom *) copyObject((Node *) old_tle->resdom);
+                               newresno->resno = length(t_list) + 1;
+                               newresno->resjunk = 1;
+                               new_tl = makeTargetEntry(newresno, old_tle->expr);
+                               t_list = lappend(t_list, new_tl);
+                       }
+               }
        }
 
        return t_list;
index 6d25950bca0de243281268dcc2381fb350011197..a914930cc9354763afe9f587305590d284477dc1 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.29 1999/05/06 23:07:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.30 1999/05/12 15:01:44 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -518,6 +518,25 @@ get_expr(TargetEntry *tle)
 }
 
 
+Var *
+get_groupclause_expr(GroupClause *groupClause, List *targetList)
+{
+       List            *l;
+       TargetEntry     *tle;
+
+       foreach(l, targetList)
+       {
+               tle = (TargetEntry *)lfirst(l);
+               if (tle->resdom->resgroupref == groupClause->tleGroupref)
+                       return get_expr(tle);
+       }
+
+       elog(ERROR, 
+               "get_groupclause_expr: GROUP BY expression not found in targetlist");
+       return NULL;
+}
+
+
 /*****************************************************************************
  *
  *****************************************************************************/
@@ -528,6 +547,11 @@ get_expr(TargetEntry *tle)
  *       in there.
  */
 #ifdef NOT_USED
+/*
+ * WARNING!!! If this ever get's used again, the new reference
+ * mechanism from group clause to targetlist entry must be implemented
+ * here too. Jan
+ */
 void
 AddGroupAttrToTlist(List *tlist, List *grpCl)
 {
index 1b2eb21c7cd0b57ce670f47a29ac6450f3fa4222..ab00040c654348c3e51ae2b9e9a4d89b9b6bb368 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.18 1999/04/29 01:13:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.19 1999/05/12 15:01:48 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,8 +32,9 @@
 #include "utils/lsyscache.h"
 
 static bool contain_agg_clause(Node *clause);
-static bool exprIsAggOrGroupCol(Node *expr, List *groupClause);
-static bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause);
+static bool exprIsAggOrGroupCol(Node *expr, List *groupClause, List *tlist);
+static bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause, 
+                                                                                                       List *tlist);
 
 /*
  * contain_agg_clause
@@ -100,7 +101,7 @@ contain_agg_clause(Node *clause)
  *       returns true if the expression does not contain non-group columns.
  */
 static bool
-exprIsAggOrGroupCol(Node *expr, List *groupClause)
+exprIsAggOrGroupCol(Node *expr, List *groupClause, List *tlist)
 {
        List       *gl;
 
@@ -113,7 +114,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
        {
                GroupClause *grpcl = lfirst(gl);
 
-               if (equal(expr, grpcl->entry->expr))
+               if (equal(expr, get_groupclause_expr(grpcl, tlist)))
                        return TRUE;
        }
 
@@ -122,7 +123,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
                List       *temp;
 
                foreach(temp, ((Expr *) expr)->args)
-                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist))
                        return FALSE;
                return TRUE;
        }
@@ -135,7 +136,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
  *       returns true if the TargetEntry is Agg or GroupCol.
  */
 static bool
-tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
+tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause, List *tlist)
 {
        Node       *expr = tle->expr;
        List       *gl;
@@ -147,7 +148,7 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
        {
                GroupClause *grpcl = lfirst(gl);
 
-               if (tle->resdom->resno == grpcl->entry->resdom->resno)
+               if (tle->resdom->resgroupref == grpcl->tleGroupref)
                {
                        if (contain_agg_clause((Node *) expr))
                                elog(ERROR, "Aggregates not allowed in GROUP BY clause");
@@ -163,7 +164,7 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
                List       *temp;
 
                foreach(temp, ((Expr *) expr)->args)
-                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist))
                        return FALSE;
                return TRUE;
        }
@@ -200,7 +201,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
        {
                TargetEntry *tle = lfirst(tl);
 
-               if (!tleIsAggOrGroupCol(tle, qry->groupClause))
+               if (!tleIsAggOrGroupCol(tle, qry->groupClause, qry->targetList))
                        elog(ERROR,
                                 "Illegal use of aggregates or non-group column in target list");
        }
@@ -210,7 +211,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
         * restriction as those in the target list.
         */
 
-       if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
+       if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause, qry->targetList))
                elog(ERROR,
                         "Illegal use of aggregates or non-group column in HAVING clause");
        return;
index 0085a4781b932821932f8fea44b81b761926d097..61359e3452a68a0bc3240a415c6bf671283b489d 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.29 1999/02/23 07:46:42 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.30 1999/05/12 15:01:50 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -550,13 +550,19 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
 
                restarget = findTargetlistEntry(pstate, lfirst(grouplist), targetlist, GROUP_CLAUSE);
 
-               grpcl->entry = restarget;
                resdom = restarget->resdom;
                grpcl->grpOpoid = oprid(oper("<",
                                                                         resdom->restype,
                                                                         resdom->restype, false));
                if (glist == NIL)
+               {
+                       int             groupref = length(glist) + 1;
+
+                       restarget->resdom->resgroupref = groupref;
+                       grpcl->tleGroupref = groupref;
+
                        gl = glist = lcons(grpcl, NIL);
+               }
                else
                {
                        List       *i;
@@ -565,11 +571,17 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
                        {
                                GroupClause *gcl = (GroupClause *) lfirst(i);
 
-                               if (gcl->entry == grpcl->entry)
+                               if (equal(get_groupclause_expr(gcl, targetlist),
+                                                       restarget->expr))
                                        break;
                        }
                        if (i == NIL)           /* not in grouplist already */
                        {
+                               int             groupref = length(glist) + 1;
+
+                               restarget->resdom->resgroupref = groupref;
+                               grpcl->tleGroupref = groupref;
+
                                lnext(gl) = lcons(grpcl, NIL);
                                gl = lnext(gl);
                        }
index 1ba1a5dd56e4a4c399ad3c40e4a82c4bc7d8abf7..654f7310805b8c9bc1b3fa53243acaadc95fcad4 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.38 1999/05/09 23:31:46 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.39 1999/05/12 15:01:53 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -170,15 +170,7 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               return rangeTableEntry_used(
-                                               (Node *)(grp->entry),
-                                               rt_index,
-                                               sublevels_up);
-                       }
-                       break;
+                       return FALSE;
 
                case T_Expr:
                        {
@@ -348,12 +340,6 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
                                                sublevels_up))
                                        return TRUE;
 
-                               if (rangeTableEntry_used(
-                                               (Node *)(qry->groupClause),
-                                               rt_index,
-                                               sublevels_up))
-                                       return TRUE;
-
                                return FALSE;
                        }
                        break;
@@ -407,16 +393,7 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               return attribute_used(
-                                               (Node *)(grp->entry),
-                                               rt_index,
-                                               attno,
-                                               sublevels_up);
-                       }
-                       break;
+                       return FALSE;
 
                case T_Expr:
                        {
@@ -558,13 +535,6 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
                                                sublevels_up))
                                        return TRUE;
 
-                               if (attribute_used(
-                                               (Node *)(qry->groupClause),
-                                               rt_index,
-                                               attno,
-                                               sublevels_up))
-                                       return TRUE;
-
                                return FALSE;
                        }
                        break;
@@ -697,8 +667,6 @@ modifyAggrefUplevel(Node *node)
                                modifyAggrefUplevel(
                                                (Node *)(qry->havingQual));
 
-                               modifyAggrefUplevel(
-                                               (Node *)(qry->groupClause));
                        }
                        break;
 
@@ -752,15 +720,6 @@ modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int subl
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               modifyAggrefChangeVarnodes(
-                                               (Node **)(&(grp->entry)),
-                                               rt_index,
-                                               new_index,
-                                               sublevels_up);
-                       }
                        break;
 
                case T_Expr:
@@ -894,12 +853,6 @@ modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int subl
                                                rt_index,
                                                new_index,
                                                sublevels_up);
-
-                               modifyAggrefChangeVarnodes(
-                                               (Node **)(&(qry->groupClause)),
-                                               rt_index,
-                                               new_index,
-                                               sublevels_up);
                        }
                        break;
 
@@ -1186,13 +1139,6 @@ modifyAggrefQual(Node **nodePtr, Query *parsetree)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               modifyAggrefQual(
-                                               (Node **)(&(grp->entry)),
-                                               parsetree);
-                       }
                        break;
 
                case T_Expr:
@@ -1386,13 +1332,6 @@ apply_RIR_adjust_sublevel(Node *node, int sublevels_up)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               apply_RIR_adjust_sublevel(
-                                               (Node *)(grp->entry),
-                                               sublevels_up);
-                       }
                        break;
 
                case T_Expr:
@@ -1539,17 +1478,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               apply_RIR_view(
-                                               (Node **)(&(grp->entry)),
-                                               rt_index,
-                                               rte,
-                                               tlist,
-                                               modified,
-                                               sublevels_up);
-                       }
                        break;
 
                case T_Expr:
@@ -1724,14 +1652,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
                                                tlist,
                                                modified,
                                                sublevels_up);
-
-                               apply_RIR_view(
-                                               (Node **)(&(qry->groupClause)),
-                                               rt_index,
-                                               rte,
-                                               tlist,
-                                               modified,
-                                               sublevels_up);
                        }
                        break;
 
@@ -1898,10 +1818,8 @@ ApplyRetrieveRule(Query *parsetree,
        }
        if (*modified && !badsql) {
          AddQual(parsetree, rule_action->qual);
-         /* This will only work if the query made to the view defined by the following
-          * groupClause groups by the same attributes or does not use group at all! */
-         if (parsetree->groupClause == NULL)
-           parsetree->groupClause=rule_action->groupClause;
+         AddGroupClause(parsetree, rule_action->groupClause, 
+                                                                       rule_action->targetList);
          AddHavingQual(parsetree, rule_action->havingQual);
          parsetree->hasAggs = (rule_action->hasAggs || parsetree->hasAggs);
          parsetree->hasSubLinks = (rule_action->hasSubLinks ||  parsetree->hasSubLinks);
@@ -1935,12 +1853,6 @@ fireRIRonSubselect(Node *node)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               fireRIRonSubselect(
-                                               (Node *)(grp->entry));
-                       }
                        break;
 
                case T_Expr:
@@ -2048,9 +1960,6 @@ fireRIRonSubselect(Node *node)
 
                                fireRIRonSubselect(
                                                (Node *)(qry->havingQual));
-
-                               fireRIRonSubselect(
-                                               (Node *)(qry->groupClause));
                        }
                        break;
 
index 95267241c5bfd1bbc6013c415a8cecdabf655576..057579669d19bdc91a62b1168dc096a84b8f03f6 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.29 1999/02/13 23:17:49 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.30 1999/05/12 15:01:55 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -65,14 +65,6 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               OffsetVarNodes(
-                                               (Node *)(grp->entry),
-                                               offset,
-                                               sublevels_up);
-                       }
                        break;
 
                case T_Expr:
@@ -199,11 +191,6 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up)
                                                (Node *)(qry->havingQual),
                                                offset,
                                                sublevels_up);
-
-                               OffsetVarNodes(
-                                               (Node *)(qry->groupClause),
-                                               offset,
-                                               sublevels_up);
                        }
                        break;
 
@@ -284,15 +271,6 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause     *grp = (GroupClause *)node;
-
-                               ChangeVarNodes(
-                                               (Node *)(grp->entry),
-                                               rt_index,
-                                               new_index,
-                                               sublevels_up);
-                       }
                        break;
 
                case T_Expr:
@@ -430,12 +408,6 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
                                                rt_index,
                                                new_index,
                                                sublevels_up);
-
-                               ChangeVarNodes(
-                                               (Node *)(qry->groupClause),
-                                               rt_index,
-                                               new_index,
-                                               sublevels_up);
                        }
                        break;
 
@@ -562,6 +534,44 @@ AddNotQual(Query *parsetree, Node *qual)
        AddQual(parsetree, copy);
 }
 
+
+void
+AddGroupClause(Query *parsetree, List *group_by, List *tlist)
+{
+       List                    *l;
+       List                    *tl;
+       GroupClause             *groupclause;
+       TargetEntry             *tle;
+       int                             new_resno;
+
+       new_resno = length(parsetree->targetList);
+
+       foreach (l, group_by)
+       {
+               groupclause = (GroupClause *)copyObject(lfirst(l));
+               tle = NULL;
+               foreach(tl, tlist)
+               {
+                       if (((TargetEntry *)lfirst(tl))->resdom->resgroupref ==
+                                               groupclause->tleGroupref)
+                       {
+                               tle = (TargetEntry *)copyObject(lfirst(tl));
+                               break;
+                       }
+               }
+               if (tle == NULL)
+                       elog(ERROR, "AddGroupClause(): GROUP BY entry not found in rules targetlist");
+
+               tle->resdom->resno = ++new_resno;
+               tle->resdom->resjunk = true;
+               tle->resdom->resgroupref = length(parsetree->groupClause) + 1;
+               groupclause->tleGroupref = tle->resdom->resgroupref;
+
+               parsetree->targetList  = lappend(parsetree->targetList, tle);
+               parsetree->groupClause = lappend(parsetree->groupClause, groupclause);
+       }
+}
+
 static Node *
 make_null(Oid type)
 {
@@ -688,7 +698,10 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
                                                        *nodePtr = make_null(((Var *) node)->vartype);
                                        }
                                        else
+                                       {
                                                *nodePtr = copyObject(n);
+                                               ((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
+                                       }
                                }
                                break;
                        }
@@ -709,6 +722,8 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
                                ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
                        }
                        break;
+               case T_GroupClause:
+                       break;
                default:
                        /* ignore the others */
                        break;
@@ -720,7 +735,10 @@ FixNew(RewriteInfo *info, Query *parsetree)
 {
        ResolveNew(info, parsetree->targetList,
                           (Node **) &(info->rule_action->targetList), 0);
-       ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0);
+       ResolveNew(info, parsetree->targetList, 
+                  (Node **) &info->rule_action->qual, 0);
+       ResolveNew(info, parsetree->targetList, 
+                  (Node **) &(info->rule_action->groupClause), 0);
 }
 
 static void
index 016d835ade51e0f57ecb1bf0e2e667b5a930c45b..1158fdc7b553a3f7cac2c59bb45cdc3ec6af9200 100644 (file)
@@ -3,7 +3,7 @@
  *                       out of it's tuple
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.11 1999/05/10 00:45:59 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.12 1999/05/12 15:01:58 wieck Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1263,9 +1263,23 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix)
                case T_GroupClause:
                        {
                                GroupClause *grp = (GroupClause *) node;
+                               List            *l;
+                               TargetEntry     *tle = NULL;
 
-                               return get_rule_expr(qh, rt_index,
-                                                                        (Node *) (grp->entry), varprefix);
+                               foreach(l, qh->query->targetList)
+                               {
+                                       if (((TargetEntry *)lfirst(l))->resdom->resgroupref ==
+                                                                       grp->tleGroupref)
+                                       {
+                                               tle = (TargetEntry *)lfirst(l);
+                                               break;
+                                       }
+                               }
+
+                               if (tle == NULL)
+                                       elog(ERROR, "GROUP BY expression not found in targetlist");
+
+                               return get_rule_expr(qh, rt_index, (Node *)tle, varprefix);
                        }
                        break;
 
@@ -1738,12 +1752,7 @@ check_if_rte_used(int rt_index, Node *node, int sup)
                        break;
 
                case T_GroupClause:
-                       {
-                               GroupClause *grp = (GroupClause *) node;
-
-                               return check_if_rte_used(rt_index,
-                                                                                (Node *) (grp->entry), sup);
-                       }
+                       return FALSE;
                        break;
 
                case T_Expr:
index c55a8cf93b6dc9282f61a0dc0bc3f750d86d30ed..fed516ccfb84933dd5836cdd8039ea767f89525b 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.71 1999/02/23 07:55:24 thomas Exp $
+ * $Id: parsenodes.h,v 1.72 1999/05/12 15:02:04 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -960,8 +960,8 @@ typedef struct SortClause
 typedef struct GroupClause
 {
        NodeTag         type;
-       TargetEntry *entry;                     /* attributes to group on */
        Oid                     grpOpoid;               /* the sort operator to use */
+       Index           tleGroupref;    /* reference into targetlist */
 } GroupClause;
 
 #define        ROW_MARK_FOR_UPDATE             (1 << 0)
index 981bd61f32cba289a8f6892ee45773154ed97739..93eafbe72c7a180409c89ccb602ec054d1d1796c 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.25 1999/02/13 23:21:40 momjian Exp $
+ * $Id: primnodes.h,v 1.26 1999/05/12 15:02:07 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,6 +30,7 @@
  *             resname                 - name of the resdom (could be NULL)
  *             reskey                  - order of key in a sort (for those > 0)
  *             reskeyop                - sort operator Oid
+ *             resgroupref             - set to nonzero if referenced from a group by clause
  *             resjunk                 - set to nonzero to eliminate the attribute
  *                                               from final target list  e.g., ctid for replace
  *                                               and delete
@@ -45,6 +46,7 @@ typedef struct Resdom
        char       *resname;
        Index           reskey;
        Oid                     reskeyop;
+       Index           resgroupref;
        int                     resjunk;
 } Resdom;
 
index d52960903e29c72a600e8c1a8596eecf16c6568e..2d47243c405c66fd28bdca73aa16a6dad72084ef 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relation.h,v 1.29 1999/02/22 19:55:44 momjian Exp $
+ * $Id: relation.h,v 1.30 1999/05/12 15:02:08 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -103,6 +103,7 @@ typedef struct RelOptInfo
 } RelOptInfo;
 
 extern Var *get_expr(TargetEntry *foo);
+extern Var *get_groupclause_expr(GroupClause *groupClause, List *targetList);
 
 typedef struct MergeOrder
 {
index 002238571c0a3baaeff9d96257960f5cb6d7ce33..e3848330dbc553ca06a93ad25a407fd4be1b96bf 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: planmain.h,v 1.24 1999/05/03 00:38:42 tgl Exp $
+ * $Id: planmain.h,v 1.25 1999/05/12 15:02:22 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,7 +62,9 @@ extern void replace_vars_with_subplan_refs(Node *clause,
                                                                                   List *subplanTargetList);
 extern bool set_agg_tlist_references(Agg *aggNode);
 extern void del_agg_tlist_references(List *tlist);
-extern void check_having_for_ungrouped_vars(Node *clause, List *groupClause);
+extern void check_having_for_ungrouped_vars(Node *clause,
+                                                                                       List *groupClause,
+                                                                                       List *targetList);
 extern void transformKeySetQuery(Query *origNode);
 
 #endif  /* PLANMAIN_H */
index 317dae8ea0d62ea18346f06f999a28a13cccfae3..e41a2267083b71032dc55dc3cfa25e8bb3153acb 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteManip.h,v 1.13 1999/02/13 23:22:00 momjian Exp $
+ * $Id: rewriteManip.h,v 1.14 1999/05/12 15:02:28 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@ void          AddHavingQual(Query *parsetree, Node *havingQual);
 
 void           AddNotQual(Query *parsetree, Node *qual);
 void            AddNotHavingQual(Query *parsetree, Node *havingQual);
+void           AddGroupClause(Query *parsetree, List *group_by, List *tlist);
 
 void           FixNew(RewriteInfo *info, Query *parsetree);
 
index f626651949c4e7ef7ace34ebdf999110f50913cc..f6b4bc4373c720a98167b3f5ba466c0cdb2edc72 100644 (file)
@@ -1,7 +1,8 @@
 QUERY: SELECT p1.oid, p1.proname
 FROM pg_proc as p1
-WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
-    p1.pronargs < 0 OR p1.pronargs > 9;
+WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
+    p1.pronargs < 0 OR p1.pronargs > 9)
+       AND p1.proname !~ '^pl[^_]+_call_handler$';
 oid|proname
 ---+-------
 (0 rows)
index f3d84ebe3d082401488f07f705b9c3f2227026df..d6f3b293af9db79011baaac47375a76cc031c6ef 100644 (file)
@@ -25,8 +25,9 @@
 
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
-WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
-    p1.pronargs < 0 OR p1.pronargs > 9;
+WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
+    p1.pronargs < 0 OR p1.pronargs > 9)
+       AND p1.proname !~ '^pl[^_]+_call_handler$';
 
 -- Look for conflicting proc definitions (same names and input datatypes).