This allows GROUP BY to use column aliases, and ORDER and GROUP BY can
authorMarc G. Fournier <[email protected]>
Sun, 22 Dec 1996 03:23:35 +0000 (03:23 +0000)
committerMarc G. Fournier <[email protected]>
Sun, 22 Dec 1996 03:23:35 +0000 (03:23 +0000)
use column numbers, like ANSI.

Submitted by: Bruce Momjian <[email protected]>

src/backend/parser/analyze.c
src/backend/parser/gram.y
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h

index e4b9fad1b5fbbd1e046b47edd6a15137c72934a0..b071881f9910380282724e6d746df9b93df30397 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.18.2.1 1996/12/22 03:21:56 scrappy 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 7f817c7c464393b4f3e4c9ae2615f526448b726f..25272b913ce5506e017097cd549c5a412790cc91 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.20.2.1 1996/12/11 23:06:40 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.20.2.2 1996/12/22 03:21:58 scrappy 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..4ab030e164850a4ba545c1df12b2298c037eed73 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.3.2.1 1996/12/22 03:23:33 scrappy 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..3d6d208afe57d23ba3507338e5fa6e7a69eb0d86 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.7.2.1 1996/12/22 03:23:35 scrappy 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