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