---------------------------------------------------------------- * ExecProjectSRF * * Project a targetlist containing one or more set-returning functions. * * 'continuing' indicates whether to continue projecting rows for the * same input tuple; or whether a new input tuple is being projected. * * Returns NULL if no output tuple has been produced. * * -------------------------------
| 129 | * ---------------------------------------------------------------- |
| 130 | */ |
| 131 | static TupleTableSlot * |
| 132 | ExecProjectSRF(ProjectSetState *node, bool continuing) |
| 133 | { |
| 134 | TupleTableSlot *resultSlot = node->ps.ps_ResultTupleSlot; |
| 135 | ExprContext *econtext = node->ps.ps_ExprContext; |
| 136 | MemoryContext oldcontext; |
| 137 | bool hassrf PG_USED_FOR_ASSERTS_ONLY; |
| 138 | bool hasresult; |
| 139 | int argno; |
| 140 | |
| 141 | ExecClearTuple(resultSlot); |
| 142 | |
| 143 | /* Call SRFs, as well as plain expressions, in per-tuple context */ |
| 144 | oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); |
| 145 | |
| 146 | /* |
| 147 | * Assume no further tuples are produced unless an ExprMultipleResult is |
| 148 | * encountered from a set returning function. |
| 149 | */ |
| 150 | node->pending_srf_tuples = false; |
| 151 | |
| 152 | hassrf = hasresult = false; |
| 153 | for (argno = 0; argno < node->nelems; argno++) |
| 154 | { |
| 155 | Node *elem = node->elems[argno]; |
| 156 | ExprDoneCond *isdone = &node->elemdone[argno]; |
| 157 | Datum *result = &resultSlot->tts_values[argno]; |
| 158 | bool *isnull = &resultSlot->tts_isnull[argno]; |
| 159 | |
| 160 | if (continuing && *isdone == ExprEndResult) |
| 161 | { |
| 162 | /* |
| 163 | * If we're continuing to project output rows from a source tuple, |
| 164 | * return NULLs once the SRF has been exhausted. |
| 165 | */ |
| 166 | *result = (Datum) 0; |
| 167 | *isnull = true; |
| 168 | hassrf = true; |
| 169 | } |
| 170 | else if (IsA(elem, SetExprState)) |
| 171 | { |
| 172 | /* |
| 173 | * Evaluate SRF - possibly continuing previously started output. |
| 174 | */ |
| 175 | *result = ExecMakeFunctionResultSet((SetExprState *) elem, |
| 176 | econtext, node->argcontext, |
| 177 | isnull, isdone); |
| 178 | |
| 179 | if (*isdone != ExprEndResult) |
| 180 | hasresult = true; |
| 181 | if (*isdone == ExprMultipleResult) |
| 182 | node->pending_srf_tuples = true; |
| 183 | hassrf = true; |
| 184 | } |
| 185 | else |
| 186 | { |
| 187 | /* Non-SRF tlist expression, just evaluate normally. */ |
| 188 | *result = ExecEvalExpr((ExprState *) elem, econtext, isnull); |
no test coverage detected