aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/index.c3
-rw-r--r--src/backend/catalog/partition.c5
-rw-r--r--src/backend/commands/copy.c2
-rw-r--r--src/backend/commands/prepare.c3
-rw-r--r--src/backend/commands/tablecmds.c3
-rw-r--r--src/backend/commands/typecmds.c2
-rw-r--r--src/backend/executor/execAmi.c44
-rw-r--r--src/backend/executor/execQual.c916
-rw-r--r--src/backend/executor/execScan.c33
-rw-r--r--src/backend/executor/execUtils.c6
-rw-r--r--src/backend/executor/nodeAgg.c52
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c2
-rw-r--r--src/backend/executor/nodeCtescan.c2
-rw-r--r--src/backend/executor/nodeCustom.c2
-rw-r--r--src/backend/executor/nodeForeignscan.c2
-rw-r--r--src/backend/executor/nodeFunctionscan.c2
-rw-r--r--src/backend/executor/nodeGather.c32
-rw-r--r--src/backend/executor/nodeGroup.c42
-rw-r--r--src/backend/executor/nodeHash.c2
-rw-r--r--src/backend/executor/nodeHashjoin.c61
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c2
-rw-r--r--src/backend/executor/nodeIndexscan.c11
-rw-r--r--src/backend/executor/nodeLimit.c19
-rw-r--r--src/backend/executor/nodeMergejoin.c63
-rw-r--r--src/backend/executor/nodeModifyTable.c4
-rw-r--r--src/backend/executor/nodeNestloop.c46
-rw-r--r--src/backend/executor/nodeProjectSet.c2
-rw-r--r--src/backend/executor/nodeResult.c36
-rw-r--r--src/backend/executor/nodeSamplescan.c8
-rw-r--r--src/backend/executor/nodeSeqscan.c2
-rw-r--r--src/backend/executor/nodeSubplan.c33
-rw-r--r--src/backend/executor/nodeSubqueryscan.c2
-rw-r--r--src/backend/executor/nodeTidscan.c8
-rw-r--r--src/backend/executor/nodeValuesscan.c5
-rw-r--r--src/backend/executor/nodeWindowAgg.c58
-rw-r--r--src/backend/executor/nodeWorktablescan.c2
-rw-r--r--src/backend/optimizer/util/clauses.c2
-rw-r--r--src/backend/optimizer/util/predtest.c2
-rw-r--r--src/backend/utils/adt/domains.c2
-rw-r--r--src/backend/utils/adt/xml.c4
-rw-r--r--src/include/executor/executor.h9
-rw-r--r--src/include/nodes/execnodes.h17
-rw-r--r--src/pl/plpgsql/src/pl_exec.c5
43 files changed, 351 insertions, 1207 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index cac0cbf7d47..26cbc0e06aa 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1805,8 +1805,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/catalog/partition.c b/src/backend/catalog/partition.c
index 45f7132f543..3f8a950f37d 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -1358,7 +1358,7 @@ get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
test_exprstate = ExecInitExpr(test_expr, NULL);
test_result = ExecEvalExprSwitchContext(test_exprstate,
GetPerTupleExprContext(estate),
- &isNull, NULL);
+ &isNull);
MemoryContextSwitchTo(oldcxt);
FreeExecutorState(estate);
@@ -1630,8 +1630,7 @@ FormPartitionKeyDatum(PartitionDispatch pd,
elog(ERROR, "wrong number of partition key expressions");
datum = ExecEvalExprSwitchContext((ExprState *) lfirst(partexpr_item),
GetPerTupleExprContext(estate),
- &isNull,
- NULL);
+ &isNull);
partexpr_item = lnext(partexpr_item);
}
values[i] = datum;
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 75386212e06..c05e14e26f7 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -3394,7 +3394,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 1ff41661a55..7d7e3daf1e7 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -413,8 +413,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 18cac9ad2d9..6ed2a3dc4d1 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4460,8 +4460,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 3ff6cbca56f..4c33d554844 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2735,7 +2735,7 @@ validateDomainConstraint(Oid domainoid, char *ccbin)
conResult = ExecEvalExprSwitchContext(exprstate,
econtext,
- &isNull, NULL);
+ &isNull);
if (!isNull && !DatumGetBool(conResult))
{
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c
index b52cfaa41f4..1ca4bcb117c 100644
--- a/src/backend/executor/execAmi.c
+++ b/src/backend/executor/execAmi.c
@@ -59,7 +59,6 @@
#include "utils/syscache.h"
-static bool TargetListSupportsBackwardScan(List *targetlist);
static bool IndexSupportsBackwardScan(Oid indexid);
@@ -120,7 +119,7 @@ ExecReScan(PlanState *node)
UpdateChangedParamSet(node->righttree, node->chgParam);
}
- /* Shut down any SRFs in the plan node's targetlist */
+ /* Call expression callbacks */
if (node->ps_ExprContext)
ReScanExprContext(node->ps_ExprContext);
@@ -460,8 +459,7 @@ ExecSupportsBackwardScan(Plan *node)
{
case T_Result:
if (outerPlan(node) != NULL)
- return ExecSupportsBackwardScan(outerPlan(node)) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return ExecSupportsBackwardScan(outerPlan(node));
else
return false;
@@ -478,13 +476,6 @@ ExecSupportsBackwardScan(Plan *node)
return true;
}
- case T_SeqScan:
- case T_TidScan:
- case T_FunctionScan:
- case T_ValuesScan:
- case T_CteScan:
- return TargetListSupportsBackwardScan(node->targetlist);
-
case T_SampleScan:
/* Simplify life for tablesample methods by disallowing this */
return false;
@@ -493,35 +484,34 @@ ExecSupportsBackwardScan(Plan *node)
return false;
case T_IndexScan:
- return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return IndexSupportsBackwardScan(((IndexScan *) node)->indexid);
case T_IndexOnlyScan:
- return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid);
case T_SubqueryScan:
- return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
- TargetListSupportsBackwardScan(node->targetlist);
+ return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
case T_CustomScan:
{
uint32 flags = ((CustomScan *) node)->flags;
- if ((flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) &&
- TargetListSupportsBackwardScan(node->targetlist))
+ if (flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN)
return true;
}
return false;
+ case T_SeqScan:
+ case T_TidScan:
+ case T_FunctionScan:
+ case T_ValuesScan:
+ case T_CteScan:
case T_Material:
case T_Sort:
- /* these don't evaluate tlist */
return true;
case T_LockRows:
case T_Limit:
- /* these don't evaluate tlist */
return ExecSupportsBackwardScan(outerPlan(node));
default:
@@ -530,18 +520,6 @@ ExecSupportsBackwardScan(Plan *node)
}
/*
- * If the tlist contains set-returning functions, we can't support backward
- * scan, because the TupFromTlist code is direction-ignorant.
- */
-static bool
-TargetListSupportsBackwardScan(List *targetlist)
-{
- if (expression_returns_set((Node *) targetlist))
- return false;
- return true;
-}
-
-/*
* An IndexScan or IndexOnlyScan node supports backward scan only if the
* index's AM does.
*/
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index eed7e95c759..19dd0b264bc 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -64,40 +64,40 @@
/* 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 allowSRF, bool needDescForSRF);
static void ShutdownFuncExpr(Datum arg);
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,
@@ -106,85 +106,85 @@ static void ExecPrepareTuplestoreResult(FuncExprState *fcache,
static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc);
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 ExecEvalSQLValueFunction(ExprState *svfExpr,
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);
/* ----------------------------------------------------------------
@@ -195,8 +195,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
@@ -220,22 +219,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
@@ -260,8 +243,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;
@@ -278,8 +260,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
@@ -287,8 +268,6 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
*/
if (*isNull)
{
- if (isDone && *isDone == ExprEndResult)
- return (Datum) NULL; /* end of set result */
if (!isAssignment)
return (Datum) NULL;
}
@@ -314,8 +293,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)
{
@@ -350,8 +328,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)
{
@@ -438,8 +415,7 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
*/
sourceData = ExecEvalExpr(astate->refassgnexpr,
econtext,
- &eisnull,
- NULL);
+ &eisnull);
econtext->caseValue_datum = save_datum;
econtext->caseValue_isNull = save_isNull;
@@ -542,11 +518,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");
@@ -563,11 +536,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");
@@ -588,15 +558,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)
{
@@ -677,15 +644,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)
{
@@ -725,7 +689,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;
@@ -733,9 +697,6 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
MemoryContext oldcontext;
bool needslow = false;
- if (isDone)
- *isDone = ExprSingleResult;
-
/* This was checked by ExecInitExpr */
Assert(variable->varattno == InvalidAttrNumber);
@@ -941,7 +902,7 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
/* Fetch the value */
return (*wrvstate->xprstate.evalfunc) ((ExprState *) wrvstate, econtext,
- isNull, isDone);
+ isNull);
}
/* ----------------------------------------------------------------
@@ -952,14 +913,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 */
@@ -1008,7 +967,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;
@@ -1018,8 +977,6 @@ ExecEvalWholeRowSlow(WholeRowVarExprState *wrvstate, ExprContext *econtext,
HeapTupleHeader dtuple;
int i;
- if (isDone)
- *isDone = ExprSingleResult;
*isNull = false;
/* Get the input slot we want */
@@ -1097,13 +1054,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;
}
@@ -1116,15 +1070,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.
@@ -1149,15 +1100,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.
*/
@@ -1421,7 +1369,6 @@ init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
/* Initialize additional state */
fcache->funcResultStore = NULL;
fcache->funcResultSlot = NULL;
- fcache->setArgsValid = false;
fcache->shutdown_reg = false;
}
@@ -1508,47 +1455,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;
}
/*
@@ -1694,9 +1620,8 @@ ExecMakeFunctionResultSet(FuncExprState *fcache,
Datum result;
FunctionCallInfo fcinfo;
PgStat_FunctionCallUsage fcusage;
- ReturnSetInfo rsinfo; /* for functions returning sets */
- ExprDoneCond argDone;
- bool hasSetArg;
+ ReturnSetInfo rsinfo;
+ bool callit;
int i;
restart:
@@ -1727,6 +1652,9 @@ restart:
else
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(fcache->xprstate.expr));
+
+ /* shouldn't get here otherwise */
+ Assert(fcache->func.fn_retset);
}
/*
@@ -1736,7 +1664,6 @@ restart:
*/
if (fcache->funcResultStore)
{
- Assert(isDone); /* it was provided before ... */
if (tuplestore_gettupleslot(fcache->funcResultStore, true, false,
fcache->funcResultSlot))
{
@@ -1756,15 +1683,9 @@ restart:
/* 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);
+ *isDone = ExprEndResult;
+ *isNull = true;
+ return (Datum) 0;
}
/*
@@ -1776,18 +1697,9 @@ restart:
fcinfo = &fcache->fcinfo_data;
arguments = fcache->args;
if (!fcache->setArgsValid)
- {
- argDone = ExecEvalFuncArgs(fcinfo, arguments, econtext);
- if (argDone != ExprSingleResult)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- hasSetArg = false;
- }
+ ExecEvalFuncArgs(fcinfo, arguments, econtext);
else
{
- /* Re-use callinfo from previous evaluation */
- hasSetArg = fcache->setHasSetArg;
/* Reset flag (we may set it again below) */
fcache->setArgsValid = false;
}
@@ -1795,213 +1707,105 @@ restart:
/*
* 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;
+ /* Prepare a resultinfo node for communication. */
+ 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.
+ */
+ callit = true;
+ if (fcache->func.fn_strict)
+ {
+ for (i = 0; i < fcinfo->nargs; i++)
{
- /*
- * 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)
+ if (fcinfo->argnull[i])
{
- /* 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;
+ callit = false;
+ break;
}
- 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 (callit)
+ {
+ pgstat_init_function_usage(fcinfo, &fcusage);
- if (argDone != ExprMultipleResult)
- {
- /* End of argument set, so we're done. */
- *isNull = true;
- *isDone = ExprEndResult;
- result = (Datum) 0;
- break;
- }
+ fcinfo->isnull = false;
+ rsinfo.isDone = ExprSingleResult;
+ result = FunctionCallInvoke(fcinfo);
+ *isNull = fcinfo->isnull;
+ *isDone = rsinfo.isDone;
- /*
- * If we reach here, loop around to run the function on the new
- * argument.
- */
- }
+ pgstat_end_function_usage(&fcusage,
+ rsinfo.isDone != ExprMultipleResult);
}
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;
+ /* for a strict SRF, result for NULL is an empty set */
+ result = (Datum) 0;
+ *isNull = true;
+ *isDone = ExprEndResult;
+ }
- /*
- * If function is strict, and there are any NULL arguments, skip
- * calling the function and return NULL.
- */
- if (fcache->func.fn_strict)
+ /* Which protocol does function want to use? */
+ if (rsinfo.returnMode == SFRM_ValuePerCall)
+ {
+ if (*isDone != ExprEndResult)
{
- for (i = 0; i < fcinfo->nargs; i++)
+ /*
+ * Save the current argument values to re-use on the next call.
+ */
+ if (*isDone == ExprMultipleResult)
{
- if (fcinfo->argnull[i])
+ fcache->setArgsValid = true;
+ /* Register cleanup callback if we didn't already */
+ if (!fcache->shutdown_reg)
{
- *isNull = true;
- return (Datum) 0;
+ RegisterExprContextCallback(econtext,
+ ShutdownFuncExpr,
+ PointerGetDatum(fcache));
+ fcache->shutdown_reg = true;
}
}
}
-
- pgstat_init_function_usage(fcinfo, &fcusage);
-
- fcinfo->isnull = false;
- result = FunctionCallInvoke(fcinfo);
- *isNull = fcinfo->isnull;
-
- pgstat_end_function_usage(&fcusage, true);
}
+ 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);
+ /* 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)));
return result;
}
@@ -2015,8 +1819,7 @@ restart:
static Datum
ExecMakeFunctionResultNoSets(FuncExprState *fcache,
ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
+ bool *isNull)
{
ListCell *arg;
Datum result;
@@ -2027,9 +1830,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;
@@ -2039,8 +1839,7 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
fcinfo->arg[i] = ExecEvalExpr(argstate,
econtext,
- &fcinfo->argnull[i],
- NULL);
+ &fcinfo->argnull[i]);
i++;
}
@@ -2137,7 +1936,6 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
IsA(funcexpr->expr, FuncExpr))
{
FuncExprState *fcache = (FuncExprState *) funcexpr;
- ExprDoneCond argDone;
/*
* This path is similar to ExecMakeFunctionResultSet.
@@ -2172,15 +1970,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
@@ -2240,8 +2032,8 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
}
else
{
- result = ExecEvalExpr(funcexpr, econtext,
- &fcinfo.isnull, &rsinfo.isDone);
+ result = ExecEvalExpr(funcexpr, econtext, &fcinfo.isnull);
+ rsinfo.isDone = ExprSingleResult;
}
/* Which protocol does function want to use? */
@@ -2435,8 +2227,7 @@ 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;
@@ -2447,7 +2238,7 @@ ExecEvalFunc(FuncExprState *fcache,
/* Change the evalfunc pointer to save a few cycles in additional calls */
fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
- return ExecMakeFunctionResultNoSets(fcache, econtext, isNull, isDone);
+ return ExecMakeFunctionResultNoSets(fcache, econtext, isNull);
}
/* ----------------------------------------------------------------
@@ -2457,8 +2248,7 @@ 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;
@@ -2469,7 +2259,7 @@ ExecEvalOper(FuncExprState *fcache,
/* Change the evalfunc pointer to save a few cycles in additional calls */
fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;
- return ExecMakeFunctionResultNoSets(fcache, econtext, isNull, isDone);
+ return ExecMakeFunctionResultNoSets(fcache, econtext, isNull);
}
/* ----------------------------------------------------------------
@@ -2486,17 +2276,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 */
+ /* Set non-null as default */
*isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
/*
* Initialize function cache if first time through
@@ -2513,11 +2299,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])
@@ -2553,7 +2335,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;
@@ -2562,7 +2344,6 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
Datum result;
bool resultnull;
FunctionCallInfo fcinfo;
- ExprDoneCond argDone;
int i;
int16 typlen;
bool typbyval;
@@ -2571,10 +2352,8 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
bits8 *bitmap;
int bitmask;
- /* Set default values for result flags: non-null, not a set result */
+ /* Set non-null as default */
*isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
/*
* Initialize function cache if first time through
@@ -2589,11 +2368,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);
/*
@@ -2739,15 +2514,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
@@ -2769,15 +2541,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;
/*
@@ -2798,7 +2567,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.
@@ -2820,15 +2589,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;
/*
@@ -2845,7 +2611,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.
@@ -2871,7 +2637,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;
@@ -2879,7 +2645,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)
@@ -2955,16 +2721,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
@@ -2989,8 +2752,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
arg_value = ExecEvalExpr(caseExpr->arg,
econtext,
- &arg_isNull,
- NULL);
+ &arg_isNull);
/* Since caseValue_datum may be read multiple times, force to R/O */
econtext->caseValue_datum =
MakeExpandedObjectReadOnly(arg_value,
@@ -3012,8 +2774,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
clause_value = ExecEvalExpr(wclause->expr,
econtext,
- &clause_isNull,
- NULL);
+ &clause_isNull);
/*
* if we have a true test, then we return the result, since the case
@@ -3026,8 +2787,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
econtext->caseValue_isNull = save_isNull;
return ExecEvalExpr(wclause->result,
econtext,
- isNull,
- isDone);
+ isNull);
}
}
@@ -3038,8 +2798,7 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
{
return ExecEvalExpr(caseExpr->defresult,
econtext,
- isNull,
- isDone);
+ isNull);
}
*isNull = true;
@@ -3054,10 +2813,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;
}
@@ -3074,17 +2831,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))
@@ -3106,7 +2859,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;
@@ -3116,10 +2869,8 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
int dims[MAXDIM];
int lbs[MAXDIM];
- /* Set default values for result flags: non-null, not a set result */
+ /* Set non-null as default */
*isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
if (!arrayExpr->multidims)
{
@@ -3144,7 +2895,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++;
}
@@ -3194,7 +2945,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)
{
@@ -3333,7 +3084,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
static Datum
ExecEvalRow(RowExprState *rstate,
ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
+ bool *isNull)
{
HeapTuple tuple;
Datum *values;
@@ -3342,10 +3093,8 @@ ExecEvalRow(RowExprState *rstate,
ListCell *arg;
int i;
- /* Set default values for result flags: non-null, not a set result */
+ /* Set non-null as default */
*isNull = false;
- if (isDone)
- *isDone = ExprSingleResult;
/* Allocate workspace */
natts = rstate->tupdesc->natts;
@@ -3361,7 +3110,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++;
}
@@ -3380,7 +3129,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;
@@ -3389,8 +3138,6 @@ ExecEvalRowCompare(RowCompareExprState *rstate,
ListCell *r;
int i;
- if (isDone)
- *isDone = ExprSingleResult;
*isNull = true; /* until we get a result */
i = 0;
@@ -3404,9 +3151,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 */
@@ -3450,20 +3197,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;
}
@@ -3479,7 +3223,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;
@@ -3488,8 +3232,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,
@@ -3504,7 +3246,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 */
@@ -3540,14 +3282,12 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
static Datum
ExecEvalSQLValueFunction(ExprState *svfExpr,
ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
+ bool *isNull)
{
Datum result = (Datum) 0;
SQLValueFunction *svf = (SQLValueFunction *) svfExpr->expr;
FunctionCallInfoData fcinfo;
- if (isDone)
- *isDone = ExprSingleResult;
*isNull = false;
/*
@@ -3608,7 +3348,7 @@ ExecEvalSQLValueFunction(ExprState *svfExpr,
*/
static Datum
ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
+ bool *isNull)
{
XmlExpr *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
Datum value;
@@ -3616,8 +3356,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
ListCell *arg;
ListCell *narg;
- if (isDone)
- *isDone = ExprSingleResult;
*isNull = true; /* until we get a result */
switch (xexpr->op)
@@ -3630,7 +3368,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));
}
@@ -3655,7 +3393,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>",
@@ -3698,13 +3436,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);
@@ -3728,7 +3466,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
@@ -3755,20 +3493,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;
@@ -3787,7 +3525,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;
@@ -3805,7 +3543,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
@@ -3832,14 +3570,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
@@ -3856,11 +3590,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 */
@@ -3890,16 +3620,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))
{
@@ -3999,16 +3725,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)
{
@@ -4084,16 +3806,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);
@@ -4138,8 +3857,8 @@ ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
cstate->constraint_ref->tcache->typlen);
econtext->domainValue_isNull = *isNull;
- conResult = ExecEvalExpr(con->check_expr,
- econtext, &conIsNull, NULL);
+ conResult = ExecEvalExpr(con->check_expr, econtext,
+ &conIsNull);
if (!conIsNull &&
!DatumGetBool(conResult))
@@ -4174,10 +3893,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;
}
@@ -4191,8 +3908,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;
@@ -4205,9 +3921,8 @@ 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)
return tupDatum;
@@ -4270,8 +3985,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;
@@ -4284,10 +3998,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,
@@ -4347,8 +4058,7 @@ ExecEvalFieldStore(FieldStoreState *fstate,
values[fieldnum - 1] = ExecEvalExpr(newval,
econtext,
- &isnull[fieldnum - 1],
- NULL);
+ &isnull[fieldnum - 1]);
}
econtext->caseValue_datum = save_datum;
@@ -4371,9 +4081,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);
}
/* ----------------------------------------------------------------
@@ -4385,16 +4095,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 */
@@ -4419,16 +4126,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 */
@@ -4496,7 +4201,7 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
*/
static Datum
ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
+ bool *isNull)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -4513,14 +4218,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;
}
@@ -5387,7 +5091,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)
{
@@ -5445,17 +5149,11 @@ 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.
+ * tupdesc must describe the rowtype of the expected result.
*
- * 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.
+ * Results are stored into the passed values and isnull arrays.
*
* 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
@@ -5464,19 +5162,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.
@@ -5486,8 +5181,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);
@@ -5496,117 +5189,14 @@ 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;
}
/*
@@ -5623,7 +5213,7 @@ ExecTargetList(List *targetlist,
* result slot.
*/
TupleTableSlot *
-ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
+ExecProject(ProjectionInfo *projInfo)
{
TupleTableSlot *slot;
ExprContext *econtext;
@@ -5640,14 +5230,9 @@ 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
- * return the slot as-is if we decide no rows can be projected.)
+ * us to use the slot's Datum/isnull arrays as workspace.
*/
ExecClearTuple(slot);
@@ -5711,26 +5296,19 @@ 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);
}
/*
- * Successfully formed a result row. Mark the result slot as containing a
- * valid virtual tuple.
+ * Mark the result slot as containing a valid virtual tuple.
*/
return ExecStoreVirtualTuple(slot);
}
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index f97db9c2112..65196795d70 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,24 +144,8 @@ 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.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -214,15 +196,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 +328,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 70646fd15a7..e49feff6c0f 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -586,12 +586,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 dc64b3262a9..e4992134bd0 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -854,7 +854,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
/* compute input for all aggregates */
if (aggstate->evalproj)
- aggstate->evalslot = ExecProject(aggstate->evalproj, NULL);
+ aggstate->evalslot = ExecProject(aggstate->evalproj);
for (transno = 0; transno < numTrans; transno++)
{
@@ -871,7 +871,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
bool isnull;
res = ExecEvalExprSwitchContext(filter, aggstate->tmpcontext,
- &isnull, NULL);
+ &isnull);
if (isnull || !DatumGetBool(res))
continue;
}
@@ -970,7 +970,7 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
Assert(aggstate->phase->numsets == 0);
/* compute input for all aggregates */
- slot = ExecProject(aggstate->evalproj, NULL);
+ slot = ExecProject(aggstate->evalproj);
for (transno = 0; transno < numTrans; transno++)
{
@@ -1368,8 +1368,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++;
}
@@ -1630,7 +1629,7 @@ finalize_aggregates(AggState *aggstate,
/*
* Project the result of a group (whose aggs have already been calculated by
* finalize_aggregates). Returns the result slot, or NULL if no row is
- * projected (suppressed by qual or by an empty SRF).
+ * projected (suppressed by qual).
*/
static TupleTableSlot *
project_aggregates(AggState *aggstate)
@@ -1643,20 +1642,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);
@@ -1911,27 +1900,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.)
- */
if (!node->agg_done)
{
/* Dispatch based on strategy */
@@ -2571,8 +2539,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
*/
@@ -3575,8 +3541,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 d5fd57ae4ba..f18827de0bd 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 2f9c007409b..610797b36b6 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -269,8 +269,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 b01e65f3626..a27430242a5 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 8f21c17f240..86a77e356c0 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 1b593dcd71f..972022784d5 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 f95c3d1b19c..45aa1132d92 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -100,8 +100,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.
*/
@@ -132,8 +130,6 @@ ExecGather(GatherState *node)
TupleTableSlot *fslot = node->funnel_slot;
int i;
TupleTableSlot *slot;
- TupleTableSlot *resultSlot;
- ExprDoneCond isDone;
ExprContext *econtext;
/*
@@ -200,25 +196,10 @@ 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
- * returned by a TupleQueueReader; to make sure we don't leave a dangling
- * pointer around, clear the working slot first.
+ * storage allocated in the previous tuple cycle. This will also clear
+ * any previous tuple returned by a TupleQueueReader; to make sure we
+ * don't leave a dangling pointer around, clear the working slot first.
*/
ExecClearTuple(node->funnel_slot);
econtext = node->ps.ps_ExprContext;
@@ -241,13 +222,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 6a05023e50f..66c095bc723 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 11db08f5fa6..af5934d2bcf 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -959,7 +959,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 b41e4e2f98a..6e576ad0b38 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,25 +82,8 @@ 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.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -314,18 +296,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);
}
@@ -353,18 +324,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);
}
@@ -392,18 +352,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);
break;
@@ -586,7 +535,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 +948,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 ddef3a42bff..d5b19b7c115 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 97a6fac34d9..5734550d2c7 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 885931e5947..aaec1322189 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)
{
@@ -346,18 +344,11 @@ pass_down_bound(LimitState *node, PlanState *child_node)
else if (IsA(child_node, ResultState))
{
/*
- * An extra consideration here is that if the Result is projecting a
- * targetlist that contains any SRFs, we can't assume that every input
- * tuple generates an output tuple, so a Sort underneath might need to
- * return more than N tuples to satisfy LIMIT N. So we cannot use
- * bounded sort.
- *
* If Result supported qual checking, we'd have to punt on seeing a
- * qual, too. Note that having a resconstantqual is not a
- * showstopper: if that fails we're not getting any rows at all.
+ * qual. Note that having a resconstantqual is not a showstopper: if
+ * that fails we're not getting any rows at all.
*/
- if (outerPlanState(child_node) &&
- !expression_returns_set((Node *) child_node->plan->targetlist))
+ if (outerPlanState(child_node))
pass_down_bound(node, outerPlanState(child_node));
}
}
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 2fd18566037..105e2dcedbe 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,9 @@ 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 +496,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,26 +622,8 @@ 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.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -856,20 +818,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 +1580,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 +1634,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 982f15d490e..2ac74073186 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);
}
/*
@@ -1300,7 +1300,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 e05842768a3..cac7ba1b9bf 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -82,26 +82,8 @@ 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.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -201,19 +183,9 @@ 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 +231,9 @@ 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 +339,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 +402,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/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 391e97ea6fe..eae0f1dad93 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -169,7 +169,7 @@ ExecProjectSRF(ProjectSetState *node, bool continuing)
else
{
/* Non-SRF tlist expression, just evaluate normally. */
- *result = ExecEvalExpr(gstate->arg, econtext, isnull, NULL);
+ *result = ExecEvalExpr(gstate->arg, econtext, isnull);
*isdone = ExprSingleResult;
}
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index 59dacd33ef2..b5b50b21e9a 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,23 +90,8 @@ 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.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
@@ -147,18 +130,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 +201,6 @@ ExecInitResult(Result *node, EState *estate, int eflags)
*/
ExecAssignExprContext(estate, &resstate->ps);
- resstate->ps.ps_TupFromTlist = false;
-
/*
* tuple table initialization
*/
@@ -295,7 +266,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 8db5469d5a4..d38265e8104 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -189,8 +189,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.
*/
@@ -300,8 +298,7 @@ tablesample_init(SampleScanState *scanstate)
params[i] = ExecEvalExprSwitchContext(argstate,
econtext,
- &isnull,
- NULL);
+ &isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
@@ -313,8 +310,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 439a94694b6..e61895de0a8 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 68edcd4567b..f8a2cd446a2 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 */
+ /* Set non-null as default */
*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)
{
@@ -572,7 +566,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.
@@ -985,8 +979,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);
}
@@ -1222,8 +1215,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,
@@ -1231,8 +1223,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 a4387da80a2..230a96f9d2e 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 e3d3fc3842b..13ed886577a 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 5b42ca93cff..9883a8b1301 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 17884d2c44c..6ac6b83cddc 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++;
}
@@ -433,7 +433,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))
{
@@ -449,7 +449,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++;
}
@@ -1584,15 +1584,12 @@ update_frametailpos(WindowObject winobj, TupleTableSlot *slot)
* ExecWindowAgg receives tuples from its outer subplan and
* stores them into a tuplestore, then processes window functions.
* This node doesn't reduce nor qualify any row so the number of
- * returned rows is exactly the same as its outer subplan's result
- * (ignoring the case of SRFs in the targetlist, that is).
+ * returned rows is exactly the same as its outer subplan's result.
* -----------------
*/
TupleTableSlot *
ExecWindowAgg(WindowAggState *winstate)
{
- TupleTableSlot *result;
- ExprDoneCond isDone;
ExprContext *econtext;
int i;
int numfuncs;
@@ -1601,23 +1598,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)
@@ -1634,8 +1614,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),
@@ -1660,8 +1639,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),
@@ -1684,7 +1662,6 @@ ExecWindowAgg(WindowAggState *winstate)
winstate->all_first = false;
}
-restart:
if (winstate->buffer == NULL)
{
/* Initialize for first partition and set current row = 0 */
@@ -1776,17 +1753,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);
}
/* -----------------
@@ -1896,8 +1864,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,
@@ -2090,8 +2056,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 */
@@ -2712,7 +2676,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
}
econtext->ecxt_outertuple = slot;
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
- econtext, isnull, NULL);
+ econtext, isnull);
}
}
@@ -2811,7 +2775,7 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno,
}
econtext->ecxt_outertuple = slot;
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
- econtext, isnull, NULL);
+ econtext, isnull);
}
}
@@ -2841,5 +2805,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 73a1a8238aa..bdba9e0bfcd 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 85ffa3afc7c..d589dc2544b 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -4685,7 +4685,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 fd009e135e4..c4a04cfa953 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 14fa119f07c..c2ad4400136 100644
--- a/src/backend/utils/adt/domains.c
+++ b/src/backend/utils/adt/domains.c
@@ -179,7 +179,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 dcc5d6287ab..e8bce3b806d 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 eb180fdb631..74aa63536bd 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -70,8 +70,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() */
@@ -257,14 +257,13 @@ extern Datum ExecMakeFunctionResultSet(FuncExprState *fcache,
bool *isNull,
ExprDoneCond *isDone);
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 1da1e1f8043..f9bcdd63de0 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -156,7 +156,8 @@ typedef struct ExprContext
} ExprContext;
/*
- * Set-result status returned by ExecEvalExpr()
+ * Set-result status used when evaluating functions potentially returning a
+ * set.
*/
typedef enum
{
@@ -228,7 +229,6 @@ typedef struct ReturnSetInfo
* targetlist target list for projection (non-Var expressions only)
* exprContext expression context in which to evaluate targetlist
* slot slot to place projection result in
- * itemIsDone workspace array for ExecProject
* directMap true if varOutputCols[] is an identity map
* numSimpleVars number of simple Vars found in original tlist
* varSlotOffsets array indicating which slot each simple Var is from
@@ -245,7 +245,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;
@@ -586,8 +585,7 @@ typedef struct ExprState ExprState;
typedef Datum (*ExprStateEvalFunc) (ExprState *expression,
ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone);
+ bool *isNull);
struct ExprState
{
@@ -732,13 +730,6 @@ typedef struct FuncExprState
bool setArgsValid;
/*
- * Flag to remember whether we found a set-valued argument to the
- * function. This causes the function result to be a set as well. Valid
- * only when setArgsValid is true or funcResultStore isn't NULL.
- */
- bool setHasSetArg; /* some argument returns a set */
-
- /*
* Flag to remember whether we have registered a shutdown callback for
* this FuncExprState. We do so only if funcResultStore or setArgsValid
* has been set at least once (since all the callback is for is to release
@@ -1081,8 +1072,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 bc7b00199ef..b48146a362b 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -5606,8 +5606,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;
@@ -6272,7 +6271,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;