diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/parse_clause.c | 40 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 72 |
2 files changed, 79 insertions, 33 deletions
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: |