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