>From 1da2ce38db1c10241d357db4b6dbed0002b456d3 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Aug 2016 19:58:05 -0700
Subject: [PATCH 3/3] Remove now unused tSRF code.

Todo:
- check fmgr readme and comments for references
---
 src/backend/catalog/index.c               |    3 +-
 src/backend/commands/copy.c               |    2 +-
 src/backend/commands/prepare.c            |    3 +-
 src/backend/commands/tablecmds.c          |    3 +-
 src/backend/commands/typecmds.c           |    2 +-
 src/backend/executor/execQual.c           | 1125 +++++------------------------
 src/backend/executor/execScan.c           |   30 +-
 src/backend/executor/execUtils.c          |    6 -
 src/backend/executor/nodeAgg.c            |   45 +-
 src/backend/executor/nodeBitmapHeapscan.c |    2 -
 src/backend/executor/nodeCtescan.c        |    2 -
 src/backend/executor/nodeCustom.c         |    2 -
 src/backend/executor/nodeForeignscan.c    |    2 -
 src/backend/executor/nodeFunctionscan.c   |    2 -
 src/backend/executor/nodeGather.c         |   25 +-
 src/backend/executor/nodeGroup.c          |   42 +-
 src/backend/executor/nodeHash.c           |    2 +-
 src/backend/executor/nodeHashjoin.c       |   52 +-
 src/backend/executor/nodeIndexonlyscan.c  |    2 -
 src/backend/executor/nodeIndexscan.c      |   11 +-
 src/backend/executor/nodeLimit.c          |    6 +-
 src/backend/executor/nodeMergejoin.c      |   59 +-
 src/backend/executor/nodeModifyTable.c    |    4 +-
 src/backend/executor/nodeNestloop.c       |   41 +-
 src/backend/executor/nodeResult.c         |   33 +-
 src/backend/executor/nodeSamplescan.c     |    8 +-
 src/backend/executor/nodeSeqscan.c        |    2 -
 src/backend/executor/nodeSubplan.c        |   31 +-
 src/backend/executor/nodeSubqueryscan.c   |    2 -
 src/backend/executor/nodeTidscan.c        |    8 +-
 src/backend/executor/nodeValuesscan.c     |    5 +-
 src/backend/executor/nodeWindowAgg.c      |   55 +-
 src/backend/executor/nodeWorktablescan.c  |    2 -
 src/backend/optimizer/util/clauses.c      |    2 +-
 src/backend/optimizer/util/predtest.c     |    2 +-
 src/backend/utils/adt/domains.c           |    2 +-
 src/backend/utils/adt/xml.c               |    4 +-
 src/include/executor/executor.h           |    9 +-
 src/include/nodes/execnodes.h             |   16 +-
 src/pl/plpgsql/src/pl_exec.c              |    5 +-
 40 files changed, 242 insertions(+), 1417 deletions(-)

diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 7b30e46..0be278f 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1788,8 +1788,7 @@ FormIndexDatum(IndexInfo *indexInfo,
 				elog(ERROR, "wrong number of index expressions");
 			iDatum = ExecEvalExprSwitchContext((ExprState *) lfirst(indexpr_item),
 											   GetPerTupleExprContext(estate),
-											   &isNull,
-											   NULL);
+											   &isNull);
 			indexpr_item = lnext(indexpr_item);
 		}
 		values[i] = iDatum;
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index f45b330..28466ac 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -3172,7 +3172,7 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext,
 		Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory);
 
 		values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
-										 &nulls[defmap[i]], NULL);
+										 &nulls[defmap[i]]);
 	}
 
 	return true;
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index cec37ce..451c8d5 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -404,8 +404,7 @@ EvaluateParams(PreparedStatement *pstmt, List *params,
 		prm->pflags = PARAM_FLAG_CONST;
 		prm->value = ExecEvalExprSwitchContext(n,
 											   GetPerTupleExprContext(estate),
-											   &prm->isnull,
-											   NULL);
+											   &prm->isnull);
 
 		i++;
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 86e9814..92e468d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4151,8 +4151,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 
 					values[ex->attnum - 1] = ExecEvalExpr(ex->exprstate,
 														  econtext,
-													 &isnull[ex->attnum - 1],
-														  NULL);
+													 &isnull[ex->attnum - 1]);
 				}
 
 				/*
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index ce04211..755af68 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2741,7 +2741,7 @@ validateDomainConstraint(Oid domainoid, char *ccbin)
 
 				conResult = ExecEvalExprSwitchContext(exprstate,
 													  econtext,
-													  &isNull, NULL);
+													  &isNull);
 
 				if (!isNull && !DatumGetBool(conResult))
 				{
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 8896455..41f7307 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -62,128 +62,119 @@
 /* static function decls */
 static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
 				 ExprContext *econtext,
-				 bool *isNull, ExprDoneCond *isDone);
+				 bool *isNull);
 static bool isAssignmentIndirectionExpr(ExprState *exprstate);
 static Datum ExecEvalAggref(AggrefExprState *aggref,
 			   ExprContext *econtext,
-			   bool *isNull, ExprDoneCond *isDone);
+			   bool *isNull);
 static Datum ExecEvalWindowFunc(WindowFuncExprState *wfunc,
 				   ExprContext *econtext,
-				   bool *isNull, ExprDoneCond *isDone);
+				   bool *isNull);
 static Datum ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
-				  bool *isNull, ExprDoneCond *isDone);
+				  bool *isNull);
 static Datum ExecEvalScalarVarFast(ExprState *exprstate, ExprContext *econtext,
-					  bool *isNull, ExprDoneCond *isDone);
+					  bool *isNull);
 static Datum ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate,
 					ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone);
+					bool *isNull);
 static Datum ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate,
 					 ExprContext *econtext,
-					 bool *isNull, ExprDoneCond *isDone);
+					 bool *isNull);
 static Datum ExecEvalWholeRowSlow(WholeRowVarExprState *wrvstate,
 					 ExprContext *econtext,
-					 bool *isNull, ExprDoneCond *isDone);
+					 bool *isNull);
 static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
-			  bool *isNull, ExprDoneCond *isDone);
+			  bool *isNull);
 static Datum ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
-				  bool *isNull, ExprDoneCond *isDone);
+				  bool *isNull);
 static Datum ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone);
+					bool *isNull);
 static void init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
-			MemoryContext fcacheCxt, bool needDescForSets);
-static void ShutdownFuncExpr(Datum arg);
+			MemoryContext fcacheCxt);
 static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
 				   TupleDesc *cache_field, ExprContext *econtext);
 static void ShutdownTupleDescRef(Datum arg);
-static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
+static void ExecEvalFuncArgs(FunctionCallInfo fcinfo,
 				 List *argList, ExprContext *econtext);
-static void ExecPrepareTuplestoreResult(FuncExprState *fcache,
-							ExprContext *econtext,
-							Tuplestorestate *resultStore,
-							TupleDesc resultDesc);
 static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc);
-static Datum ExecMakeFunctionResult(FuncExprState *fcache,
-					   ExprContext *econtext,
-					   bool *isNull,
-					   ExprDoneCond *isDone);
 static Datum ExecMakeFunctionResultNoSets(FuncExprState *fcache,
 							 ExprContext *econtext,
-							 bool *isNull, ExprDoneCond *isDone);
+							 bool *isNull);
 static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,
-			 bool *isNull, ExprDoneCond *isDone);
+			 bool *isNull);
 static Datum ExecEvalOper(FuncExprState *fcache, ExprContext *econtext,
-			 bool *isNull, ExprDoneCond *isDone);
+			 bool *isNull);
 static Datum ExecEvalDistinct(FuncExprState *fcache, ExprContext *econtext,
-				 bool *isNull, ExprDoneCond *isDone);
+				 bool *isNull);
 static Datum ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
 					  ExprContext *econtext,
-					  bool *isNull, ExprDoneCond *isDone);
+					  bool *isNull);
 static Datum ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone);
+			bool *isNull);
 static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
-		   bool *isNull, ExprDoneCond *isDone);
+		   bool *isNull);
 static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone);
+			bool *isNull);
 static Datum ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
 					   ExprContext *econtext,
-					   bool *isNull, ExprDoneCond *isDone);
+					   bool *isNull);
 static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
-			 bool *isNull, ExprDoneCond *isDone);
+			 bool *isNull);
 static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
 					 ExprContext *econtext,
-					 bool *isNull, ExprDoneCond *isDone);
+					 bool *isNull);
 static Datum ExecEvalArray(ArrayExprState *astate,
 			  ExprContext *econtext,
-			  bool *isNull, ExprDoneCond *isDone);
+			  bool *isNull);
 static Datum ExecEvalRow(RowExprState *rstate,
 			ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone);
+			bool *isNull);
 static Datum ExecEvalRowCompare(RowCompareExprState *rstate,
 				   ExprContext *econtext,
-				   bool *isNull, ExprDoneCond *isDone);
+				   bool *isNull);
 static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
 				 ExprContext *econtext,
-				 bool *isNull, ExprDoneCond *isDone);
+				 bool *isNull);
 static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
 			   ExprContext *econtext,
-			   bool *isNull, ExprDoneCond *isDone);
+			   bool *isNull);
 static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone);
+			bool *isNull);
 static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
 			   ExprContext *econtext,
-			   bool *isNull, ExprDoneCond *isDone);
+			   bool *isNull);
 static Datum ExecEvalNullTest(NullTestState *nstate,
 				 ExprContext *econtext,
-				 bool *isNull, ExprDoneCond *isDone);
+				 bool *isNull);
 static Datum ExecEvalBooleanTest(GenericExprState *bstate,
 					ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone);
+					bool *isNull);
 static Datum ExecEvalCoerceToDomain(CoerceToDomainState *cstate,
 					   ExprContext *econtext,
-					   bool *isNull, ExprDoneCond *isDone);
+					   bool *isNull);
 static Datum ExecEvalCoerceToDomainValue(ExprState *exprstate,
 							ExprContext *econtext,
-							bool *isNull, ExprDoneCond *isDone);
+							bool *isNull);
 static Datum ExecEvalFieldSelect(FieldSelectState *fstate,
 					ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone);
+					bool *isNull);
 static Datum ExecEvalFieldStore(FieldStoreState *fstate,
 				   ExprContext *econtext,
-				   bool *isNull, ExprDoneCond *isDone);
+				   bool *isNull);
 static Datum ExecEvalRelabelType(GenericExprState *exprstate,
 					ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone);
+					bool *isNull);
 static Datum ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
 					ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone);
+					bool *isNull);
 static Datum ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
 						ExprContext *econtext,
-						bool *isNull, ExprDoneCond *isDone);
+						bool *isNull);
 static Datum ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
-					  bool *isNull, ExprDoneCond *isDone);
+					  bool *isNull);
 static Datum ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
 						 ExprContext *econtext,
-						 bool *isNull, ExprDoneCond *isDone);
+						 bool *isNull);
 
 
 /* ----------------------------------------------------------------
@@ -194,8 +185,7 @@ static Datum ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
  * Each of the following routines having the signature
  *		Datum ExecEvalFoo(ExprState *expression,
  *						  ExprContext *econtext,
- *						  bool *isNull,
- *						  ExprDoneCond *isDone);
+ *						  bool *isNull);
  * is responsible for evaluating one type or subtype of ExprState node.
  * They are normally called via the ExecEvalExpr macro, which makes use of
  * the function pointer set up when the ExprState node was built by
@@ -219,22 +209,6 @@ static Datum ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
  *		return value: Datum value of result
  *		*isNull: set to TRUE if result is NULL (actual return value is
  *				 meaningless if so); set to FALSE if non-null result
- *		*isDone: set to indicator of set-result status
- *
- * A caller that can only accept a singleton (non-set) result should pass
- * NULL for isDone; if the expression computes a set result then an error
- * will be reported via ereport.  If the caller does pass an isDone pointer
- * then *isDone is set to one of these three states:
- *		ExprSingleResult		singleton result (not a set)
- *		ExprMultipleResult		return value is one element of a set
- *		ExprEndResult			there are no more elements in the set
- * When ExprMultipleResult is returned, the caller should invoke
- * ExecEvalExpr() repeatedly until ExprEndResult is returned.  ExprEndResult
- * is returned after the last real set element.  For convenience isNull will
- * always be set TRUE when ExprEndResult is returned, but this should not be
- * taken as indicating a NULL element of the set.  Note that these return
- * conventions allow us to distinguish among a singleton NULL, a NULL element
- * of a set, and an empty set.
  *
  * The caller should already have switched into the temporary memory
  * context econtext->ecxt_per_tuple_memory.  The convenience entry point
@@ -259,8 +233,7 @@ static Datum ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
 static Datum
 ExecEvalArrayRef(ArrayRefExprState *astate,
 				 ExprContext *econtext,
-				 bool *isNull,
-				 ExprDoneCond *isDone)
+				 bool *isNull)
 {
 	ArrayRef   *arrayRef = (ArrayRef *) astate->xprstate.expr;
 	Datum		array_source;
@@ -277,8 +250,7 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
 
 	array_source = ExecEvalExpr(astate->refexpr,
 								econtext,
-								isNull,
-								isDone);
+								isNull);
 
 	/*
 	 * If refexpr yields NULL, and it's a fetch, then result is NULL. In the
@@ -286,8 +258,6 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
 	 */
 	if (*isNull)
 	{
-		if (isDone && *isDone == ExprEndResult)
-			return (Datum) NULL;	/* end of set result */
 		if (!isAssignment)
 			return (Datum) NULL;
 	}
@@ -313,8 +283,7 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
 
 		upper.indx[i++] = DatumGetInt32(ExecEvalExpr(eltstate,
 													 econtext,
-													 &eisnull,
-													 NULL));
+													 &eisnull));
 		/* If any index expr yields NULL, result is NULL or error */
 		if (eisnull)
 		{
@@ -349,8 +318,7 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
 
 			lower.indx[j++] = DatumGetInt32(ExecEvalExpr(eltstate,
 														 econtext,
-														 &eisnull,
-														 NULL));
+														 &eisnull));
 			/* If any index expr yields NULL, result is NULL or error */
 			if (eisnull)
 			{
@@ -437,8 +405,7 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
 		 */
 		sourceData = ExecEvalExpr(astate->refassgnexpr,
 								  econtext,
-								  &eisnull,
-								  NULL);
+								  &eisnull);
 
 		econtext->caseValue_datum = save_datum;
 		econtext->caseValue_isNull = save_isNull;
@@ -541,11 +508,8 @@ isAssignmentIndirectionExpr(ExprState *exprstate)
  */
 static Datum
 ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
-			   bool *isNull, ExprDoneCond *isDone)
+			   bool *isNull)
 {
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	if (econtext->ecxt_aggvalues == NULL)		/* safety check */
 		elog(ERROR, "no aggregates in this expression context");
 
@@ -562,11 +526,8 @@ ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
  */
 static Datum
 ExecEvalWindowFunc(WindowFuncExprState *wfunc, ExprContext *econtext,
-				   bool *isNull, ExprDoneCond *isDone)
+				   bool *isNull)
 {
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	if (econtext->ecxt_aggvalues == NULL)		/* safety check */
 		elog(ERROR, "no window functions in this expression context");
 
@@ -587,15 +548,12 @@ ExecEvalWindowFunc(WindowFuncExprState *wfunc, ExprContext *econtext,
  */
 static Datum
 ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
-				  bool *isNull, ExprDoneCond *isDone)
+				  bool *isNull)
 {
 	Var		   *variable = (Var *) exprstate->expr;
 	TupleTableSlot *slot;
 	AttrNumber	attnum;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/* Get the input slot and attribute number we want */
 	switch (variable->varno)
 	{
@@ -676,15 +634,12 @@ ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
  */
 static Datum
 ExecEvalScalarVarFast(ExprState *exprstate, ExprContext *econtext,
-					  bool *isNull, ExprDoneCond *isDone)
+					  bool *isNull)
 {
 	Var		   *variable = (Var *) exprstate->expr;
 	TupleTableSlot *slot;
 	AttrNumber	attnum;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/* Get the input slot and attribute number we want */
 	switch (variable->varno)
 	{
@@ -724,7 +679,7 @@ ExecEvalScalarVarFast(ExprState *exprstate, ExprContext *econtext,
  */
 static Datum
 ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone)
+					bool *isNull)
 {
 	Var		   *variable = (Var *) wrvstate->xprstate.expr;
 	TupleTableSlot *slot;
@@ -732,9 +687,6 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
 	MemoryContext oldcontext;
 	bool		needslow = false;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/* This was checked by ExecInitExpr */
 	Assert(variable->varattno == InvalidAttrNumber);
 
@@ -940,7 +892,7 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
 
 	/* Fetch the value */
 	return (*wrvstate->xprstate.evalfunc) ((ExprState *) wrvstate, econtext,
-										   isNull, isDone);
+										   isNull);
 }
 
 /* ----------------------------------------------------------------
@@ -951,14 +903,12 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
  */
 static Datum
 ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext,
-					 bool *isNull, ExprDoneCond *isDone)
+					 bool *isNull)
 {
 	Var		   *variable = (Var *) wrvstate->xprstate.expr;
 	TupleTableSlot *slot;
 	HeapTupleHeader dtuple;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
 	*isNull = false;
 
 	/* Get the input slot we want */
@@ -1007,7 +957,7 @@ ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext,
  */
 static Datum
 ExecEvalWholeRowSlow(WholeRowVarExprState *wrvstate, ExprContext *econtext,
-					 bool *isNull, ExprDoneCond *isDone)
+					 bool *isNull)
 {
 	Var		   *variable = (Var *) wrvstate->xprstate.expr;
 	TupleTableSlot *slot;
@@ -1017,8 +967,6 @@ ExecEvalWholeRowSlow(WholeRowVarExprState *wrvstate, ExprContext *econtext,
 	HeapTupleHeader dtuple;
 	int			i;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
 	*isNull = false;
 
 	/* Get the input slot we want */
@@ -1096,13 +1044,10 @@ ExecEvalWholeRowSlow(WholeRowVarExprState *wrvstate, ExprContext *econtext,
  */
 static Datum
 ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
-			  bool *isNull, ExprDoneCond *isDone)
+			  bool *isNull)
 {
 	Const	   *con = (Const *) exprstate->expr;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	*isNull = con->constisnull;
 	return con->constvalue;
 }
@@ -1115,15 +1060,12 @@ ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
  */
 static Datum
 ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
-				  bool *isNull, ExprDoneCond *isDone)
+				  bool *isNull)
 {
 	Param	   *expression = (Param *) exprstate->expr;
 	int			thisParamId = expression->paramid;
 	ParamExecData *prm;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/*
 	 * PARAM_EXEC params (internal executor parameters) are stored in the
 	 * ecxt_param_exec_vals array, and can be accessed by array index.
@@ -1148,15 +1090,12 @@ ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
  */
 static Datum
 ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone)
+					bool *isNull)
 {
 	Param	   *expression = (Param *) exprstate->expr;
 	int			thisParamId = expression->paramid;
 	ParamListInfo paramInfo = econtext->ecxt_param_list_info;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/*
 	 * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
 	 */
@@ -1322,7 +1261,7 @@ GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
  */
 static void
 init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
-			MemoryContext fcacheCxt, bool needDescForSets)
+			MemoryContext fcacheCxt)
 {
 	AclResult	aclresult;
 
@@ -1355,88 +1294,9 @@ init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
 							 list_length(fcache->args),
 							 input_collation, NULL, NULL);
 
-	/* If function returns set, prepare expected tuple descriptor */
-	if (fcache->func.fn_retset && needDescForSets)
-	{
-		TypeFuncClass functypclass;
-		Oid			funcrettype;
-		TupleDesc	tupdesc;
-		MemoryContext oldcontext;
-
-		functypclass = get_expr_result_type(fcache->func.fn_expr,
-											&funcrettype,
-											&tupdesc);
-
-		/* Must save tupdesc in fcache's context */
-		oldcontext = MemoryContextSwitchTo(fcacheCxt);
-
-		if (functypclass == TYPEFUNC_COMPOSITE)
-		{
-			/* Composite data type, e.g. a table's row type */
-			Assert(tupdesc);
-			/* Must copy it out of typcache for safety */
-			fcache->funcResultDesc = CreateTupleDescCopy(tupdesc);
-			fcache->funcReturnsTuple = true;
-		}
-		else if (functypclass == TYPEFUNC_SCALAR)
-		{
-			/* Base data type, i.e. scalar */
-			tupdesc = CreateTemplateTupleDesc(1, false);
-			TupleDescInitEntry(tupdesc,
-							   (AttrNumber) 1,
-							   NULL,
-							   funcrettype,
-							   -1,
-							   0);
-			fcache->funcResultDesc = tupdesc;
-			fcache->funcReturnsTuple = false;
-		}
-		else if (functypclass == TYPEFUNC_RECORD)
-		{
-			/* This will work if function doesn't need an expectedDesc */
-			fcache->funcResultDesc = NULL;
-			fcache->funcReturnsTuple = true;
-		}
-		else
-		{
-			/* Else, we will fail if function needs an expectedDesc */
-			fcache->funcResultDesc = NULL;
-		}
-
-		MemoryContextSwitchTo(oldcontext);
-	}
-	else
-		fcache->funcResultDesc = NULL;
-
 	/* Initialize additional state */
 	fcache->funcResultStore = NULL;
 	fcache->funcResultSlot = NULL;
-	fcache->setArgsValid = false;
-	fcache->shutdown_reg = false;
-}
-
-/*
- * callback function in case a FuncExpr returning a set needs to be shut down
- * before it has been run to completion
- */
-static void
-ShutdownFuncExpr(Datum arg)
-{
-	FuncExprState *fcache = (FuncExprState *) DatumGetPointer(arg);
-
-	/* If we have a slot, make sure it's let go of any tuplestore pointer */
-	if (fcache->funcResultSlot)
-		ExecClearTuple(fcache->funcResultSlot);
-
-	/* Release any open tuplestore */
-	if (fcache->funcResultStore)
-		tuplestore_end(fcache->funcResultStore);
-	fcache->funcResultStore = NULL;
-
-	/* Clear any active set-argument state */
-	fcache->setArgsValid = false;
-
-	/* execUtils will deregister the callback... */
 	fcache->shutdown_reg = false;
 }
 
@@ -1498,123 +1358,26 @@ ShutdownTupleDescRef(Datum arg)
 /*
  * Evaluate arguments for a function.
  */
-static ExprDoneCond
+static void
 ExecEvalFuncArgs(FunctionCallInfo fcinfo,
 				 List *argList,
 				 ExprContext *econtext)
 {
-	ExprDoneCond argIsDone;
 	int			i;
 	ListCell   *arg;
 
-	argIsDone = ExprSingleResult;		/* default assumption */
-
 	i = 0;
 	foreach(arg, argList)
 	{
 		ExprState  *argstate = (ExprState *) lfirst(arg);
-		ExprDoneCond thisArgIsDone;
 
 		fcinfo->arg[i] = ExecEvalExpr(argstate,
 									  econtext,
-									  &fcinfo->argnull[i],
-									  &thisArgIsDone);
-
-		if (thisArgIsDone != ExprSingleResult)
-		{
-			/*
-			 * We allow only one argument to have a set value; we'd need much
-			 * more complexity to keep track of multiple set arguments (cf.
-			 * ExecTargetList) and it doesn't seem worth it.
-			 */
-			if (argIsDone != ExprSingleResult)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("functions and operators can take at most one set argument")));
-			argIsDone = thisArgIsDone;
-		}
+									  &fcinfo->argnull[i]);
 		i++;
 	}
 
 	Assert(i == fcinfo->nargs);
-
-	return argIsDone;
-}
-
-/*
- *		ExecPrepareTuplestoreResult
- *
- * Subroutine for ExecMakeFunctionResult: prepare to extract rows from a
- * tuplestore function result.  We must set up a funcResultSlot (unless
- * already done in a previous call cycle) and verify that the function
- * returned the expected tuple descriptor.
- */
-static void
-ExecPrepareTuplestoreResult(FuncExprState *fcache,
-							ExprContext *econtext,
-							Tuplestorestate *resultStore,
-							TupleDesc resultDesc)
-{
-	fcache->funcResultStore = resultStore;
-
-	if (fcache->funcResultSlot == NULL)
-	{
-		/* Create a slot so we can read data out of the tuplestore */
-		TupleDesc	slotDesc;
-		MemoryContext oldcontext;
-
-		oldcontext = MemoryContextSwitchTo(fcache->func.fn_mcxt);
-
-		/*
-		 * If we were not able to determine the result rowtype from context,
-		 * and the function didn't return a tupdesc, we have to fail.
-		 */
-		if (fcache->funcResultDesc)
-			slotDesc = fcache->funcResultDesc;
-		else if (resultDesc)
-		{
-			/* don't assume resultDesc is long-lived */
-			slotDesc = CreateTupleDescCopy(resultDesc);
-		}
-		else
-		{
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("function returning setof record called in "
-							"context that cannot accept type record")));
-			slotDesc = NULL;	/* keep compiler quiet */
-		}
-
-		fcache->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
-		MemoryContextSwitchTo(oldcontext);
-	}
-
-	/*
-	 * If function provided a tupdesc, cross-check it.  We only really need to
-	 * do this for functions returning RECORD, but might as well do it always.
-	 */
-	if (resultDesc)
-	{
-		if (fcache->funcResultDesc)
-			tupledesc_match(fcache->funcResultDesc, resultDesc);
-
-		/*
-		 * If it is a dynamically-allocated TupleDesc, free it: it is
-		 * typically allocated in a per-query context, so we must avoid
-		 * leaking it across multiple usages.
-		 */
-		if (resultDesc->tdrefcount == -1)
-			FreeTupleDesc(resultDesc);
-	}
-
-	/* Register cleanup callback if we didn't already */
-	if (!fcache->shutdown_reg)
-	{
-		RegisterExprContextCallback(econtext,
-									ShutdownFuncExpr,
-									PointerGetDatum(fcache));
-		fcache->shutdown_reg = true;
-	}
 }
 
 /*
@@ -1668,330 +1431,15 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
 }
 
 /*
- *		ExecMakeFunctionResult
- *
- * Evaluate the arguments to a function and then the function itself.
- * init_fcache is presumed already run on the FuncExprState.
- *
- * This function handles the most general case, wherein the function or
- * one of its arguments can return a set.
- */
-static Datum
-ExecMakeFunctionResult(FuncExprState *fcache,
-					   ExprContext *econtext,
-					   bool *isNull,
-					   ExprDoneCond *isDone)
-{
-	List	   *arguments;
-	Datum		result;
-	FunctionCallInfo fcinfo;
-	PgStat_FunctionCallUsage fcusage;
-	ReturnSetInfo rsinfo;		/* for functions returning sets */
-	ExprDoneCond argDone;
-	bool		hasSetArg;
-	int			i;
-
-restart:
-
-	/* Guard against stack overflow due to overly complex expressions */
-	check_stack_depth();
-
-	/*
-	 * If a previous call of the function returned a set result in the form of
-	 * a tuplestore, continue reading rows from the tuplestore until it's
-	 * empty.
-	 */
-	if (fcache->funcResultStore)
-	{
-		Assert(isDone);			/* it was provided before ... */
-		if (tuplestore_gettupleslot(fcache->funcResultStore, true, false,
-									fcache->funcResultSlot))
-		{
-			*isDone = ExprMultipleResult;
-			if (fcache->funcReturnsTuple)
-			{
-				/* We must return the whole tuple as a Datum. */
-				*isNull = false;
-				return ExecFetchSlotTupleDatum(fcache->funcResultSlot);
-			}
-			else
-			{
-				/* Extract the first column and return it as a scalar. */
-				return slot_getattr(fcache->funcResultSlot, 1, isNull);
-			}
-		}
-		/* Exhausted the tuplestore, so clean up */
-		tuplestore_end(fcache->funcResultStore);
-		fcache->funcResultStore = NULL;
-		/* We are done unless there was a set-valued argument */
-		if (!fcache->setHasSetArg)
-		{
-			*isDone = ExprEndResult;
-			*isNull = true;
-			return (Datum) 0;
-		}
-		/* If there was, continue evaluating the argument values */
-		Assert(!fcache->setArgsValid);
-	}
-
-	/*
-	 * arguments is a list of expressions to evaluate before passing to the
-	 * function manager.  We skip the evaluation if it was already done in the
-	 * previous call (ie, we are continuing the evaluation of a set-valued
-	 * function).  Otherwise, collect the current argument values into fcinfo.
-	 */
-	fcinfo = &fcache->fcinfo_data;
-	arguments = fcache->args;
-	if (!fcache->setArgsValid)
-	{
-		argDone = ExecEvalFuncArgs(fcinfo, arguments, econtext);
-		if (argDone == ExprEndResult)
-		{
-			/* input is an empty set, so return an empty set. */
-			*isNull = true;
-			if (isDone)
-				*isDone = ExprEndResult;
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("set-valued function called in context that cannot accept a set")));
-			return (Datum) 0;
-		}
-		hasSetArg = (argDone != ExprSingleResult);
-	}
-	else
-	{
-		/* Re-use callinfo from previous evaluation */
-		hasSetArg = fcache->setHasSetArg;
-		/* Reset flag (we may set it again below) */
-		fcache->setArgsValid = false;
-	}
-
-	/*
-	 * Now call the function, passing the evaluated parameter values.
-	 */
-	if (fcache->func.fn_retset || hasSetArg)
-	{
-		/*
-		 * We need to return a set result.  Complain if caller not ready to
-		 * accept one.
-		 */
-		if (isDone == NULL)
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("set-valued function called in context that cannot accept a set")));
-
-		/*
-		 * Prepare a resultinfo node for communication.  If the function
-		 * doesn't itself return set, we don't pass the resultinfo to the
-		 * function, but we need to fill it in anyway for internal use.
-		 */
-		if (fcache->func.fn_retset)
-			fcinfo->resultinfo = (Node *) &rsinfo;
-		rsinfo.type = T_ReturnSetInfo;
-		rsinfo.econtext = econtext;
-		rsinfo.expectedDesc = fcache->funcResultDesc;
-		rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
-		/* note we do not set SFRM_Materialize_Random or _Preferred */
-		rsinfo.returnMode = SFRM_ValuePerCall;
-		/* isDone is filled below */
-		rsinfo.setResult = NULL;
-		rsinfo.setDesc = NULL;
-
-		/*
-		 * This loop handles the situation where we have both a set argument
-		 * and a set-valued function.  Once we have exhausted the function's
-		 * value(s) for a particular argument value, we have to get the next
-		 * argument value and start the function over again. We might have to
-		 * do it more than once, if the function produces an empty result set
-		 * for a particular input value.
-		 */
-		for (;;)
-		{
-			/*
-			 * If function is strict, and there are any NULL arguments, skip
-			 * calling the function (at least for this set of args).
-			 */
-			bool		callit = true;
-
-			if (fcache->func.fn_strict)
-			{
-				for (i = 0; i < fcinfo->nargs; i++)
-				{
-					if (fcinfo->argnull[i])
-					{
-						callit = false;
-						break;
-					}
-				}
-			}
-
-			if (callit)
-			{
-				pgstat_init_function_usage(fcinfo, &fcusage);
-
-				fcinfo->isnull = false;
-				rsinfo.isDone = ExprSingleResult;
-				result = FunctionCallInvoke(fcinfo);
-				*isNull = fcinfo->isnull;
-				*isDone = rsinfo.isDone;
-
-				pgstat_end_function_usage(&fcusage,
-										rsinfo.isDone != ExprMultipleResult);
-			}
-			else if (fcache->func.fn_retset)
-			{
-				/* for a strict SRF, result for NULL is an empty set */
-				result = (Datum) 0;
-				*isNull = true;
-				*isDone = ExprEndResult;
-			}
-			else
-			{
-				/* for a strict non-SRF, result for NULL is a NULL */
-				result = (Datum) 0;
-				*isNull = true;
-				*isDone = ExprSingleResult;
-			}
-
-			/* Which protocol does function want to use? */
-			if (rsinfo.returnMode == SFRM_ValuePerCall)
-			{
-				if (*isDone != ExprEndResult)
-				{
-					/*
-					 * Got a result from current argument. If function itself
-					 * returns set, save the current argument values to re-use
-					 * on the next call.
-					 */
-					if (fcache->func.fn_retset &&
-						*isDone == ExprMultipleResult)
-					{
-						fcache->setHasSetArg = hasSetArg;
-						fcache->setArgsValid = true;
-						/* Register cleanup callback if we didn't already */
-						if (!fcache->shutdown_reg)
-						{
-							RegisterExprContextCallback(econtext,
-														ShutdownFuncExpr,
-													PointerGetDatum(fcache));
-							fcache->shutdown_reg = true;
-						}
-					}
-
-					/*
-					 * Make sure we say we are returning a set, even if the
-					 * function itself doesn't return sets.
-					 */
-					if (hasSetArg)
-						*isDone = ExprMultipleResult;
-					break;
-				}
-			}
-			else if (rsinfo.returnMode == SFRM_Materialize)
-			{
-				/* check we're on the same page as the function author */
-				if (rsinfo.isDone != ExprSingleResult)
-					ereport(ERROR,
-							(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
-							 errmsg("table-function protocol for materialize mode was not followed")));
-				if (rsinfo.setResult != NULL)
-				{
-					/* prepare to return values from the tuplestore */
-					ExecPrepareTuplestoreResult(fcache, econtext,
-												rsinfo.setResult,
-												rsinfo.setDesc);
-					/* remember whether we had set arguments */
-					fcache->setHasSetArg = hasSetArg;
-					/* loop back to top to start returning from tuplestore */
-					goto restart;
-				}
-				/* if setResult was left null, treat it as empty set */
-				*isDone = ExprEndResult;
-				*isNull = true;
-				result = (Datum) 0;
-			}
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
-						 errmsg("unrecognized table-function returnMode: %d",
-								(int) rsinfo.returnMode)));
-
-			/* Else, done with this argument */
-			if (!hasSetArg)
-				break;			/* input not a set, so done */
-
-			/* Re-eval args to get the next element of the input set */
-			argDone = ExecEvalFuncArgs(fcinfo, arguments, econtext);
-
-			if (argDone != ExprMultipleResult)
-			{
-				/* End of argument set, so we're done. */
-				*isNull = true;
-				*isDone = ExprEndResult;
-				result = (Datum) 0;
-				break;
-			}
-
-			/*
-			 * If we reach here, loop around to run the function on the new
-			 * argument.
-			 */
-		}
-	}
-	else
-	{
-		/*
-		 * Non-set case: much easier.
-		 *
-		 * In common cases, this code path is unreachable because we'd have
-		 * selected ExecMakeFunctionResultNoSets instead.  However, it's
-		 * possible to get here if an argument sometimes produces set results
-		 * and sometimes scalar results.  For example, a CASE expression might
-		 * call a set-returning function in only some of its arms.
-		 */
-		if (isDone)
-			*isDone = ExprSingleResult;
-
-		/*
-		 * If function is strict, and there are any NULL arguments, skip
-		 * calling the function and return NULL.
-		 */
-		if (fcache->func.fn_strict)
-		{
-			for (i = 0; i < fcinfo->nargs; i++)
-			{
-				if (fcinfo->argnull[i])
-				{
-					*isNull = true;
-					return (Datum) 0;
-				}
-			}
-		}
-
-		pgstat_init_function_usage(fcinfo, &fcusage);
-
-		fcinfo->isnull = false;
-		result = FunctionCallInvoke(fcinfo);
-		*isNull = fcinfo->isnull;
-
-		pgstat_end_function_usage(&fcusage, true);
-	}
-
-	return result;
-}
-
-/*
  *		ExecMakeFunctionResultNoSets
  *
- * Simplified version of ExecMakeFunctionResult that can only handle
- * non-set cases.  Hand-tuned for speed.
+ * Portion of ExecMakeFunctionResult that does not need initialization.
+ * Hand-tuned for speed.
  */
 static Datum
 ExecMakeFunctionResultNoSets(FuncExprState *fcache,
 							 ExprContext *econtext,
-							 bool *isNull,
-							 ExprDoneCond *isDone)
+							 bool *isNull)
 {
 	ListCell   *arg;
 	Datum		result;
@@ -2002,9 +1450,6 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
 	/* Guard against stack overflow due to overly complex expressions */
 	check_stack_depth();
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/* inlined, simplified version of ExecEvalFuncArgs */
 	fcinfo = &fcache->fcinfo_data;
 	i = 0;
@@ -2014,8 +1459,7 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
 
 		fcinfo->arg[i] = ExecEvalExpr(argstate,
 									  econtext,
-									  &fcinfo->argnull[i],
-									  NULL);
+									  &fcinfo->argnull[i]);
 		i++;
 	}
 
@@ -2112,7 +1556,6 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 		IsA(funcexpr->expr, FuncExpr))
 	{
 		FuncExprState *fcache = (FuncExprState *) funcexpr;
-		ExprDoneCond argDone;
 
 		/*
 		 * This path is similar to ExecMakeFunctionResult.
@@ -2127,7 +1570,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 			FuncExpr   *func = (FuncExpr *) fcache->xprstate.expr;
 
 			init_fcache(func->funcid, func->inputcollid, fcache,
-						econtext->ecxt_per_query_memory, false);
+						econtext->ecxt_per_query_memory);
 		}
 		returnsSet = fcache->func.fn_retset;
 		InitFunctionCallInfoData(fcinfo, &(fcache->func),
@@ -2147,15 +1590,9 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 		 */
 		MemoryContextReset(argContext);
 		oldcontext = MemoryContextSwitchTo(argContext);
-		argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
+		ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
 		MemoryContextSwitchTo(oldcontext);
 
-		/* We don't allow sets in the arguments of the table function */
-		if (argDone != ExprSingleResult)
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("set-valued function called in context that cannot accept a set")));
-
 		/*
 		 * If function is strict, and there are any NULL arguments, skip
 		 * calling the function and act like it returned NULL (or an empty
@@ -2215,8 +1652,9 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 		}
 		else
 		{
+			rsinfo.isDone = ExprSingleResult;
 			result = ExecEvalExpr(funcexpr, econtext,
-								  &fcinfo.isnull, &rsinfo.isDone);
+								  &fcinfo.isnull);
 		}
 
 		/* Which protocol does function want to use? */
@@ -2410,15 +1848,14 @@ no_function_result:
 static Datum
 ExecEvalFunc(FuncExprState *fcache,
 			 ExprContext *econtext,
-			 bool *isNull,
-			 ExprDoneCond *isDone)
+			 bool *isNull)
 {
 	/* This is called only the first time through */
 	FuncExpr   *func = (FuncExpr *) fcache->xprstate.expr;
 
 	/* Initialize function lookup info */
 	init_fcache(func->funcid, func->inputcollid, fcache,
-				econtext->ecxt_per_query_memory, true);
+				econtext->ecxt_per_query_memory);
 
 	if (fcache->func.fn_retset)
 	{
@@ -2427,22 +1864,9 @@ ExecEvalFunc(FuncExprState *fcache,
 				 errmsg("set-valued function called in context that cannot accept a set")));
 	}
 
-	/*
-	 * We need to invoke ExecMakeFunctionResult if either the function itself
-	 * or any of its input expressions can return a set.  Otherwise, invoke
-	 * ExecMakeFunctionResultNoSets.  In either case, change the evalfunc
-	 * pointer to go directly there on subsequent uses.
-	 */
-	if (fcache->func.fn_retset || expression_returns_set((Node *) func->args))
-	{
-		fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;
-		return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
-	}
-	else
-	{
-		fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
-		return ExecMakeFunctionResultNoSets(fcache, econtext, isNull, isDone);
-	}
+	/* Change the evalfunc pointer, to skip the above initialization. */
+	fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
+	return ExecMakeFunctionResultNoSets(fcache, econtext, isNull);
 }
 
 /* ----------------------------------------------------------------
@@ -2452,32 +1876,25 @@ ExecEvalFunc(FuncExprState *fcache,
 static Datum
 ExecEvalOper(FuncExprState *fcache,
 			 ExprContext *econtext,
-			 bool *isNull,
-			 ExprDoneCond *isDone)
+			 bool *isNull)
 {
 	/* This is called only the first time through */
 	OpExpr	   *op = (OpExpr *) fcache->xprstate.expr;
 
 	/* Initialize function lookup info */
 	init_fcache(op->opfuncid, op->inputcollid, fcache,
-				econtext->ecxt_per_query_memory, true);
+				econtext->ecxt_per_query_memory);
 
-	/*
-	 * We need to invoke ExecMakeFunctionResult if either the function itself
-	 * or any of its input expressions can return a set.  Otherwise, invoke
-	 * ExecMakeFunctionResultNoSets.  In either case, change the evalfunc
-	 * pointer to go directly there on subsequent uses.
-	 */
-	if (fcache->func.fn_retset || expression_returns_set((Node *) op->args))
+	if (fcache->func.fn_retset)
 	{
-		fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;
-		return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
-	}
-	else
-	{
-		fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
-		return ExecMakeFunctionResultNoSets(fcache, econtext, isNull, isDone);
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
 	}
+
+	/* Change the evalfunc pointer, to skip the above initialization. */
+	fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
+	return ExecMakeFunctionResultNoSets(fcache, econtext, isNull);
 }
 
 /* ----------------------------------------------------------------
@@ -2494,17 +1911,13 @@ ExecEvalOper(FuncExprState *fcache,
 static Datum
 ExecEvalDistinct(FuncExprState *fcache,
 				 ExprContext *econtext,
-				 bool *isNull,
-				 ExprDoneCond *isDone)
+				 bool *isNull)
 {
 	Datum		result;
 	FunctionCallInfo fcinfo;
-	ExprDoneCond argDone;
 
 	/* Set default values for result flags: non-null, not a set result */
 	*isNull = false;
-	if (isDone)
-		*isDone = ExprSingleResult;
 
 	/*
 	 * Initialize function cache if first time through
@@ -2514,7 +1927,7 @@ ExecEvalDistinct(FuncExprState *fcache,
 		DistinctExpr *op = (DistinctExpr *) fcache->xprstate.expr;
 
 		init_fcache(op->opfuncid, op->inputcollid, fcache,
-					econtext->ecxt_per_query_memory, true);
+					econtext->ecxt_per_query_memory);
 		Assert(!fcache->func.fn_retset);
 	}
 
@@ -2522,11 +1935,7 @@ ExecEvalDistinct(FuncExprState *fcache,
 	 * Evaluate arguments
 	 */
 	fcinfo = &fcache->fcinfo_data;
-	argDone = ExecEvalFuncArgs(fcinfo, fcache->args, econtext);
-	if (argDone != ExprSingleResult)
-		ereport(ERROR,
-				(errcode(ERRCODE_DATATYPE_MISMATCH),
-				 errmsg("IS DISTINCT FROM does not support set arguments")));
+	ExecEvalFuncArgs(fcinfo, fcache->args, econtext);
 	Assert(fcinfo->nargs == 2);
 
 	if (fcinfo->argnull[0] && fcinfo->argnull[1])
@@ -2562,7 +1971,7 @@ ExecEvalDistinct(FuncExprState *fcache,
 static Datum
 ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
 					  ExprContext *econtext,
-					  bool *isNull, ExprDoneCond *isDone)
+					  bool *isNull)
 {
 	ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) sstate->fxprstate.xprstate.expr;
 	bool		useOr = opexpr->useOr;
@@ -2571,7 +1980,6 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
 	Datum		result;
 	bool		resultnull;
 	FunctionCallInfo fcinfo;
-	ExprDoneCond argDone;
 	int			i;
 	int16		typlen;
 	bool		typbyval;
@@ -2582,8 +1990,6 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
 
 	/* Set default values for result flags: non-null, not a set result */
 	*isNull = false;
-	if (isDone)
-		*isDone = ExprSingleResult;
 
 	/*
 	 * Initialize function cache if first time through
@@ -2591,7 +1997,7 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
 	if (sstate->fxprstate.func.fn_oid == InvalidOid)
 	{
 		init_fcache(opexpr->opfuncid, opexpr->inputcollid, &sstate->fxprstate,
-					econtext->ecxt_per_query_memory, true);
+					econtext->ecxt_per_query_memory);
 		Assert(!sstate->fxprstate.func.fn_retset);
 	}
 
@@ -2599,11 +2005,7 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
 	 * Evaluate arguments
 	 */
 	fcinfo = &sstate->fxprstate.fcinfo_data;
-	argDone = ExecEvalFuncArgs(fcinfo, sstate->fxprstate.args, econtext);
-	if (argDone != ExprSingleResult)
-		ereport(ERROR,
-				(errcode(ERRCODE_DATATYPE_MISMATCH),
-			   errmsg("op ANY/ALL (array) does not support set arguments")));
+	ExecEvalFuncArgs(fcinfo, sstate->fxprstate.args, econtext);
 	Assert(fcinfo->nargs == 2);
 
 	/*
@@ -2749,15 +2151,12 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
  */
 static Datum
 ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone)
+			bool *isNull)
 {
 	ExprState  *clause = linitial(notclause->args);
 	Datum		expr_value;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
-	expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
+	expr_value = ExecEvalExpr(clause, econtext, isNull);
 
 	/*
 	 * if the expression evaluates to null, then we just cascade the null back
@@ -2779,15 +2178,12 @@ ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
  */
 static Datum
 ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
-		   bool *isNull, ExprDoneCond *isDone)
+		   bool *isNull)
 {
 	List	   *clauses = orExpr->args;
 	ListCell   *clause;
 	bool		AnyNull;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	AnyNull = false;
 
 	/*
@@ -2808,7 +2204,7 @@ ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
 		ExprState  *clausestate = (ExprState *) lfirst(clause);
 		Datum		clause_value;
 
-		clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
+		clause_value = ExecEvalExpr(clausestate, econtext, isNull);
 
 		/*
 		 * if we have a non-null true result, then return it.
@@ -2830,15 +2226,12 @@ ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
  */
 static Datum
 ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone)
+			bool *isNull)
 {
 	List	   *clauses = andExpr->args;
 	ListCell   *clause;
 	bool		AnyNull;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	AnyNull = false;
 
 	/*
@@ -2855,7 +2248,7 @@ ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
 		ExprState  *clausestate = (ExprState *) lfirst(clause);
 		Datum		clause_value;
 
-		clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
+		clause_value = ExecEvalExpr(clausestate, econtext, isNull);
 
 		/*
 		 * if we have a non-null false result, then return it.
@@ -2881,7 +2274,7 @@ ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
 static Datum
 ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
 					   ExprContext *econtext,
-					   bool *isNull, ExprDoneCond *isDone)
+					   bool *isNull)
 {
 	ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) cstate->xprstate.expr;
 	HeapTuple	result;
@@ -2889,7 +2282,7 @@ ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
 	HeapTupleHeader tuple;
 	HeapTupleData tmptup;
 
-	tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
+	tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull);
 
 	/* this test covers the isDone exception too: */
 	if (*isNull)
@@ -2965,16 +2358,13 @@ ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
  */
 static Datum
 ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
-			 bool *isNull, ExprDoneCond *isDone)
+			 bool *isNull)
 {
 	List	   *clauses = caseExpr->args;
 	ListCell   *clause;
 	Datum		save_datum;
 	bool		save_isNull;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/*
 	 * If there's a test expression, we have to evaluate it and save the value
 	 * where the CaseTestExpr placeholders can find it. We must save and
@@ -2988,8 +2378,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
 	{
 		econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg,
 												 econtext,
-												 &econtext->caseValue_isNull,
-												 NULL);
+												 &econtext->caseValue_isNull);
 	}
 
 	/*
@@ -3004,8 +2393,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
 
 		clause_value = ExecEvalExpr(wclause->expr,
 									econtext,
-									isNull,
-									NULL);
+									isNull);
 
 		/*
 		 * if we have a true test, then we return the result, since the case
@@ -3018,8 +2406,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
 			econtext->caseValue_isNull = save_isNull;
 			return ExecEvalExpr(wclause->result,
 								econtext,
-								isNull,
-								isDone);
+								isNull);
 		}
 	}
 
@@ -3030,8 +2417,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
 	{
 		return ExecEvalExpr(caseExpr->defresult,
 							econtext,
-							isNull,
-							isDone);
+							isNull);
 	}
 
 	*isNull = true;
@@ -3046,10 +2432,8 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
 static Datum
 ExecEvalCaseTestExpr(ExprState *exprstate,
 					 ExprContext *econtext,
-					 bool *isNull, ExprDoneCond *isDone)
+					 bool *isNull)
 {
-	if (isDone)
-		*isDone = ExprSingleResult;
 	*isNull = econtext->caseValue_isNull;
 	return econtext->caseValue_datum;
 }
@@ -3066,17 +2450,13 @@ ExecEvalCaseTestExpr(ExprState *exprstate,
 static Datum
 ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
 						 ExprContext *econtext,
-						 bool *isNull,
-						 ExprDoneCond *isDone)
+						 bool *isNull)
 {
 	int			result = 0;
 	int			attnum = 0;
 	Bitmapset  *grouped_cols = gstate->aggstate->grouped_cols;
 	ListCell   *lc;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	*isNull = false;
 
 	foreach(lc, (gstate->clauses))
@@ -3098,7 +2478,7 @@ ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
  */
 static Datum
 ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
-			  bool *isNull, ExprDoneCond *isDone)
+			  bool *isNull)
 {
 	ArrayExpr  *arrayExpr = (ArrayExpr *) astate->xprstate.expr;
 	ArrayType  *result;
@@ -3110,8 +2490,6 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 
 	/* Set default values for result flags: non-null, not a set result */
 	*isNull = false;
-	if (isDone)
-		*isDone = ExprSingleResult;
 
 	if (!arrayExpr->multidims)
 	{
@@ -3136,7 +2514,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 		{
 			ExprState  *e = (ExprState *) lfirst(element);
 
-			dvalues[i] = ExecEvalExpr(e, econtext, &dnulls[i], NULL);
+			dvalues[i] = ExecEvalExpr(e, econtext, &dnulls[i]);
 			i++;
 		}
 
@@ -3186,7 +2564,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 			ArrayType  *array;
 			int			this_ndims;
 
-			arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);
+			arraydatum = ExecEvalExpr(e, econtext, &eisnull);
 			/* temporarily ignore null subarrays */
 			if (eisnull)
 			{
@@ -3325,7 +2703,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 static Datum
 ExecEvalRow(RowExprState *rstate,
 			ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone)
+			bool *isNull)
 {
 	HeapTuple	tuple;
 	Datum	   *values;
@@ -3336,8 +2714,6 @@ ExecEvalRow(RowExprState *rstate,
 
 	/* Set default values for result flags: non-null, not a set result */
 	*isNull = false;
-	if (isDone)
-		*isDone = ExprSingleResult;
 
 	/* Allocate workspace */
 	natts = rstate->tupdesc->natts;
@@ -3353,7 +2729,7 @@ ExecEvalRow(RowExprState *rstate,
 	{
 		ExprState  *e = (ExprState *) lfirst(arg);
 
-		values[i] = ExecEvalExpr(e, econtext, &isnull[i], NULL);
+		values[i] = ExecEvalExpr(e, econtext, &isnull[i]);
 		i++;
 	}
 
@@ -3372,7 +2748,7 @@ ExecEvalRow(RowExprState *rstate,
 static Datum
 ExecEvalRowCompare(RowCompareExprState *rstate,
 				   ExprContext *econtext,
-				   bool *isNull, ExprDoneCond *isDone)
+				   bool *isNull)
 {
 	bool		result;
 	RowCompareType rctype = ((RowCompareExpr *) rstate->xprstate.expr)->rctype;
@@ -3381,8 +2757,6 @@ ExecEvalRowCompare(RowCompareExprState *rstate,
 	ListCell   *r;
 	int			i;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
 	*isNull = true;				/* until we get a result */
 
 	i = 0;
@@ -3396,9 +2770,9 @@ ExecEvalRowCompare(RowCompareExprState *rstate,
 								 rstate->collations[i],
 								 NULL, NULL);
 		locfcinfo.arg[0] = ExecEvalExpr(le, econtext,
-										&locfcinfo.argnull[0], NULL);
+										&locfcinfo.argnull[0]);
 		locfcinfo.arg[1] = ExecEvalExpr(re, econtext,
-										&locfcinfo.argnull[1], NULL);
+										&locfcinfo.argnull[1]);
 		if (rstate->funcs[i].fn_strict &&
 			(locfcinfo.argnull[0] || locfcinfo.argnull[1]))
 			return (Datum) 0;	/* force NULL result */
@@ -3442,20 +2816,17 @@ ExecEvalRowCompare(RowCompareExprState *rstate,
  */
 static Datum
 ExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,
-				 bool *isNull, ExprDoneCond *isDone)
+				 bool *isNull)
 {
 	ListCell   *arg;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/* Simply loop through until something NOT NULL is found */
 	foreach(arg, coalesceExpr->args)
 	{
 		ExprState  *e = (ExprState *) lfirst(arg);
 		Datum		value;
 
-		value = ExecEvalExpr(e, econtext, isNull, NULL);
+		value = ExecEvalExpr(e, econtext, isNull);
 		if (!*isNull)
 			return value;
 	}
@@ -3471,7 +2842,7 @@ ExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,
  */
 static Datum
 ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
-			   bool *isNull, ExprDoneCond *isDone)
+			   bool *isNull)
 {
 	Datum		result = (Datum) 0;
 	MinMaxExpr *minmax = (MinMaxExpr *) minmaxExpr->xprstate.expr;
@@ -3480,8 +2851,6 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
 	FunctionCallInfoData locfcinfo;
 	ListCell   *arg;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
 	*isNull = true;				/* until we get a result */
 
 	InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2,
@@ -3496,7 +2865,7 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
 		bool		valueIsNull;
 		int32		cmpresult;
 
-		value = ExecEvalExpr(e, econtext, &valueIsNull, NULL);
+		value = ExecEvalExpr(e, econtext, &valueIsNull);
 		if (valueIsNull)
 			continue;			/* ignore NULL inputs */
 
@@ -3531,7 +2900,7 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
  */
 static Datum
 ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
-			bool *isNull, ExprDoneCond *isDone)
+			bool *isNull)
 {
 	XmlExpr    *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
 	Datum		value;
@@ -3539,8 +2908,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 	ListCell   *arg;
 	ListCell   *narg;
 
-	if (isDone)
-		*isDone = ExprSingleResult;
 	*isNull = true;				/* until we get a result */
 
 	switch (xexpr->op)
@@ -3553,7 +2920,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 				{
 					ExprState  *e = (ExprState *) lfirst(arg);
 
-					value = ExecEvalExpr(e, econtext, &isnull, NULL);
+					value = ExecEvalExpr(e, econtext, &isnull);
 					if (!isnull)
 						values = lappend(values, DatumGetPointer(value));
 				}
@@ -3578,7 +2945,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 					ExprState  *e = (ExprState *) lfirst(arg);
 					char	   *argname = strVal(lfirst(narg));
 
-					value = ExecEvalExpr(e, econtext, &isnull, NULL);
+					value = ExecEvalExpr(e, econtext, &isnull);
 					if (!isnull)
 					{
 						appendStringInfo(&buf, "<%s>%s</%s>",
@@ -3621,13 +2988,13 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 				Assert(list_length(xmlExpr->args) == 2);
 
 				e = (ExprState *) linitial(xmlExpr->args);
-				value = ExecEvalExpr(e, econtext, &isnull, NULL);
+				value = ExecEvalExpr(e, econtext, &isnull);
 				if (isnull)
 					return (Datum) 0;
 				data = DatumGetTextP(value);
 
 				e = (ExprState *) lsecond(xmlExpr->args);
-				value = ExecEvalExpr(e, econtext, &isnull, NULL);
+				value = ExecEvalExpr(e, econtext, &isnull);
 				if (isnull)		/* probably can't happen */
 					return (Datum) 0;
 				preserve_whitespace = DatumGetBool(value);
@@ -3651,7 +3018,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 				if (xmlExpr->args)
 				{
 					e = (ExprState *) linitial(xmlExpr->args);
-					value = ExecEvalExpr(e, econtext, &isnull, NULL);
+					value = ExecEvalExpr(e, econtext, &isnull);
 					if (isnull)
 						arg = NULL;
 					else
@@ -3678,20 +3045,20 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 				Assert(list_length(xmlExpr->args) == 3);
 
 				e = (ExprState *) linitial(xmlExpr->args);
-				value = ExecEvalExpr(e, econtext, &isnull, NULL);
+				value = ExecEvalExpr(e, econtext, &isnull);
 				if (isnull)
 					return (Datum) 0;
 				data = DatumGetXmlP(value);
 
 				e = (ExprState *) lsecond(xmlExpr->args);
-				value = ExecEvalExpr(e, econtext, &isnull, NULL);
+				value = ExecEvalExpr(e, econtext, &isnull);
 				if (isnull)
 					version = NULL;
 				else
 					version = DatumGetTextP(value);
 
 				e = (ExprState *) lthird(xmlExpr->args);
-				value = ExecEvalExpr(e, econtext, &isnull, NULL);
+				value = ExecEvalExpr(e, econtext, &isnull);
 				standalone = DatumGetInt32(value);
 
 				*isNull = false;
@@ -3710,7 +3077,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 				Assert(list_length(xmlExpr->args) == 1);
 
 				e = (ExprState *) linitial(xmlExpr->args);
-				value = ExecEvalExpr(e, econtext, &isnull, NULL);
+				value = ExecEvalExpr(e, econtext, &isnull);
 				if (isnull)
 					return (Datum) 0;
 
@@ -3728,7 +3095,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 				Assert(list_length(xmlExpr->args) == 1);
 
 				e = (ExprState *) linitial(xmlExpr->args);
-				value = ExecEvalExpr(e, econtext, &isnull, NULL);
+				value = ExecEvalExpr(e, econtext, &isnull);
 				if (isnull)
 					return (Datum) 0;
 				else
@@ -3755,14 +3122,10 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
 static Datum
 ExecEvalNullIf(FuncExprState *nullIfExpr,
 			   ExprContext *econtext,
-			   bool *isNull, ExprDoneCond *isDone)
+			   bool *isNull)
 {
 	Datum		result;
 	FunctionCallInfo fcinfo;
-	ExprDoneCond argDone;
-
-	if (isDone)
-		*isDone = ExprSingleResult;
 
 	/*
 	 * Initialize function cache if first time through
@@ -3772,7 +3135,7 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
 		NullIfExpr *op = (NullIfExpr *) nullIfExpr->xprstate.expr;
 
 		init_fcache(op->opfuncid, op->inputcollid, nullIfExpr,
-					econtext->ecxt_per_query_memory, true);
+					econtext->ecxt_per_query_memory);
 		Assert(!nullIfExpr->func.fn_retset);
 	}
 
@@ -3780,11 +3143,7 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
 	 * Evaluate arguments
 	 */
 	fcinfo = &nullIfExpr->fcinfo_data;
-	argDone = ExecEvalFuncArgs(fcinfo, nullIfExpr->args, econtext);
-	if (argDone != ExprSingleResult)
-		ereport(ERROR,
-				(errcode(ERRCODE_DATATYPE_MISMATCH),
-				 errmsg("NULLIF does not support set arguments")));
+	ExecEvalFuncArgs(fcinfo, nullIfExpr->args, econtext);
 	Assert(fcinfo->nargs == 2);
 
 	/* if either argument is NULL they can't be equal */
@@ -3814,16 +3173,12 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
 static Datum
 ExecEvalNullTest(NullTestState *nstate,
 				 ExprContext *econtext,
-				 bool *isNull,
-				 ExprDoneCond *isDone)
+				 bool *isNull)
 {
 	NullTest   *ntest = (NullTest *) nstate->xprstate.expr;
 	Datum		result;
 
-	result = ExecEvalExpr(nstate->arg, econtext, isNull, isDone);
-
-	if (isDone && *isDone == ExprEndResult)
-		return result;			/* nothing to check */
+	result = ExecEvalExpr(nstate->arg, econtext, isNull);
 
 	if (ntest->argisrow && !(*isNull))
 	{
@@ -3923,16 +3278,12 @@ ExecEvalNullTest(NullTestState *nstate,
 static Datum
 ExecEvalBooleanTest(GenericExprState *bstate,
 					ExprContext *econtext,
-					bool *isNull,
-					ExprDoneCond *isDone)
+					bool *isNull)
 {
 	BooleanTest *btest = (BooleanTest *) bstate->xprstate.expr;
 	Datum		result;
 
-	result = ExecEvalExpr(bstate->arg, econtext, isNull, isDone);
-
-	if (isDone && *isDone == ExprEndResult)
-		return result;			/* nothing to check */
+	result = ExecEvalExpr(bstate->arg, econtext, isNull);
 
 	switch (btest->booltesttype)
 	{
@@ -4008,16 +3359,13 @@ ExecEvalBooleanTest(GenericExprState *bstate,
  */
 static Datum
 ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
-					   bool *isNull, ExprDoneCond *isDone)
+					   bool *isNull)
 {
 	CoerceToDomain *ctest = (CoerceToDomain *) cstate->xprstate.expr;
 	Datum		result;
 	ListCell   *l;
 
-	result = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
-
-	if (isDone && *isDone == ExprEndResult)
-		return result;			/* nothing to check */
+	result = ExecEvalExpr(cstate->arg, econtext, isNull);
 
 	/* Make sure we have up-to-date constraints */
 	UpdateDomainConstraintRef(cstate->constraint_ref);
@@ -4055,8 +3403,8 @@ ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
 					econtext->domainValue_datum = result;
 					econtext->domainValue_isNull = *isNull;
 
-					conResult = ExecEvalExpr(con->check_expr,
-											 econtext, &conIsNull, NULL);
+					conResult = ExecEvalExpr(con->check_expr, econtext,
+											 &conIsNull);
 
 					if (!conIsNull &&
 						!DatumGetBool(conResult))
@@ -4091,10 +3439,8 @@ ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
 static Datum
 ExecEvalCoerceToDomainValue(ExprState *exprstate,
 							ExprContext *econtext,
-							bool *isNull, ExprDoneCond *isDone)
+							bool *isNull)
 {
-	if (isDone)
-		*isDone = ExprSingleResult;
 	*isNull = econtext->domainValue_isNull;
 	return econtext->domainValue_datum;
 }
@@ -4108,8 +3454,7 @@ ExecEvalCoerceToDomainValue(ExprState *exprstate,
 static Datum
 ExecEvalFieldSelect(FieldSelectState *fstate,
 					ExprContext *econtext,
-					bool *isNull,
-					ExprDoneCond *isDone)
+					bool *isNull)
 {
 	FieldSelect *fselect = (FieldSelect *) fstate->xprstate.expr;
 	AttrNumber	fieldnum = fselect->fieldnum;
@@ -4122,7 +3467,7 @@ ExecEvalFieldSelect(FieldSelectState *fstate,
 	Form_pg_attribute attr;
 	HeapTupleData tmptup;
 
-	tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);
+	tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull);
 
 	/* this test covers the isDone exception too: */
 	if (*isNull)
@@ -4187,8 +3532,7 @@ ExecEvalFieldSelect(FieldSelectState *fstate,
 static Datum
 ExecEvalFieldStore(FieldStoreState *fstate,
 				   ExprContext *econtext,
-				   bool *isNull,
-				   ExprDoneCond *isDone)
+				   bool *isNull)
 {
 	FieldStore *fstore = (FieldStore *) fstate->xprstate.expr;
 	HeapTuple	tuple;
@@ -4201,10 +3545,7 @@ ExecEvalFieldStore(FieldStoreState *fstate,
 	ListCell   *l1,
 			   *l2;
 
-	tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);
-
-	if (isDone && *isDone == ExprEndResult)
-		return tupDatum;
+	tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull);
 
 	/* Lookup tupdesc if first time through or after rescan */
 	tupDesc = get_cached_rowtype(fstore->resulttype, -1,
@@ -4264,8 +3605,7 @@ ExecEvalFieldStore(FieldStoreState *fstate,
 
 		values[fieldnum - 1] = ExecEvalExpr(newval,
 											econtext,
-											&isnull[fieldnum - 1],
-											NULL);
+											&isnull[fieldnum - 1]);
 	}
 
 	econtext->caseValue_datum = save_datum;
@@ -4288,9 +3628,9 @@ ExecEvalFieldStore(FieldStoreState *fstate,
 static Datum
 ExecEvalRelabelType(GenericExprState *exprstate,
 					ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone)
+					bool *isNull)
 {
-	return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
+	return ExecEvalExpr(exprstate->arg, econtext, isNull);
 }
 
 /* ----------------------------------------------------------------
@@ -4302,16 +3642,13 @@ ExecEvalRelabelType(GenericExprState *exprstate,
 static Datum
 ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
 					ExprContext *econtext,
-					bool *isNull, ExprDoneCond *isDone)
+					bool *isNull)
 {
 	Datum		result;
 	Datum		inputval;
 	char	   *string;
 
-	inputval = ExecEvalExpr(iostate->arg, econtext, isNull, isDone);
-
-	if (isDone && *isDone == ExprEndResult)
-		return inputval;		/* nothing to do */
+	inputval = ExecEvalExpr(iostate->arg, econtext, isNull);
 
 	if (*isNull)
 		string = NULL;			/* output functions are not called on nulls */
@@ -4336,16 +3673,14 @@ ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
 static Datum
 ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
 						ExprContext *econtext,
-						bool *isNull, ExprDoneCond *isDone)
+						bool *isNull)
 {
 	ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) astate->xprstate.expr;
 	Datum		result;
 	FunctionCallInfoData locfcinfo;
 
-	result = ExecEvalExpr(astate->arg, econtext, isNull, isDone);
+	result = ExecEvalExpr(astate->arg, econtext, isNull);
 
-	if (isDone && *isDone == ExprEndResult)
-		return result;			/* nothing to do */
 	if (*isNull)
 		return result;			/* nothing to do */
 
@@ -4413,7 +3748,7 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
  */
 static Datum
 ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
-					  bool *isNull, ExprDoneCond *isDone)
+					  bool *isNull)
 {
 	ereport(ERROR,
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -4430,14 +3765,13 @@ ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
 Datum
 ExecEvalExprSwitchContext(ExprState *expression,
 						  ExprContext *econtext,
-						  bool *isNull,
-						  ExprDoneCond *isDone)
+						  bool *isNull)
 {
 	Datum		retDatum;
 	MemoryContext oldContext;
 
 	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
-	retDatum = ExecEvalExpr(expression, econtext, isNull, isDone);
+	retDatum = ExecEvalExpr(expression, econtext, isNull);
 	MemoryContextSwitchTo(oldContext);
 	return retDatum;
 }
@@ -5293,7 +4627,7 @@ ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
 		Datum		expr_value;
 		bool		isNull;
 
-		expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
+		expr_value = ExecEvalExpr(clause, econtext, &isNull);
 
 		if (isNull)
 		{
@@ -5351,17 +4685,9 @@ ExecCleanTargetListLength(List *targetlist)
 /*
  * ExecTargetList
  *		Evaluates a targetlist with respect to the given
- *		expression context.  Returns TRUE if we were able to create
- *		a result, FALSE if we have exhausted a set-valued expression.
+ *		expression context.
  *
  * Results are stored into the passed values and isnull arrays.
- * The caller must provide an itemIsDone array that persists across calls.
- *
- * As with ExecEvalExpr, the caller should pass isDone = NULL if not
- * prepared to deal with sets of result tuples.  Otherwise, a return
- * of *isDone = ExprMultipleResult signifies a set element, and a return
- * of *isDone = ExprEndResult signifies end of the set of tuple.
- * We assume that *isDone has been initialized to ExprSingleResult by caller.
  *
  * Since fields of the result tuple might be multiply referenced in higher
  * plan nodes, we have to force any read/write expanded values to read-only
@@ -5370,19 +4696,16 @@ ExecCleanTargetListLength(List *targetlist)
  * actually-multiply-referenced Vars and insert an expression node that
  * would do that only where really required.
  */
-static bool
+static void
 ExecTargetList(List *targetlist,
 			   TupleDesc tupdesc,
 			   ExprContext *econtext,
 			   Datum *values,
-			   bool *isnull,
-			   ExprDoneCond *itemIsDone,
-			   ExprDoneCond *isDone)
+			   bool *isnull)
 {
 	Form_pg_attribute *att = tupdesc->attrs;
 	MemoryContext oldContext;
 	ListCell   *tl;
-	bool		haveDoneSets;
 
 	/*
 	 * Run in short-lived per-tuple context while computing expressions.
@@ -5392,8 +4715,6 @@ ExecTargetList(List *targetlist,
 	/*
 	 * evaluate all the expressions in the target list
 	 */
-	haveDoneSets = false;		/* any exhausted set exprs in tlist? */
-
 	foreach(tl, targetlist)
 	{
 		GenericExprState *gstate = (GenericExprState *) lfirst(tl);
@@ -5402,117 +4723,15 @@ ExecTargetList(List *targetlist,
 
 		values[resind] = ExecEvalExpr(gstate->arg,
 									  econtext,
-									  &isnull[resind],
-									  &itemIsDone[resind]);
+									  &isnull[resind]);
 
 		values[resind] = MakeExpandedObjectReadOnly(values[resind],
 													isnull[resind],
 													att[resind]->attlen);
-
-		if (itemIsDone[resind] != ExprSingleResult)
-		{
-			/* We have a set-valued expression in the tlist */
-			if (isDone == NULL)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("set-valued function called in context that cannot accept a set")));
-			if (itemIsDone[resind] == ExprMultipleResult)
-			{
-				/* we have undone sets in the tlist, set flag */
-				*isDone = ExprMultipleResult;
-			}
-			else
-			{
-				/* we have done sets in the tlist, set flag for that */
-				haveDoneSets = true;
-			}
-		}
-	}
-
-	if (haveDoneSets)
-	{
-		/*
-		 * note: can't get here unless we verified isDone != NULL
-		 */
-		if (*isDone == ExprSingleResult)
-		{
-			/*
-			 * all sets are done, so report that tlist expansion is complete.
-			 */
-			*isDone = ExprEndResult;
-			MemoryContextSwitchTo(oldContext);
-			return false;
-		}
-		else
-		{
-			/*
-			 * We have some done and some undone sets.  Restart the done ones
-			 * so that we can deliver a tuple (if possible).
-			 */
-			foreach(tl, targetlist)
-			{
-				GenericExprState *gstate = (GenericExprState *) lfirst(tl);
-				TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
-				AttrNumber	resind = tle->resno - 1;
-
-				if (itemIsDone[resind] == ExprEndResult)
-				{
-					values[resind] = ExecEvalExpr(gstate->arg,
-												  econtext,
-												  &isnull[resind],
-												  &itemIsDone[resind]);
-
-					values[resind] = MakeExpandedObjectReadOnly(values[resind],
-															  isnull[resind],
-														att[resind]->attlen);
-
-					if (itemIsDone[resind] == ExprEndResult)
-					{
-						/*
-						 * Oh dear, this item is returning an empty set. Guess
-						 * we can't make a tuple after all.
-						 */
-						*isDone = ExprEndResult;
-						break;
-					}
-				}
-			}
-
-			/*
-			 * If we cannot make a tuple because some sets are empty, we still
-			 * have to cycle the nonempty sets to completion, else resources
-			 * will not be released from subplans etc.
-			 *
-			 * XXX is that still necessary?
-			 */
-			if (*isDone == ExprEndResult)
-			{
-				foreach(tl, targetlist)
-				{
-					GenericExprState *gstate = (GenericExprState *) lfirst(tl);
-					TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
-					AttrNumber	resind = tle->resno - 1;
-
-					while (itemIsDone[resind] == ExprMultipleResult)
-					{
-						values[resind] = ExecEvalExpr(gstate->arg,
-													  econtext,
-													  &isnull[resind],
-													  &itemIsDone[resind]);
-						/* no need for MakeExpandedObjectReadOnly */
-					}
-				}
-
-				MemoryContextSwitchTo(oldContext);
-				return false;
-			}
-		}
 	}
 
 	/* Report success */
 	MemoryContextSwitchTo(oldContext);
-
-	return true;
 }
 
 /*
@@ -5529,7 +4748,7 @@ ExecTargetList(List *targetlist,
  *		result slot.
  */
 TupleTableSlot *
-ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
+ExecProject(ProjectionInfo *projInfo)
 {
 	TupleTableSlot *slot;
 	ExprContext *econtext;
@@ -5546,10 +4765,6 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
 	slot = projInfo->pi_slot;
 	econtext = projInfo->pi_exprContext;
 
-	/* Assume single result row until proven otherwise */
-	if (isDone)
-		*isDone = ExprSingleResult;
-
 	/*
 	 * Clear any former contents of the result slot.  This makes it safe for
 	 * us to use the slot's Datum/isnull arrays as workspace. (Also, we can
@@ -5617,21 +4832,15 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
 	}
 
 	/*
-	 * If there are any generic expressions, evaluate them.  It's possible
-	 * that there are set-returning functions in such expressions; if so and
-	 * we have reached the end of the set, we return the result slot, which we
-	 * already marked empty.
+	 * If there are any generic expressions, evaluate them.
 	 */
 	if (projInfo->pi_targetlist)
 	{
-		if (!ExecTargetList(projInfo->pi_targetlist,
-							slot->tts_tupleDescriptor,
-							econtext,
-							slot->tts_values,
-							slot->tts_isnull,
-							projInfo->pi_itemIsDone,
-							isDone))
-			return slot;		/* no more result rows, return empty slot */
+		ExecTargetList(projInfo->pi_targetlist,
+					   slot->tts_tupleDescriptor,
+					   econtext,
+					   slot->tts_values,
+					   slot->tts_isnull);
 	}
 
 	/*
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index fb0013d..eb224b4 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -125,8 +125,6 @@ ExecScan(ScanState *node,
 	ExprContext *econtext;
 	List	   *qual;
 	ProjectionInfo *projInfo;
-	ExprDoneCond isDone;
-	TupleTableSlot *resultSlot;
 
 	/*
 	 * Fetch data from node
@@ -146,21 +144,6 @@ ExecScan(ScanState *node,
 	}
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous scan
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->ps.ps_TupFromTlist)
-	{
-		Assert(projInfo);		/* can't get here if not projecting */
-		resultSlot = ExecProject(projInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return resultSlot;
-		/* Done with that source tuple... */
-		node->ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * Reset per-tuple memory context to free any expression evaluation
 	 * storage allocated in the previous tuple cycle.  Note this can't happen
 	 * until we're done projecting out tuples from a scan tuple.
@@ -214,15 +197,9 @@ ExecScan(ScanState *node,
 			{
 				/*
 				 * Form a projection tuple, store it in the result tuple slot
-				 * and return it --- unless we find we can project no tuples
-				 * from this scan tuple, in which case continue scan.
+				 * and return it.
 				 */
-				resultSlot = ExecProject(projInfo, &isDone);
-				if (isDone != ExprEndResult)
-				{
-					node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
-					return resultSlot;
-				}
+				return ExecProject(projInfo);
 			}
 			else
 			{
@@ -352,9 +329,6 @@ ExecScanReScan(ScanState *node)
 {
 	EState	   *estate = node->ps.state;
 
-	/* Stop projecting any tuples from SRFs in the targetlist */
-	node->ps.ps_TupFromTlist = false;
-
 	/* Rescan EvalPlanQual tuple if we're inside an EvalPlanQual recheck */
 	if (estate->es_epqScanDone != NULL)
 	{
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index e937cf8..ded073a 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -592,12 +592,6 @@ ExecBuildProjectionInfo(List *targetList,
 	projInfo->pi_numSimpleVars = numSimpleVars;
 	projInfo->pi_directMap = directMap;
 
-	if (exprlist == NIL)
-		projInfo->pi_itemIsDone = NULL; /* not needed */
-	else
-		projInfo->pi_itemIsDone = (ExprDoneCond *)
-			palloc(len * sizeof(ExprDoneCond));
-
 	return projInfo;
 }
 
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 1ec2515..046e1b2 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -859,13 +859,13 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
 			bool		isnull;
 
 			res = ExecEvalExprSwitchContext(filter, aggstate->tmpcontext,
-											&isnull, NULL);
+											&isnull);
 			if (isnull || !DatumGetBool(res))
 				continue;
 		}
 
 		/* Evaluate the current input expressions for this aggregate */
-		slot = ExecProject(pertrans->evalproj, NULL);
+		slot = ExecProject(pertrans->evalproj);
 
 		if (pertrans->numSortCols > 0)
 		{
@@ -951,7 +951,7 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
 		FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
 
 		/* Evaluate the current input expressions for this aggregate */
-		slot = ExecProject(pertrans->evalproj, NULL);
+		slot = ExecProject(pertrans->evalproj);
 		Assert(slot->tts_nvalid >= 1);
 
 		/*
@@ -1325,8 +1325,7 @@ finalize_aggregate(AggState *aggstate,
 
 		fcinfo.arg[i] = ExecEvalExpr(expr,
 									 aggstate->ss.ps.ps_ExprContext,
-									 &fcinfo.argnull[i],
-									 NULL);
+									 &fcinfo.argnull[i]);
 		anynull |= fcinfo.argnull[i];
 		i++;
 	}
@@ -1579,20 +1578,10 @@ project_aggregates(AggState *aggstate)
 	if (ExecQual(aggstate->ss.ps.qual, econtext, false))
 	{
 		/*
-		 * Form and return or store a projection tuple using the aggregate
-		 * results and the representative input tuple.
+		 * Form and return projection tuple using the aggregate results and
+		 * the representative input tuple.
 		 */
-		ExprDoneCond isDone;
-		TupleTableSlot *result;
-
-		result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
-
-		if (isDone != ExprEndResult)
-		{
-			aggstate->ss.ps.ps_TupFromTlist =
-				(isDone == ExprMultipleResult);
-			return result;
-		}
+		return ExecProject(aggstate->ss.ps.ps_ProjInfo);
 	}
 	else
 		InstrCountFiltered1(aggstate, 1);
@@ -1803,22 +1792,6 @@ ExecAgg(AggState *node)
 	TupleTableSlot *result;
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous agg
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->ss.ps.ps_TupFromTlist)
-	{
-		ExprDoneCond isDone;
-
-		result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return result;
-		/* Done with that source tuple... */
-		node->ss.ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * (We must do the ps_TupFromTlist check first, because in some cases
 	 * agg_done gets set before we emit the final aggregate tuple, and we have
 	 * to finish running SRFs for it.)
@@ -2443,8 +2416,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	ExecAssignResultTypeFromTL(&aggstate->ss.ps);
 	ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
 
-	aggstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * get the count of aggregates in targetlist and quals
 	 */
@@ -3411,8 +3382,6 @@ ExecReScanAgg(AggState *node)
 
 	node->agg_done = false;
 
-	node->ss.ps.ps_TupFromTlist = false;
-
 	if (aggnode->aggstrategy == AGG_HASHED)
 	{
 		/*
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 449aacb..16381f6 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -575,8 +575,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &scanstate->ss.ps);
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * initialize child expressions
 	 */
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index 3c2f684..1acb166 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -265,8 +265,6 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
 	ExecAssignResultTypeFromTL(&scanstate->ss.ps);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	return scanstate;
 }
 
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index 322abca..b465252 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -48,8 +48,6 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
 	/* create expression context for node */
 	ExecAssignExprContext(estate, &css->ss.ps);
 
-	css->ss.ps.ps_TupFromTlist = false;
-
 	/* initialize child expressions */
 	css->ss.ps.targetlist = (List *)
 		ExecInitExpr((Expr *) cscan->scan.plan.targetlist,
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index d886aaf..3762843 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -152,8 +152,6 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &scanstate->ss.ps);
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * initialize child expressions
 	 */
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index a03f6e7..7d0fe14 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -331,8 +331,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &scanstate->ss.ps);
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * tuple table initialization
 	 */
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 438d1b2..51754c8 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -99,8 +99,6 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
 	outerNode = outerPlan(node);
 	outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags);
 
-	gatherstate->ps.ps_TupFromTlist = false;
-
 	/*
 	 * Initialize result tuple type and projection info.
 	 */
@@ -131,8 +129,6 @@ ExecGather(GatherState *node)
 	TupleTableSlot *fslot = node->funnel_slot;
 	int			i;
 	TupleTableSlot *slot;
-	TupleTableSlot *resultSlot;
-	ExprDoneCond isDone;
 	ExprContext *econtext;
 
 	/*
@@ -198,20 +194,6 @@ ExecGather(GatherState *node)
 	}
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous scan
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->ps.ps_TupFromTlist)
-	{
-		resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return resultSlot;
-		/* Done with that source tuple... */
-		node->ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * Reset per-tuple memory context to free any expression evaluation
 	 * storage allocated in the previous tuple cycle.  Note we can't do this
 	 * until we're done projecting.  This will also clear any previous tuple
@@ -239,13 +221,8 @@ ExecGather(GatherState *node)
 		 * back around for another tuple
 		 */
 		econtext->ecxt_outertuple = slot;
-		resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
 
-		if (isDone != ExprEndResult)
-		{
-			node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
-			return resultSlot;
-		}
+		return ExecProject(node->ps.ps_ProjInfo);
 	}
 
 	return slot;
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index dcf5175..2f55c70 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -50,23 +50,6 @@ ExecGroup(GroupState *node)
 	grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous group
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->ss.ps.ps_TupFromTlist)
-	{
-		TupleTableSlot *result;
-		ExprDoneCond isDone;
-
-		result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return result;
-		/* Done with that source tuple... */
-		node->ss.ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * The ScanTupleSlot holds the (copied) first tuple of each group.
 	 */
 	firsttupleslot = node->ss.ss_ScanTupleSlot;
@@ -107,16 +90,7 @@ ExecGroup(GroupState *node)
 			/*
 			 * Form and return a projection tuple using the first input tuple.
 			 */
-			TupleTableSlot *result;
-			ExprDoneCond isDone;
-
-			result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
-
-			if (isDone != ExprEndResult)
-			{
-				node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
-				return result;
-			}
+			return ExecProject(node->ss.ps.ps_ProjInfo);
 		}
 		else
 			InstrCountFiltered1(node, 1);
@@ -170,16 +144,7 @@ ExecGroup(GroupState *node)
 			/*
 			 * Form and return a projection tuple using the first input tuple.
 			 */
-			TupleTableSlot *result;
-			ExprDoneCond isDone;
-
-			result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
-
-			if (isDone != ExprEndResult)
-			{
-				node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
-				return result;
-			}
+			return ExecProject(node->ss.ps.ps_ProjInfo);
 		}
 		else
 			InstrCountFiltered1(node, 1);
@@ -246,8 +211,6 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
 	ExecAssignResultTypeFromTL(&grpstate->ss.ps);
 	ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
 
-	grpstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * Precompute fmgr lookup data for inner loop
 	 */
@@ -283,7 +246,6 @@ ExecReScanGroup(GroupState *node)
 	PlanState  *outerPlan = outerPlanState(node);
 
 	node->grp_done = FALSE;
-	node->ss.ps.ps_TupFromTlist = false;
 	/* must clear first tuple */
 	ExecClearTuple(node->ss.ss_ScanTupleSlot);
 
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 9ed09a7..e008a51 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -963,7 +963,7 @@ ExecHashGetHashValue(HashJoinTable hashtable,
 		/*
 		 * Get the join attribute value of the tuple
 		 */
-		keyval = ExecEvalExpr(keyexpr, econtext, &isNull, NULL);
+		keyval = ExecEvalExpr(keyexpr, econtext, &isNull);
 
 		/*
 		 * If the attribute is NULL, and the join operator is strict, then
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 369e666..45c7be2 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -66,7 +66,6 @@ ExecHashJoin(HashJoinState *node)
 	List	   *joinqual;
 	List	   *otherqual;
 	ExprContext *econtext;
-	ExprDoneCond isDone;
 	HashJoinTable hashtable;
 	TupleTableSlot *outerTupleSlot;
 	uint32		hashvalue;
@@ -83,22 +82,6 @@ ExecHashJoin(HashJoinState *node)
 	econtext = node->js.ps.ps_ExprContext;
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous join
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->js.ps.ps_TupFromTlist)
-	{
-		TupleTableSlot *result;
-
-		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return result;
-		/* Done with that source tuple... */
-		node->js.ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * Reset per-tuple memory context to free any expression evaluation
 	 * storage allocated in the previous tuple cycle.  Note this can't happen
 	 * until we're done projecting out tuples from a join tuple.
@@ -315,16 +298,7 @@ ExecHashJoin(HashJoinState *node)
 					if (otherqual == NIL ||
 						ExecQual(otherqual, econtext, false))
 					{
-						TupleTableSlot *result;
-
-						result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
-						if (isDone != ExprEndResult)
-						{
-							node->js.ps.ps_TupFromTlist =
-								(isDone == ExprMultipleResult);
-							return result;
-						}
+						return ExecProject(node->js.ps.ps_ProjInfo);
 					}
 					else
 						InstrCountFiltered2(node, 1);
@@ -354,16 +328,7 @@ ExecHashJoin(HashJoinState *node)
 					if (otherqual == NIL ||
 						ExecQual(otherqual, econtext, false))
 					{
-						TupleTableSlot *result;
-
-						result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
-						if (isDone != ExprEndResult)
-						{
-							node->js.ps.ps_TupFromTlist =
-								(isDone == ExprMultipleResult);
-							return result;
-						}
+						return ExecProject(node->js.ps.ps_ProjInfo);
 					}
 					else
 						InstrCountFiltered2(node, 1);
@@ -393,16 +358,7 @@ ExecHashJoin(HashJoinState *node)
 				if (otherqual == NIL ||
 					ExecQual(otherqual, econtext, false))
 				{
-					TupleTableSlot *result;
-
-					result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
-					if (isDone != ExprEndResult)
-					{
-						node->js.ps.ps_TupFromTlist =
-							(isDone == ExprMultipleResult);
-						return result;
-					}
+					return ExecProject(node->js.ps.ps_ProjInfo);
 				}
 				else
 					InstrCountFiltered2(node, 1);
@@ -586,7 +542,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 	/* child Hash node needs to evaluate inner hash keys, too */
 	((HashState *) innerPlanState(hjstate))->hashkeys = rclauses;
 
-	hjstate->js.ps.ps_TupFromTlist = false;
 	hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
 	hjstate->hj_MatchedOuter = false;
 	hjstate->hj_OuterNotEmpty = false;
@@ -1000,7 +955,6 @@ ExecReScanHashJoin(HashJoinState *node)
 	node->hj_CurSkewBucketNo = INVALID_SKEW_BUCKET_NO;
 	node->hj_CurTuple = NULL;
 
-	node->js.ps.ps_TupFromTlist = false;
 	node->hj_MatchedOuter = false;
 	node->hj_FirstOuterTupleSlot = NULL;
 
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 4f6f91c..edd45661 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -412,8 +412,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &indexstate->ss.ps);
 
-	indexstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * initialize child expressions
 	 *
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 3143bd9..d1b1c23 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -336,8 +336,7 @@ EvalOrderByExpressions(IndexScanState *node, ExprContext *econtext)
 
 		node->iss_OrderByValues[i] = ExecEvalExpr(orderby,
 												  econtext,
-												  &node->iss_OrderByNulls[i],
-												  NULL);
+												  &node->iss_OrderByNulls[i]);
 		i++;
 	}
 
@@ -590,8 +589,7 @@ ExecIndexEvalRuntimeKeys(ExprContext *econtext,
 		 */
 		scanvalue = ExecEvalExpr(key_expr,
 								 econtext,
-								 &isNull,
-								 NULL);
+								 &isNull);
 		if (isNull)
 		{
 			scan_key->sk_argument = scanvalue;
@@ -648,8 +646,7 @@ ExecIndexEvalArrayKeys(ExprContext *econtext,
 		 */
 		arraydatum = ExecEvalExpr(array_expr,
 								  econtext,
-								  &isNull,
-								  NULL);
+								  &isNull);
 		if (isNull)
 		{
 			result = false;
@@ -837,8 +834,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &indexstate->ss.ps);
 
-	indexstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * initialize child expressions
 	 *
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index faf32e1..7fed1c0 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -239,8 +239,7 @@ recompute_limits(LimitState *node)
 	{
 		val = ExecEvalExprSwitchContext(node->limitOffset,
 										econtext,
-										&isNull,
-										NULL);
+										&isNull);
 		/* Interpret NULL offset as no offset */
 		if (isNull)
 			node->offset = 0;
@@ -263,8 +262,7 @@ recompute_limits(LimitState *node)
 	{
 		val = ExecEvalExprSwitchContext(node->limitCount,
 										econtext,
-										&isNull,
-										NULL);
+										&isNull);
 		/* Interpret NULL count as no count (LIMIT ALL) */
 		if (isNull)
 		{
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 6db09b8..340a2a9 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -313,7 +313,7 @@ MJEvalOuterValues(MergeJoinState *mergestate)
 		MergeJoinClause clause = &mergestate->mj_Clauses[i];
 
 		clause->ldatum = ExecEvalExpr(clause->lexpr, econtext,
-									  &clause->lisnull, NULL);
+									  &clause->lisnull);
 		if (clause->lisnull)
 		{
 			/* match is impossible; can we end the join early? */
@@ -360,7 +360,7 @@ MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
 		MergeJoinClause clause = &mergestate->mj_Clauses[i];
 
 		clause->rdatum = ExecEvalExpr(clause->rexpr, econtext,
-									  &clause->risnull, NULL);
+									  &clause->risnull);
 		if (clause->risnull)
 		{
 			/* match is impossible; can we end the join early? */
@@ -465,19 +465,10 @@ MJFillOuter(MergeJoinState *node)
 		 * qualification succeeded.  now form the desired projection tuple and
 		 * return the slot containing it.
 		 */
-		TupleTableSlot *result;
-		ExprDoneCond isDone;
 
 		MJ_printf("ExecMergeJoin: returning outer fill tuple\n");
 
-		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
-		if (isDone != ExprEndResult)
-		{
-			node->js.ps.ps_TupFromTlist =
-				(isDone == ExprMultipleResult);
-			return result;
-		}
+		return ExecProject(node->js.ps.ps_ProjInfo);
 	}
 	else
 		InstrCountFiltered2(node, 1);
@@ -506,19 +497,9 @@ MJFillInner(MergeJoinState *node)
 		 * qualification succeeded.  now form the desired projection tuple and
 		 * return the slot containing it.
 		 */
-		TupleTableSlot *result;
-		ExprDoneCond isDone;
-
 		MJ_printf("ExecMergeJoin: returning inner fill tuple\n");
 
-		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
-		if (isDone != ExprEndResult)
-		{
-			node->js.ps.ps_TupFromTlist =
-				(isDone == ExprMultipleResult);
-			return result;
-		}
+		return ExecProject(node->js.ps.ps_ProjInfo);
 	}
 	else
 		InstrCountFiltered2(node, 1);
@@ -642,23 +623,6 @@ ExecMergeJoin(MergeJoinState *node)
 	doFillInner = node->mj_FillInner;
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous join
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->js.ps.ps_TupFromTlist)
-	{
-		TupleTableSlot *result;
-		ExprDoneCond isDone;
-
-		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return result;
-		/* Done with that source tuple... */
-		node->js.ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * Reset per-tuple memory context to free any expression evaluation
 	 * storage allocated in the previous tuple cycle.  Note this can't happen
 	 * until we're done projecting out tuples from a join tuple.
@@ -856,20 +820,9 @@ ExecMergeJoin(MergeJoinState *node)
 						 * qualification succeeded.  now form the desired
 						 * projection tuple and return the slot containing it.
 						 */
-						TupleTableSlot *result;
-						ExprDoneCond isDone;
-
 						MJ_printf("ExecMergeJoin: returning tuple\n");
 
-						result = ExecProject(node->js.ps.ps_ProjInfo,
-											 &isDone);
-
-						if (isDone != ExprEndResult)
-						{
-							node->js.ps.ps_TupFromTlist =
-								(isDone == ExprMultipleResult);
-							return result;
-						}
+						return ExecProject(node->js.ps.ps_ProjInfo);
 					}
 					else
 						InstrCountFiltered2(node, 1);
@@ -1629,7 +1582,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 	 * initialize join state
 	 */
 	mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
-	mergestate->js.ps.ps_TupFromTlist = false;
 	mergestate->mj_MatchedOuter = false;
 	mergestate->mj_MatchedInner = false;
 	mergestate->mj_OuterTupleSlot = NULL;
@@ -1684,7 +1636,6 @@ ExecReScanMergeJoin(MergeJoinState *node)
 	ExecClearTuple(node->mj_MarkedTupleSlot);
 
 	node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
-	node->js.ps.ps_TupFromTlist = false;
 	node->mj_MatchedOuter = false;
 	node->mj_MatchedInner = false;
 	node->mj_OuterTupleSlot = NULL;
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index af7b26c..0e6187b 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -175,7 +175,7 @@ ExecProcessReturning(ResultRelInfo *resultRelInfo,
 	econtext->ecxt_outertuple = planSlot;
 
 	/* Compute the RETURNING expressions */
-	return ExecProject(projectReturning, NULL);
+	return ExecProject(projectReturning);
 }
 
 /*
@@ -1216,7 +1216,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
 	}
 
 	/* Project the new tuple version */
-	ExecProject(resultRelInfo->ri_onConflictSetProj, NULL);
+	ExecProject(resultRelInfo->ri_onConflictSetProj);
 
 	/*
 	 * Note that it is possible that the target tuple has been modified in
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 555fa09..5d30e75 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -82,23 +82,6 @@ ExecNestLoop(NestLoopState *node)
 	econtext = node->js.ps.ps_ExprContext;
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous join
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->js.ps.ps_TupFromTlist)
-	{
-		TupleTableSlot *result;
-		ExprDoneCond isDone;
-
-		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return result;
-		/* Done with that source tuple... */
-		node->js.ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * Reset per-tuple memory context to free any expression evaluation
 	 * storage allocated in the previous tuple cycle.  Note this can't happen
 	 * until we're done projecting out tuples from a join tuple.
@@ -201,19 +184,10 @@ ExecNestLoop(NestLoopState *node)
 					 * the slot containing the result tuple using
 					 * ExecProject().
 					 */
-					TupleTableSlot *result;
-					ExprDoneCond isDone;
 
 					ENL1_printf("qualification succeeded, projecting tuple");
 
-					result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
-					if (isDone != ExprEndResult)
-					{
-						node->js.ps.ps_TupFromTlist =
-							(isDone == ExprMultipleResult);
-						return result;
-					}
+					return ExecProject(node->js.ps.ps_ProjInfo);
 				}
 				else
 					InstrCountFiltered2(node, 1);
@@ -259,19 +233,10 @@ ExecNestLoop(NestLoopState *node)
 				 * qualification was satisfied so we project and return the
 				 * slot containing the result tuple using ExecProject().
 				 */
-				TupleTableSlot *result;
-				ExprDoneCond isDone;
 
 				ENL1_printf("qualification succeeded, projecting tuple");
 
-				result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
-
-				if (isDone != ExprEndResult)
-				{
-					node->js.ps.ps_TupFromTlist =
-						(isDone == ExprMultipleResult);
-					return result;
-				}
+				return ExecProject(node->js.ps.ps_ProjInfo);
 			}
 			else
 				InstrCountFiltered2(node, 1);
@@ -377,7 +342,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
 	/*
 	 * finally, wipe the current outer tuple clean.
 	 */
-	nlstate->js.ps.ps_TupFromTlist = false;
 	nlstate->nl_NeedNewOuter = true;
 	nlstate->nl_MatchedOuter = false;
 
@@ -441,7 +405,6 @@ ExecReScanNestLoop(NestLoopState *node)
 	 * outer Vars are used as run-time keys...
 	 */
 
-	node->js.ps.ps_TupFromTlist = false;
 	node->nl_NeedNewOuter = true;
 	node->nl_MatchedOuter = false;
 }
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index 4007b76..3901351 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -67,10 +67,8 @@ TupleTableSlot *
 ExecResult(ResultState *node)
 {
 	TupleTableSlot *outerTupleSlot;
-	TupleTableSlot *resultSlot;
 	PlanState  *outerPlan;
 	ExprContext *econtext;
-	ExprDoneCond isDone;
 
 	econtext = node->ps.ps_ExprContext;
 
@@ -92,20 +90,6 @@ ExecResult(ResultState *node)
 	}
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous scan
-	 * tuple (because there is a function-returning-set in the projection
-	 * expressions).  If so, try to project another one.
-	 */
-	if (node->ps.ps_TupFromTlist)
-	{
-		resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return resultSlot;
-		/* Done with that source tuple... */
-		node->ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * Reset per-tuple memory context to free any expression evaluation
 	 * storage allocated in the previous tuple cycle.  Note this can't happen
 	 * until we're done projecting out tuples from a scan tuple.
@@ -147,18 +131,8 @@ ExecResult(ResultState *node)
 			node->rs_done = true;
 		}
 
-		/*
-		 * form the result tuple using ExecProject(), and return it --- unless
-		 * the projection produces an empty set, in which case we must loop
-		 * back to see if there are more outerPlan tuples.
-		 */
-		resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
-
-		if (isDone != ExprEndResult)
-		{
-			node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
-			return resultSlot;
-		}
+		/* form the result tuple using ExecProject(), and return it */
+		return ExecProject(node->ps.ps_ProjInfo);
 	}
 
 	return NULL;
@@ -228,8 +202,6 @@ ExecInitResult(Result *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &resstate->ps);
 
-	resstate->ps.ps_TupFromTlist = false;
-
 	/*
 	 * tuple table initialization
 	 */
@@ -295,7 +267,6 @@ void
 ExecReScanResult(ResultState *node)
 {
 	node->rs_done = false;
-	node->ps.ps_TupFromTlist = false;
 	node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
 
 	/*
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 9ce7c02..64396e1 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -188,8 +188,6 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 	 */
 	InitScanRelation(scanstate, estate, eflags);
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * Initialize result tuple type and projection info.
 	 */
@@ -299,8 +297,7 @@ tablesample_init(SampleScanState *scanstate)
 
 		params[i] = ExecEvalExprSwitchContext(argstate,
 											  econtext,
-											  &isnull,
-											  NULL);
+											  &isnull);
 		if (isnull)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
@@ -312,8 +309,7 @@ tablesample_init(SampleScanState *scanstate)
 	{
 		datum = ExecEvalExprSwitchContext(scanstate->repeatable,
 										  econtext,
-										  &isnull,
-										  NULL);
+										  &isnull);
 		if (isnull)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TABLESAMPLE_REPEAT),
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 00bf3a5..477dc42 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -206,8 +206,6 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
 	 */
 	InitScanRelation(scanstate, estate, eflags);
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * Initialize result tuple type and projection info.
 	 */
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index e503494..5800ca8 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -41,12 +41,10 @@
 
 static Datum ExecSubPlan(SubPlanState *node,
 			ExprContext *econtext,
-			bool *isNull,
-			ExprDoneCond *isDone);
+			bool *isNull);
 static Datum ExecAlternativeSubPlan(AlternativeSubPlanState *node,
 					   ExprContext *econtext,
-					   bool *isNull,
-					   ExprDoneCond *isDone);
+					   bool *isNull);
 static Datum ExecHashSubPlan(SubPlanState *node,
 				ExprContext *econtext,
 				bool *isNull);
@@ -69,15 +67,12 @@ static bool slotNoNulls(TupleTableSlot *slot);
 static Datum
 ExecSubPlan(SubPlanState *node,
 			ExprContext *econtext,
-			bool *isNull,
-			ExprDoneCond *isDone)
+			bool *isNull)
 {
 	SubPlan    *subplan = (SubPlan *) node->xprstate.expr;
 
 	/* Set default values for result flags: non-null, not a set result */
 	*isNull = false;
-	if (isDone)
-		*isDone = ExprSingleResult;
 
 	/* Sanity checks */
 	if (subplan->subLinkType == CTE_SUBLINK)
@@ -128,7 +123,7 @@ ExecHashSubPlan(SubPlanState *node,
 	 * have to set the econtext to use (hack alert!).
 	 */
 	node->projLeft->pi_exprContext = econtext;
-	slot = ExecProject(node->projLeft, NULL);
+	slot = ExecProject(node->projLeft);
 
 	/*
 	 * Note: because we are typically called in a per-tuple context, we have
@@ -285,8 +280,7 @@ ExecScanSubPlan(SubPlanState *node,
 
 		prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
 											   econtext,
-											   &(prm->isnull),
-											   NULL);
+											   &(prm->isnull));
 		planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
 	}
 
@@ -403,7 +397,7 @@ ExecScanSubPlan(SubPlanState *node,
 		}
 
 		rowresult = ExecEvalExprSwitchContext(node->testexpr, econtext,
-											  &rownull, NULL);
+											  &rownull);
 
 		if (subLinkType == ANY_SUBLINK)
 		{
@@ -570,7 +564,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
 										  &(prmdata->isnull));
 			col++;
 		}
-		slot = ExecProject(node->projRight, NULL);
+		slot = ExecProject(node->projRight);
 
 		/*
 		 * If result contains any nulls, store separately or not at all.
@@ -987,8 +981,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 
 		prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
 											   econtext,
-											   &(prm->isnull),
-											   NULL);
+											   &(prm->isnull));
 		planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
 	}
 
@@ -1224,8 +1217,7 @@ ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
 static Datum
 ExecAlternativeSubPlan(AlternativeSubPlanState *node,
 					   ExprContext *econtext,
-					   bool *isNull,
-					   ExprDoneCond *isDone)
+					   bool *isNull)
 {
 	/* Just pass control to the active subplan */
 	SubPlanState *activesp = (SubPlanState *) list_nth(node->subplans,
@@ -1233,8 +1225,5 @@ ExecAlternativeSubPlan(AlternativeSubPlanState *node,
 
 	Assert(IsA(activesp, SubPlanState));
 
-	return ExecSubPlan(activesp,
-					   econtext,
-					   isNull,
-					   isDone);
+	return ExecSubPlan(activesp, econtext, isNull);
 }
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 9bafc62..4de7024 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -138,8 +138,6 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
 	 */
 	subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
 
-	subquerystate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
 	 */
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 2604103..e1c736c 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -104,8 +104,7 @@ TidListCreate(TidScanState *tidstate)
 			itemptr = (ItemPointer)
 				DatumGetPointer(ExecEvalExprSwitchContext(exstate,
 														  econtext,
-														  &isNull,
-														  NULL));
+														  &isNull));
 			if (!isNull &&
 				ItemPointerIsValid(itemptr) &&
 				ItemPointerGetBlockNumber(itemptr) < nblocks)
@@ -133,8 +132,7 @@ TidListCreate(TidScanState *tidstate)
 			exstate = (ExprState *) lsecond(saexstate->fxprstate.args);
 			arraydatum = ExecEvalExprSwitchContext(exstate,
 												   econtext,
-												   &isNull,
-												   NULL);
+												   &isNull);
 			if (isNull)
 				continue;
 			itemarray = DatumGetArrayTypeP(arraydatum);
@@ -469,8 +467,6 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &tidstate->ss.ps);
 
-	tidstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * initialize child expressions
 	 */
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index 9c03f8a..18c8ae9 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -140,8 +140,7 @@ ValuesNext(ValuesScanState *node)
 
 			values[resind] = ExecEvalExpr(estate,
 										  econtext,
-										  &isnull[resind],
-										  NULL);
+										  &isnull[resind]);
 
 			/*
 			 * We must force any R/W expanded datums to read-only state, in
@@ -272,8 +271,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 		scanstate->exprlists[i++] = (List *) lfirst(vtl);
 	}
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	/*
 	 * Initialize result tuple type and projection info.
 	 */
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index d4c88a1..fc111fa 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -256,7 +256,7 @@ advance_windowaggregate(WindowAggState *winstate,
 	if (filter)
 	{
 		bool		isnull;
-		Datum		res = ExecEvalExpr(filter, econtext, &isnull, NULL);
+		Datum		res = ExecEvalExpr(filter, econtext, &isnull);
 
 		if (isnull || !DatumGetBool(res))
 		{
@@ -272,7 +272,7 @@ advance_windowaggregate(WindowAggState *winstate,
 		ExprState  *argstate = (ExprState *) lfirst(arg);
 
 		fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
-									  &fcinfo->argnull[i], NULL);
+									  &fcinfo->argnull[i]);
 		i++;
 	}
 
@@ -418,7 +418,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
 	if (filter)
 	{
 		bool		isnull;
-		Datum		res = ExecEvalExpr(filter, econtext, &isnull, NULL);
+		Datum		res = ExecEvalExpr(filter, econtext, &isnull);
 
 		if (isnull || !DatumGetBool(res))
 		{
@@ -434,7 +434,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
 		ExprState  *argstate = (ExprState *) lfirst(arg);
 
 		fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
-									  &fcinfo->argnull[i], NULL);
+									  &fcinfo->argnull[i]);
 		i++;
 	}
 
@@ -1558,8 +1558,6 @@ update_frametailpos(WindowObject winobj, TupleTableSlot *slot)
 TupleTableSlot *
 ExecWindowAgg(WindowAggState *winstate)
 {
-	TupleTableSlot *result;
-	ExprDoneCond isDone;
 	ExprContext *econtext;
 	int			i;
 	int			numfuncs;
@@ -1568,23 +1566,6 @@ ExecWindowAgg(WindowAggState *winstate)
 		return NULL;
 
 	/*
-	 * Check to see if we're still projecting out tuples from a previous
-	 * output tuple (because there is a function-returning-set in the
-	 * projection expressions).  If so, try to project another one.
-	 */
-	if (winstate->ss.ps.ps_TupFromTlist)
-	{
-		TupleTableSlot *result;
-		ExprDoneCond isDone;
-
-		result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
-		if (isDone == ExprMultipleResult)
-			return result;
-		/* Done with that source tuple... */
-		winstate->ss.ps.ps_TupFromTlist = false;
-	}
-
-	/*
 	 * Compute frame offset values, if any, during first call.
 	 */
 	if (winstate->all_first)
@@ -1601,8 +1582,7 @@ ExecWindowAgg(WindowAggState *winstate)
 			Assert(winstate->startOffset != NULL);
 			value = ExecEvalExprSwitchContext(winstate->startOffset,
 											  econtext,
-											  &isnull,
-											  NULL);
+											  &isnull);
 			if (isnull)
 				ereport(ERROR,
 						(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
@@ -1627,8 +1607,7 @@ ExecWindowAgg(WindowAggState *winstate)
 			Assert(winstate->endOffset != NULL);
 			value = ExecEvalExprSwitchContext(winstate->endOffset,
 											  econtext,
-											  &isnull,
-											  NULL);
+											  &isnull);
 			if (isnull)
 				ereport(ERROR,
 						(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
@@ -1651,7 +1630,6 @@ ExecWindowAgg(WindowAggState *winstate)
 		winstate->all_first = false;
 	}
 
-restart:
 	if (winstate->buffer == NULL)
 	{
 		/* Initialize for first partition and set current row = 0 */
@@ -1743,17 +1721,8 @@ restart:
 	 * evaluated with respect to that row.
 	 */
 	econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
-	result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
 
-	if (isDone == ExprEndResult)
-	{
-		/* SRF in tlist returned no rows, so advance to next input tuple */
-		goto restart;
-	}
-
-	winstate->ss.ps.ps_TupFromTlist =
-		(isDone == ExprMultipleResult);
-	return result;
+	return ExecProject(winstate->ss.ps.ps_ProjInfo);
 }
 
 /* -----------------
@@ -1867,8 +1836,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	ExecAssignResultTypeFromTL(&winstate->ss.ps);
 	ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
 
-	winstate->ss.ps.ps_TupFromTlist = false;
-
 	/* Set up data for comparing tuples */
 	if (node->partNumCols > 0)
 		winstate->partEqfunctions = execTuplesMatchPrepare(node->partNumCols,
@@ -2061,8 +2028,6 @@ ExecReScanWindowAgg(WindowAggState *node)
 	ExprContext *econtext = node->ss.ps.ps_ExprContext;
 
 	node->all_done = false;
-
-	node->ss.ps.ps_TupFromTlist = false;
 	node->all_first = true;
 
 	/* release tuplestore et al */
@@ -2685,7 +2650,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
 		}
 		econtext->ecxt_outertuple = slot;
 		return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
-							econtext, isnull, NULL);
+							econtext, isnull);
 	}
 }
 
@@ -2784,7 +2749,7 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno,
 		}
 		econtext->ecxt_outertuple = slot;
 		return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
-							econtext, isnull, NULL);
+							econtext, isnull);
 	}
 }
 
@@ -2814,5 +2779,5 @@ WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)
 
 	econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
 	return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
-						econtext, isnull, NULL);
+						econtext, isnull);
 }
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
index cfed6e6..dbb8ea3 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -174,8 +174,6 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
 	 */
 	ExecAssignResultTypeFromTL(&scanstate->ss.ps);
 
-	scanstate->ss.ps.ps_TupFromTlist = false;
-
 	return scanstate;
 }
 
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 7e60694..ab30f7e 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -5171,7 +5171,7 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
 	 */
 	const_val = ExecEvalExprSwitchContext(exprstate,
 										  GetPerTupleExprContext(estate),
-										  &const_is_null, NULL);
+										  &const_is_null);
 
 	/* Get info needed about result datatype */
 	get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 2c2efb1..0c59fe8 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -1596,7 +1596,7 @@ operator_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
 	/* And execute it. */
 	test_result = ExecEvalExprSwitchContext(test_exprstate,
 											GetPerTupleExprContext(estate),
-											&isNull, NULL);
+											&isNull);
 
 	/* Get back to outer memory context */
 	MemoryContextSwitchTo(oldcontext);
diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c
index 19ee4ce..c568c6c 100644
--- a/src/backend/utils/adt/domains.c
+++ b/src/backend/utils/adt/domains.c
@@ -164,7 +164,7 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
 
 					conResult = ExecEvalExprSwitchContext(con->check_expr,
 														  econtext,
-														  &conIsNull, NULL);
+														  &conIsNull);
 
 					if (!conIsNull &&
 						!DatumGetBool(conResult))
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 7ed5bcb..65bf6ad 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -603,7 +603,7 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
 		bool		isnull;
 		char	   *str;
 
-		value = ExecEvalExpr(e, econtext, &isnull, NULL);
+		value = ExecEvalExpr(e, econtext, &isnull);
 		if (isnull)
 			str = NULL;
 		else
@@ -620,7 +620,7 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
 		bool		isnull;
 		char	   *str;
 
-		value = ExecEvalExpr(e, econtext, &isnull, NULL);
+		value = ExecEvalExpr(e, econtext, &isnull);
 		/* here we can just forget NULL elements immediately */
 		if (!isnull)
 		{
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 39521ed..7f6a2bc 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -69,8 +69,8 @@
  * now it's just a macro invoking the function pointed to by an ExprState
  * node.  Beware of double evaluation of the ExprState argument!
  */
-#define ExecEvalExpr(expr, econtext, isNull, isDone) \
-	((*(expr)->evalfunc) (expr, econtext, isNull, isDone))
+#define ExecEvalExpr(expr, econtext, isNull) \
+	((*(expr)->evalfunc) (expr, econtext, isNull))
 
 
 /* Hook for plugins to get control in ExecutorStart() */
@@ -240,14 +240,13 @@ extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr,
 							TupleDesc expectedDesc,
 							bool randomAccess);
 extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
-						  bool *isNull, ExprDoneCond *isDone);
+						  bool *isNull);
 extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
 extern ExprState *ExecPrepareExpr(Expr *node, EState *estate);
 extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
 extern int	ExecTargetListLength(List *targetlist);
 extern int	ExecCleanTargetListLength(List *targetlist);
-extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo,
-			ExprDoneCond *isDone);
+extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo);
 
 /*
  * prototypes from functions in execScan.c
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e7fd7bd..043f969 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -243,7 +243,6 @@ typedef struct ProjectionInfo
 	List	   *pi_targetlist;
 	ExprContext *pi_exprContext;
 	TupleTableSlot *pi_slot;
-	ExprDoneCond *pi_itemIsDone;
 	bool		pi_directMap;
 	int			pi_numSimpleVars;
 	int		   *pi_varSlotOffsets;
@@ -569,8 +568,7 @@ typedef struct ExprState ExprState;
 
 typedef Datum (*ExprStateEvalFunc) (ExprState *expression,
 												ExprContext *econtext,
-												bool *isNull,
-												ExprDoneCond *isDone);
+												bool *isNull);
 
 struct ExprState
 {
@@ -692,21 +690,13 @@ typedef struct FuncExprState
 	TupleTableSlot *funcResultSlot;
 
 	/*
-	 * In some cases we need to compute a tuple descriptor for the function's
-	 * output.  If so, it's stored here.
-	 */
-	TupleDesc	funcResultDesc;
-	bool		funcReturnsTuple;		/* valid when funcResultDesc isn't
-										 * NULL */
-
-	/*
 	 * setArgsValid is true when we are evaluating a set-returning function
 	 * that uses value-per-call mode and we are in the middle of a call
 	 * series; we want to pass the same argument values to the function again
 	 * (and again, until it returns ExprEndResult).  This indicates that
 	 * fcinfo_data already contains valid argument data.
 	 */
-	bool		setArgsValid;
+	bool		setArgsValid2;
 
 	/*
 	 * Flag to remember whether we found a set-valued argument to the
@@ -1057,8 +1047,6 @@ typedef struct PlanState
 	TupleTableSlot *ps_ResultTupleSlot; /* slot for my result tuples */
 	ExprContext *ps_ExprContext;	/* node's expression-evaluation context */
 	ProjectionInfo *ps_ProjInfo;	/* info for doing tuple projection */
-	bool		ps_TupFromTlist;/* state flag for processing set-valued
-								 * functions in targetlist */
 } PlanState;
 
 /* ----------------
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 586ff1f..3ae4489 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -5443,8 +5443,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
 	 */
 	*result = ExecEvalExpr(expr->expr_simple_state,
 						   econtext,
-						   isNull,
-						   NULL);
+						   isNull);
 
 	/* Assorted cleanup */
 	expr->expr_simple_in_use = false;
@@ -6112,7 +6111,7 @@ exec_cast_value(PLpgSQL_execstate *estate,
 			cast_entry->cast_in_use = true;
 
 			value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
-								 isnull, NULL);
+								 isnull);
 
 			cast_entry->cast_in_use = false;
 
-- 
2.8.1

