]> granicus.if.org Git - postgresql/commitdiff
Make GROUP BY work with aliases, ORDER BY with column numbers
authorBruce Momjian <bruce@momjian.us>
Tue, 17 Dec 1996 01:53:43 +0000 (01:53 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 17 Dec 1996 01:53:43 +0000 (01:53 +0000)
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h

index e4b9fad1b5fbbd1e046b47edd6a15137c72934a0..29eb7d3cf981ae3f04d92f556fc9275ced4cff07 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.18 1996/11/30 18:06:20 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.19 1996/12/17 01:53:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,8 @@ static TargetEntry *make_targetlist_expr(ParseState *pstate,
                                         char *colname, Node *expr,
                                         List *arrayRef);
 static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
-static List *transformGroupClause(ParseState *pstate, List *grouplist);
+static List *transformGroupClause(ParseState *pstate, List *grouplist,
+                                                       List *targetlist);
 static List *transformSortClause(ParseState *pstate,
                                 List *orderlist, List *targetlist,
                                 char* uniqueFlag);
@@ -422,13 +423,14 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
 
     /* fix order clause */
     qry->sortClause = transformSortClause(pstate,
-                                         stmt->orderClause,
+                                         stmt->sortClause,
                                          qry->targetList,
                                          qry->uniqueFlag);
 
     /* fix group by clause */
     qry->groupClause = transformGroupClause(pstate,
-                                           stmt->groupClause);
+                                         stmt->groupClause,
+                                         qry->targetList);
     qry->rtable = pstate->p_rtable;
 
     if (pstate->p_numAgg > 0)
@@ -505,12 +507,13 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
 
     /* fix order clause */
     qry->sortClause = transformSortClause(pstate,
-                                         stmt->orderClause,
+                                         stmt->sortClause,
                                          qry->targetList,
                                          qry->uniqueFlag);
     /* fix group by clause */
     qry->groupClause = transformGroupClause(pstate,
-                                          stmt->groupClause);
+                                          stmt->groupClause,
+                                         qry->targetList);
 
     qry->rtable = pstate->p_rtable;
 
@@ -1426,19 +1429,21 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
  *****************************************************************************/
 
 /*
- *  find_tl_elt -
+ *  find_targetlist_entry -
  *    returns the Resdom in the target list matching the specified varname
  *    and range
  *
  */
-static Resdom *
-find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist)
+static TargetEntry *
+find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
 {
     List *i;
-    int real_rtable_pos = 0;
-
-    if(refname)
-       real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable, refname);
+    int real_rtable_pos = 0, target_pos = 0;
+    TargetEntry *target_result = NULL;
+    
+    if(sortgroupby->range)
+       real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
+                                                       sortgroupby->range);
 
     foreach(i, tlist) {
        TargetEntry *target = (TargetEntry *)lfirst(i);
@@ -1447,17 +1452,30 @@ find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist)
        char *resname = resnode->resname;
        int test_rtable_pos = var->varno;
 
-       if (!strcmp(resname, colname)) {
-           if(refname) {
-               if(real_rtable_pos == test_rtable_pos) {
-                   return (resnode);
-               }
-           } else {
-               return (resnode);
+       if (!sortgroupby->name) {
+           if (sortgroupby->resno == ++target_pos) {
+               target_result = target;
+               break;
+           }
+       }
+       else {
+           if (!strcmp(resname, sortgroupby->name)) {
+               if(sortgroupby->range) {
+                   if(real_rtable_pos == test_rtable_pos) {
+                       if (target_result != NULL)
+                           elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
+                       else    target_result = target;
+                   }
+               }                       
+               else {
+                   if (target_result != NULL)
+                       elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
+                   else        target_result = target;
+               }
            }
        }
     }
-    return ((Resdom *)NULL);
+    return target_result;
 }
 
 static Oid
@@ -1478,22 +1496,27 @@ any_ordering_op(int restype)
  *
  */
 static List *
-transformGroupClause(ParseState *pstate, List *grouplist)
+transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
 {
     List *glist = NIL, *gl = NIL;
 
     while (grouplist != NIL) {
        GroupClause *grpcl = makeNode(GroupClause);
-       Var *groupAttr = (Var*)transformExpr(pstate, (Node*)lfirst(grouplist));
+       TargetEntry *restarget;
 
-       if (nodeTag(groupAttr) != T_Var) {
-           elog(WARN, "parser: can only specify attribute in group by");
-       }
-       grpcl->grpAttr = groupAttr;
-       grpcl->grpOpoid = any_ordering_op(groupAttr->vartype);
-       if (glist == NIL) {
+       restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
+
+       if (restarget == NULL)
+           elog(WARN,"The field being grouped by must appear in the target list");
+        if (nodeTag(restarget->expr) != T_Var) {
+            elog(WARN, "parser: can only specify attribute in group by");
+        }
+
+       grpcl->grpAttr = (Var *)restarget->expr;
+       grpcl->grpOpoid = any_ordering_op(grpcl->grpAttr->vartype);
+       if (glist == NIL)
            gl = glist = lcons(grpcl, NIL);
-       else {
+       else {
            lnext(gl) = lcons(grpcl, NIL);
            gl = lnext(gl);
        }
@@ -1517,15 +1540,16 @@ transformSortClause(ParseState *pstate,
     List *s = NIL, *i;
 
     while(orderlist != NIL) {
-       SortBy *sortby = lfirst(orderlist);
+       SortGroupBy *sortby = lfirst(orderlist);
        SortClause *sortcl = makeNode(SortClause);
+       TargetEntry *restarget;
        Resdom *resdom;
-       
-       resdom = find_tl_elt(pstate, sortby->range, sortby->name, targetlist);
-       if (resdom == NULL)
-           elog(WARN,"The field being sorted by must appear in the target list");
-       
-       sortcl->resdom = resdom;
+
+       restarget = find_targetlist_entry(pstate, sortby, targetlist);
+       if (restarget == NULL)
+           elog(WARN,"The field being ordered by must appear in the target list");
+
+       sortcl->resdom = resdom = restarget->resdom;
        sortcl->opoid = oprid(oper(sortby->useOp,
                                   resdom->restype,
                                   resdom->restype));
index 2dc6c6145b99ffc4831680af23452226bfce3145..2e4e1f7a830f1788acd2fcc953f3c74ecfb80e3f 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.21 1996/12/11 22:55:53 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.22 1996/12/17 01:53:29 momjian Exp $
  *
  * HISTORY
  *    AUTHOR           DATE            MAJOR EVENT
@@ -82,7 +82,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
     TypeName           *typnam;
     DefElem            *defelt;
     ParamString                *param;
-    SortBy             *sortby;
+    SortGroupBy                *sortgroupby;
     IndexElem          *ielem;
     RangeVar           *range;
     RelExpr            *relexp;
@@ -146,10 +146,11 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
 %type <defelt> def_elem
 %type <node>   def_arg, columnElem, where_clause, 
                a_expr, AexprConst, in_expr_nodes, not_in_expr_nodes,
-               having_clause, groupby
+               having_clause
 %type <value>  NumConst
 %type <attr>   event_object, attr
-%type <sortby> sortby
+%type <sortgroupby>    groupby
+%type <sortgroupby>    sortby
 %type <ielem>  index_elem, func_index
 %type <range>  from_val
 %type <relexp> relation_expr
@@ -1359,7 +1360,7 @@ CursorStmt:  DECLARE name opt_binary CURSOR FOR
                    n->fromClause = $9;
                    n->whereClause = $10;
                    n->groupClause = $11;
-                   n->orderClause = $12;
+                   n->sortClause = $12;
                    $$ = (Node *)n;
                }
        ;
@@ -1385,7 +1386,7 @@ RetrieveStmt:  SELECT opt_unique res_target_list2
                    n->whereClause = $6;
                    n->groupClause = $7;
                    n->havingClause = $8;
-                   n->orderClause = $9;
+                   n->sortClause = $9;
                    $$ = (Node *)n;
                }
        ;
@@ -1413,22 +1414,28 @@ sortby_list:  sortby
 
 sortby:  Id OptUseOp
                { 
-                   $$ = makeNode(SortBy);
+                   $$ = makeNode(SortGroupBy);
+                   $$->resno = 0;
                    $$->range = NULL;
                    $$->name = $1;
                    $$->useOp = $2;
                }
        | Id '.' Id OptUseOp
                {
-                   $$ = makeNode(SortBy);
+                   $$ = makeNode(SortGroupBy);
+                   $$->resno = 0;
                    $$->range = $1;
                    $$->name = $3;
                    $$->useOp = $4;
                }
-        | /*EMPTY*/
-                { 
-                  yyerror("parse error: use 'order by attribute_name'");
-                }
+       | Iconst OptUseOp
+               {
+                   $$ = makeNode(SortGroupBy);
+                   $$->resno = $1;
+                   $$->range = NULL;
+                   $$->name = NULL;
+                   $$->useOp = $2;
+               }
        ;
 
 OptUseOp:  USING Op                            { $$ = $2; }
@@ -1509,16 +1516,29 @@ groupby_list: groupby                           { $$ = lcons($1, NIL); }
        | groupby_list ',' groupby              { $$ = lappend($1, $3); }
        ;
 
-groupby: Id                                    
-               { 
-                  Ident *n = makeNode(Ident);
-                  n->name = $1;
-                  n->indirection = NULL;
-                  $$ = (Node*)n;
+groupby:  Id
+               {
+                   $$ = makeNode(SortGroupBy);
+                   $$->resno = 0;
+                   $$->range = NULL;
+                   $$->name = $1;
+                   $$->useOp = NULL;
                }
-       | attr
+       | Id '.' Id
                {
-                  $$ = (Node*)$1;
+                   $$ = makeNode(SortGroupBy);
+                   $$->resno = 0;
+                   $$->range = $1;
+                   $$->name = $3;
+                   $$->useOp = NULL;
+               }
+       | Iconst
+               {
+                   $$ = makeNode(SortGroupBy);
+                   $$->resno = $1;
+                   $$->range = NULL;
+                   $$->name = NULL;
+                   $$->useOp = NULL;
                }
        ;
 
index 992933c59f5e2bf9dff06a5dfc98c7cd68dc03d7..c1203ac78b634ea87d4e786d914174c99693a063 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.3 1996/11/03 12:12:52 scrappy Exp $
+ * $Id: nodes.h,v 1.4 1996/12/17 01:53:40 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -190,7 +190,7 @@ typedef enum NodeTag {
     T_ParamString,
     T_TimeRange,
     T_RelExpr,
-    T_SortBy,
+    T_SortGroupBy,
     T_RangeVar,
     T_TypeName,
     T_IndexElem,
index 01c037b54fead5287150bb756d32e83027365eab..9c6500135c9acc0b9db8b76853fbc02621ee4c71 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.7 1996/11/13 20:56:15 scrappy Exp $
+ * $Id: parsenodes.h,v 1.8 1996/12/17 01:53:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -463,7 +463,7 @@ typedef struct CursorStmt {
     List               *fromClause;    /* the from clause */
     Node               *whereClause;   /* qualifications */
     List              *groupClause;   /* group by clause */
-    List               *orderClause;   /* sort clause (a list of SortBy's) */
+    List               *sortClause;    /* sort clause (a list of SortGroupBy's) */
 } CursorStmt;    
 
 /* ----------------------
@@ -480,7 +480,7 @@ typedef struct RetrieveStmt {
     Node               *whereClause;   /* qualifications */
     List               *groupClause;   /* group by clause */
     Node               *havingClause;  /* having conditional-expression */
-    List               *orderClause;   /* sort clause (a list of SortBy's) */
+    List               *sortClause;    /* sort clause (a list of SortGroupBy's) */
 } RetrieveStmt;    
 
 
@@ -627,14 +627,15 @@ typedef struct RelExpr {
 } RelExpr;
 
 /*
- * Sortby - for order by clause
+ * SortGroupBy - for order by clause
  */
-typedef struct SortBy {
+typedef struct SortGroupBy {
     NodeTag            type;
+    int                        resno;          /* target number */
     char                *range;
     char               *name;          /* name of column to sort on */
     char               *useOp;         /* operator to use */
-} SortBy;
+} SortGroupBy;
 
 /*
  * RangeVar - range variable, used in from clauses