|
|
@ -7,7 +7,7 @@ |
|
|
|
* |
|
|
|
* |
|
|
|
* |
|
|
|
* |
|
|
|
* IDENTIFICATION |
|
|
|
* 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, |
|
|
|
char *colname, Node *expr, |
|
|
|
List *arrayRef); |
|
|
|
List *arrayRef); |
|
|
|
static Node *transformWhereClause(ParseState *pstate, Node *a_expr); |
|
|
|
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, |
|
|
|
static List *transformSortClause(ParseState *pstate, |
|
|
|
List *orderlist, List *targetlist, |
|
|
|
List *orderlist, List *targetlist, |
|
|
|
char* uniqueFlag); |
|
|
|
char* uniqueFlag); |
|
|
@ -422,13 +423,14 @@ transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt) |
|
|
|
|
|
|
|
|
|
|
|
/* fix order clause */ |
|
|
|
/* fix order clause */ |
|
|
|
qry->sortClause = transformSortClause(pstate, |
|
|
|
qry->sortClause = transformSortClause(pstate, |
|
|
|
stmt->orderClause, |
|
|
|
stmt->sortClause, |
|
|
|
qry->targetList, |
|
|
|
qry->targetList, |
|
|
|
qry->uniqueFlag); |
|
|
|
qry->uniqueFlag); |
|
|
|
|
|
|
|
|
|
|
|
/* fix group by clause */ |
|
|
|
/* fix group by clause */ |
|
|
|
qry->groupClause = transformGroupClause(pstate, |
|
|
|
qry->groupClause = transformGroupClause(pstate, |
|
|
|
stmt->groupClause); |
|
|
|
stmt->groupClause, |
|
|
|
|
|
|
|
qry->targetList); |
|
|
|
qry->rtable = pstate->p_rtable; |
|
|
|
qry->rtable = pstate->p_rtable; |
|
|
|
|
|
|
|
|
|
|
|
if (pstate->p_numAgg > 0) |
|
|
|
if (pstate->p_numAgg > 0) |
|
|
@ -505,12 +507,13 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt) |
|
|
|
|
|
|
|
|
|
|
|
/* fix order clause */ |
|
|
|
/* fix order clause */ |
|
|
|
qry->sortClause = transformSortClause(pstate, |
|
|
|
qry->sortClause = transformSortClause(pstate, |
|
|
|
stmt->orderClause, |
|
|
|
stmt->sortClause, |
|
|
|
qry->targetList, |
|
|
|
qry->targetList, |
|
|
|
qry->uniqueFlag); |
|
|
|
qry->uniqueFlag); |
|
|
|
/* fix group by clause */ |
|
|
|
/* fix group by clause */ |
|
|
|
qry->groupClause = transformGroupClause(pstate, |
|
|
|
qry->groupClause = transformGroupClause(pstate, |
|
|
|
stmt->groupClause); |
|
|
|
stmt->groupClause, |
|
|
|
|
|
|
|
qry->targetList); |
|
|
|
|
|
|
|
|
|
|
|
qry->rtable = pstate->p_rtable; |
|
|
|
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 |
|
|
|
* returns the Resdom in the target list matching the specified varname |
|
|
|
* and range |
|
|
|
* and range |
|
|
|
* |
|
|
|
* |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static Resdom * |
|
|
|
static TargetEntry * |
|
|
|
find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist) |
|
|
|
find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist) |
|
|
|
{ |
|
|
|
{ |
|
|
|
List *i; |
|
|
|
List *i; |
|
|
|
int real_rtable_pos = 0; |
|
|
|
int real_rtable_pos = 0, target_pos = 0; |
|
|
|
|
|
|
|
TargetEntry *target_result = NULL; |
|
|
|
|
|
|
|
|
|
|
|
if(refname) |
|
|
|
if(sortgroupby->range) |
|
|
|
real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable, refname); |
|
|
|
real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable, |
|
|
|
|
|
|
|
sortgroupby->range); |
|
|
|
|
|
|
|
|
|
|
|
foreach(i, tlist) { |
|
|
|
foreach(i, tlist) { |
|
|
|
TargetEntry *target = (TargetEntry *)lfirst(i); |
|
|
|
TargetEntry *target = (TargetEntry *)lfirst(i); |
|
|
@ -1447,17 +1452,30 @@ find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist) |
|
|
|
char *resname = resnode->resname; |
|
|
|
char *resname = resnode->resname; |
|
|
|
int test_rtable_pos = var->varno; |
|
|
|
int test_rtable_pos = var->varno; |
|
|
|
|
|
|
|
|
|
|
|
if (!strcmp(resname, colname)) { |
|
|
|
if (!sortgroupby->name) { |
|
|
|
if(refname) { |
|
|
|
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(real_rtable_pos == test_rtable_pos) { |
|
|
|
return (resnode); |
|
|
|
if (target_result != NULL) |
|
|
|
|
|
|
|
elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name); |
|
|
|
|
|
|
|
else target_result = target; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
return (resnode); |
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 |
|
|
|
static Oid |
|
|
@ -1478,22 +1496,27 @@ any_ordering_op(int restype) |
|
|
|
* |
|
|
|
* |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static List * |
|
|
|
static List * |
|
|
|
transformGroupClause(ParseState *pstate, List *grouplist) |
|
|
|
transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist) |
|
|
|
{ |
|
|
|
{ |
|
|
|
List *glist = NIL, *gl = NIL; |
|
|
|
List *glist = NIL, *gl = NIL; |
|
|
|
|
|
|
|
|
|
|
|
while (grouplist != NIL) { |
|
|
|
while (grouplist != NIL) { |
|
|
|
GroupClause *grpcl = makeNode(GroupClause); |
|
|
|
GroupClause *grpcl = makeNode(GroupClause); |
|
|
|
Var *groupAttr = (Var*)transformExpr(pstate, (Node*)lfirst(grouplist)); |
|
|
|
TargetEntry *restarget; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist); |
|
|
|
|
|
|
|
|
|
|
|
if (nodeTag(groupAttr) != T_Var) { |
|
|
|
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"); |
|
|
|
elog(WARN, "parser: can only specify attribute in group by"); |
|
|
|
} |
|
|
|
} |
|
|
|
grpcl->grpAttr = groupAttr; |
|
|
|
|
|
|
|
grpcl->grpOpoid = any_ordering_op(groupAttr->vartype); |
|
|
|
grpcl->grpAttr = (Var *)restarget->expr; |
|
|
|
if (glist == NIL) { |
|
|
|
grpcl->grpOpoid = any_ordering_op(grpcl->grpAttr->vartype); |
|
|
|
|
|
|
|
if (glist == NIL) |
|
|
|
gl = glist = lcons(grpcl, NIL); |
|
|
|
gl = glist = lcons(grpcl, NIL); |
|
|
|
} else { |
|
|
|
else { |
|
|
|
lnext(gl) = lcons(grpcl, NIL); |
|
|
|
lnext(gl) = lcons(grpcl, NIL); |
|
|
|
gl = lnext(gl); |
|
|
|
gl = lnext(gl); |
|
|
|
} |
|
|
|
} |
|
|
@ -1517,15 +1540,16 @@ transformSortClause(ParseState *pstate, |
|
|
|
List *s = NIL, *i; |
|
|
|
List *s = NIL, *i; |
|
|
|
|
|
|
|
|
|
|
|
while(orderlist != NIL) { |
|
|
|
while(orderlist != NIL) { |
|
|
|
SortBy *sortby = lfirst(orderlist); |
|
|
|
SortGroupBy *sortby = lfirst(orderlist); |
|
|
|
SortClause *sortcl = makeNode(SortClause); |
|
|
|
SortClause *sortcl = makeNode(SortClause); |
|
|
|
|
|
|
|
TargetEntry *restarget; |
|
|
|
Resdom *resdom; |
|
|
|
Resdom *resdom; |
|
|
|
|
|
|
|
|
|
|
|
resdom = find_tl_elt(pstate, sortby->range, sortby->name, targetlist); |
|
|
|
restarget = find_targetlist_entry(pstate, sortby, targetlist); |
|
|
|
if (resdom == NULL) |
|
|
|
if (restarget == NULL) |
|
|
|
elog(WARN,"The field being sorted by must appear in the target list"); |
|
|
|
elog(WARN,"The field being ordered by must appear in the target list"); |
|
|
|
|
|
|
|
|
|
|
|
sortcl->resdom = resdom; |
|
|
|
sortcl->resdom = resdom = restarget->resdom; |
|
|
|
sortcl->opoid = oprid(oper(sortby->useOp, |
|
|
|
sortcl->opoid = oprid(oper(sortby->useOp, |
|
|
|
resdom->restype, |
|
|
|
resdom->restype, |
|
|
|
resdom->restype)); |
|
|
|
resdom->restype)); |
|
|
|