Commit 9f3d6393 authored by Marc G. Fournier's avatar Marc G. Fournier

From: David Hartwig <daveh@insightdist.com>

Here is a patch to remove the requirement that ORDER/GROUP BY clause
identifiers be included in the target list.
parent a4534197
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.45 1998/02/27 08:43:52 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.46 1998/05/21 03:53:50 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -521,14 +521,16 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) ...@@ -521,14 +521,16 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
* NOTE: in the future we might want to initialize the junk * NOTE: in the future we might want to initialize the junk
* filter for all queries. * filter for all queries.
* ---------------- * ----------------
* SELECT added by daveh@insightdist.com 5/20/98 to allow
* ORDER/GROUP BY have an identifier missing from the target.
*/ */
if (operation == CMD_UPDATE || operation == CMD_DELETE || if (operation == CMD_UPDATE || operation == CMD_DELETE ||
operation == CMD_INSERT) operation == CMD_INSERT || operation == CMD_SELECT)
{ {
JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList); JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList);
estate->es_junkFilter = j; estate->es_junkFilter = j;
tupType = j->jf_cleanTupType; /* Added by daveh@insightdist.com 5/20/98 */
} }
else else
estate->es_junkFilter = NULL; estate->es_junkFilter = NULL;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.15 1998/03/31 04:43:53 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.16 1998/05/21 03:53:50 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -182,6 +182,37 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist) ...@@ -182,6 +182,37 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
} }
} }
} }
/* BEGIN add missing target entry hack.
*
* Prior to this hack, this function returned NIL if no target_result.
* Thus, ORDER/GROUP BY required the attributes be in the target list.
* Now it constructs a new target entry which is appended to the end of
* the target list. This target is set to be resjunk = TRUE so that
* it will not be projected into the final tuple.
* daveh@insightdist.com 5/20/98
*/
if ( ! target_result) {
List *p_target = tlist;
Ident *missingTargetId = (Ident *)makeNode(Ident);
TargetEntry *tent = makeNode(TargetEntry);
/* Fill in the constructed Ident node */
missingTargetId->type = T_Ident;
missingTargetId->name = palloc(strlen(sortgroupby->name) + 1);
strcpy(missingTargetId->name, sortgroupby->name);
transformTargetId(pstate, missingTargetId, tent, missingTargetId->name, TRUE);
/* Add to the end of the target list */
while (lnext(p_target) != NIL) {
p_target = lnext(p_target);
}
lnext(p_target) = lcons(tent, NIL);
target_result = tent;
}
/* END add missing target entry hack. */
return target_result; return target_result;
} }
...@@ -203,10 +234,6 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist) ...@@ -203,10 +234,6 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
Resdom *resdom; Resdom *resdom;
restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist); restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
if (restarget == NULL)
elog(ERROR, "The field being grouped by must appear in the target list");
grpcl->entry = restarget; grpcl->entry = restarget;
resdom = restarget->resdom; resdom = restarget->resdom;
grpcl->grpOpoid = oprid(oper("<", grpcl->grpOpoid = oprid(oper("<",
...@@ -262,9 +289,6 @@ transformSortClause(ParseState *pstate, ...@@ -262,9 +289,6 @@ transformSortClause(ParseState *pstate,
restarget = find_targetlist_entry(pstate, sortby, targetlist); restarget = find_targetlist_entry(pstate, sortby, targetlist);
if (restarget == NULL)
elog(ERROR, "The field being ordered by must appear in the target list");
sortcl->resdom = resdom = restarget->resdom; sortcl->resdom = resdom = restarget->resdom;
sortcl->opoid = oprid(oper(sortby->useOp, sortcl->opoid = oprid(oper(sortby->useOp,
resdom->restype, resdom->restype,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.12 1998/05/09 23:29:54 thomas Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.13 1998/05/21 03:53:51 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -52,6 +52,51 @@ coerce_target_expr(ParseState *pstate, ...@@ -52,6 +52,51 @@ coerce_target_expr(ParseState *pstate,
Oid type_id, Oid type_id,
Oid attrtype); Oid attrtype);
/*
* transformTargetId - transforms an Ident Node to a Target Entry
* Created this a function to allow the ORDER/GROUP BY clause be able
* to construct a TargetEntry from an Ident.
*
* resjunk = TRUE will hide the target entry in the final result tuple.
* daveh@insightdist.com 5/20/98
*/
void
transformTargetId(ParseState *pstate,
Ident *ident,
TargetEntry *tent,
char *resname,
int16 resjunk)
{
Node *expr;
Oid type_id;
int16 type_mod;
/*
* here we want to look for column names only, not
* relation names (even though they can be stored in
* Ident nodes, too)
*/
expr = transformIdent(pstate, (Node *) ident, EXPR_COLUMN_FIRST);
type_id = exprType(expr);
if (nodeTag(expr) == T_Var)
type_mod = ((Var *) expr)->vartypmod;
else
type_mod = -1;
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
(Oid) type_id,
type_mod,
resname,
(Index) 0,
(Oid) 0,
resjunk);
tent->expr = expr;
return;
}
/* /*
* transformTargetList - * transformTargetList -
* turns a list of ResTarget's into a list of TargetEntry's * turns a list of ResTarget's into a list of TargetEntry's
...@@ -71,36 +116,13 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -71,36 +116,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
{ {
case T_Ident: case T_Ident:
{ {
Node *expr;
Oid type_id;
int16 type_mod;
char *identname; char *identname;
char *resname; char *resname;
identname = ((Ident *) res->val)->name; identname = ((Ident *) res->val)->name;
handleTargetColname(pstate, &res->name, NULL, identname); handleTargetColname(pstate, &res->name, NULL, identname);
/*
* here we want to look for column names only, not
* relation names (even though they can be stored in
* Ident nodes, too)
*/
expr = transformIdent(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
type_id = exprType(expr);
if (nodeTag(expr) == T_Var)
type_mod = ((Var *) expr)->vartypmod;
else
type_mod = -1;
resname = (res->name) ? res->name : identname; resname = (res->name) ? res->name : identname;
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++, transformTargetId(pstate, (Ident*)res->val, tent, resname, FALSE);
(Oid) type_id,
type_mod,
resname,
(Index) 0,
(Oid) 0,
0);
tent->expr = expr;
break; break;
} }
case T_ParamNo: case T_ParamNo:
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_target.h,v 1.4 1998/02/26 04:42:49 momjian Exp $ * $Id: parse_target.h,v 1.5 1998/05/21 03:53:51 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
extern List *transformTargetList(ParseState *pstate, List *targetlist); extern List *transformTargetList(ParseState *pstate, List *targetlist);
extern List *makeTargetNames(ParseState *pstate, List *cols); extern List *makeTargetNames(ParseState *pstate, List *cols);
extern void transformTargetId(ParseState *pstate, Ident *ident,
TargetEntry *tent, char *resname, int16 resjunk);
#endif /* PARSE_TARGET_H */ #endif /* PARSE_TARGET_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment