diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index a445a57d9cf6e6ecbb70e2940b046ad076314ce1..6e934a177251004bb706c2d08419c330a5b8e8bb 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.76 2000/07/23 01:35:58 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.77 2000/08/08 15:41:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -294,8 +294,6 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
 	AttrNumber	attnum;
 	HeapTuple	heapTuple;
 	TupleDesc	tuple_type;
-	bool		byval;
-	int16		len;
 
 	/*
 	 * get the slot we want
@@ -363,36 +361,6 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
 						  tuple_type,	/* tuple descriptor of tuple */
 						  isNull);		/* return: is attribute null? */
 
-	/*
-	 * return null if att is null
-	 */
-	if (*isNull)
-		return (Datum) 0;
-
-	/*
-	 * get length and type information.. ??? what should we do about
-	 * variable length attributes - variable length attributes have their
-	 * length stored in the first 4 bytes of the memory pointed to by the
-	 * returned value.. If we can determine that the type is a variable
-	 * length type, we can do the right thing. -cim 9/15/89
-	 */
-	if (attnum < 0)
-	{
-
-		/*
-		 * If this is a pseudo-att, we get the type and fake the length.
-		 * There ought to be a routine to return the real lengths, so
-		 * we'll mark this one ... XXX -mao
-		 */
-		len = heap_sysattrlen(attnum);	/* XXX see -mao above */
-		byval = heap_sysattrbyval(attnum);		/* XXX see -mao above */
-	}
-	else
-	{
-		len = tuple_type->attrs[attnum - 1]->attlen;
-		byval = tuple_type->attrs[attnum - 1]->attbyval ? true : false;
-	}
-
 	return result;
 }
 
@@ -519,25 +487,7 @@ ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
 	/*
 	 * return the value.
 	 */
-	if (paramList->isnull)
-	{
-		*isNull = true;
-		return (Datum) 0;
-	}
-
-	if (expression->param_tlist != NIL)
-	{
-		HeapTuple	tup;
-		Datum		value;
-		List	   *tlist = expression->param_tlist;
-		TargetEntry *tle = (TargetEntry *) lfirst(tlist);
-		TupleTableSlot *slot = (TupleTableSlot *) paramList->value;
-
-		tup = slot->val;
-		value = ProjectAttribute(slot->ttc_tupleDescriptor,
-								 tle, tup, isNull);
-		return value;
-	}
+	*isNull = paramList->isnull;
 	return paramList->value;
 }
 
@@ -686,7 +636,6 @@ ExecMakeFunctionResult(Node *node,
 {
 	FunctionCallInfoData	fcinfo;
 	FunctionCachePtr		fcache;
-	List				   *ftlist;
 	bool					funcisset;
 	Datum					result;
 	bool					argDone;
@@ -702,13 +651,11 @@ ExecMakeFunctionResult(Node *node,
 	if (IsA(node, Func))
 	{
 		fcache = ((Func *) node)->func_fcache;
-		ftlist = ((Func *) node)->func_tlist;
 		funcisset = (((Func *) node)->funcid == F_SETEVAL);
 	}
 	else
 	{
 		fcache = ((Oper *) node)->op_fcache;
-		ftlist = NIL;
 		funcisset = false;
 	}
 
@@ -822,7 +769,7 @@ ExecMakeFunctionResult(Node *node,
 
 			if (callit)
 			{
-				result = postquel_function(&fcinfo, fcache, ftlist, isDone);
+				result = postquel_function(&fcinfo, fcache, isDone);
 				*isNull = fcinfo.isnull;
 			}
 			else
@@ -1214,6 +1161,34 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull)
 	return (Datum) 0;
 }
 
+/* ----------------------------------------------------------------
+ *		ExecEvalFieldSelect
+ *
+ *		Evaluate a FieldSelect node.
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalFieldSelect(FieldSelect *fselect,
+					ExprContext *econtext,
+					bool *isNull,
+					bool *isDone)
+{
+	Datum			result;
+	TupleTableSlot *resSlot;
+
+	result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone);
+	if (*isNull)
+		return result;
+	/* XXX what about isDone? */
+	resSlot = (TupleTableSlot *) DatumGetPointer(result);
+	Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
+	result = heap_getattr(resSlot->val,
+						  fselect->fieldnum,
+						  resSlot->ttc_tupleDescriptor,
+						  isNull);
+	return result;
+}
+
 /* ----------------------------------------------------------------
  *		ExecEvalExpr
  *
@@ -1319,6 +1294,12 @@ ExecEvalExpr(Node *expression,
 				}
 				break;
 			}
+		case T_FieldSelect:
+			retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
+										   econtext,
+										   isNull,
+										   isDone);
+			break;
 		case T_RelabelType:
 			retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
 									econtext,
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index a92811d0342a0409d6f6c2c6a409c09ec53e29d9..001feb267ffe02e0b65f14228ae3f8dc902f0430 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.36 2000/07/12 02:37:03 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.37 2000/08/08 15:41:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,24 +47,21 @@ static void postquel_end(execution_state *es);
 static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo);
 static Datum postquel_execute(execution_state *es,
 							  FunctionCallInfo fcinfo,
-							  FunctionCachePtr fcache,
-							  List *func_tlist);
+							  FunctionCachePtr fcache);
 
 
-Datum
-ProjectAttribute(TupleDesc TD,
-				 TargetEntry *tlist,
-				 HeapTuple tup,
+static Datum
+ProjectAttribute(HeapTuple tup,
+				 AttrNumber	attrno,
+				 TupleDesc TD,
 				 bool *isnullP)
 {
 	Datum		val;
-	Var		   *attrVar = (Var *) tlist->expr;
-	AttrNumber	attrno = attrVar->varattno;
 
 	val = heap_getattr(tup, attrno, TD, isnullP);
 
 	if (*isnullP)
-		return (Datum) 0;
+		return val;
 
 	return datumCopy(val,
 					 TD->attrs[attrno - 1]->attbyval,
@@ -216,39 +213,29 @@ copy_function_result(FunctionCachePtr fcache,
 {
 	TupleTableSlot *funcSlot;
 	TupleDesc	resultTd;
+	HeapTuple	resultTuple;
 	HeapTuple	newTuple;
-	HeapTuple	oldTuple;
 
 	Assert(!TupIsNull(resultSlot));
-	oldTuple = resultSlot->val;
+	resultTuple = resultSlot->val;
 
 	funcSlot = (TupleTableSlot *) fcache->funcSlot;
 
 	if (funcSlot == (TupleTableSlot *) NULL)
 		return resultSlot;
 
-	resultTd = resultSlot->ttc_tupleDescriptor;
-
 	/*
-	 * When the funcSlot is NULL we have to initialize the funcSlot's
+	 * If first time through, we have to initialize the funcSlot's
 	 * tuple descriptor.
 	 */
 	if (TupIsNull(funcSlot))
 	{
-		int			i = 0;
-		TupleDesc	funcTd = funcSlot->ttc_tupleDescriptor;
-
-		while (i < oldTuple->t_data->t_natts)
-		{
-			funcTd->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
-			memmove(funcTd->attrs[i],
-					resultTd->attrs[i],
-					ATTRIBUTE_TUPLE_SIZE);
-			i++;
-		}
+		resultTd = resultSlot->ttc_tupleDescriptor;
+		funcSlot->ttc_tupleDescriptor = CreateTupleDescCopy(resultTd);
+		funcSlot->ttc_descIsNew = true;
 	}
 
-	newTuple = heap_copytuple(oldTuple);
+	newTuple = heap_copytuple(resultTuple);
 
 	return ExecStoreTuple(newTuple, funcSlot, InvalidBuffer, true);
 }
@@ -256,8 +243,7 @@ copy_function_result(FunctionCachePtr fcache,
 static Datum
 postquel_execute(execution_state *es,
 				 FunctionCallInfo fcinfo,
-				 FunctionCachePtr fcache,
-				 List *func_tlist)
+				 FunctionCachePtr fcache)
 {
 	TupleTableSlot *slot;
 	Datum		value;
@@ -305,27 +291,35 @@ postquel_execute(execution_state *es,
 		 * logic and code redundancy here.
 		 */
 		resSlot = copy_function_result(fcache, slot);
-		if (func_tlist != NIL)
-		{
-			TargetEntry *tle = lfirst(func_tlist);
 
-			value = ProjectAttribute(resSlot->ttc_tupleDescriptor,
-									 tle,
-									 resSlot->val,
-									 &fcinfo->isnull);
-		}
-		else
+		/*
+		 * If we are supposed to return a tuple, we return the tuple slot
+		 * pointer converted to Datum.  If we are supposed to return a simple
+		 * value, then project out the first attribute of the result tuple
+		 * (ie, take the first result column of the final SELECT).
+		 */
+		if (fcache->returnsTuple)
 		{
-			/* XXX is this right?  Return whole tuple slot?? */
+			/*
+			 * XXX do we need to remove junk attrs from the result tuple?
+			 * Probably OK to leave them, as long as they are at the end.
+			 */
 			value = PointerGetDatum(resSlot);
 			fcinfo->isnull = false;
 		}
+		else
+		{
+			value = ProjectAttribute(resSlot->val,
+									 1,
+									 resSlot->ttc_tupleDescriptor,
+									 &fcinfo->isnull);
+		}
 
 		/*
 		 * If this is a single valued function we have to end the function
 		 * execution now.
 		 */
-		if (fcache->oneResult)
+		if (!fcache->returnsSet)
 		{
 			postquel_end(es);
 			es->status = F_EXEC_DONE;
@@ -346,7 +340,6 @@ postquel_execute(execution_state *es,
 Datum
 postquel_function(FunctionCallInfo fcinfo,
 				  FunctionCachePtr fcache,
-				  List *func_tlist,
 				  bool *isDone)
 {
 	MemoryContext oldcontext;
@@ -388,10 +381,7 @@ postquel_function(FunctionCallInfo fcinfo,
 	 */
 	while (es != (execution_state *) NULL)
 	{
-		result = postquel_execute(es,
-								  fcinfo,
-								  fcache,
-								  func_tlist);
+		result = postquel_execute(es, fcinfo, fcache);
 		if (es->status != F_EXEC_DONE)
 			break;
 		es = es->next;
@@ -423,7 +413,7 @@ postquel_function(FunctionCallInfo fcinfo,
 		 */
 		*isDone = true;
 		MemoryContextSwitchTo(oldcontext);
-		return (fcache->oneResult) ? result : (Datum) NULL;
+		return (fcache->returnsSet) ? (Datum) NULL : result;
 	}
 
 	/*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 2def370e9fb36d432514138652937de5f616ae34..33b630c7934d100244561e30e8bb6ad984be7b7a 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -19,7 +19,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.118 2000/07/22 04:22:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.119 2000/08/08 15:41:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -717,14 +717,8 @@ _copyOper(Oper *from)
 	newnode->opno = from->opno;
 	newnode->opid = from->opid;
 	newnode->opresulttype = from->opresulttype;
-	newnode->opsize = from->opsize;
-
-	/*
-	 * NOTE: shall we copy the cache structure or just the pointer ?
-	 * Alternatively we can set 'op_fcache' to NULL, in which case the
-	 * executor will initialize it when it needs it...
-	 */
-	newnode->op_fcache = from->op_fcache;
+	/* Do not copy the run-time state, if any */
+	newnode->op_fcache = NULL;
 
 	return newnode;
 }
@@ -797,7 +791,6 @@ _copyParam(Param *from)
 	if (from->paramname != NULL)
 		newnode->paramname = pstrdup(from->paramname);
 	newnode->paramtype = from->paramtype;
-	Node_Copy(from, newnode, param_tlist);
 
 	return newnode;
 }
@@ -817,11 +810,8 @@ _copyFunc(Func *from)
 	 */
 	newnode->funcid = from->funcid;
 	newnode->functype = from->functype;
-	newnode->funcisindex = from->funcisindex;
-	newnode->funcsize = from->funcsize;
-	newnode->func_fcache = from->func_fcache;
-	Node_Copy(from, newnode, func_tlist);
-	Node_Copy(from, newnode, func_planlist);
+	/* Do not copy the run-time state, if any */
+	newnode->func_fcache = NULL;
 
 	return newnode;
 }
@@ -872,6 +862,27 @@ _copySubLink(SubLink *from)
 	return newnode;
 }
 
+/* ----------------
+ *		_copyFieldSelect
+ * ----------------
+ */
+static FieldSelect *
+_copyFieldSelect(FieldSelect *from)
+{
+	FieldSelect *newnode = makeNode(FieldSelect);
+
+	/* ----------------
+	 *	copy remainder of node
+	 * ----------------
+	 */
+	Node_Copy(from, newnode, arg);
+	newnode->fieldnum = from->fieldnum;
+	newnode->resulttype = from->resulttype;
+	newnode->resulttypmod = from->resulttypmod;
+
+	return newnode;
+}
+
 /* ----------------
  *		_copyRelabelType
  * ----------------
@@ -1710,6 +1721,9 @@ copyObject(void *from)
 		case T_Iter:
 			retval = _copyIter(from);
 			break;
+		case T_FieldSelect:
+			retval = _copyFieldSelect(from);
+			break;
 		case T_RelabelType:
 			retval = _copyRelabelType(from);
 			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index b85c410c253fbec3564983078de0d8eec25735bd..701e6511e4441e344504dd0b2628cdce26b198d1 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -24,7 +24,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.70 2000/07/22 04:22:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.71 2000/08/08 15:41:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -154,7 +154,7 @@ _equalOper(Oper *a, Oper *b)
 		return false;
 
 	/*
-	 * We do not examine opid, opsize, or op_fcache, since these are
+	 * We do not examine opid or op_fcache, since these are
 	 * logically derived from opno, and they may not be set yet depending
 	 * on how far along the node is in the parse/plan pipeline.
 	 *
@@ -195,8 +195,6 @@ _equalParam(Param *a, Param *b)
 		return false;
 	if (a->paramtype != b->paramtype)
 		return false;
-	if (!equal(a->param_tlist, b->param_tlist))
-		return false;
 
 	switch (a->paramkind)
 	{
@@ -233,15 +231,7 @@ _equalFunc(Func *a, Func *b)
 		return false;
 	if (a->functype != b->functype)
 		return false;
-	if (a->funcisindex != b->funcisindex)
-		return false;
-	if (a->funcsize != b->funcsize)
-		return false;
-	/* Note we do not look at func_fcache */
-	if (!equal(a->func_tlist, b->func_tlist))
-		return false;
-	if (!equal(a->func_planlist, b->func_planlist))
-		return false;
+	/* Note we do not look at func_fcache; see notes for _equalOper */
 
 	return true;
 }
@@ -281,6 +271,20 @@ _equalSubLink(SubLink *a, SubLink *b)
 	return true;
 }
 
+static bool
+_equalFieldSelect(FieldSelect *a, FieldSelect *b)
+{
+	if (!equal(a->arg, b->arg))
+		return false;
+	if (a->fieldnum != b->fieldnum)
+		return false;
+	if (a->resulttype != b->resulttype)
+		return false;
+	if (a->resulttypmod != b->resulttypmod)
+		return false;
+	return true;
+}
+
 static bool
 _equalRelabelType(RelabelType *a, RelabelType *b)
 {
@@ -787,6 +791,9 @@ equal(void *a, void *b)
 		case T_Iter:
 			retval = _equalIter(a, b);
 			break;
+		case T_FieldSelect:
+			retval = _equalFieldSelect(a, b);
+			break;
 		case T_RelabelType:
 			retval = _equalRelabelType(a, b);
 			break;
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 4bad2008d77a8dd206440fc85af9111fdeeb2c18..45e1c03738c6de3aac16578707e0ef32eb4578ac 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.21 2000/04/12 17:15:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.22 2000/08/08 15:41:24 tgl Exp $
  *
  * NOTES
  *	  Creator functions in POSTGRES 4.2 are generated automatically. Most of
@@ -29,17 +29,14 @@
 Oper *
 makeOper(Oid opno,
 		 Oid opid,
-		 Oid opresulttype,
-		 int opsize,
-		 FunctionCachePtr op_fcache)
+		 Oid opresulttype)
 {
 	Oper	   *oper = makeNode(Oper);
 
 	oper->opno = opno;
 	oper->opid = opid;
 	oper->opresulttype = opresulttype;
-	oper->opsize = opsize;
-	oper->op_fcache = op_fcache;
+	oper->op_fcache = NULL;
 	return oper;
 }
 
@@ -99,8 +96,6 @@ makeResdom(AttrNumber resno,
 		   Oid restype,
 		   int32 restypmod,
 		   char *resname,
-		   Index reskey,
-		   Oid reskeyop,
 		   bool resjunk)
 {
 	Resdom	   *resdom = makeNode(Resdom);
@@ -111,12 +106,14 @@ makeResdom(AttrNumber resno,
 	resdom->resname = resname;
 
 	/*
-	 * For historical reasons, ressortgroupref defaults to 0 while
-	 * reskey/reskeyop are passed in explicitly.  This is pretty silly.
+	 * We always set the sorting/grouping fields to 0.  If the caller wants
+	 * to change them he must do so explicitly.  Few if any callers should
+	 * be doing that, so omitting these arguments reduces the chance of error.
 	 */
 	resdom->ressortgroupref = 0;
-	resdom->reskey = reskey;
-	resdom->reskeyop = reskeyop;
+	resdom->reskey = 0;
+	resdom->reskeyop = InvalidOid;
+
 	resdom->resjunk = resjunk;
 	return resdom;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 155aae37ad2f7026c74455d3e4a9a24d6466310f..14f2ab106c73e1e4d6a0fa2d87f508ac91075530 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.124 2000/07/22 04:22:46 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.125 2000/08/08 15:41:26 tgl Exp $
  *
  * NOTES
  *	  Every (plan) node in POSTGRES has an associated "out" routine which
@@ -757,6 +757,19 @@ _outSubLink(StringInfo str, SubLink *node)
 	_outNode(str, node->subselect);
 }
 
+/*
+ *	FieldSelect
+ */
+static void
+_outFieldSelect(StringInfo str, FieldSelect *node)
+{
+	appendStringInfo(str, " FIELDSELECT :arg ");
+	_outNode(str, node->arg);
+
+	appendStringInfo(str, " :fieldnum %d :resulttype %u :resulttypmod %d ",
+					 node->fieldnum, node->resulttype, node->resulttypmod);
+}
+
 /*
  *	RelabelType
  */
@@ -802,19 +815,9 @@ _outArrayRef(StringInfo str, ArrayRef *node)
 static void
 _outFunc(StringInfo str, Func *node)
 {
-	appendStringInfo(str,
-		   " FUNC :funcid %u :functype %u :funcisindex %s :funcsize %d ",
+	appendStringInfo(str, " FUNC :funcid %u :functype %u ",
 					 node->funcid,
-					 node->functype,
-					 node->funcisindex ? "true" : "false",
-					 node->funcsize);
-
-	appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
-					 (int) node->func_fcache);
-	_outNode(str, node->func_tlist);
-
-	appendStringInfo(str, " :func_planlist ");
-	_outNode(str, node->func_planlist);
+					 node->functype);
 }
 
 /*
@@ -840,9 +843,7 @@ _outParam(StringInfo str, Param *node)
 					 node->paramkind,
 					 node->paramid);
 	_outToken(str, node->paramname);
-	appendStringInfo(str, " :paramtype %u :param_tlist ",
-					 node->paramtype);
-	_outNode(str, node->param_tlist);
+	appendStringInfo(str, " :paramtype %u ", node->paramtype);
 }
 
 /*
@@ -1482,6 +1483,9 @@ _outNode(StringInfo str, void *obj)
 			case T_SubLink:
 				_outSubLink(str, obj);
 				break;
+			case T_FieldSelect:
+				_outFieldSelect(str, obj);
+				break;
 			case T_RelabelType:
 				_outRelabelType(str, obj);
 				break;
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index c663ba304fc285c591b5a17b3a014666ce5783db..17e0396e5fee4f4d7e67a611b22f1575116835bf 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.94 2000/07/22 04:22:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.95 2000/08/08 15:41:27 tgl Exp $
  *
  * NOTES
  *	  Most of the read functions for plan nodes are tested. (In fact, they
@@ -942,29 +942,7 @@ _readFunc()
 	token = lsptok(NULL, &length);		/* now read it */
 	local_node->functype = (Oid) atol(token);
 
-	token = lsptok(NULL, &length);		/* get :funcisindex */
-	token = lsptok(NULL, &length);		/* now read it */
-
-	if (!strncmp(token, "true", 4))
-		local_node->funcisindex = true;
-	else
-		local_node->funcisindex = false;
-
-	token = lsptok(NULL, &length);		/* get :funcsize */
-	token = lsptok(NULL, &length);		/* now read it */
-	local_node->funcsize = atol(token);
-
-	token = lsptok(NULL, &length);		/* get :func_fcache */
-	token = lsptok(NULL, &length);		/* get @ */
-	token = lsptok(NULL, &length);		/* now read it */
-
-	local_node->func_fcache = (FunctionCache *) NULL;
-
-	token = lsptok(NULL, &length);		/* get :func_tlist */
-	local_node->func_tlist = nodeRead(true);	/* now read it */
-
-	token = lsptok(NULL, &length);		/* get :func_planlist */
-	local_node->func_planlist = nodeRead(true); /* now read it */
+	local_node->func_fcache = NULL;
 
 	return local_node;
 }
@@ -996,11 +974,7 @@ _readOper()
 	token = lsptok(NULL, &length);		/* now read it */
 	local_node->opresulttype = (Oid) atol(token);
 
-	/*
-	 * NOTE: Alternatively we can call 'replace_opid' which initializes
-	 * both 'opid' and 'op_fcache'.
-	 */
-	local_node->op_fcache = (FunctionCache *) NULL;
+	local_node->op_fcache = NULL;
 
 	return local_node;
 }
@@ -1039,9 +1013,6 @@ _readParam()
 	token = lsptok(NULL, &length);		/* now read it */
 	local_node->paramtype = (Oid) atol(token);
 
-	token = lsptok(NULL, &length);		/* get :param_tlist */
-	local_node->param_tlist = nodeRead(true);	/* now read it */
-
 	return local_node;
 }
 
@@ -1121,6 +1092,39 @@ _readSubLink()
 	return local_node;
 }
 
+/* ----------------
+ *		_readFieldSelect
+ *
+ *	FieldSelect is a subclass of Node
+ * ----------------
+ */
+static FieldSelect *
+_readFieldSelect()
+{
+	FieldSelect *local_node;
+	char	   *token;
+	int			length;
+
+	local_node = makeNode(FieldSelect);
+
+	token = lsptok(NULL, &length);		/* eat :arg */
+	local_node->arg = nodeRead(true);	/* now read it */
+
+	token = lsptok(NULL, &length);		/* eat :fieldnum */
+	token = lsptok(NULL, &length);		/* get fieldnum */
+	local_node->fieldnum = (AttrNumber) atoi(token);
+
+	token = lsptok(NULL, &length);		/* eat :resulttype */
+	token = lsptok(NULL, &length);		/* get resulttype */
+	local_node->resulttype = (Oid) atol(token);
+
+	token = lsptok(NULL, &length);		/* eat :resulttypmod */
+	token = lsptok(NULL, &length);		/* get resulttypmod */
+	local_node->resulttypmod = atoi(token);
+
+	return local_node;
+}
+
 /* ----------------
  *		_readRelabelType
  *
@@ -1781,6 +1785,8 @@ parsePlanString(void)
 		return_value = _readAggref();
 	else if (length == 7 && strncmp(token, "SUBLINK", length) == 0)
 		return_value = _readSubLink();
+	else if (length == 11 && strncmp(token, "FIELDSELECT", length) == 0)
+		return_value = _readFieldSelect();
 	else if (length == 11 && strncmp(token, "RELABELTYPE", length) == 0)
 		return_value = _readRelabelType();
 	else if (length == 3 && strncmp(token, "AGG", length) == 0)
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 44305558abb3e580c9a622cf191ba5486da96caa..13bf65e699040fc90ec98083694efafa1658cd4c 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.91 2000/08/03 16:34:12 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.92 2000/08/08 15:41:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1339,9 +1339,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
 	 */
 	test_oper = makeOper(test_op,		/* opno */
 						 InvalidOid,	/* opid */
-						 BOOLOID,		/* opresulttype */
-						 0,		/* opsize */
-						 NULL); /* op_fcache */
+						 BOOLOID);		/* opresulttype */
 	replace_opid(test_oper);
 
 	test_expr = make_opclause(test_oper,
@@ -1934,7 +1932,7 @@ prefix_quals(Var *leftop, Oid expr_op,
 		if (oproid == InvalidOid)
 			elog(ERROR, "prefix_quals: no = operator for type %u", datatype);
 		con = string_to_const(prefix, datatype);
-		op = makeOper(oproid, InvalidOid, BOOLOID, 0, NULL);
+		op = makeOper(oproid, InvalidOid, BOOLOID);
 		expr = make_opclause(op, leftop, (Var *) con);
 		result = lcons(expr, NIL);
 		return result;
@@ -1949,7 +1947,7 @@ prefix_quals(Var *leftop, Oid expr_op,
 	if (oproid == InvalidOid)
 		elog(ERROR, "prefix_quals: no >= operator for type %u", datatype);
 	con = string_to_const(prefix, datatype);
-	op = makeOper(oproid, InvalidOid, BOOLOID, 0, NULL);
+	op = makeOper(oproid, InvalidOid, BOOLOID);
 	expr = make_opclause(op, leftop, (Var *) con);
 	result = lcons(expr, NIL);
 
@@ -1964,7 +1962,7 @@ prefix_quals(Var *leftop, Oid expr_op,
 		if (oproid == InvalidOid)
 			elog(ERROR, "prefix_quals: no < operator for type %u", datatype);
 		con = string_to_const(greaterstr, datatype);
-		op = makeOper(oproid, InvalidOid, BOOLOID, 0, NULL);
+		op = makeOper(oproid, InvalidOid, BOOLOID);
 		expr = make_opclause(op, leftop, (Var *) con);
 		result = lappend(result, expr);
 		pfree(greaterstr);
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index e9906bfef2549b45f129d7bea8d8bd67d21dd475..6d7b67bee3df6a359f54bdc05a29ba4965ff527b 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.23 2000/07/24 03:10:56 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.24 2000/08/08 15:41:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -436,12 +436,7 @@ build_index_pathkeys(Query *root,
 
 		funcnode->funcid = index->indproc;
 		funcnode->functype = get_func_rettype(index->indproc);
-		funcnode->funcisindex = false;
-		funcnode->funcsize = 0;
 		funcnode->func_fcache = NULL;
-		/* we assume here that the function returns a base type... */
-		funcnode->func_tlist = setup_base_tlist(funcnode->functype);
-		funcnode->func_planlist = NIL;
 
 		while (*indexkeys != 0)
 		{
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 8b95deca5874d3eee2634d69674704d1171e6669..d2bbff7e6006c532fffac5268ac53b44d55b898c 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.47 2000/07/24 03:11:01 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.48 2000/08/08 15:41:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -382,9 +382,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
 	clause->opType = OP_EXPR;
 	clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */
 									 InvalidOid, /* opid */
-									 BOOLOID, /* operator result type */
-									 0,
-									 NULL);
+									 BOOLOID); /* operator result type */
 	clause->args = lcons(item1, lcons(item2, NIL));
 
 	add_restrict_and_join_to_rel(root, (Node *) clause);
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 42545750d393a695952341c29236050056bb9612..1a9a7d36fa6de7d022fdfd3933392dd4458c7d0a 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.86 2000/07/27 23:15:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.87 2000/08/08 15:41:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -373,8 +373,6 @@ union_planner(Query *parse,
 									TIDOID,
 									-1,
 									resname,
-									0,
-									0,
 									true);
 
 				var = makeVar(rowmark->rti, -1, TIDOID, -1, 0);
@@ -761,8 +759,6 @@ make_subplanTargetList(Query *parse,
 												exprType(groupexpr),
 												exprTypmod(groupexpr),
 												NULL,
-												(Index) 0,
-												(Oid) 0,
 												false),
 									 groupexpr);
 				sub_tlist = lappend(sub_tlist, te);
diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c
index c13cc598485ef1a0e439b4a13eced745c4df08fa..d77e138f193a279efd744bd64954e168fca1f813 100644
--- a/src/backend/optimizer/prep/prepqual.c
+++ b/src/backend/optimizer/prep/prepqual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.26 2000/06/08 22:37:14 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.27 2000/08/08 15:41:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -504,8 +504,7 @@ push_nots(Expr *qual)
 		{
 			Oper	   *op = (Oper *) makeOper(negator,
 											   InvalidOid,
-											   oper->opresulttype,
-											   0, NULL);
+											   oper->opresulttype);
 
 			return make_opclause(op, get_leftop(qual), get_rightop(qual));
 		}
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index a782203cd9b95595f4913c5fe30a7eb5de0072f4..e3b9803d0ab0c19232b0be7904700b265c532342 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.37 2000/07/22 06:19:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.38 2000/08/08 15:41:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,8 +75,6 @@ preprocess_targetlist(List *tlist,
 							TIDOID,
 							-1,
 							pstrdup("ctid"),
-							0,
-							0,
 							true);
 
 		var = makeVar(result_relation, SelfItemPointerAttributeNumber,
@@ -219,8 +217,6 @@ expand_targetlist(List *tlist, int command_type,
 															 atttype,
 															 -1,
 													   pstrdup(attrname),
-															 0,
-															 (Oid) 0,
 															 false),
 												  (Node *) temp_const);
 						break;
@@ -251,8 +247,6 @@ expand_targetlist(List *tlist, int command_type,
 															 atttype,
 															 atttypmod,
 															 pstrdup(attrname),
-															 0,
-															 (Oid) 0,
 															 false),
 												  (Node *) temp_var);
 						break;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index d3a813fb86c134f9f4c1ef21e64edb05fd2cf481..adda68b636aaf9d4b4bf7f0593d02af232ea65e1 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.69 2000/07/12 02:37:11 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.70 2000/08/08 15:41:53 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -910,9 +910,7 @@ CommuteClause(Expr *clause)
 
 	commu = makeOper(heapTup->t_data->t_oid,
 					 commuTup->oprcode,
-					 commuTup->oprresult,
-					 ((Oper *) clause->oper)->opsize,
-					 NULL);
+					 commuTup->oprresult);
 
 	/*
 	 * re-form the clause in-place!
@@ -1596,6 +1594,8 @@ bool
 					return true;
 			}
 			break;
+		case T_FieldSelect:
+			return walker(((FieldSelect *) node)->arg, context);
 		case T_RelabelType:
 			return walker(((RelabelType *) node)->arg, context);
 		case T_CaseExpr:
@@ -1824,6 +1824,16 @@ Node *
 				return (Node *) newnode;
 			}
 			break;
+		case T_FieldSelect:
+			{
+				FieldSelect *fselect = (FieldSelect *) node;
+				FieldSelect *newnode;
+
+				FLATCOPY(newnode, fselect, FieldSelect);
+				MUTATE(newnode->arg, fselect->arg, Node *);
+				return (Node *) newnode;
+			}
+			break;
 		case T_RelabelType:
 			{
 				RelabelType *relabel = (RelabelType *) node;
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index d55c5177089df41632cb196d823729ec4539b564..93b3fc6f568e87b33e82dd4af13cf68cfa2370c9 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.46 2000/06/08 22:37:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.47 2000/08/08 15:41:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -110,8 +110,6 @@ create_tl_element(Var *var, int resdomno)
 									  var->vartype,
 									  var->vartypmod,
 									  NULL,
-									  (Index) 0,
-									  (Oid) 0,
 									  false),
 						   (Node *) var);
 }
@@ -199,8 +197,6 @@ add_to_flat_tlist(List *tlist, List *vars)
 						   var->vartype,
 						   var->vartypmod,
 						   NULL,
-						   (Index) 0,
-						   (Oid) 0,
 						   false);
 			tlist = lappend(tlist,
 							makeTargetEntry(r, copyObject(var)));
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 5824c300d7c85c7dbaeae35891599413c5ca8d35..09f90fe3bc3080abdeff0610d58103457e2ea453 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Id: analyze.c,v 1.152 2000/08/03 16:35:08 tgl Exp $
+ *	$Id: analyze.c,v 1.153 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -470,7 +470,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
 											thisatt->atttypid,
 											thisatt->atttypmod,
 									  pstrdup(NameStr(thisatt->attname)),
-											0, 0, false),
+											false),
 								 stringToNode(defval[ndef].adbin));
 			qry->targetList = lappend(qry->targetList, te);
 
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 8c3e64d6d863c1b3f07db4c4aa4cbc7539237e0a..7976f5e779590ee41d59a98209ba5dc4b631d379 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.81 2000/06/15 03:32:20 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.82 2000/08/08 15:42:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -133,7 +133,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
 				param->paramid = (AttrNumber) paramno;
 				param->paramname = "<unnamed>";
 				param->paramtype = toid;
-				param->param_tlist = NIL;
 				result = transformIndirection(pstate, (Node *) param,
 											  pno->indirection);
 				/* cope with typecast applied to param */
@@ -381,9 +380,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
 
 						newop = makeOper(oprid(optup),	/* opno */
 										 InvalidOid,	/* opid */
-										 opform->oprresult,
-										 0,
-										 NULL);
+										 opform->oprresult);
 						sublink->oper = lappend(sublink->oper, newop);
 					}
 					if (left_list != NIL)
@@ -579,6 +576,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
 		case T_Param:
 		case T_Aggref:
 		case T_ArrayRef:
+		case T_FieldSelect:
 		case T_RelabelType:
 			{
 				result = (Node *) expr;
@@ -690,6 +688,9 @@ exprType(Node *expr)
 		case T_Param:
 			type = ((Param *) expr)->paramtype;
 			break;
+		case T_FieldSelect:
+			type = ((FieldSelect *) expr)->resulttype;
+			break;
 		case T_RelabelType:
 			type = ((RelabelType *) expr)->resulttype;
 			break;
@@ -773,6 +774,9 @@ exprTypmod(Node *expr)
 					return coercedTypmod;
 			}
 			break;
+		case T_FieldSelect:
+			return ((FieldSelect *) expr)->resulttypmod;
+			break;
 		case T_RelabelType:
 			return ((RelabelType *) expr)->resulttypmod;
 			break;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index d1a5e44f8735a2ab88f22a921ab189022091e0a3..44a750c166e38756934b8766a8bd720e367d2fed 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.86 2000/08/03 19:19:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.87 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +59,7 @@ static int match_argtypes(int nargs,
 			   Oid *input_typeids,
 			   CandidateList function_typeids,
 			   CandidateList *candidates);
-static List *setup_tlist(char *attname, Oid relid);
+static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
 static Oid *func_select_candidate(int nargs, Oid *input_typeids,
 					  CandidateList candidates);
 static int	agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
@@ -394,10 +394,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 				argrelid = typeidTypeRelid(toid);
 
 				/*
-				 * A projection contains either an attribute name or "*".
+				 * A projection must match an attribute name of the rel.
 				 */
-				if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
-					&& strcmp(funcname, "*"))
+				if (get_attnum(argrelid, funcname) == InvalidAttrNumber)
 					elog(ERROR, "Functions on sets are not yet supported");
 			}
 
@@ -670,42 +669,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 	funcnode = makeNode(Func);
 	funcnode->funcid = funcid;
 	funcnode->functype = rettype;
-	funcnode->funcisindex = false;
-	funcnode->funcsize = 0;
 	funcnode->func_fcache = NULL;
-	funcnode->func_tlist = NIL;
-	funcnode->func_planlist = NIL;
 
-	/* perform the necessary typecasting */
+	/* perform the necessary typecasting of arguments */
 	make_arguments(pstate, nargs, fargs, oid_array, true_oid_array);
 
-	/*
-	 * for functions returning base types, we want to project out the
-	 * return value.  set up a target list to do that.	the executor will
-	 * ignore these for c functions, and do the right thing for postquel
-	 * functions.
-	 */
-
-	if (typeidTypeRelid(rettype) == InvalidOid)
-		funcnode->func_tlist = setup_base_tlist(rettype);
-
-	/*
-	 * For sets, we want to make a targetlist to project out this
-	 * attribute of the set tuples.
-	 */
-	if (attisset)
-	{
-		if (!strcmp(funcname, "*"))
-			funcnode->func_tlist = expandAll(pstate, relname,
-											 makeAttr(refname, NULL),
-											 curr_resno);
-		else
-		{
-			funcnode->func_tlist = setup_tlist(funcname, argrelid);
-			rettype = get_atttype(argrelid, get_attnum(argrelid, funcname));
-		}
-	}
-
 	/*
 	 * Special checks to disallow sequence functions with side-effects
 	 * in WHERE clauses.  This is pretty much of a hack; why disallow these
@@ -723,6 +691,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 	expr->args = fargs;
 	retval = (Node *) expr;
 
+	/*
+	 * For sets, we want to project out the desired attribute of the tuples.
+	 */
+	if (attisset)
+	{
+		FieldSelect	   *fselect;
+
+		fselect = setup_field_select(retval, funcname, argrelid);
+		rettype = fselect->resulttype;
+		retval = (Node *) fselect;
+	}
+
 	/*
 	 * if the function returns a set of values, then we need to iterate
 	 * over all the returned values in the executor, so we stick an iter
@@ -1524,66 +1504,30 @@ make_arguments(ParseState *pstate,
 }
 
 /*
- ** setup_tlist
- **		Build a tlist that says which attribute to project to.
- **		This routine is called by ParseFuncOrColumn() to set up a target list
- **		on a tuple parameter or return value.  Due to a bug in 4.0,
- **		it's not possible to refer to system attributes in this case.
+ ** setup_field_select
+ **		Build a FieldSelect node that says which attribute to project to.
+ **		This routine is called by ParseFuncOrColumn() when we have found
+ **		a projection on a function result or parameter.
  */
-static List *
-setup_tlist(char *attname, Oid relid)
+static FieldSelect *
+setup_field_select(Node *input, char *attname, Oid relid)
 {
-	TargetEntry *tle;
-	Resdom	   *resnode;
-	Var		   *varnode;
-	Oid			typeid;
-	int32		type_mod;
-	int			attno;
+	FieldSelect *fselect = makeNode(FieldSelect);
+	AttrNumber	attno;
 
 	attno = get_attnum(relid, attname);
+
+	/* XXX Is there still a reason for this restriction? */
 	if (attno < 0)
 		elog(ERROR, "Cannot reference attribute '%s'"
 			 " of tuple params/return values for functions", attname);
 
-	typeid = get_atttype(relid, attno);
-	type_mod = get_atttypmod(relid, attno);
-
-	resnode = makeResdom(1,
-						 typeid,
-						 type_mod,
-						 get_attname(relid, attno),
-						 0,
-						 InvalidOid,
-						 false);
-	varnode = makeVar(-1, attno, typeid, type_mod, 0);
+	fselect->arg = input;
+	fselect->fieldnum = attno;
+	fselect->resulttype = get_atttype(relid, attno);
+	fselect->resulttypmod = get_atttypmod(relid, attno);
 
-	tle = makeTargetEntry(resnode, (Node *) varnode);
-	return lcons(tle, NIL);
-}
-
-/*
- ** setup_base_tlist
- **		Build a tlist that extracts a base type from the tuple
- **		returned by the executor.
- */
-List *
-setup_base_tlist(Oid typeid)
-{
-	TargetEntry *tle;
-	Resdom	   *resnode;
-	Var		   *varnode;
-
-	resnode = makeResdom(1,
-						 typeid,
-						 -1,
-						 "<noname>",
-						 0,
-						 InvalidOid,
-						 false);
-	varnode = makeVar(-1, 1, typeid, -1, 0);
-	tle = makeTargetEntry(resnode, (Node *) varnode);
-
-	return lcons(tle, NIL);
+	return fselect;
 }
 
 /*
@@ -1599,51 +1543,32 @@ ParseComplexProjection(ParseState *pstate,
 {
 	Oid			argtype;
 	Oid			argrelid;
-	Relation	rd;
-	Oid			relid;
-	int			attnum;
+	FieldSelect *fselect;
 
 	switch (nodeTag(first_arg))
 	{
 		case T_Iter:
 			{
-				Func	   *func;
-				Iter	   *iter;
+				Iter	   *iter = (Iter *) first_arg;
 
-				iter = (Iter *) first_arg;
-				func = (Func *) ((Expr *) iter->iterexpr)->oper;
-				argtype = get_func_rettype(func->funcid);
+				/*
+				 * If the argument of the Iter returns a tuple,
+				 * funcname may be a projection.  If so, we stick
+				 * the FieldSelect *inside* the Iter --- this is
+				 * klugy, but necessary because ExecTargetList()
+				 * currently does the right thing only when the
+				 * Iter node is at the top level of a targetlist item.
+				 */
+				argtype = iter->itertype;
 				argrelid = typeidTypeRelid(argtype);
 				if (argrelid &&
-					((attnum = get_attnum(argrelid, funcname))
-					 != InvalidAttrNumber))
+					get_attnum(argrelid, funcname) != InvalidAttrNumber)
 				{
-
-					/*
-					 * the argument is a function returning a tuple, so
-					 * funcname may be a projection
-					 */
-
-					/* add a tlist to the func node and return the Iter */
-					rd = heap_openr_nofail(typeidTypeName(argtype));
-					if (RelationIsValid(rd))
-					{
-						relid = RelationGetRelid(rd);
-						func->func_tlist = setup_tlist(funcname, argrelid);
-						iter->itertype = attnumTypeId(rd, attnum);
-						heap_close(rd, NoLock);
-						return (Node *) iter;
-					}
-					else
-					{
-						elog(ERROR, "Function '%s' has bad return type %d",
-							 funcname, argtype);
-					}
-				}
-				else
-				{
-					/* drop through */
-					;
+					fselect = setup_field_select(iter->iterexpr,
+												 funcname, argrelid);
+					iter->iterexpr = (Node *) fselect;
+					iter->itertype = fselect->resulttype;
+					return (Node *) iter;
 				}
 				break;
 			}
@@ -1665,38 +1590,20 @@ ParseComplexProjection(ParseState *pstate,
 				if (expr->opType != FUNC_EXPR)
 					break;
 
-				funcnode = (Func *) expr->oper;
-				argtype = get_func_rettype(funcnode->funcid);
-				argrelid = typeidTypeRelid(argtype);
-
 				/*
-				 * the argument is a function returning a tuple, so
+				 * If the argument is a function returning a tuple,
 				 * funcname may be a projection
 				 */
+				funcnode = (Func *) expr->oper;
+				argtype = funcnode->functype;
+				argrelid = typeidTypeRelid(argtype);
 				if (argrelid &&
-					(attnum = get_attnum(argrelid, funcname))
-					!= InvalidAttrNumber)
+					get_attnum(argrelid, funcname) != InvalidAttrNumber)
 				{
-					Expr	   *newexpr;
-
-					/* add a tlist to the func node */
-					rd = heap_openr(typeidTypeName(argtype), NoLock);
-
-					relid = RelationGetRelid(rd);
-					funcnode->func_tlist = setup_tlist(funcname, argrelid);
-					funcnode->functype = attnumTypeId(rd, attnum);
-
-					newexpr = makeNode(Expr);
-					newexpr->typeOid = funcnode->functype;
-					newexpr->opType = FUNC_EXPR;
-					newexpr->oper = (Node *) funcnode;
-					newexpr->args = expr->args;
-
-					heap_close(rd, NoLock);
-
-					return (Node *) newexpr;
+					fselect = setup_field_select((Node *) expr,
+												 funcname, argrelid);
+					return (Node *) fselect;
 				}
-
 				break;
 			}
 		case T_Param:
@@ -1707,19 +1614,14 @@ ParseComplexProjection(ParseState *pstate,
 				 * If the Param is a complex type, this could be a
 				 * projection
 				 */
-				rd = heap_openr_nofail(typeidTypeName(param->paramtype));
-				if (RelationIsValid(rd))
+				argtype = param->paramtype;
+				argrelid = typeidTypeRelid(argtype);
+				if (argrelid &&
+					get_attnum(argrelid, funcname) != InvalidAttrNumber)
 				{
-					relid = RelationGetRelid(rd);
-					if ((attnum = get_attnum(relid, funcname))
-						!= InvalidAttrNumber)
-					{
-						param->paramtype = attnumTypeId(rd, attnum);
-						param->param_tlist = setup_tlist(funcname, relid);
-						heap_close(rd, NoLock);
-						return (Node *) param;
-					}
-					heap_close(rd, NoLock);
+					fselect = setup_field_select((Node *) param,
+												 funcname, argrelid);
+					return (Node *) fselect;
 				}
 				break;
 			}
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 273dc0ef64414d4f5d4035c4d0fdb5a5d4af621c..2bda101538ce88af27123b4df1649b75e393d97e 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.43 2000/07/05 23:11:32 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.44 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -161,9 +161,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
 
 	newop = makeOper(oprid(tup),/* opno */
 					 InvalidOid,/* opid */
-					 opform->oprresult, /* operator result type */
-					 0,
-					 NULL);
+					 opform->oprresult); /* operator result type */
 
 	result = makeNode(Expr);
 	result->typeOid = opform->oprresult;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 7a3e3c2d6ad0435d196a73626290185044c4dd17..802299c8966856265f752fd30d4b80664c679fa7 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.45 2000/07/02 22:00:41 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.46 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -412,8 +412,6 @@ expandAll(ParseState *pstate, char *relname, Attr *ref, int *this_resno)
 								varnode->vartype,
 								varnode->vartypmod,
 								label,
-								(Index) 0,
-								(Oid) 0,
 								false);
 		te->expr = (Node *) varnode;
 		te_list = lappend(te_list, te);
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 2f076028cc9f11e79a0e543eecf096b99f78520f..1564f976b042b0ef13154b5640b51e76ecacbda0 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.60 2000/06/15 03:32:20 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.61 2000/08/08 15:42:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,8 +71,6 @@ transformTargetEntry(ParseState *pstate,
 						 type_id,
 						 type_mod,
 						 colname,
-						 (Index) 0,
-						 (Oid) InvalidOid,
 						 resjunk);
 
 	return makeTargetEntry(resnode, expr);
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index acd62c9c70e9082065b795b5c11418a5e9d2c455..1f4073f9fcf9683d9589cf3bae9f172b2a71cd32 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.77 2000/06/30 07:04:22 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.78 2000/08/08 15:42:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1882,9 +1882,7 @@ Except_Intersect_Rewrite(Query *parsetree)
 
 				newop = makeOper(oprid(optup),	/* opno */
 								 InvalidOid,	/* opid */
-								 opform->oprresult,
-								 0,
-								 NULL);
+								 opform->oprresult);
 
 				n->oper = lappend(n->oper, newop);
 
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 502df7713d64d41e1057e3527b6fd80a011f9d26..6d4da07207af6a09e00f36e9ccf93cd32c30792b 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
  *			  out of its tuple
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.57 2000/07/06 23:03:37 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.58 2000/08/08 15:42:21 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1430,6 +1430,32 @@ get_rule_expr(Node *node, deparse_context *context)
 			}
 			break;
 
+		case T_FieldSelect:
+			{
+				FieldSelect *fselect = (FieldSelect *) node;
+				HeapTuple	typetup;
+				Form_pg_type typeStruct;
+				Oid			typrelid;
+				char	   *fieldname;
+
+				/* we do NOT parenthesize the arg expression, for now */
+				get_rule_expr(fselect->arg, context);
+				typetup = SearchSysCacheTuple(TYPEOID,
+								   ObjectIdGetDatum(exprType(fselect->arg)),
+											  0, 0, 0);
+				if (!HeapTupleIsValid(typetup))
+					elog(ERROR, "cache lookup of type %u failed",
+						 exprType(fselect->arg));
+				typeStruct = (Form_pg_type) GETSTRUCT(typetup);
+				typrelid = typeStruct->typrelid;
+				if (!OidIsValid(typrelid))
+					elog(ERROR, "Argument type %s of FieldSelect is not a tuple type",
+						 NameStr(typeStruct->typname));
+				fieldname = get_attribute_name(typrelid, fselect->fieldnum);
+				appendStringInfo(buf, ".%s", quote_identifier(fieldname));
+			}
+			break;
+
 		case T_RelabelType:
 			{
 				RelabelType *relabel = (RelabelType *) node;
diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c
index ba34dfd03dc9448f40bf78800396d3c405828870..15ac990e31d7376c44088d6ef6ead47cf3763e65 100644
--- a/src/backend/utils/cache/fcache.c
+++ b/src/backend/utils/cache/fcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.34 2000/07/12 02:37:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.35 2000/08/08 15:42:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,6 +50,9 @@ GetDynamicFuncArgType(Var *arg, ExprContext *econtext)
 		elog(ERROR, "Lookup failed on type tuple for class %s",
 			 relname);
 
+	/* TEST: I bet this routine is unnecessary ... */
+	Assert(arg->vartype == tup->t_data->t_oid);
+
 	return tup->t_data->t_oid;
 }
 
@@ -116,22 +119,25 @@ init_fcache(Oid foid,
 	{
 		/* The return type is not a relation, so just use byval */
 		retval->typbyval = typeStruct->typbyval;
+		retval->returnsTuple = false;
 	}
 	else
 	{
 
 		/*
 		 * This is a hack.	We assume here that any function returning a
-		 * relation returns it by reference.  This needs to be fixed.
+		 * tuple returns it by reference.  This needs to be fixed, since
+		 * actually the mechanism isn't quite like return-by-reference.
 		 */
 		retval->typbyval = false;
+		retval->returnsTuple = true;
 	}
 	retval->foid = foid;
 	retval->language = procedureStruct->prolang;
+	retval->returnsSet = procedureStruct->proretset;
+	retval->hasSetArg = false;
 	retval->func_state = (char *) NULL;
 	retval->setArg = (Datum) 0;
-	retval->hasSetArg = false;
-	retval->oneResult = !procedureStruct->proretset;
 
 	/*
 	 * If we are returning exactly one result then we have to copy tuples
@@ -140,12 +146,9 @@ init_fcache(Oid foid,
 	 * allocated by the executor (i.e. slots and tuples) is freed.
 	 */
 	if ((retval->language == SQLlanguageId) &&
-		retval->oneResult &&
+		!retval->returnsSet &&
 		!retval->typbyval)
 	{
-		Form_pg_class relationStruct;
-		HeapTuple	relationTuple;
-		TupleDesc	td;
 		TupleTableSlot *slot;
 
 		slot = makeNode(TupleTableSlot);
@@ -155,21 +158,6 @@ init_fcache(Oid foid,
 		slot->ttc_buffer = InvalidBuffer;
 		slot->ttc_whichplan = -1;
 
-		relationTuple =
-			SearchSysCacheTuple(RELNAME,
-								PointerGetDatum(&typeStruct->typname),
-								0, 0, 0);
-
-		if (relationTuple)
-		{
-			relationStruct = (Form_pg_class) GETSTRUCT(relationTuple);
-			td = CreateTemplateTupleDesc(relationStruct->relnatts);
-		}
-		else
-			td = CreateTemplateTupleDesc(1);
-
-		slot->ttc_tupleDescriptor = td;
-
 		retval->funcSlot = (Pointer) slot;
 	}
 	else
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index d0c0b8e2bf9a01e2c6e2c0ec790e3a00f2af5bc5..e69b5753e3a212d71b07ce94d45bd3edcedd0977 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.40 2000/08/06 18:06:13 thomas Exp $
+ * $Id: catversion.h,v 1.41 2000/08/08 15:42:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200008061
+#define CATALOG_VERSION_NO	200008071
 
 #endif
diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h
index 26f2daac535eb7a0fd3103151145d67fc474b774..0e55be1980ed24fc6d6a9a1bfbe605ffe45a68f3 100644
--- a/src/include/executor/functions.h
+++ b/src/include/executor/functions.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: functions.h,v 1.12 2000/05/28 17:56:18 tgl Exp $
+ * $Id: functions.h,v 1.13 2000/08/08 15:42:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,12 +17,8 @@
 #include "nodes/parsenodes.h"
 #include "utils/syscache.h"
 
-extern Datum ProjectAttribute(TupleDesc TD, TargetEntry *tlist,
-							  HeapTuple tup, bool *isnullP);
-
 extern Datum postquel_function(FunctionCallInfo fcinfo,
 							   FunctionCachePtr fcache,
-							   List *func_tlist,
 							   bool *isDone);
 
 #endif	 /* FUNCTIONS_H */
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 3b470b150a29fae8721200a08a19865ea5778498..1ec37fc7b6fefad4ff05faf308ae8186067442ea 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: makefuncs.h,v 1.24 2000/04/12 17:16:40 momjian Exp $
+ * $Id: makefuncs.h,v 1.25 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,9 +18,7 @@
 
 extern Oper *makeOper(Oid opno,
 		 Oid opid,
-		 Oid opresulttype,
-		 int opsize,
-		 FunctionCachePtr op_fcache);
+		 Oid opresulttype);
 
 extern Var *makeVar(Index varno,
 		AttrNumber varattno,
@@ -34,8 +32,6 @@ extern Resdom *makeResdom(AttrNumber resno,
 		   Oid restype,
 		   int32 restypmod,
 		   char *resname,
-		   Index reskey,
-		   Oid reskeyop,
 		   bool resjunk);
 
 extern Const *makeConst(Oid consttype,
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 08a44675fc8c9d03758bd10dda9181256dec9504..27de4d54ebfea7072d7a8f9f299155d83ad51dee 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.72 2000/07/22 04:22:47 tgl Exp $
+ * $Id: nodes.h,v 1.73 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,7 +64,7 @@ typedef enum NodeTag
 	T_Aggref,
 	T_SubLink,
 	T_Func,
-	T_ArrayXXX,					/* not used anymore; this tag# is available */
+	T_FieldSelect,
 	T_ArrayRef,
 	T_Iter,
 	T_RelabelType,
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 47de5779ae57f1e7f23016615bacccaf8ffc89f8..1ad9a3d082ad1bd5ecfbf87771482a910fb7b692 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.45 2000/07/22 04:22:47 tgl Exp $
+ * $Id: primnodes.h,v 1.46 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -160,10 +160,9 @@ typedef struct Var
 /* ----------------
  * Oper
  *		opno			- PG_OPERATOR OID of the operator
- *		opid			- PG_PROC OID for the operator
+ *		opid			- PG_PROC OID for the operator's underlying function
  *		opresulttype	- PG_TYPE OID of the operator's return value
- *		opsize			- size of return result (cached by executor)
- *		op_fcache		- XXX comment me.
+ *		op_fcache		- runtime state while running the function
  *
  * ----
  * NOTE: in the good old days 'opno' used to be both (or either, or
@@ -175,6 +174,10 @@ typedef struct Var
  * (i.e. a mess) some comments were referring to 'opno' using the name
  * 'opid'. Anyway, now we have two separate fields, and of course that
  * immediately removes all bugs from the code...		[ sp :-) ].
+ *
+ * Note also that opid is not necessarily filled in immediately on creation
+ * of the node.  The planner makes sure it is valid before passing the node
+ * tree to the executor, but during parsing/planning opid is typically 0.
  * ----------------
  */
 typedef struct Oper
@@ -183,7 +186,6 @@ typedef struct Oper
 	Oid			opno;
 	Oid			opid;
 	Oid			opresulttype;
-	int			opsize;
 	FunctionCachePtr op_fcache;
 } Oper;
 
@@ -240,7 +242,6 @@ typedef struct Const
  *		paramid - numeric identifier for literal-constant parameters ("$1")
  *		paramname - attribute name for tuple-substitution parameters ("$.foo")
  *		paramtype - PG_TYPE OID of the parameter's value
- *		param_tlist - allows for projection in a param node.
  * ----------------
  */
 typedef struct Param
@@ -250,23 +251,17 @@ typedef struct Param
 	AttrNumber	paramid;
 	char	   *paramname;
 	Oid			paramtype;
-	List	   *param_tlist;
 } Param;
 
 
 /* ----------------
  * Func
- *		funcid			- PG_FUNCTION OID of the function
+ *		funcid			- PG_PROC OID of the function
  *		functype		- PG_TYPE OID of the function's return value
- *		funcisindex		- the function can be evaluated by scanning an index
- *						  (set during query optimization)
- *		funcsize		- size of return result (cached by executor)
  *		func_fcache		- runtime state while running this function.  Where
  *						  we are in the execution of the function if it
  *						  returns more than one value, etc.
  *						  See utils/fcache.h
- *		func_tlist		- projection of functions returning tuples
- *		func_planlist	- result of planning this func, if it's a PQ func
  * ----------------
  */
 typedef struct Func
@@ -274,11 +269,7 @@ typedef struct Func
 	NodeTag		type;
 	Oid			funcid;
 	Oid			functype;
-	bool		funcisindex;
-	int			funcsize;
 	FunctionCachePtr func_fcache;
-	List	   *func_tlist;
-	List	   *func_planlist;
 } Func;
 
 /* ----------------
@@ -439,6 +430,29 @@ typedef struct ArrayRef
 	Node	   *refassgnexpr;
 } ArrayRef;
 
+/* ----------------
+ * FieldSelect
+ *		arg				- input expression
+ *		fieldnum		- attribute number of field to extract
+ *		resulttype		- type of the field (result type of this node)
+ *		resulttypmod	- output typmod (usually -1)
+ *
+ * FieldSelect represents the operation of extracting one field from a tuple
+ * value.  At runtime, the input expression is expected to yield a Datum
+ * that contains a pointer-to-TupleTableSlot.  The specified field number
+ * is extracted and returned as a Datum.
+ * ----------------
+ */
+
+typedef struct FieldSelect
+{
+	NodeTag		type;
+	Node	   *arg;
+	AttrNumber	fieldnum;
+	Oid			resulttype;
+	int32		resulttypmod;
+} FieldSelect;
+
 /* ----------------
  * RelabelType
  *		arg				- input expression
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index 836626486b75c5608e458db6ea0ce4f22efc51a7..79b193a2b5117e63d1456c07ba45b099a9df4dd1 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_func.h,v 1.24 2000/04/12 17:16:45 momjian Exp $
+ * $Id: parse_func.h,v 1.25 2000/08/08 15:42:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,8 +45,6 @@ extern Node *ParseFuncOrColumn(ParseState *pstate,
 				  bool agg_star, bool agg_distinct,
 				  int *curr_resno, int precedence);
 
-extern List *setup_base_tlist(Oid typeid);
-
 extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
 
 extern void func_error(char *caller, char *funcname,
diff --git a/src/include/utils/fcache.h b/src/include/utils/fcache.h
index 59f35867a72b278cc2fd24db1fb450a38cb91dce..efae7613959a75a75491483dd5fd3c91ef73d102 100644
--- a/src/include/utils/fcache.h
+++ b/src/include/utils/fcache.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fcache.h,v 1.12 2000/07/12 02:37:35 tgl Exp $
+ * $Id: fcache.h,v 1.13 2000/08/08 15:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,8 +29,9 @@ typedef struct
 	int			typlen;			/* length of the return type */
 	bool		typbyval;		/* true if return type is pass by value */
 
-	bool		oneResult;		/* true we only want 1 result from the
-								 * function */
+	bool		returnsTuple;	/* true if return type is a tuple */
+	bool		returnsSet;		/* true if func returns a set (multi rows) */
+
 	bool		hasSetArg;		/* true if func is part of a nested dot
 								 * expr whose argument is func returning a
 								 * set ugh! */