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