diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 64f857ff53..ce1f443d55 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -3444,7 +3444,7 @@ process_query_params(ExprContext *econtext, bool isNull; /* Evaluate the parameter expression */ - expr_value = ExecEvalExpr(expr_state, econtext, &isNull, NULL); + expr_value = ExecEvalExpr(expr_state, econtext, &isNull); /* * Get string representation of each parameter value by invoking diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index cac0cbf7d4..26cbc0e06a 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 45f7132f54..3f8a950f37 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 75386212e0..c05e14e26f 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 1ff41661a5..7d7e3daf1e 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 18cac9ad2d..6ed2a3dc4d 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 3ff6cbca56..4c33d55484 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 b52cfaa41f..1ca4bcb117 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: @@ -529,18 +519,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 eed7e95c75..19dd0b264b 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) + + /* 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; + + /* + * If function is strict, and there are any NULL arguments, skip calling + * the function. + */ + callit = true; + if (fcache->func.fn_strict) { - /* - * We need to return a set result. Complain if caller not ready to - * accept one. - */ - if (isDone == NULL) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("set-valued function called in context that cannot accept a set"))); - - /* - * Prepare a resultinfo node for communication. If the function - * doesn't itself return set, we don't pass the resultinfo to the - * function, but we need to fill it in anyway for internal use. - */ - if (fcache->func.fn_retset) - fcinfo->resultinfo = (Node *) &rsinfo; - rsinfo.type = T_ReturnSetInfo; - rsinfo.econtext = econtext; - rsinfo.expectedDesc = fcache->funcResultDesc; - rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize); - /* note we do not set SFRM_Materialize_Random or _Preferred */ - rsinfo.returnMode = SFRM_ValuePerCall; - /* isDone is filled below */ - rsinfo.setResult = NULL; - rsinfo.setDesc = NULL; - - /* - * This loop handles the situation where we have both a set argument - * and a set-valued function. Once we have exhausted the function's - * value(s) for a particular argument value, we have to get the next - * argument value and start the function over again. We might have to - * do it more than once, if the function produces an empty result set - * for a particular input value. - */ - for (;;) + 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) + if (fcinfo->argnull[i]) { - for (i = 0; i < fcinfo->nargs; i++) - { - if (fcinfo->argnull[i]) - { - callit = false; - break; - } - } - } - - if (callit) - { - pgstat_init_function_usage(fcinfo, &fcusage); - - fcinfo->isnull = false; - rsinfo.isDone = ExprSingleResult; - result = FunctionCallInvoke(fcinfo); - *isNull = fcinfo->isnull; - *isDone = rsinfo.isDone; - - pgstat_end_function_usage(&fcusage, - rsinfo.isDone != ExprMultipleResult); - } - else if (fcache->func.fn_retset) - { - /* for a strict SRF, result for NULL is an empty set */ - result = (Datum) 0; - *isNull = true; - *isDone = ExprEndResult; - } - else - { - /* for a strict non-SRF, result for NULL is a NULL */ - result = (Datum) 0; - *isNull = true; - *isDone = ExprSingleResult; - } - - /* Which protocol does function want to use? */ - if (rsinfo.returnMode == SFRM_ValuePerCall) - { - if (*isDone != ExprEndResult) - { - /* - * Got a result from current argument. If function itself - * returns set, save the current argument values to re-use - * on the next call. - */ - if (fcache->func.fn_retset && - *isDone == ExprMultipleResult) - { - fcache->setHasSetArg = hasSetArg; - fcache->setArgsValid = true; - /* Register cleanup callback if we didn't already */ - if (!fcache->shutdown_reg) - { - RegisterExprContextCallback(econtext, - ShutdownFuncExpr, - PointerGetDatum(fcache)); - fcache->shutdown_reg = true; - } - } - - /* - * Make sure we say we are returning a set, even if the - * function itself doesn't return sets. - */ - if (hasSetArg) - *isDone = ExprMultipleResult; - break; - } - } - else if (rsinfo.returnMode == SFRM_Materialize) - { - /* check we're on the same page as the function author */ - if (rsinfo.isDone != ExprSingleResult) - ereport(ERROR, - (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED), - errmsg("table-function protocol for materialize mode was not followed"))); - if (rsinfo.setResult != NULL) - { - /* prepare to return values from the tuplestore */ - ExecPrepareTuplestoreResult(fcache, econtext, - rsinfo.setResult, - rsinfo.setDesc); - /* remember whether we had set arguments */ - fcache->setHasSetArg = hasSetArg; - /* loop back to top to start returning from tuplestore */ - goto restart; - } - /* if setResult was left null, treat it as empty set */ - *isDone = ExprEndResult; - *isNull = true; - result = (Datum) 0; - } - else - ereport(ERROR, - (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED), - errmsg("unrecognized table-function returnMode: %d", - (int) rsinfo.returnMode))); - - /* Else, done with this argument */ - if (!hasSetArg) - break; /* input not a set, so done */ - - /* Re-eval args to get the next element of the input set */ - argDone = ExecEvalFuncArgs(fcinfo, arguments, econtext); - - if (argDone != ExprMultipleResult) - { - /* End of argument set, so we're done. */ - *isNull = true; - *isDone = ExprEndResult; - result = (Datum) 0; + callit = false; break; } - - /* - * If we reach here, loop around to run the function on the new - * argument. - */ } } - else + + if (callit) { - /* - * Non-set case: much easier. - * - * In common cases, this code path is unreachable because we'd have - * selected ExecMakeFunctionResultNoSets instead. However, it's - * possible to get here if an argument sometimes produces set results - * and sometimes scalar results. For example, a CASE expression might - * call a set-returning function in only some of its arms. - */ - if (isDone) - *isDone = ExprSingleResult; - - /* - * If function is strict, and there are any NULL arguments, skip - * calling the function and return NULL. - */ - if (fcache->func.fn_strict) - { - for (i = 0; i < fcinfo->nargs; i++) - { - if (fcinfo->argnull[i]) - { - *isNull = true; - return (Datum) 0; - } - } - } - pgstat_init_function_usage(fcinfo, &fcusage); fcinfo->isnull = false; + rsinfo.isDone = ExprSingleResult; result = FunctionCallInvoke(fcinfo); *isNull = fcinfo->isnull; + *isDone = rsinfo.isDone; - pgstat_end_function_usage(&fcusage, true); + pgstat_end_function_usage(&fcusage, + rsinfo.isDone != ExprMultipleResult); } + else + { + /* for a strict SRF, result for NULL is an empty set */ + result = (Datum) 0; + *isNull = true; + *isDone = ExprEndResult; + } + + /* Which protocol does function want to use? */ + if (rsinfo.returnMode == SFRM_ValuePerCall) + { + if (*isDone != ExprEndResult) + { + /* + * Save the current argument values to re-use on the next call. + */ + if (*isDone == ExprMultipleResult) + { + fcache->setArgsValid = true; + /* Register cleanup callback if we didn't already */ + if (!fcache->shutdown_reg) + { + RegisterExprContextCallback(econtext, + ShutdownFuncExpr, + PointerGetDatum(fcache)); + fcache->shutdown_reg = 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", @@ -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. + * + * tupdesc must describe the rowtype of the expected result. * * Results are stored into the passed values and isnull arrays. - * The caller must provide an itemIsDone array that persists across calls. - * - * As with ExecEvalExpr, the caller should pass isDone = NULL if not - * prepared to deal with sets of result tuples. Otherwise, a return - * of *isDone = ExprMultipleResult signifies a set element, and a return - * of *isDone = ExprEndResult signifies end of the set of tuple. - * We assume that *isDone has been initialized to ExprSingleResult by caller. * * Since fields of the result tuple might be multiply referenced in higher * plan nodes, we have to force any read/write expanded values to read-only @@ -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 f97db9c211..65196795d7 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 @@ -145,25 +143,9 @@ ExecScan(ScanState *node, return ExecScanFetch(node, accessMtd, recheckMtd); } - /* - * 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 70646fd15a..e49feff6c0 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 dc64b3262a..e4992134bd 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 d5fd57ae4b..f18827de0b 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 2f9c007409..610797b36b 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 b01e65f362..a27430242a 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 8f21c17f24..86a77e356c 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 1b593dcd71..972022784d 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 f95c3d1b19..45aa1132d9 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; /* @@ -199,26 +195,11 @@ ExecGather(GatherState *node) node->initialized = true; } - /* - * 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 6a05023e50..66c095bc72 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -49,23 +49,6 @@ ExecGroup(GroupState *node) numCols = ((Group *) node->ss.ps.plan)->numCols; 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. */ @@ -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 11db08f5fa..af5934d2bc 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 b41e4e2f98..6e576ad0b3 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; @@ -82,26 +81,9 @@ ExecHashJoin(HashJoinState *node) hashtable = node->hj_HashTable; 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 ddef3a42bf..d5b19b7c11 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 97a6fac34d..5734550d2c 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 885931e594..aaec132218 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 2fd1856603..105e2dcedb 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); @@ -641,27 +621,9 @@ ExecMergeJoin(MergeJoinState *node) doFillOuter = node->mj_FillOuter; 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 982f15d490..2ac7407318 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 e05842768a..cac7ba1b9b 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -81,27 +81,9 @@ ExecNestLoop(NestLoopState *node) innerPlan = innerPlanState(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 391e97ea6f..eae0f1dad9 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 59dacd33ef..b5b50b21e9 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; @@ -91,24 +89,9 @@ 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 8db5469d5a..d38265e810 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 439a94694b..e61895de0a 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 68edcd4567..f8a2cd446a 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 a4387da80a..230a96f9d2 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 e3d3fc3842..13ed886577 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 5b42ca93cf..9883a8b130 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 17884d2c44..6ac6b83cdd 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; @@ -1600,23 +1597,6 @@ ExecWindowAgg(WindowAggState *winstate) if (winstate->all_done) 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. */ @@ -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 73a1a8238a..bdba9e0bfc 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 85ffa3afc7..d589dc2544 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 fd009e135e..c4a04cfa95 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 14fa119f07..c2ad440013 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 dcc5d6287a..e8bce3b806 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 eb180fdb63..74aa63536b 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 1da1e1f804..f9bcdd63de 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 { @@ -731,13 +729,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 @@ -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 bc7b00199e..b48146a362 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;