8000 This allows GROUP BY to use column aliases, and ORDER and GROUP BY can · MangeshVC/postgres@502a653 · GitHub
[go: up one dir, main page]

Skip to content

Commit 502a653

Browse files
committed
This allows GROUP BY to use column aliases, and ORDER and GROUP BY can
use column numbers, like ANSI. Submitted by: Bruce Momjian <maillist@candle.pha.pa.us>
1 parent b1c7cba commit 502a653

File tree

4 files changed

+110
-65
lines changed

4 files changed

+110
-65
lines changed

src/backend/parser/analyze.c

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.18 1996/11/30 18:06:20 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.18.2.1 1996/12/22 03:21:56 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -63,7 +63,8 @@ static TargetEntry *make_targetlist_expr(ParseState *pstate,
6363
char *colname, Node *expr,
6464
List *arrayRef);
6565
static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
66-
static List *transformGroupClause(ParseState *pstate, List *grouplist);
66+
static List *transformGroupClause(ParseState *pstate, List *grouplist,
67+
List *targetlist);
6768
static List *transformSortClause(ParseState *pstate,
6869
List *orderlist, List *targetlist,
6970
char* uniqueFlag);
@@ -422,13 +423,14 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
422423

423424
/* fix order clause */
424425
qry->sortClause = transformSortClause(pstate,
425-
stmt->orderClause,
426+
stmt->sortClause,
426427
qry->targetList,
427428
qry->uniqueFlag);
428429

429430
/* fix group by clause */
430431
qry->groupClause = transformGroupClause(pstate,
431-
stmt->groupClause);
432+
stmt->groupClause,
433+
qry->targetList);
432434
qry->rtable = pstate->p_rtable;
433435

434436
if (pstate->p_numAgg > 0)
@@ -505,12 +507,13 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
505507

506508
/* fix order clause */
507509
qry->sortClause = transformSortClause(pstate,
508-
stmt->orderClause,
510+
stmt->sortClause,
509511
qry->targetList,
510512
qry->uniqueFlag);
511513
/* fix group by clause */
512514
qry->groupClause = transformGroupClause(pstate,
513-
stmt->groupClause);
515+
stmt->groupClause,
516+
qry->targetList);
514517

515518
qry->rtable = pstate->p_rtable;
516519

@@ -1426,19 +1429,21 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
14261429
*****************************************************************************/
14271430

14281431
/*
1429-
* find_tl_elt -
1432+
* find_targetlist_entry -
14301433
* returns the Resdom in the target list matching the specified varname
14311434
* and range
14321435
*
14331436
*/
1434-
static Resdom *
1435-
find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist)
1437+
static TargetEntry *
1438+
find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
14361439
{
14371440
List *i;
1438-
int real_rtable_pos = 0;
1439-
1440-
if(refname)
1441-
real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable, refname);
1441+
int real_rtable_pos = 0, target_pos = 0;
1442+
TargetEntry *target_result = NULL;
1443+
1444+
if(sortgroupby->range)
1445+
real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
1446+
sortgroupby->range);
14421447

14431448
foreach(i, tlist) {
14441449
TargetEntry *target = (TargetEntry *)lfirst(i);
@@ -1447,17 +1452,30 @@ find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist)
14471452
char *resname = resnode->resname;
14481453
int test_rtable_pos = var->varno;
14491454

1450-
if (!strcmp(resname, colname)) {
1451-
if(refname) {
1452-
if(real_rtable_pos == test_rtable_pos) {
1453-
return (resnode);
1454-
}
1455-
} else {
1456-
return (resnode);
1455+
if (!sortgroupby->name) {
1456+
if (sortgroupby->resno == ++target_pos) {
1457+
target_result = target;
1458+
break;
1459+
}
1460+
}
1461+
else {
1462+
if (!strcmp(resname, sortgroupby->name)) {
1463+
if(sortgroupby->range) {
1464+
if(real_rtable_pos == test_rtable_pos) {
1465+
if (target_result != NULL)
1466+
elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
1467+
else target_result = target;
1468+
}
1469+
}
1470+
else {
1471+
if (target_result != NULL)
1472+
elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
1473+
else target_result = target;
1474+
}
14571475
}
14581476
}
14591477
}
1460-
return ((Resdom *)NULL);
1478+
return target_result;
14611479
}
14621480

14631481
static Oid
@@ -1478,22 +1496,27 @@ any_ordering_op(int restype)
14781496
*
14791497
*/
14801498
static List *
1481-
transformGroupClause(ParseState *pstate, List *grouplist)
1499+
transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
14821500
{
14831501
List *glist = NIL, *gl = NIL;
14841502

14851503
while (grouplist != NIL) {
14861504
GroupClause *grpcl = makeNode(GroupClause);
1487-
Var *groupAttr = (Var*)transformExpr(pstate, (Node*)lfirst(grouplist));
1505+
TargetEntry *restarget;
14881506

1489-
if (nodeTag(groupAttr) != T_Var) {
1490-
elog(WARN, "parser: can only specify attribute in group by");
1491-
}
1492-
grpcl->grpAttr = groupAttr;
1493-
grpcl->grpOpoid = any_ordering_op(groupAttr->vartype);
1494-
if (glist == NIL) {
1507+
restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
1508+
1509+
if (restarget == NULL)
1510+
elog(WARN,"The field being grouped by must appear in the target list");
1511+
if (nodeTag(restarget->expr) != T_Var) {
1512+
elog(WARN, "parser: can only specify attribute in group by");
1513+
}
1514+
1515+
grpcl->grpAttr = (Var *)restarget->expr;
1516+
grpcl->grpOpoid = any_ordering_op(grpcl->grpAttr->vartype);
1517+
if (glist == NIL)
14951518
gl = glist = lcons(grpcl, NIL);
1496-
} else {
1519+
else {
14971520
lnext(gl) = lcons(grpcl, NIL);
14981521
gl = lnext(gl);
14991522
}
@@ -1517,15 +1540,16 @@ transformSortClause(ParseState *pstate,
15171540
List *s = NIL, *i;
15181541

15191542
while(orderlist != NIL) {
1520-
SortBy *sortby = lfirst(orderlist);
1543+
SortGroupBy *sortby = lfirst(orderlist);
15211544
SortClause *sortcl = makeNode(SortClause);
1545+
TargetEntry *restarget;
15221546
Resdom *resdom;
1523-
1524-
resdom = find_tl_elt(pstate, sortby->range, sortby->name, targetlist);
1525-
if (resdom == NULL)
1526-
elog(WARN,"The field being sorted by must appear in the target list");
1527-
1528-
sortcl->resdom = resdom;
1547+
1548+
restarget = find_targetlist_entry(pstate, sortby, targetlist);
1549+
if (restarget == NULL)
1550+
elog(WARN,"The field being ordered by must appear in the target list");
1551+
1552+
sortcl->resdom = resdom = restarget->resdom;
15291553
sortcl->opoid = oprid(oper(sortby->useOp,
15301554
resdom->restype,
15311555
resdom->restype));

src/backend/parser/gram.y

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.20.2.1 1996/12/11 23:06:40 momjian Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.20.2.2 1996/12/22 03:21:58 scrappy Exp $
1414
*
1515
* HISTORY
1616
* AUTHOR DATE MAJOR EVENT
@@ -82,7 +82,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
8282
TypeName *typnam;
8383
DefElem *defelt;
8484
ParamString *param;
85-
SortBy *sortby;
85+
SortGroupBy *sortgroupby;
8686
IndexElem *ielem;
8787
RangeVar *range;
8888
RelExpr *relexp;
@@ -146,10 +146,11 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
146146
%type <defelt> def_elem
147147
%type <node> def_arg, columnElem, where_clause,
148148
a_expr, AexprConst, in_expr_nodes, not_in_expr_nodes,
149-
having_clause, groupby
149+
having_clause
150150
%type <value> NumConst
151151
%type <attr> event_object, attr
152-
%type <sortby> sortby
152+
%type <sortgroupby> groupby
153+
%type <sortgroupby> sortby
153154
%type <ielem> index_elem, func_index
154155
%type <range> from_val
155156
%type <relexp> relation_expr
@@ -1359,7 +1360,7 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
13591360
n->fromClause = $9;
13601361
n->whereClause = $10;
13611362
n->groupClause = $11;
1362-
n->orderClause = $12;
1363+
n->sortClause = $12;
13631364
$$ = (Node *)n;
13641365
}
13651366
;
@@ -1385,7 +1386,7 @@ RetrieveStmt: SELECT opt_unique res_target_list2
13851386
n->whereClause = $6;
13861387
n->groupClause = $7;
13871388
n->havingClause = $8;
1388-
n->orderClause = $9;
1389+
n->sortClause = $9;
13891390
$$ = (Node *)n;
13901391
}
13911392
;
@@ -1413,22 +1414,28 @@ sortby_list: sortby
14131414

14141415
sortby: Id OptUseOp
14151416
{
1416-
$$ = makeNode(SortBy);
1417+
$$ = makeNode(SortGroupBy);
1418+
$$->resno = 0;
14171419
$$->range = NULL;
14181420
$$->name = $1;
14191421
$$->useOp = $2;
14201422
}
14211423
| Id '.' Id OptUseOp
14221424
{
1423-
$$ = makeNode(SortBy);
1425+
$$ = makeNode(SortGroupBy);
1426+
$$->resno = 0;
14241427
$$->range = $1;
14251428
$$->name = $3;
14261429
$$->useOp = $4;
14271430
}
1428-
| /*EMPTY*/
1429-
{
1430-
yyerror("parse error: use 'order by attribute_name'");
1431-
}
1431+
| Iconst OptUseOp
1432+
{
1433+
$$ = makeNode(SortGroupBy);
1434+
$$->resno = $1;
1435+
$$->range = NULL;
1436+
$$->name = NULL;
1437+
$$->useOp = $2;
1438+
}
14321439
;
14331440

14341441
OptUseOp: USING Op { $$ = $2; }
@@ -1509,16 +1516,29 @@ groupby_list: groupby { $$ = lcons($1, NIL); }
15091516
| groupby_list ',' groupby { $$ = lappend($1, $3); }
15101517
;
15111518

1512-
groupby: Id
1513-
{
1514-
Ident *n = makeNode(Ident);
1515-
n->name = $1;
1516-
n->indirection = NULL;
1517-
$$ = (Node*)n;
1519+
groupby: Id
1520+
{
1521+
$$ = makeNode(SortGroupBy);
1522+
$$->resno = 0;
1523+
$$->range = NULL;
1524+
$$->name = $1;
1525+
$$->useOp = NULL;
15181526
}
1519-
| attr
1527+
| Id '.' Id
15201528
{
1521-
$$ = (Node*)$1;
1529+
$$ = makeNode(SortGroupBy);
1530+
$$->resno = 0;
1531+
$$->range = $1;
1532+
$$->name = $3;
1533+
$$->useOp = NULL;
1534+
}
1535+
| Iconst
1536+
{
1537+
$$ = makeNode(SortGroupBy);
1538+
$$->resno = $1;
1539+
$$->range = NULL;
1540+
$$->name = NULL;
1541+
$$->useOp = NULL;
15221542
}
15231543
;
15241544

src/include/nodes/nodes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: nodes.h,v 1.3 1996/11/03 12:12:52 scrappy Exp $
9+
* $Id: nodes.h,v 1.3.2.1 1996/12/22 03:23:33 scrappy Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -190,7 +190,7 @@ typedef enum NodeTag {
190190
T_ParamString,
191191
T_TimeRange,
192192
T_RelExpr,
193-
T_SortBy,
193+
T_SortGroupBy,
194194
T_RangeVar,
195195
T_TypeName,
196196
T_IndexElem,

src/include/nodes/parsenodes.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: parsenodes.h,v 1.7 1996/11/13 20:56:15 scrappy Exp $
9+
* $Id: parsenodes.h,v 1.7.2.1 1996/12/22 03:23:35 scrappy Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -463,7 +463,7 @@ typedef struct CursorStmt {
463463
List *fromClause; /* the from clause */
464464
Node *whereClause; /* qualifications */
465465
List *groupClause; /* group by clause */
466-
List *orderClause; /* sort clause (a list of SortBy's) */
466+
List *sortClause; /* sort clause (a list of SortGroupBy's) */
467467
} CursorStmt;
468468

469469
/* ----------------------
@@ -480,7 +480,7 @@ typedef struct RetrieveStmt {
480480
Node *whereClause; /* qualifications */
481481
List *groupClause; /* group by clause */
482482
Node *havingClause; /* having conditional-expression */
483-
List *orderClause; /* sort clause (a list of SortBy's) */
483+
List *sortClause; /* sort clause (a list of SortGroupBy's) */
484484
} RetrieveStmt;
485485

486486

@@ -627,14 +627,15 @@ typedef struct RelExpr {
627627
} RelExpr;
628628

629629
/*
630-
* Sortby - for order by clause
630+
* SortGroupBy - for order by clause
631631
*/
632-
typedef struct SortBy {
632+
typedef struct SortGroupBy {
633633
NodeTag type;
634+
int resno; /* target number */
634635
char *range;
635636
char *name; /* name of column to sort on */
636637
char *useOp; /* operator to use */
637-
} SortBy;
638+
} SortGroupBy;
638639

639640
/*
640641
* RangeVar - range variable, used in from clauses

0 commit comments

Comments
 (0)
0