1 /*-------------------------------------------------------------------------
2 *
3 * execSRF.c
4 * Routines implementing the API for set-returning functions
5 *
6 * This file serves nodeFunctionscan.c and nodeProjectSet.c, providing
7 * common code for calling set-returning functions according to the
8 * ReturnSetInfo API.
9 *
10 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
11 * Portions Copyright (c) 1994, Regents of the University of California
12 *
13 *
14 * IDENTIFICATION
15 * src/backend/executor/execSRF.c
16 *
17 *-------------------------------------------------------------------------
18 */
19 #include "postgres.h"
20
21 #include "access/htup_details.h"
22 #include "catalog/objectaccess.h"
23 #include "executor/execdebug.h"
24 #include "funcapi.h"
25 #include "miscadmin.h"
26 #include "nodes/nodeFuncs.h"
27 #include "parser/parse_coerce.h"
28 #include "pgstat.h"
29 #include "utils/acl.h"
30 #include "utils/builtins.h"
31 #include "utils/lsyscache.h"
32 #include "utils/memutils.h"
33 #include "utils/typcache.h"
34
35
36 /* static function decls */
37 static void init_sexpr(Oid foid, Oid input_collation, Expr *node,
38 SetExprState *sexpr, PlanState *parent,
39 MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF);
40 static void ShutdownSetExpr(Datum arg);
41 static void ExecEvalFuncArgs(FunctionCallInfo fcinfo,
42 List *argList, ExprContext *econtext);
43 static void ExecPrepareTuplestoreResult(SetExprState *sexpr,
44 ExprContext *econtext,
45 Tuplestorestate *resultStore,
46 TupleDesc resultDesc);
47 static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc);
48
49
50 /*
51 * Prepare function call in FROM (ROWS FROM) for execution.
52 *
53 * This is used by nodeFunctionscan.c.
54 */
55 SetExprState *
ExecInitTableFunctionResult(Expr * expr,ExprContext * econtext,PlanState * parent)56 ExecInitTableFunctionResult(Expr *expr,
57 ExprContext *econtext, PlanState *parent)
58 {
59 SetExprState *state = makeNode(SetExprState);
60
61 state->funcReturnsSet = false;
62 state->expr = expr;
63 state->func.fn_oid = InvalidOid;
64
65 /*
66 * Normally the passed expression tree will be a FuncExpr, since the
67 * grammar only allows a function call at the top level of a table
68 * function reference. However, if the function doesn't return set then
69 * the planner might have replaced the function call via constant-folding
70 * or inlining. So if we see any other kind of expression node, execute
71 * it via the general ExecEvalExpr() code. That code path will not
72 * support set-returning functions buried in the expression, though.
73 */
74 if (IsA(expr, FuncExpr))
75 {
76 FuncExpr *func = (FuncExpr *) expr;
77
78 state->funcReturnsSet = func->funcretset;
79 state->args = ExecInitExprList(func->args, parent);
80
81 init_sexpr(func->funcid, func->inputcollid, expr, state, parent,
82 econtext->ecxt_per_query_memory, func->funcretset, false);
83 }
84 else
85 {
86 state->elidedFuncState = ExecInitExpr(expr, parent);
87 }
88
89 return state;
90 }
91
92 /*
93 * ExecMakeTableFunctionResult
94 *
95 * Evaluate a table function, producing a materialized result in a Tuplestore
96 * object.
97 *
98 * This is used by nodeFunctionscan.c.
99 */
100 Tuplestorestate *
ExecMakeTableFunctionResult(SetExprState * setexpr,ExprContext * econtext,MemoryContext argContext,TupleDesc expectedDesc,bool randomAccess)101 ExecMakeTableFunctionResult(SetExprState *setexpr,
102 ExprContext *econtext,
103 MemoryContext argContext,
104 TupleDesc expectedDesc,
105 bool randomAccess)
106 {
107 Tuplestorestate *tupstore = NULL;
108 TupleDesc tupdesc = NULL;
109 Oid funcrettype;
110 bool returnsTuple;
111 bool returnsSet = false;
112 FunctionCallInfoData fcinfo;
113 PgStat_FunctionCallUsage fcusage;
114 ReturnSetInfo rsinfo;
115 HeapTupleData tmptup;
116 MemoryContext callerContext;
117 MemoryContext oldcontext;
118 bool first_time = true;
119
120 callerContext = CurrentMemoryContext;
121
122 funcrettype = exprType((Node *) setexpr->expr);
123
124 returnsTuple = type_is_rowtype(funcrettype);
125
126 /*
127 * Prepare a resultinfo node for communication. We always do this even if
128 * not expecting a set result, so that we can pass expectedDesc. In the
129 * generic-expression case, the expression doesn't actually get to see the
130 * resultinfo, but set it up anyway because we use some of the fields as
131 * our own state variables.
132 */
133 rsinfo.type = T_ReturnSetInfo;
134 rsinfo.econtext = econtext;
135 rsinfo.expectedDesc = expectedDesc;
136 rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize | SFRM_Materialize_Preferred);
137 if (randomAccess)
138 rsinfo.allowedModes |= (int) SFRM_Materialize_Random;
139 rsinfo.returnMode = SFRM_ValuePerCall;
140 /* isDone is filled below */
141 rsinfo.setResult = NULL;
142 rsinfo.setDesc = NULL;
143
144 /*
145 * Normally the passed expression tree will be a SetExprState, since the
146 * grammar only allows a function call at the top level of a table
147 * function reference. However, if the function doesn't return set then
148 * the planner might have replaced the function call via constant-folding
149 * or inlining. So if we see any other kind of expression node, execute
150 * it via the general ExecEvalExpr() code; the only difference is that we
151 * don't get a chance to pass a special ReturnSetInfo to any functions
152 * buried in the expression.
153 */
154 if (!setexpr->elidedFuncState)
155 {
156 /*
157 * This path is similar to ExecMakeFunctionResultSet.
158 */
159 returnsSet = setexpr->funcReturnsSet;
160 InitFunctionCallInfoData(fcinfo, &(setexpr->func),
161 list_length(setexpr->args),
162 setexpr->fcinfo_data.fncollation,
163 NULL, (Node *) &rsinfo);
164
165 /*
166 * Evaluate the function's argument list.
167 *
168 * We can't do this in the per-tuple context: the argument values
169 * would disappear when we reset that context in the inner loop. And
170 * the caller's CurrentMemoryContext is typically a query-lifespan
171 * context, so we don't want to leak memory there. We require the
172 * caller to pass a separate memory context that can be used for this,
173 * and can be reset each time through to avoid bloat.
174 */
175 MemoryContextReset(argContext);
176 oldcontext = MemoryContextSwitchTo(argContext);
177 ExecEvalFuncArgs(&fcinfo, setexpr->args, econtext);
178 MemoryContextSwitchTo(oldcontext);
179
180 /*
181 * If function is strict, and there are any NULL arguments, skip
182 * calling the function and act like it returned NULL (or an empty
183 * set, in the returns-set case).
184 */
185 if (setexpr->func.fn_strict)
186 {
187 int i;
188
189 for (i = 0; i < fcinfo.nargs; i++)
190 {
191 if (fcinfo.argnull[i])
192 goto no_function_result;
193 }
194 }
195 }
196 else
197 {
198 /* Treat setexpr as a generic expression */
199 InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
200 }
201
202 /*
203 * Switch to short-lived context for calling the function or expression.
204 */
205 MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
206
207 /*
208 * Loop to handle the ValuePerCall protocol (which is also the same
209 * behavior needed in the generic ExecEvalExpr path).
210 */
211 for (;;)
212 {
213 Datum result;
214
215 CHECK_FOR_INTERRUPTS();
216
217 /*
218 * reset per-tuple memory context before each call of the function or
219 * expression. This cleans up any local memory the function may leak
220 * when called.
221 */
222 ResetExprContext(econtext);
223
224 /* Call the function or expression one time */
225 if (!setexpr->elidedFuncState)
226 {
227 pgstat_init_function_usage(&fcinfo, &fcusage);
228
229 fcinfo.isnull = false;
230 rsinfo.isDone = ExprSingleResult;
231 result = FunctionCallInvoke(&fcinfo);
232
233 pgstat_end_function_usage(&fcusage,
234 rsinfo.isDone != ExprMultipleResult);
235 }
236 else
237 {
238 result =
239 ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo.isnull);
240 rsinfo.isDone = ExprSingleResult;
241 }
242
243 /* Which protocol does function want to use? */
244 if (rsinfo.returnMode == SFRM_ValuePerCall)
245 {
246 /*
247 * Check for end of result set.
248 */
249 if (rsinfo.isDone == ExprEndResult)
250 break;
251
252 /*
253 * If first time through, build tuplestore for result. For a
254 * scalar function result type, also make a suitable tupdesc.
255 */
256 if (first_time)
257 {
258 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
259 tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
260 rsinfo.setResult = tupstore;
261 if (!returnsTuple)
262 {
263 tupdesc = CreateTemplateTupleDesc(1, false);
264 TupleDescInitEntry(tupdesc,
265 (AttrNumber) 1,
266 "column",
267 funcrettype,
268 -1,
269 0);
270 rsinfo.setDesc = tupdesc;
271 }
272 MemoryContextSwitchTo(oldcontext);
273 }
274
275 /*
276 * Store current resultset item.
277 */
278 if (returnsTuple)
279 {
280 if (!fcinfo.isnull)
281 {
282 HeapTupleHeader td = DatumGetHeapTupleHeader(result);
283
284 if (tupdesc == NULL)
285 {
286 /*
287 * This is the first non-NULL result from the
288 * function. Use the type info embedded in the
289 * rowtype Datum to look up the needed tupdesc. Make
290 * a copy for the query.
291 */
292 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
293 tupdesc = lookup_rowtype_tupdesc_copy(HeapTupleHeaderGetTypeId(td),
294 HeapTupleHeaderGetTypMod(td));
295 rsinfo.setDesc = tupdesc;
296 MemoryContextSwitchTo(oldcontext);
297 }
298 else
299 {
300 /*
301 * Verify all later returned rows have same subtype;
302 * necessary in case the type is RECORD.
303 */
304 if (HeapTupleHeaderGetTypeId(td) != tupdesc->tdtypeid ||
305 HeapTupleHeaderGetTypMod(td) != tupdesc->tdtypmod)
306 ereport(ERROR,
307 (errcode(ERRCODE_DATATYPE_MISMATCH),
308 errmsg("rows returned by function are not all of the same row type")));
309 }
310
311 /*
312 * tuplestore_puttuple needs a HeapTuple not a bare
313 * HeapTupleHeader, but it doesn't need all the fields.
314 */
315 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
316 tmptup.t_data = td;
317
318 tuplestore_puttuple(tupstore, &tmptup);
319 }
320 else
321 {
322 /*
323 * NULL result from a tuple-returning function; expand it
324 * to a row of all nulls. We rely on the expectedDesc to
325 * form such rows. (Note: this would be problematic if
326 * tuplestore_putvalues saved the tdtypeid/tdtypmod from
327 * the provided descriptor, since that might not match
328 * what we get from the function itself. But it doesn't.)
329 */
330 int natts = expectedDesc->natts;
331 bool *nullflags;
332
333 nullflags = (bool *) palloc(natts * sizeof(bool));
334 memset(nullflags, true, natts * sizeof(bool));
335 tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
336 }
337 }
338 else
339 {
340 /* Scalar-type case: just store the function result */
341 tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
342 }
343
344 /*
345 * Are we done?
346 */
347 if (rsinfo.isDone != ExprMultipleResult)
348 break;
349 }
350 else if (rsinfo.returnMode == SFRM_Materialize)
351 {
352 /* check we're on the same page as the function author */
353 if (!first_time || rsinfo.isDone != ExprSingleResult)
354 ereport(ERROR,
355 (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
356 errmsg("table-function protocol for materialize mode was not followed")));
357 /* Done evaluating the set result */
358 break;
359 }
360 else
361 ereport(ERROR,
362 (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
363 errmsg("unrecognized table-function returnMode: %d",
364 (int) rsinfo.returnMode)));
365
366 first_time = false;
367 }
368
369 no_function_result:
370
371 /*
372 * If we got nothing from the function (ie, an empty-set or NULL result),
373 * we have to create the tuplestore to return, and if it's a
374 * non-set-returning function then insert a single all-nulls row. As
375 * above, we depend on the expectedDesc to manufacture the dummy row.
376 */
377 if (rsinfo.setResult == NULL)
378 {
379 MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
380 tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
381 rsinfo.setResult = tupstore;
382 if (!returnsSet)
383 {
384 int natts = expectedDesc->natts;
385 bool *nullflags;
386
387 MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
388 nullflags = (bool *) palloc(natts * sizeof(bool));
389 memset(nullflags, true, natts * sizeof(bool));
390 tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
391 }
392 }
393
394 /*
395 * If function provided a tupdesc, cross-check it. We only really need to
396 * do this for functions returning RECORD, but might as well do it always.
397 */
398 if (rsinfo.setDesc)
399 {
400 tupledesc_match(expectedDesc, rsinfo.setDesc);
401
402 /*
403 * If it is a dynamically-allocated TupleDesc, free it: it is
404 * typically allocated in a per-query context, so we must avoid
405 * leaking it across multiple usages.
406 */
407 if (rsinfo.setDesc->tdrefcount == -1)
408 FreeTupleDesc(rsinfo.setDesc);
409 }
410
411 MemoryContextSwitchTo(callerContext);
412
413 /* All done, pass back the tuplestore */
414 return rsinfo.setResult;
415 }
416
417
418 /*
419 * Prepare targetlist SRF function call for execution.
420 *
421 * This is used by nodeProjectSet.c.
422 */
423 SetExprState *
ExecInitFunctionResultSet(Expr * expr,ExprContext * econtext,PlanState * parent)424 ExecInitFunctionResultSet(Expr *expr,
425 ExprContext *econtext, PlanState *parent)
426 {
427 SetExprState *state = makeNode(SetExprState);
428
429 state->funcReturnsSet = true;
430 state->expr = expr;
431 state->func.fn_oid = InvalidOid;
432
433 /*
434 * Initialize metadata. The expression node could be either a FuncExpr or
435 * an OpExpr.
436 */
437 if (IsA(expr, FuncExpr))
438 {
439 FuncExpr *func = (FuncExpr *) expr;
440
441 state->args = ExecInitExprList(func->args, parent);
442 init_sexpr(func->funcid, func->inputcollid, expr, state, parent,
443 econtext->ecxt_per_query_memory, true, true);
444 }
445 else if (IsA(expr, OpExpr))
446 {
447 OpExpr *op = (OpExpr *) expr;
448
449 state->args = ExecInitExprList(op->args, parent);
450 init_sexpr(op->opfuncid, op->inputcollid, expr, state, parent,
451 econtext->ecxt_per_query_memory, true, true);
452 }
453 else
454 elog(ERROR, "unrecognized node type: %d",
455 (int) nodeTag(expr));
456
457 /* shouldn't get here unless the selected function returns set */
458 Assert(state->func.fn_retset);
459
460 return state;
461 }
462
463 /*
464 * ExecMakeFunctionResultSet
465 *
466 * Evaluate the arguments to a set-returning function and then call the
467 * function itself. The argument expressions may not contain set-returning
468 * functions (the planner is supposed to have separated evaluation for those).
469 *
470 * This should be called in a short-lived (per-tuple) context, argContext
471 * needs to live until all rows have been returned (i.e. *isDone set to
472 * ExprEndResult or ExprSingleResult).
473 *
474 * This is used by nodeProjectSet.c.
475 */
476 Datum
ExecMakeFunctionResultSet(SetExprState * fcache,ExprContext * econtext,MemoryContext argContext,bool * isNull,ExprDoneCond * isDone)477 ExecMakeFunctionResultSet(SetExprState *fcache,
478 ExprContext *econtext,
479 MemoryContext argContext,
480 bool *isNull,
481 ExprDoneCond *isDone)
482 {
483 List *arguments;
484 Datum result;
485 FunctionCallInfo fcinfo;
486 PgStat_FunctionCallUsage fcusage;
487 ReturnSetInfo rsinfo;
488 bool callit;
489 int i;
490
491 restart:
492
493 /* Guard against stack overflow due to overly complex expressions */
494 check_stack_depth();
495
496 /*
497 * If a previous call of the function returned a set result in the form of
498 * a tuplestore, continue reading rows from the tuplestore until it's
499 * empty.
500 */
501 if (fcache->funcResultStore)
502 {
503 TupleTableSlot *slot = fcache->funcResultSlot;
504 MemoryContext oldContext;
505 bool foundTup;
506
507 /*
508 * Have to make sure tuple in slot lives long enough, otherwise
509 * clearing the slot could end up trying to free something already
510 * freed.
511 */
512 oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
513 foundTup = tuplestore_gettupleslot(fcache->funcResultStore, true, false,
514 fcache->funcResultSlot);
515 MemoryContextSwitchTo(oldContext);
516
517 if (foundTup)
518 {
519 *isDone = ExprMultipleResult;
520 if (fcache->funcReturnsTuple)
521 {
522 /* We must return the whole tuple as a Datum. */
523 *isNull = false;
524 return ExecFetchSlotTupleDatum(fcache->funcResultSlot);
525 }
526 else
527 {
528 /* Extract the first column and return it as a scalar. */
529 return slot_getattr(fcache->funcResultSlot, 1, isNull);
530 }
531 }
532 /* Exhausted the tuplestore, so clean up */
533 tuplestore_end(fcache->funcResultStore);
534 fcache->funcResultStore = NULL;
535 *isDone = ExprEndResult;
536 *isNull = true;
537 return (Datum) 0;
538 }
539
540 /*
541 * arguments is a list of expressions to evaluate before passing to the
542 * function manager. We skip the evaluation if it was already done in the
543 * previous call (ie, we are continuing the evaluation of a set-valued
544 * function). Otherwise, collect the current argument values into fcinfo.
545 *
546 * The arguments have to live in a context that lives at least until all
547 * rows from this SRF have been returned, otherwise ValuePerCall SRFs
548 * would reference freed memory after the first returned row.
549 */
550 fcinfo = &fcache->fcinfo_data;
551 arguments = fcache->args;
552 if (!fcache->setArgsValid)
553 {
554 MemoryContext oldContext = MemoryContextSwitchTo(argContext);
555
556 ExecEvalFuncArgs(fcinfo, arguments, econtext);
557 MemoryContextSwitchTo(oldContext);
558 }
559 else
560 {
561 /* Reset flag (we may set it again below) */
562 fcache->setArgsValid = false;
563 }
564
565 /*
566 * Now call the function, passing the evaluated parameter values.
567 */
568
569 /* Prepare a resultinfo node for communication. */
570 fcinfo->resultinfo = (Node *) &rsinfo;
571 rsinfo.type = T_ReturnSetInfo;
572 rsinfo.econtext = econtext;
573 rsinfo.expectedDesc = fcache->funcResultDesc;
574 rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
575 /* note we do not set SFRM_Materialize_Random or _Preferred */
576 rsinfo.returnMode = SFRM_ValuePerCall;
577 /* isDone is filled below */
578 rsinfo.setResult = NULL;
579 rsinfo.setDesc = NULL;
580
581 /*
582 * If function is strict, and there are any NULL arguments, skip calling
583 * the function.
584 */
585 callit = true;
586 if (fcache->func.fn_strict)
587 {
588 for (i = 0; i < fcinfo->nargs; i++)
589 {
590 if (fcinfo->argnull[i])
591 {
592 callit = false;
593 break;
594 }
595 }
596 }
597
598 if (callit)
599 {
600 pgstat_init_function_usage(fcinfo, &fcusage);
601
602 fcinfo->isnull = false;
603 rsinfo.isDone = ExprSingleResult;
604 result = FunctionCallInvoke(fcinfo);
605 *isNull = fcinfo->isnull;
606 *isDone = rsinfo.isDone;
607
608 pgstat_end_function_usage(&fcusage,
609 rsinfo.isDone != ExprMultipleResult);
610 }
611 else
612 {
613 /* for a strict SRF, result for NULL is an empty set */
614 result = (Datum) 0;
615 *isNull = true;
616 *isDone = ExprEndResult;
617 }
618
619 /* Which protocol does function want to use? */
620 if (rsinfo.returnMode == SFRM_ValuePerCall)
621 {
622 if (*isDone != ExprEndResult)
623 {
624 /*
625 * Save the current argument values to re-use on the next call.
626 */
627 if (*isDone == ExprMultipleResult)
628 {
629 fcache->setArgsValid = true;
630 /* Register cleanup callback if we didn't already */
631 if (!fcache->shutdown_reg)
632 {
633 RegisterExprContextCallback(econtext,
634 ShutdownSetExpr,
635 PointerGetDatum(fcache));
636 fcache->shutdown_reg = true;
637 }
638 }
639 }
640 }
641 else if (rsinfo.returnMode == SFRM_Materialize)
642 {
643 /* check we're on the same page as the function author */
644 if (rsinfo.isDone != ExprSingleResult)
645 ereport(ERROR,
646 (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
647 errmsg("table-function protocol for materialize mode was not followed")));
648 if (rsinfo.setResult != NULL)
649 {
650 /* prepare to return values from the tuplestore */
651 ExecPrepareTuplestoreResult(fcache, econtext,
652 rsinfo.setResult,
653 rsinfo.setDesc);
654 /* loop back to top to start returning from tuplestore */
655 goto restart;
656 }
657 /* if setResult was left null, treat it as empty set */
658 *isDone = ExprEndResult;
659 *isNull = true;
660 result = (Datum) 0;
661 }
662 else
663 ereport(ERROR,
664 (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
665 errmsg("unrecognized table-function returnMode: %d",
666 (int) rsinfo.returnMode)));
667
668 return result;
669 }
670
671
672 /*
673 * init_sexpr - initialize a SetExprState node during first use
674 */
675 static void
init_sexpr(Oid foid,Oid input_collation,Expr * node,SetExprState * sexpr,PlanState * parent,MemoryContext sexprCxt,bool allowSRF,bool needDescForSRF)676 init_sexpr(Oid foid, Oid input_collation, Expr *node,
677 SetExprState *sexpr, PlanState *parent,
678 MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF)
679 {
680 AclResult aclresult;
681
682 /* Check permission to call function */
683 aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
684 if (aclresult != ACLCHECK_OK)
685 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
686 InvokeFunctionExecuteHook(foid);
687
688 /*
689 * Safety check on nargs. Under normal circumstances this should never
690 * fail, as parser should check sooner. But possibly it might fail if
691 * server has been compiled with FUNC_MAX_ARGS smaller than some functions
692 * declared in pg_proc?
693 */
694 if (list_length(sexpr->args) > FUNC_MAX_ARGS)
695 ereport(ERROR,
696 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
697 errmsg_plural("cannot pass more than %d argument to a function",
698 "cannot pass more than %d arguments to a function",
699 FUNC_MAX_ARGS,
700 FUNC_MAX_ARGS)));
701
702 /* Set up the primary fmgr lookup information */
703 fmgr_info_cxt(foid, &(sexpr->func), sexprCxt);
704 fmgr_info_set_expr((Node *) sexpr->expr, &(sexpr->func));
705
706 /* Initialize the function call parameter struct as well */
707 InitFunctionCallInfoData(sexpr->fcinfo_data, &(sexpr->func),
708 list_length(sexpr->args),
709 input_collation, NULL, NULL);
710
711 /* If function returns set, check if that's allowed by caller */
712 if (sexpr->func.fn_retset && !allowSRF)
713 ereport(ERROR,
714 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
715 errmsg("set-valued function called in context that cannot accept a set"),
716 parent ? executor_errposition(parent->state,
717 exprLocation((Node *) node)) : 0));
718
719 /* Otherwise, caller should have marked the sexpr correctly */
720 Assert(sexpr->func.fn_retset == sexpr->funcReturnsSet);
721
722 /* If function returns set, prepare expected tuple descriptor */
723 if (sexpr->func.fn_retset && needDescForSRF)
724 {
725 TypeFuncClass functypclass;
726 Oid funcrettype;
727 TupleDesc tupdesc;
728 MemoryContext oldcontext;
729
730 functypclass = get_expr_result_type(sexpr->func.fn_expr,
731 &funcrettype,
732 &tupdesc);
733
734 /* Must save tupdesc in sexpr's context */
735 oldcontext = MemoryContextSwitchTo(sexprCxt);
736
737 if (functypclass == TYPEFUNC_COMPOSITE ||
738 functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
739 {
740 /* Composite data type, e.g. a table's row type */
741 Assert(tupdesc);
742 /* Must copy it out of typcache for safety */
743 sexpr->funcResultDesc = CreateTupleDescCopy(tupdesc);
744 sexpr->funcReturnsTuple = true;
745 }
746 else if (functypclass == TYPEFUNC_SCALAR)
747 {
748 /* Base data type, i.e. scalar */
749 tupdesc = CreateTemplateTupleDesc(1, false);
750 TupleDescInitEntry(tupdesc,
751 (AttrNumber) 1,
752 NULL,
753 funcrettype,
754 -1,
755 0);
756 sexpr->funcResultDesc = tupdesc;
757 sexpr->funcReturnsTuple = false;
758 }
759 else if (functypclass == TYPEFUNC_RECORD)
760 {
761 /* This will work if function doesn't need an expectedDesc */
762 sexpr->funcResultDesc = NULL;
763 sexpr->funcReturnsTuple = true;
764 }
765 else
766 {
767 /* Else, we will fail if function needs an expectedDesc */
768 sexpr->funcResultDesc = NULL;
769 }
770
771 MemoryContextSwitchTo(oldcontext);
772 }
773 else
774 sexpr->funcResultDesc = NULL;
775
776 /* Initialize additional state */
777 sexpr->funcResultStore = NULL;
778 sexpr->funcResultSlot = NULL;
779 sexpr->shutdown_reg = false;
780 }
781
782 /*
783 * callback function in case a SetExprState needs to be shut down before it
784 * has been run to completion
785 */
786 static void
ShutdownSetExpr(Datum arg)787 ShutdownSetExpr(Datum arg)
788 {
789 SetExprState *sexpr = castNode(SetExprState, DatumGetPointer(arg));
790
791 /* If we have a slot, make sure it's let go of any tuplestore pointer */
792 if (sexpr->funcResultSlot)
793 ExecClearTuple(sexpr->funcResultSlot);
794
795 /* Release any open tuplestore */
796 if (sexpr->funcResultStore)
797 tuplestore_end(sexpr->funcResultStore);
798 sexpr->funcResultStore = NULL;
799
800 /* Clear any active set-argument state */
801 sexpr->setArgsValid = false;
802
803 /* execUtils will deregister the callback... */
804 sexpr->shutdown_reg = false;
805 }
806
807 /*
808 * Evaluate arguments for a function.
809 */
810 static void
ExecEvalFuncArgs(FunctionCallInfo fcinfo,List * argList,ExprContext * econtext)811 ExecEvalFuncArgs(FunctionCallInfo fcinfo,
812 List *argList,
813 ExprContext *econtext)
814 {
815 int i;
816 ListCell *arg;
817
818 i = 0;
819 foreach(arg, argList)
820 {
821 ExprState *argstate = (ExprState *) lfirst(arg);
822
823 fcinfo->arg[i] = ExecEvalExpr(argstate,
824 econtext,
825 &fcinfo->argnull[i]);
826 i++;
827 }
828
829 Assert(i == fcinfo->nargs);
830 }
831
832 /*
833 * ExecPrepareTuplestoreResult
834 *
835 * Subroutine for ExecMakeFunctionResultSet: prepare to extract rows from a
836 * tuplestore function result. We must set up a funcResultSlot (unless
837 * already done in a previous call cycle) and verify that the function
838 * returned the expected tuple descriptor.
839 */
840 static void
ExecPrepareTuplestoreResult(SetExprState * sexpr,ExprContext * econtext,Tuplestorestate * resultStore,TupleDesc resultDesc)841 ExecPrepareTuplestoreResult(SetExprState *sexpr,
842 ExprContext *econtext,
843 Tuplestorestate *resultStore,
844 TupleDesc resultDesc)
845 {
846 sexpr->funcResultStore = resultStore;
847
848 if (sexpr->funcResultSlot == NULL)
849 {
850 /* Create a slot so we can read data out of the tuplestore */
851 TupleDesc slotDesc;
852 MemoryContext oldcontext;
853
854 oldcontext = MemoryContextSwitchTo(sexpr->func.fn_mcxt);
855
856 /*
857 * If we were not able to determine the result rowtype from context,
858 * and the function didn't return a tupdesc, we have to fail.
859 */
860 if (sexpr->funcResultDesc)
861 slotDesc = sexpr->funcResultDesc;
862 else if (resultDesc)
863 {
864 /* don't assume resultDesc is long-lived */
865 slotDesc = CreateTupleDescCopy(resultDesc);
866 }
867 else
868 {
869 ereport(ERROR,
870 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
871 errmsg("function returning setof record called in "
872 "context that cannot accept type record")));
873 slotDesc = NULL; /* keep compiler quiet */
874 }
875
876 sexpr->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
877 MemoryContextSwitchTo(oldcontext);
878 }
879
880 /*
881 * If function provided a tupdesc, cross-check it. We only really need to
882 * do this for functions returning RECORD, but might as well do it always.
883 */
884 if (resultDesc)
885 {
886 if (sexpr->funcResultDesc)
887 tupledesc_match(sexpr->funcResultDesc, resultDesc);
888
889 /*
890 * If it is a dynamically-allocated TupleDesc, free it: it is
891 * typically allocated in a per-query context, so we must avoid
892 * leaking it across multiple usages.
893 */
894 if (resultDesc->tdrefcount == -1)
895 FreeTupleDesc(resultDesc);
896 }
897
898 /* Register cleanup callback if we didn't already */
899 if (!sexpr->shutdown_reg)
900 {
901 RegisterExprContextCallback(econtext,
902 ShutdownSetExpr,
903 PointerGetDatum(sexpr));
904 sexpr->shutdown_reg = true;
905 }
906 }
907
908 /*
909 * Check that function result tuple type (src_tupdesc) matches or can
910 * be considered to match what the query expects (dst_tupdesc). If
911 * they don't match, ereport.
912 *
913 * We really only care about number of attributes and data type.
914 * Also, we can ignore type mismatch on columns that are dropped in the
915 * destination type, so long as the physical storage matches. This is
916 * helpful in some cases involving out-of-date cached plans.
917 */
918 static void
tupledesc_match(TupleDesc dst_tupdesc,TupleDesc src_tupdesc)919 tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
920 {
921 int i;
922
923 if (dst_tupdesc->natts != src_tupdesc->natts)
924 ereport(ERROR,
925 (errcode(ERRCODE_DATATYPE_MISMATCH),
926 errmsg("function return row and query-specified return row do not match"),
927 errdetail_plural("Returned row contains %d attribute, but query expects %d.",
928 "Returned row contains %d attributes, but query expects %d.",
929 src_tupdesc->natts,
930 src_tupdesc->natts, dst_tupdesc->natts)));
931
932 for (i = 0; i < dst_tupdesc->natts; i++)
933 {
934 Form_pg_attribute dattr = TupleDescAttr(dst_tupdesc, i);
935 Form_pg_attribute sattr = TupleDescAttr(src_tupdesc, i);
936
937 if (IsBinaryCoercible(sattr->atttypid, dattr->atttypid))
938 continue; /* no worries */
939 if (!dattr->attisdropped)
940 ereport(ERROR,
941 (errcode(ERRCODE_DATATYPE_MISMATCH),
942 errmsg("function return row and query-specified return row do not match"),
943 errdetail("Returned type %s at ordinal position %d, but query expects %s.",
944 format_type_be(sattr->atttypid),
945 i + 1,
946 format_type_be(dattr->atttypid))));
947
948 if (dattr->attlen != sattr->attlen ||
949 dattr->attalign != sattr->attalign)
950 ereport(ERROR,
951 (errcode(ERRCODE_DATATYPE_MISMATCH),
952 errmsg("function return row and query-specified return row do not match"),
953 errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
954 i + 1)));
955 }
956 }
957