Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9f3d639

Browse files
committed
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.
1 parent a453419 commit 9f3d639

File tree

4 files changed

+88
-38
lines changed

4 files changed

+88
-38
lines changed

src/backend/executor/execMain.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.45 1998/02/27 08:43:52 vadim Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.46 1998/05/21 03:53:50 scrappy Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -521,14 +521,16 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
521521
* NOTE: in the future we might want to initialize the junk
522522
* filter for all queries.
523523
* ----------------
524+
* SELECT added by daveh@insightdist.com 5/20/98 to allow
525+
* ORDER/GROUP BY have an identifier missing from the target.
524526
*/
525527
if (operation == CMD_UPDATE || operation == CMD_DELETE ||
526-
operation == CMD_INSERT)
528+
operation == CMD_INSERT || operation == CMD_SELECT)
527529
{
528-
529530
JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList);
530-
531531
estate->es_junkFilter = j;
532+
533+
tupType = j->jf_cleanTupType; /* Added by daveh@insightdist.com 5/20/98 */
532534
}
533535
else
534536
estate->es_junkFilter = NULL;

src/backend/parser/parse_clause.c

+32-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.15 1998/03/31 04:43:53 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.16 1998/05/21 03:53:50 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -182,6 +182,37 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
182182
}
183183
}
184184
}
185+
186+
/* BEGIN add missing target entry hack.
187+
*
188+
* Prior to this hack, this function returned NIL if no target_result.
189+
* Thus, ORDER/GROUP BY required the attributes be in the target list.
190+
* Now it constructs a new target entry which is appended to the end of
191+
* the target list. This target is set to be resjunk = TRUE so that
192+
* it will not be projected into the final tuple.
193+
* daveh@insightdist.com 5/20/98
194+
*/
195+
if ( ! target_result) {
196+
List *p_target = tlist;
197+
Ident *missingTargetId = (Ident *)makeNode(Ident);
198+
TargetEntry *tent = makeNode(TargetEntry);
199+
200+
/* Fill in the constructed Ident node */
201+
missingTargetId->type = T_Ident;
202+
missingTargetId->name = palloc(strlen(sortgroupby->name) + 1);
203+
strcpy(missingTargetId->name, sortgroupby->name);
204+
205+
transformTargetId(pstate, missingTargetId, tent, missingTargetId->name, TRUE);
206+
207+
/* Add to the end of the target list */
208+
while (lnext(p_target) != NIL) {
209+
p_target = lnext(p_target);
210+
}
211+
lnext(p_target) = lcons(tent, NIL);
212+
target_result = tent;
213+
}
214+
/* END add missing target entry hack. */
215+
185216
return target_result;
186217
}
187218

@@ -203,10 +234,6 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
203234
Resdom *resdom;
204235

205236
restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
206-
207-
if (restarget == NULL)
208-
elog(ERROR, "The field being grouped by must appear in the target list");
209-
210237
grpcl->entry = restarget;
211238
resdom = restarget->resdom;
212239
grpcl->grpOpoid = oprid(oper("<",
@@ -262,9 +289,6 @@ transformSortClause(ParseState *pstate,
262289

263290

264291
restarget = find_targetlist_entry(pstate, sortby, targetlist);
265-
if (restarget == NULL)
266-
elog(ERROR, "The field being ordered by must appear in the target list");
267-
268292
sortcl->resdom = resdom = restarget->resdom;
269293
sortcl->opoid = oprid(oper(sortby->useOp,
270294
resdom->restype,

src/backend/parser/parse_target.c

+47-25
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.12 1998/05/09 23:29:54 thomas Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.13 1998/05/21 03:53:51 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -52,6 +52,51 @@ coerce_target_expr(ParseState *pstate,
5252
Oid type_id,
5353
Oid attrtype);
5454

55+
56+
/*
57+
* transformTargetId - transforms an Ident Node to a Target Entry
58+
* Created this a function to allow the ORDER/GROUP BY clause be able
59+
* to construct a TargetEntry from an Ident.
60+
*
61+
* resjunk = TRUE will hide the target entry in the final result tuple.
62+
* daveh@insightdist.com 5/20/98
63+
*/
64+
void
65+
transformTargetId(ParseState *pstate,
66+
Ident *ident,
67+
TargetEntry *tent,
68+
char *resname,
69+
int16 resjunk)
70+
{
71+
Node *expr;
72+
Oid type_id;
73+
int16 type_mod;
74+
75+
/*
76+
* here we want to look for column names only, not
77+
* relation names (even though they can be stored in
78+
* Ident nodes, too)
79+
*/
80+
expr = transformIdent(pstate, (Node *) ident, EXPR_COLUMN_FIRST);
81+
type_id = exprType(expr);
82+
if (nodeTag(expr) == T_Var)
83+
type_mod = ((Var *) expr)->vartypmod;
84+
else
85+
type_mod = -1;
86+
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
87+
(Oid) type_id,
88+
type_mod,
89+
resname,
90+
(Index) 0,
91+
(Oid) 0,
92+
resjunk);
93+
94+
tent->expr = expr;
95+
return;
96+
}
97+
98+
99+
55100
/*
56101
* transformTargetList -
57102
* turns a list of ResTarget's into a list of TargetEntry's
@@ -71,36 +116,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
71116
{
72117
case T_Ident:
73118
{
74-
Node *expr;
75-
Oid type_id;
76-
int16 type_mod;
77119
char *identname;
78120
char *resname;
79121

80122
identname = ((Ident *) res->val)->name;
81123
handleTargetColname(pstate, &res->name, NULL, identname);
82-
83-
/*
84-
* here we want to look for column names only, not
85-
* relation names (even though they can be stored in
86-
* Ident nodes, too)
87-
*/
88-
expr = transformIdent(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
89-
type_id = exprType(expr);
90-
if (nodeTag(expr) == T_Var)
91-
type_mod = ((Var *) expr)->vartypmod;
92-
else
93-
type_mod = -1;
94124
resname = (res->name) ? res->name : identname;
95-
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
96-
(Oid) type_id,
97-
type_mod,
98-
resname,
99-
(Index) 0,
100-
(Oid) 0,
101-
0);
102-
103-
tent->expr = expr;
125+
transformTargetId(pstate, (Ident*)res->val, tent, resname, FALSE);
104126
break;
105127
}
106128
case T_ParamNo:

src/include/parser/parse_target.h

+3-1
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: parse_target.h,v 1.4 1998/02/26 04:42:49 momjian Exp $
9+
* $Id: parse_target.h,v 1.5 1998/05/21 03:53:51 scrappy Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -24,5 +24,7 @@
2424

2525
extern List *transformTargetList(ParseState *pstate, List *targetlist);
2626
extern List *makeTargetNames(ParseState *pstate, List *cols);
27+
extern void transformTargetId(ParseState *pstate, Ident *ident,
28+
TargetEntry *tent, char *resname, int16 resjunk);
2729

2830
#endif /* PARSE_TARGET_H */

0 commit comments

Comments
 (0)