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-2017, 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.
471  *
472  * This is used by nodeProjectSet.c.
473  */
474 Datum
ExecMakeFunctionResultSet(SetExprState * fcache,ExprContext * econtext,bool * isNull,ExprDoneCond * isDone)475 ExecMakeFunctionResultSet(SetExprState *fcache,
476 						  ExprContext *econtext,
477 						  bool *isNull,
478 						  ExprDoneCond *isDone)
479 {
480 	List	   *arguments;
481 	Datum		result;
482 	FunctionCallInfo fcinfo;
483 	PgStat_FunctionCallUsage fcusage;
484 	ReturnSetInfo rsinfo;
485 	bool		callit;
486 	int			i;
487 
488 restart:
489 
490 	/* Guard against stack overflow due to overly complex expressions */
491 	check_stack_depth();
492 
493 	/*
494 	 * If a previous call of the function returned a set result in the form of
495 	 * a tuplestore, continue reading rows from the tuplestore until it's
496 	 * empty.
497 	 */
498 	if (fcache->funcResultStore)
499 	{
500 		if (tuplestore_gettupleslot(fcache->funcResultStore, true, false,
501 									fcache->funcResultSlot))
502 		{
503 			*isDone = ExprMultipleResult;
504 			if (fcache->funcReturnsTuple)
505 			{
506 				/* We must return the whole tuple as a Datum. */
507 				*isNull = false;
508 				return ExecFetchSlotTupleDatum(fcache->funcResultSlot);
509 			}
510 			else
511 			{
512 				/* Extract the first column and return it as a scalar. */
513 				return slot_getattr(fcache->funcResultSlot, 1, isNull);
514 			}
515 		}
516 		/* Exhausted the tuplestore, so clean up */
517 		tuplestore_end(fcache->funcResultStore);
518 		fcache->funcResultStore = NULL;
519 		*isDone = ExprEndResult;
520 		*isNull = true;
521 		return (Datum) 0;
522 	}
523 
524 	/*
525 	 * arguments is a list of expressions to evaluate before passing to the
526 	 * function manager.  We skip the evaluation if it was already done in the
527 	 * previous call (ie, we are continuing the evaluation of a set-valued
528 	 * function).  Otherwise, collect the current argument values into fcinfo.
529 	 */
530 	fcinfo = &fcache->fcinfo_data;
531 	arguments = fcache->args;
532 	if (!fcache->setArgsValid)
533 		ExecEvalFuncArgs(fcinfo, arguments, econtext);
534 	else
535 	{
536 		/* Reset flag (we may set it again below) */
537 		fcache->setArgsValid = false;
538 	}
539 
540 	/*
541 	 * Now call the function, passing the evaluated parameter values.
542 	 */
543 
544 	/* Prepare a resultinfo node for communication. */
545 	fcinfo->resultinfo = (Node *) &rsinfo;
546 	rsinfo.type = T_ReturnSetInfo;
547 	rsinfo.econtext = econtext;
548 	rsinfo.expectedDesc = fcache->funcResultDesc;
549 	rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
550 	/* note we do not set SFRM_Materialize_Random or _Preferred */
551 	rsinfo.returnMode = SFRM_ValuePerCall;
552 	/* isDone is filled below */
553 	rsinfo.setResult = NULL;
554 	rsinfo.setDesc = NULL;
555 
556 	/*
557 	 * If function is strict, and there are any NULL arguments, skip calling
558 	 * the function.
559 	 */
560 	callit = true;
561 	if (fcache->func.fn_strict)
562 	{
563 		for (i = 0; i < fcinfo->nargs; i++)
564 		{
565 			if (fcinfo->argnull[i])
566 			{
567 				callit = false;
568 				break;
569 			}
570 		}
571 	}
572 
573 	if (callit)
574 	{
575 		pgstat_init_function_usage(fcinfo, &fcusage);
576 
577 		fcinfo->isnull = false;
578 		rsinfo.isDone = ExprSingleResult;
579 		result = FunctionCallInvoke(fcinfo);
580 		*isNull = fcinfo->isnull;
581 		*isDone = rsinfo.isDone;
582 
583 		pgstat_end_function_usage(&fcusage,
584 								  rsinfo.isDone != ExprMultipleResult);
585 	}
586 	else
587 	{
588 		/* for a strict SRF, result for NULL is an empty set */
589 		result = (Datum) 0;
590 		*isNull = true;
591 		*isDone = ExprEndResult;
592 	}
593 
594 	/* Which protocol does function want to use? */
595 	if (rsinfo.returnMode == SFRM_ValuePerCall)
596 	{
597 		if (*isDone != ExprEndResult)
598 		{
599 			/*
600 			 * Save the current argument values to re-use on the next call.
601 			 */
602 			if (*isDone == ExprMultipleResult)
603 			{
604 				fcache->setArgsValid = true;
605 				/* Register cleanup callback if we didn't already */
606 				if (!fcache->shutdown_reg)
607 				{
608 					RegisterExprContextCallback(econtext,
609 												ShutdownSetExpr,
610 												PointerGetDatum(fcache));
611 					fcache->shutdown_reg = true;
612 				}
613 			}
614 		}
615 	}
616 	else if (rsinfo.returnMode == SFRM_Materialize)
617 	{
618 		/* check we're on the same page as the function author */
619 		if (rsinfo.isDone != ExprSingleResult)
620 			ereport(ERROR,
621 					(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
622 					 errmsg("table-function protocol for materialize mode was not followed")));
623 		if (rsinfo.setResult != NULL)
624 		{
625 			/* prepare to return values from the tuplestore */
626 			ExecPrepareTuplestoreResult(fcache, econtext,
627 										rsinfo.setResult,
628 										rsinfo.setDesc);
629 			/* loop back to top to start returning from tuplestore */
630 			goto restart;
631 		}
632 		/* if setResult was left null, treat it as empty set */
633 		*isDone = ExprEndResult;
634 		*isNull = true;
635 		result = (Datum) 0;
636 	}
637 	else
638 		ereport(ERROR,
639 				(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
640 				 errmsg("unrecognized table-function returnMode: %d",
641 						(int) rsinfo.returnMode)));
642 
643 	return result;
644 }
645 
646 
647 /*
648  * init_sexpr - initialize a SetExprState node during first use
649  */
650 static void
init_sexpr(Oid foid,Oid input_collation,Expr * node,SetExprState * sexpr,PlanState * parent,MemoryContext sexprCxt,bool allowSRF,bool needDescForSRF)651 init_sexpr(Oid foid, Oid input_collation, Expr *node,
652 		   SetExprState *sexpr, PlanState *parent,
653 		   MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF)
654 {
655 	AclResult	aclresult;
656 
657 	/* Check permission to call function */
658 	aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
659 	if (aclresult != ACLCHECK_OK)
660 		aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid));
661 	InvokeFunctionExecuteHook(foid);
662 
663 	/*
664 	 * Safety check on nargs.  Under normal circumstances this should never
665 	 * fail, as parser should check sooner.  But possibly it might fail if
666 	 * server has been compiled with FUNC_MAX_ARGS smaller than some functions
667 	 * declared in pg_proc?
668 	 */
669 	if (list_length(sexpr->args) > FUNC_MAX_ARGS)
670 		ereport(ERROR,
671 				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
672 				 errmsg_plural("cannot pass more than %d argument to a function",
673 							   "cannot pass more than %d arguments to a function",
674 							   FUNC_MAX_ARGS,
675 							   FUNC_MAX_ARGS)));
676 
677 	/* Set up the primary fmgr lookup information */
678 	fmgr_info_cxt(foid, &(sexpr->func), sexprCxt);
679 	fmgr_info_set_expr((Node *) sexpr->expr, &(sexpr->func));
680 
681 	/* Initialize the function call parameter struct as well */
682 	InitFunctionCallInfoData(sexpr->fcinfo_data, &(sexpr->func),
683 							 list_length(sexpr->args),
684 							 input_collation, NULL, NULL);
685 
686 	/* If function returns set, check if that's allowed by caller */
687 	if (sexpr->func.fn_retset && !allowSRF)
688 		ereport(ERROR,
689 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
690 				 errmsg("set-valued function called in context that cannot accept a set"),
691 				 parent ? executor_errposition(parent->state,
692 											   exprLocation((Node *) node)) : 0));
693 
694 	/* Otherwise, caller should have marked the sexpr correctly */
695 	Assert(sexpr->func.fn_retset == sexpr->funcReturnsSet);
696 
697 	/* If function returns set, prepare expected tuple descriptor */
698 	if (sexpr->func.fn_retset && needDescForSRF)
699 	{
700 		TypeFuncClass functypclass;
701 		Oid			funcrettype;
702 		TupleDesc	tupdesc;
703 		MemoryContext oldcontext;
704 
705 		functypclass = get_expr_result_type(sexpr->func.fn_expr,
706 											&funcrettype,
707 											&tupdesc);
708 
709 		/* Must save tupdesc in sexpr's context */
710 		oldcontext = MemoryContextSwitchTo(sexprCxt);
711 
712 		if (functypclass == TYPEFUNC_COMPOSITE)
713 		{
714 			/* Composite data type, e.g. a table's row type */
715 			Assert(tupdesc);
716 			/* Must copy it out of typcache for safety */
717 			sexpr->funcResultDesc = CreateTupleDescCopy(tupdesc);
718 			sexpr->funcReturnsTuple = true;
719 		}
720 		else if (functypclass == TYPEFUNC_SCALAR)
721 		{
722 			/* Base data type, i.e. scalar */
723 			tupdesc = CreateTemplateTupleDesc(1, false);
724 			TupleDescInitEntry(tupdesc,
725 							   (AttrNumber) 1,
726 							   NULL,
727 							   funcrettype,
728 							   -1,
729 							   0);
730 			sexpr->funcResultDesc = tupdesc;
731 			sexpr->funcReturnsTuple = false;
732 		}
733 		else if (functypclass == TYPEFUNC_RECORD)
734 		{
735 			/* This will work if function doesn't need an expectedDesc */
736 			sexpr->funcResultDesc = NULL;
737 			sexpr->funcReturnsTuple = true;
738 		}
739 		else
740 		{
741 			/* Else, we will fail if function needs an expectedDesc */
742 			sexpr->funcResultDesc = NULL;
743 		}
744 
745 		MemoryContextSwitchTo(oldcontext);
746 	}
747 	else
748 		sexpr->funcResultDesc = NULL;
749 
750 	/* Initialize additional state */
751 	sexpr->funcResultStore = NULL;
752 	sexpr->funcResultSlot = NULL;
753 	sexpr->shutdown_reg = false;
754 }
755 
756 /*
757  * callback function in case a SetExprState needs to be shut down before it
758  * has been run to completion
759  */
760 static void
ShutdownSetExpr(Datum arg)761 ShutdownSetExpr(Datum arg)
762 {
763 	SetExprState *sexpr = castNode(SetExprState, DatumGetPointer(arg));
764 
765 	/* If we have a slot, make sure it's let go of any tuplestore pointer */
766 	if (sexpr->funcResultSlot)
767 		ExecClearTuple(sexpr->funcResultSlot);
768 
769 	/* Release any open tuplestore */
770 	if (sexpr->funcResultStore)
771 		tuplestore_end(sexpr->funcResultStore);
772 	sexpr->funcResultStore = NULL;
773 
774 	/* Clear any active set-argument state */
775 	sexpr->setArgsValid = false;
776 
777 	/* execUtils will deregister the callback... */
778 	sexpr->shutdown_reg = false;
779 }
780 
781 /*
782  * Evaluate arguments for a function.
783  */
784 static void
ExecEvalFuncArgs(FunctionCallInfo fcinfo,List * argList,ExprContext * econtext)785 ExecEvalFuncArgs(FunctionCallInfo fcinfo,
786 				 List *argList,
787 				 ExprContext *econtext)
788 {
789 	int			i;
790 	ListCell   *arg;
791 
792 	i = 0;
793 	foreach(arg, argList)
794 	{
795 		ExprState  *argstate = (ExprState *) lfirst(arg);
796 
797 		fcinfo->arg[i] = ExecEvalExpr(argstate,
798 									  econtext,
799 									  &fcinfo->argnull[i]);
800 		i++;
801 	}
802 
803 	Assert(i == fcinfo->nargs);
804 }
805 
806 /*
807  *		ExecPrepareTuplestoreResult
808  *
809  * Subroutine for ExecMakeFunctionResultSet: prepare to extract rows from a
810  * tuplestore function result.  We must set up a funcResultSlot (unless
811  * already done in a previous call cycle) and verify that the function
812  * returned the expected tuple descriptor.
813  */
814 static void
ExecPrepareTuplestoreResult(SetExprState * sexpr,ExprContext * econtext,Tuplestorestate * resultStore,TupleDesc resultDesc)815 ExecPrepareTuplestoreResult(SetExprState *sexpr,
816 							ExprContext *econtext,
817 							Tuplestorestate *resultStore,
818 							TupleDesc resultDesc)
819 {
820 	sexpr->funcResultStore = resultStore;
821 
822 	if (sexpr->funcResultSlot == NULL)
823 	{
824 		/* Create a slot so we can read data out of the tuplestore */
825 		TupleDesc	slotDesc;
826 		MemoryContext oldcontext;
827 
828 		oldcontext = MemoryContextSwitchTo(sexpr->func.fn_mcxt);
829 
830 		/*
831 		 * If we were not able to determine the result rowtype from context,
832 		 * and the function didn't return a tupdesc, we have to fail.
833 		 */
834 		if (sexpr->funcResultDesc)
835 			slotDesc = sexpr->funcResultDesc;
836 		else if (resultDesc)
837 		{
838 			/* don't assume resultDesc is long-lived */
839 			slotDesc = CreateTupleDescCopy(resultDesc);
840 		}
841 		else
842 		{
843 			ereport(ERROR,
844 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
845 					 errmsg("function returning setof record called in "
846 							"context that cannot accept type record")));
847 			slotDesc = NULL;	/* keep compiler quiet */
848 		}
849 
850 		sexpr->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
851 		MemoryContextSwitchTo(oldcontext);
852 	}
853 
854 	/*
855 	 * If function provided a tupdesc, cross-check it.  We only really need to
856 	 * do this for functions returning RECORD, but might as well do it always.
857 	 */
858 	if (resultDesc)
859 	{
860 		if (sexpr->funcResultDesc)
861 			tupledesc_match(sexpr->funcResultDesc, resultDesc);
862 
863 		/*
864 		 * If it is a dynamically-allocated TupleDesc, free it: it is
865 		 * typically allocated in a per-query context, so we must avoid
866 		 * leaking it across multiple usages.
867 		 */
868 		if (resultDesc->tdrefcount == -1)
869 			FreeTupleDesc(resultDesc);
870 	}
871 
872 	/* Register cleanup callback if we didn't already */
873 	if (!sexpr->shutdown_reg)
874 	{
875 		RegisterExprContextCallback(econtext,
876 									ShutdownSetExpr,
877 									PointerGetDatum(sexpr));
878 		sexpr->shutdown_reg = true;
879 	}
880 }
881 
882 /*
883  * Check that function result tuple type (src_tupdesc) matches or can
884  * be considered to match what the query expects (dst_tupdesc). If
885  * they don't match, ereport.
886  *
887  * We really only care about number of attributes and data type.
888  * Also, we can ignore type mismatch on columns that are dropped in the
889  * destination type, so long as the physical storage matches.  This is
890  * helpful in some cases involving out-of-date cached plans.
891  */
892 static void
tupledesc_match(TupleDesc dst_tupdesc,TupleDesc src_tupdesc)893 tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
894 {
895 	int			i;
896 
897 	if (dst_tupdesc->natts != src_tupdesc->natts)
898 		ereport(ERROR,
899 				(errcode(ERRCODE_DATATYPE_MISMATCH),
900 				 errmsg("function return row and query-specified return row do not match"),
901 				 errdetail_plural("Returned row contains %d attribute, but query expects %d.",
902 								  "Returned row contains %d attributes, but query expects %d.",
903 								  src_tupdesc->natts,
904 								  src_tupdesc->natts, dst_tupdesc->natts)));
905 
906 	for (i = 0; i < dst_tupdesc->natts; i++)
907 	{
908 		Form_pg_attribute dattr = dst_tupdesc->attrs[i];
909 		Form_pg_attribute sattr = src_tupdesc->attrs[i];
910 
911 		if (IsBinaryCoercible(sattr->atttypid, dattr->atttypid))
912 			continue;			/* no worries */
913 		if (!dattr->attisdropped)
914 			ereport(ERROR,
915 					(errcode(ERRCODE_DATATYPE_MISMATCH),
916 					 errmsg("function return row and query-specified return row do not match"),
917 					 errdetail("Returned type %s at ordinal position %d, but query expects %s.",
918 							   format_type_be(sattr->atttypid),
919 							   i + 1,
920 							   format_type_be(dattr->atttypid))));
921 
922 		if (dattr->attlen != sattr->attlen ||
923 			dattr->attalign != sattr->attalign)
924 			ereport(ERROR,
925 					(errcode(ERRCODE_DATATYPE_MISMATCH),
926 					 errmsg("function return row and query-specified return row do not match"),
927 					 errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
928 							   i + 1)));
929 	}
930 }
931