*** ./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