aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/parser/analyze.c98
-rw-r--r--src/backend/parser/gram.y60
2 files changed, 101 insertions, 57 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index e4b9fad1b5f..29eb7d3cf98 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -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));
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 2dc6c6145b9..2e4e1f7a830 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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;
}
;