*** ./backend/executor/execMain.c.orig Wed May 20 10:45:53 1998 --- ./backend/executor/execMain.c Wed May 20 13:18:45 1998 *************** *** 521,534 **** * NOTE: in the future we might want to initialize the junk * filter for all queries. * ---------------- */ if (operation == CMD_UPDATE || operation == CMD_DELETE || ! operation == CMD_INSERT) { - JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList); - estate->es_junkFilter = j; } else estate->es_junkFilter = NULL; --- 521,536 ---- * 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_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; *** ./backend/parser/parse_clause.c.orig Tue May 19 10:31:52 1998 --- ./backend/parser/parse_clause.c Wed May 20 15:32:43 1998 *************** *** 182,187 **** --- 182,218 ---- } } } + + /* 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,212 **** 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("<", --- 234,239 ---- *************** *** 262,270 **** 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, --- 289,294 ---- *** ./backend/parser/parse_target.c.orig Tue May 19 10:31:17 1998 --- ./backend/parser/parse_target.c Wed May 20 15:35:16 1998 *************** *** 35,41 **** --- 35,86 ---- Node *expr, List *arrayRef); + /* + * 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 */ *************** *** 54,89 **** { 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; break; } case T_ParamNo: --- 99,111 ---- { case T_Ident: { char *identname; char *resname; identname = ((Ident *) res->val)->name; handleTargetColname(pstate, &res->name, NULL, identname); resname = (res->name) ? res->name : identname; ! transformTargetId(pstate, (Ident*)res->val, tent, resname, FALSE); break; } case T_ParamNo: *** ./include/parser/parse_target.h.orig Tue May 19 11:31:00 1998 --- ./include/parser/parse_target.h Tue May 19 11:31:27 1998 *************** *** 24,28 **** --- 24,30 ---- 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 */ *** ./backend/parser/parse_clause.c.orig Thu May 21 10:19:17 1998 --- ./backend/parser/parse_clause.c Mon May 25 13:53:37 1998 *************** *** 192,208 **** * 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) { --- 192,223 ---- * it will not be projected into the final tuple. * daveh@insightdist.com 5/20/98 */ ! if ( ! target_result && sortgroupby->name) { List *p_target = tlist; TargetEntry *tent = makeNode(TargetEntry); ! if (sortgroupby->range) { ! Attr *missingTarget = (Attr *)makeNode(Attr); ! missingTarget->type = T_Attr; ! ! missingTarget->relname = palloc(strlen(sortgroupby->range) + 1); ! strcpy(missingTarget->relname, sortgroupby->range); ! ! missingTarget->attrs = lcons(makeString(sortgroupby->name), NIL); ! ! transformTargetId(pstate, (Node*)missingTarget, tent, sortgroupby->name, TRUE); ! } ! else { ! Ident *missingTarget = (Ident *)makeNode(Ident); ! missingTarget->type = T_Ident; ! ! missingTarget->name = palloc(strlen(sortgroupby->name) + 1); ! strcpy(missingTarget->name, sortgroupby->name); ! ! transformTargetId(pstate, (Node*)missingTarget, tent, sortgroupby->name, TRUE); ! } ! /* Add to the end of the target list */ while (lnext(p_target) != NIL) { *** ./backend/parser/parse_target.c.orig Thu May 21 12:51:33 1998 --- ./backend/parser/parse_target.c Thu May 21 13:21:09 1998 *************** *** 46,52 **** */ void transformTargetId(ParseState *pstate, ! Ident *ident, TargetEntry *tent, char *resname, int16 resjunk) --- 46,52 ---- */ void transformTargetId(ParseState *pstate, ! Node *node, TargetEntry *tent, char *resname, int16 resjunk) *************** *** 60,66 **** * 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; --- 60,66 ---- * relation names (even though they can be stored in * Ident nodes, too) */ ! expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST); type_id = exprType(expr); if (nodeTag(expr) == T_Var) type_mod = ((Var *) expr)->vartypmod; *************** *** 105,111 **** identname = ((Ident *) res->val)->name; handleTargetColname(pstate, &res->name, NULL, identname); resname = (res->name) ? res->name : identname; ! transformTargetId(pstate, (Ident*)res->val, tent, resname, FALSE); break; } case T_ParamNo: --- 105,111 ---- identname = ((Ident *) res->val)->name; handleTargetColname(pstate, &res->name, NULL, identname); resname = (res->name) ? res->name : identname; ! transformTargetId(pstate, (Node*)res->val, tent, resname, FALSE); break; } case T_ParamNo: *** ./include/parser/parse_target.h.orig Thu May 21 14:46:09 1998 --- ./include/parser/parse_target.h Thu May 21 14:46:27 1998 *************** *** 24,30 **** 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 */ --- 24,30 ---- extern List *transformTargetList(ParseState *pstate, List *targetlist); extern List *makeTargetNames(ParseState *pstate, List *cols); ! extern void transformTargetId(ParseState *pstate, Node *node, TargetEntry *tent, char *resname, int16 resjunk); #endif /* PARSE_TARGET_H */ *** ./test/regress/sql/tests.orig Mon May 25 13:36:24 1998 --- ./test/regress/sql/tests Mon May 25 13:36:43 1998 *************** *** 60,62 **** --- 60,63 ---- select_views alter_table portals_p2 + junkfilter