aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/executor/execMain.c10
-rw-r--r--src/backend/parser/parse_clause.c40
-rw-r--r--src/backend/parser/parse_target.c72
-rw-r--r--src/include/parser/parse_target.h4
4 files changed, 88 insertions, 38 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 35107c8af20..1437c2e8c9c 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
*
*
* 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)
* NOTE: in the future we might want to initialize the junk
* 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 ||
- operation == CMD_INSERT)
+ operation == CMD_INSERT || operation == CMD_SELECT)
{
-
JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList);
-
estate->es_junkFilter = j;
+
+ tupType = j->jf_cleanTupType; /* Added by daveh@insightdist.com 5/20/98 */
}
else
estate->es_junkFilter = NULL;
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 30be8335351..06c7cdee5f2 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -7,7 +7,7 @@
*
*
* 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)
}
}
}
+
+ /* 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;
}
@@ -203,10 +234,6 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
Resdom *resdom;
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;
resdom = restarget->resdom;
grpcl->grpOpoid = oprid(oper("<",
@@ -262,9 +289,6 @@ transformSortClause(ParseState *pstate,
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->opoid = oprid(oper(sortby->useOp,
resdom->restype,
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index e3d5654ec4a..e76fa1829e3 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -7,7 +7,7 @@
*
*
* 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,
Oid type_id,
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 -
* turns a list of ResTarget's into a list of TargetEntry's
@@ -71,36 +116,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
{
case T_Ident:
{
- Node *expr;
- Oid type_id;
- int16 type_mod;
char *identname;
char *resname;
identname = ((Ident *) res->val)->name;
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;
- tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
- (Oid) type_id,
- type_mod,
- resname,
- (Index) 0,
- (Oid) 0,
- 0);
-
- tent->expr = expr;
+ transformTargetId(pstate, (Ident*)res->val, tent, resname, FALSE);
break;
}
case T_ParamNo:
diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h
index 98dd31f68c3..cb75d61615e 100644
--- a/src/include/parser/parse_target.h
+++ b/src/include/parser/parse_target.h
@@ -6,7 +6,7 @@
*
* 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 @@
extern List *transformTargetList(ParseState *pstate, List *targetlist);
extern List *makeTargetNames(ParseState *pstate, List *cols);
+extern void transformTargetId(ParseState *pstate, Ident *ident,
+ TargetEntry *tent, char *resname, int16 resjunk);
#endif /* PARSE_TARGET_H */