diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 9ea32d7707aeb49877634745ed974956a6a69466..7b2c521a3535dd833cee3fccb4868b62f1468ab5 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.154 2007/02/14 01:58:56 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.155 2007/02/19 02:23:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -640,6 +640,7 @@ explain_outNode(StringInfo str,
 			{
 				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
 											  es->rtable);
+				Node	   *funcexpr;
 				char	   *proname;
 
 				/* Assert it's on a RangeFunction */
@@ -651,10 +652,10 @@ explain_outNode(StringInfo str,
 				 * happen if the optimizer simplified away the function call,
 				 * for example).
 				 */
-				if (rte->funcexpr && IsA(rte->funcexpr, FuncExpr))
+				funcexpr = ((FunctionScan *) plan)->funcexpr;
+				if (funcexpr && IsA(funcexpr, FuncExpr))
 				{
-					FuncExpr   *funcexpr = (FuncExpr *) rte->funcexpr;
-					Oid			funcid = funcexpr->funcid;
+					Oid			funcid = ((FuncExpr *) funcexpr)->funcid;
 
 					/* We only show the func name, not schema name */
 					proname = get_func_name(funcid);
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c
index 68d0d54a53c54f08bca345400be39cf32a601085..3b48a5cf18bd7aceeea742d61dd6338fcf56f334 100644
--- a/src/backend/executor/execAmi.c
+++ b/src/backend/executor/execAmi.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.91 2007/02/15 03:07:13 tgl Exp $
+ *	$PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.92 2007/02/19 02:23:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -444,13 +444,16 @@ ExecMayReturnRawTuples(PlanState *node)
 		case T_IndexScanState:
 		case T_BitmapHeapScanState:
 		case T_TidScanState:
-		case T_SubqueryScanState:
-		case T_FunctionScanState:
-		case T_ValuesScanState:
 			if (node->ps_ProjInfo == NULL)
 				return true;
 			break;
 
+		case T_SubqueryScanState:
+			/* If not projecting, look at input plan */
+			if (node->ps_ProjInfo == NULL)
+				return ExecMayReturnRawTuples(((SubqueryScanState *) node)->subplan);
+			break;
+
 			/* Non-projecting nodes */
 		case T_HashState:
 		case T_MaterialState:
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index f7ca022f1c7d1970fd51733a565db60128d05494..d3d9886e3c3aee128500537974eec19cf7893b27 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.42 2007/01/05 22:19:28 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.43 2007/02/19 02:23:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -118,7 +118,6 @@ FunctionScanState *
 ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 {
 	FunctionScanState *scanstate;
-	RangeTblEntry *rte;
 	Oid			funcrettype;
 	TypeFuncClass functypclass;
 	TupleDesc	tupdesc = NULL;
@@ -161,17 +160,11 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 		ExecInitExpr((Expr *) node->scan.plan.qual,
 					 (PlanState *) scanstate);
 
-	/*
-	 * get info about function
-	 */
-	rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
-	Assert(rte->rtekind == RTE_FUNCTION);
-
 	/*
 	 * Now determine if the function returns a simple or composite type, and
 	 * build an appropriate tupdesc.
 	 */
-	functypclass = get_expr_result_type(rte->funcexpr,
+	functypclass = get_expr_result_type(node->funcexpr,
 										&funcrettype,
 										&tupdesc);
 
@@ -185,7 +178,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	else if (functypclass == TYPEFUNC_SCALAR)
 	{
 		/* Base data type, i.e. scalar */
-		char	   *attname = strVal(linitial(rte->eref->colnames));
+		char	   *attname = strVal(linitial(node->funccolnames));
 
 		tupdesc = CreateTemplateTupleDesc(1, false);
 		TupleDescInitEntry(tupdesc,
@@ -197,9 +190,9 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	}
 	else if (functypclass == TYPEFUNC_RECORD)
 	{
-		tupdesc = BuildDescFromLists(rte->eref->colnames,
-									 rte->funccoltypes,
-									 rte->funccoltypmods);
+		tupdesc = BuildDescFromLists(node->funccolnames,
+									 node->funccoltypes,
+									 node->funccoltypmods);
 	}
 	else
 	{
@@ -221,7 +214,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	 * Other node-specific setup
 	 */
 	scanstate->tuplestorestate = NULL;
-	scanstate->funcexpr = ExecInitExpr((Expr *) rte->funcexpr,
+	scanstate->funcexpr = ExecInitExpr((Expr *) node->funcexpr,
 									   (PlanState *) scanstate);
 
 	scanstate->ss.ps.ps_TupFromTlist = false;
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index d055b0160c5361ad578454964b210250b93e13f1..96e4b98a4e25cd947c30d2b5f16ca85796264810 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.5 2007/01/05 22:19:28 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.6 2007/02/19 02:23:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -182,7 +182,6 @@ ValuesScanState *
 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 {
 	ValuesScanState *scanstate;
-	RangeTblEntry *rte;
 	TupleDesc	tupdesc;
 	ListCell   *vtl;
 	int			i;
@@ -236,9 +235,7 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 	/*
 	 * get info about values list
 	 */
-	rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
-	Assert(rte->rtekind == RTE_VALUES);
-	tupdesc = ExecTypeFromExprList((List *) linitial(rte->values_lists));
+	tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
 
 	ExecAssignScanType(&scanstate->ss, tupdesc);
 
@@ -247,13 +244,13 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 	 */
 	scanstate->marked_idx = -1;
 	scanstate->curr_idx = -1;
-	scanstate->array_len = list_length(rte->values_lists);
+	scanstate->array_len = list_length(node->values_lists);
 
 	/* convert list of sublists into array of sublists for easy addressing */
 	scanstate->exprlists = (List **)
 		palloc(scanstate->array_len * sizeof(List *));
 	i = 0;
-	foreach(vtl, rte->values_lists)
+	foreach(vtl, node->values_lists)
 	{
 		scanstate->exprlists[i++] = (List *) lfirst(vtl);
 	}
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 2d38d7fd60c0160a97a399c6fd7c5ae12f78d777..cdf98de568a6e158c0e496ccff8a2280c77ebe04 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.365 2007/02/03 14:06:54 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.366 2007/02/19 02:23:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -363,6 +363,14 @@ _copyFunctionScan(FunctionScan *from)
 	 */
 	CopyScanFields((Scan *) from, (Scan *) newnode);
 
+	/*
+	 * copy remainder of node
+	 */
+	COPY_NODE_FIELD(funcexpr);
+	COPY_NODE_FIELD(funccolnames);
+	COPY_NODE_FIELD(funccoltypes);
+	COPY_NODE_FIELD(funccoltypmods);
+
 	return newnode;
 }
 
@@ -379,6 +387,11 @@ _copyValuesScan(ValuesScan *from)
 	 */
 	CopyScanFields((Scan *) from, (Scan *) newnode);
 
+	/*
+	 * copy remainder of node
+	 */
+	COPY_NODE_FIELD(values_lists);
+
 	return newnode;
 }
 
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index d3f18c1ce7366bf14bf4366d3802f71e7036ce37..a173cf59dff671e75bde996a1b6778d61a1ed8f9 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.297 2007/02/12 17:19:30 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.298 2007/02/19 02:23:12 tgl Exp $
  *
  * NOTES
  *	  Every node type that can appear in stored rules' parsetrees *must*
@@ -408,6 +408,11 @@ _outFunctionScan(StringInfo str, FunctionScan *node)
 	WRITE_NODE_TYPE("FUNCTIONSCAN");
 
 	_outScanInfo(str, (Scan *) node);
+
+	WRITE_NODE_FIELD(funcexpr);
+	WRITE_NODE_FIELD(funccolnames);
+	WRITE_NODE_FIELD(funccoltypes);
+	WRITE_NODE_FIELD(funccoltypmods);
 }
 
 static void
@@ -416,6 +421,8 @@ _outValuesScan(StringInfo str, ValuesScan *node)
 	WRITE_NODE_TYPE("VALUESSCAN");
 
 	_outScanInfo(str, (Scan *) node);
+
+	WRITE_NODE_FIELD(values_lists);
 }
 
 static void
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index fdaed3d472ed3908aafe8b1cf5f4e4db3abae25e..4d3d926a167fa58b1d2f06af0ae60013cbba26a3 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.224 2007/01/30 01:33:36 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.225 2007/02/19 02:23:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -96,9 +96,10 @@ static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,
 static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
 			 List *tidquals);
 static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
-				  Index scanrelid);
+				  Index scanrelid, Node *funcexpr, List *funccolnames,
+				  List *funccoltypes, List *funccoltypmods);
 static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
-				Index scanrelid);
+				Index scanrelid, List *values_lists);
 static BitmapAnd *make_bitmap_and(List *bitmapplans);
 static BitmapOr *make_bitmap_or(List *bitmapplans);
 static NestLoop *make_nestloop(List *tlist,
@@ -1350,10 +1351,12 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
 {
 	FunctionScan *scan_plan;
 	Index		scan_relid = best_path->parent->relid;
+	RangeTblEntry *rte;
 
 	/* it should be a function base rel... */
 	Assert(scan_relid > 0);
-	Assert(best_path->parent->rtekind == RTE_FUNCTION);
+	rte = rt_fetch(scan_relid, root->parse->rtable);
+	Assert(rte->rtekind == RTE_FUNCTION);
 
 	/* Sort clauses into best execution order */
 	scan_clauses = order_qual_clauses(root, scan_clauses);
@@ -1361,7 +1364,11 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
 	/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
 	scan_clauses = extract_actual_clauses(scan_clauses, false);
 
-	scan_plan = make_functionscan(tlist, scan_clauses, scan_relid);
+	scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
+								  rte->funcexpr,
+								  rte->eref->colnames,
+								  rte->funccoltypes,
+								  rte->funccoltypmods);
 
 	copy_path_costsize(&scan_plan->scan.plan, best_path);
 
@@ -1379,10 +1386,12 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path,
 {
 	ValuesScan *scan_plan;
 	Index		scan_relid = best_path->parent->relid;
+	RangeTblEntry *rte;
 
 	/* it should be a values base rel... */
 	Assert(scan_relid > 0);
-	Assert(best_path->parent->rtekind == RTE_VALUES);
+	rte = rt_fetch(scan_relid, root->parse->rtable);
+	Assert(rte->rtekind == RTE_VALUES);
 
 	/* Sort clauses into best execution order */
 	scan_clauses = order_qual_clauses(root, scan_clauses);
@@ -1390,7 +1399,8 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path,
 	/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
 	scan_clauses = extract_actual_clauses(scan_clauses, false);
 
-	scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid);
+	scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
+								rte->values_lists);
 
 	copy_path_costsize(&scan_plan->scan.plan, best_path);
 
@@ -2342,7 +2352,11 @@ make_subqueryscan(List *qptlist,
 static FunctionScan *
 make_functionscan(List *qptlist,
 				  List *qpqual,
-				  Index scanrelid)
+				  Index scanrelid,
+				  Node *funcexpr,
+				  List *funccolnames,
+				  List *funccoltypes,
+				  List *funccoltypmods)
 {
 	FunctionScan *node = makeNode(FunctionScan);
 	Plan	   *plan = &node->scan.plan;
@@ -2353,6 +2367,10 @@ make_functionscan(List *qptlist,
 	plan->lefttree = NULL;
 	plan->righttree = NULL;
 	node->scan.scanrelid = scanrelid;
+	node->funcexpr = funcexpr;
+	node->funccolnames = funccolnames;
+	node->funccoltypes = funccoltypes;
+	node->funccoltypmods = funccoltypmods;
 
 	return node;
 }
@@ -2360,7 +2378,8 @@ make_functionscan(List *qptlist,
 static ValuesScan *
 make_valuesscan(List *qptlist,
 				List *qpqual,
-				Index scanrelid)
+				Index scanrelid,
+				List *values_lists)
 {
 	ValuesScan *node = makeNode(ValuesScan);
 	Plan	   *plan = &node->scan.plan;
@@ -2371,6 +2390,7 @@ make_valuesscan(List *qptlist,
 	plan->lefttree = NULL;
 	plan->righttree = NULL;
 	node->scan.scanrelid = scanrelid;
+	node->values_lists = values_lists;
 
 	return node;
 }
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index bec0ddf7c4b33aeae0769d82e10f18788eda6412..3d9f5486bccfce75f312eee1be38fb6b7ec90a75 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.129 2007/02/16 03:49:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.130 2007/02/19 02:23:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -171,28 +171,15 @@ set_plan_references(Plan *plan, List *rtable)
 			/* Needs special treatment, see comments below */
 			return set_subqueryscan_references((SubqueryScan *) plan, rtable);
 		case T_FunctionScan:
-			{
-				RangeTblEntry *rte;
-
-				fix_expr_references(plan, (Node *) plan->targetlist);
-				fix_expr_references(plan, (Node *) plan->qual);
-				rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
-							   rtable);
-				Assert(rte->rtekind == RTE_FUNCTION);
-				fix_expr_references(plan, rte->funcexpr);
-			}
+			fix_expr_references(plan, (Node *) plan->targetlist);
+			fix_expr_references(plan, (Node *) plan->qual);
+			fix_expr_references(plan, ((FunctionScan *) plan)->funcexpr);
 			break;
 		case T_ValuesScan:
-			{
-				RangeTblEntry *rte;
-
-				fix_expr_references(plan, (Node *) plan->targetlist);
-				fix_expr_references(plan, (Node *) plan->qual);
-				rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid,
-							   rtable);
-				Assert(rte->rtekind == RTE_VALUES);
-				fix_expr_references(plan, (Node *) rte->values_lists);
-			}
+			fix_expr_references(plan, (Node *) plan->targetlist);
+			fix_expr_references(plan, (Node *) plan->qual);
+			fix_expr_references(plan,
+								(Node *) ((ValuesScan *) plan)->values_lists);
 			break;
 		case T_NestLoop:
 			set_join_references((Join *) plan);
@@ -369,10 +356,6 @@ set_subqueryscan_references(SubqueryScan *plan, List *rtable)
 				   *lc;
 
 		sub_rtable = copyObject(rte->subquery->rtable);
-		range_table_walker(sub_rtable,
-						   adjust_expr_varnos_walker,
-						   (void *) &rtoffset,
-						   QTW_IGNORE_RT_SUBQUERIES);
 		rtable = list_concat(rtable, sub_rtable);
 
 		/*
@@ -544,13 +527,15 @@ adjust_plan_varnos(Plan *plan, int rtoffset)
 			((FunctionScan *) plan)->scan.scanrelid += rtoffset;
 			adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
 			adjust_expr_varnos((Node *) plan->qual, rtoffset);
-			/* rte was already fixed by set_subqueryscan_references */
+			adjust_expr_varnos(((FunctionScan *) plan)->funcexpr,
+							   rtoffset);
 			break;
 		case T_ValuesScan:
 			((ValuesScan *) plan)->scan.scanrelid += rtoffset;
 			adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
 			adjust_expr_varnos((Node *) plan->qual, rtoffset);
-			/* rte was already fixed by set_subqueryscan_references */
+			adjust_expr_varnos((Node *) ((ValuesScan *) plan)->values_lists,
+							   rtoffset);
 			break;
 		case T_NestLoop:
 			adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index e79991a0f60b039d89e661f7150b5e62b485ee8b..af035d9b104cbbff3e3fd395f85fa7c3d019f122 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.118 2007/02/06 02:59:11 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.119 2007/02/19 02:23:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1103,25 +1103,13 @@ finalize_plan(Plan *plan, List *rtable,
 			break;
 
 		case T_FunctionScan:
-			{
-				RangeTblEntry *rte;
-
-				rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
-							   rtable);
-				Assert(rte->rtekind == RTE_FUNCTION);
-				finalize_primnode(rte->funcexpr, &context);
-			}
+			finalize_primnode(((FunctionScan *) plan)->funcexpr,
+							  &context);
 			break;
 
 		case T_ValuesScan:
-			{
-				RangeTblEntry *rte;
-
-				rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid,
-							   rtable);
-				Assert(rte->rtekind == RTE_VALUES);
-				finalize_primnode((Node *) rte->values_lists, &context);
-			}
+			finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
+							  &context);
 			break;
 
 		case T_Append:
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index c9aa190b33dc6b260fd5fec6965292cfaa3a4fc3..cdd7b4d2e43707fb574fb0ae2e7c040a2117d2f3 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.89 2007/01/10 18:06:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.90 2007/02/19 02:23:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -270,9 +270,11 @@ typedef struct TidScan
  *		subquery scan node
  *
  * SubqueryScan is for scanning the output of a sub-query in the range table.
- * We need a special plan node above the sub-query's plan as a place to switch
- * execution contexts.	Although we are not scanning a physical relation,
- * we make this a descendant of Scan anyway for code-sharing purposes.
+ * We often need an extra plan node above the sub-query's plan to perform
+ * expression evaluations (which we can't push into the sub-query without
+ * risking changing its semantics).  Although we are not scanning a physical
+ * relation, we make this a descendant of Scan anyway for code-sharing
+ * purposes.
  *
  * Note: we store the sub-plan in the type-specific subplan field, not in
  * the generic lefttree field as you might expect.	This is because we do
@@ -293,7 +295,10 @@ typedef struct SubqueryScan
 typedef struct FunctionScan
 {
 	Scan		scan;
-	/* no other fields needed at present */
+	Node	   *funcexpr;		/* expression tree for func call */
+	List	   *funccolnames;	/* output column names (string Value nodes) */
+	List	   *funccoltypes;	/* OID list of column type OIDs */
+	List	   *funccoltypmods; /* integer list of column typmods */
 } FunctionScan;
 
 /* ----------------
@@ -303,7 +308,7 @@ typedef struct FunctionScan
 typedef struct ValuesScan
 {
 	Scan		scan;
-	/* no other fields needed at present */
+	List	   *values_lists;	/* list of expression lists */
 } ValuesScan;
 
 /*