Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * functions.c
4 : * Execution of SQL-language functions
5 : *
6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/executor/functions.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/htup_details.h"
18 : #include "access/xact.h"
19 : #include "catalog/pg_proc.h"
20 : #include "catalog/pg_type.h"
21 : #include "executor/functions.h"
22 : #include "funcapi.h"
23 : #include "miscadmin.h"
24 : #include "nodes/makefuncs.h"
25 : #include "nodes/nodeFuncs.h"
26 : #include "parser/parse_coerce.h"
27 : #include "parser/parse_collate.h"
28 : #include "parser/parse_func.h"
29 : #include "rewrite/rewriteHandler.h"
30 : #include "storage/proc.h"
31 : #include "tcop/utility.h"
32 : #include "utils/builtins.h"
33 : #include "utils/datum.h"
34 : #include "utils/funccache.h"
35 : #include "utils/lsyscache.h"
36 : #include "utils/memutils.h"
37 : #include "utils/plancache.h"
38 : #include "utils/snapmgr.h"
39 : #include "utils/syscache.h"
40 :
41 :
42 : /*
43 : * Specialized DestReceiver for collecting query output in a SQL function
44 : */
45 : typedef struct
46 : {
47 : DestReceiver pub; /* publicly-known function pointers */
48 : Tuplestorestate *tstore; /* where to put result tuples, or NULL */
49 : JunkFilter *filter; /* filter to convert tuple type */
50 : } DR_sqlfunction;
51 :
52 : /*
53 : * We have an execution_state record for each query in a function. Each
54 : * record references a plantree for its query. If the query is currently in
55 : * F_EXEC_RUN state then there's a QueryDesc too.
56 : *
57 : * The "next" fields chain together all the execution_state records generated
58 : * from a single original parsetree. (There will only be more than one in
59 : * case of rule expansion of the original parsetree.) The chain structure is
60 : * quite vestigial at this point, because we allocate the records in an array
61 : * for ease of memory management. But we'll get rid of it some other day.
62 : */
63 : typedef enum
64 : {
65 : F_EXEC_START, F_EXEC_RUN, F_EXEC_DONE,
66 : } ExecStatus;
67 :
68 : typedef struct execution_state
69 : {
70 : struct execution_state *next;
71 : ExecStatus status;
72 : bool setsResult; /* true if this query produces func's result */
73 : bool lazyEval; /* true if should fetch one row at a time */
74 : PlannedStmt *stmt; /* plan for this query */
75 : QueryDesc *qd; /* null unless status == RUN */
76 : } execution_state;
77 :
78 :
79 : /*
80 : * Data associated with a SQL-language function is kept in two main
81 : * data structures:
82 : *
83 : * 1. SQLFunctionHashEntry is a long-lived (potentially session-lifespan)
84 : * struct that holds all the info we need out of the function's pg_proc row.
85 : * In addition it holds pointers to CachedPlanSource(s) that manage creation
86 : * of plans for the query(s) within the function. A SQLFunctionHashEntry is
87 : * potentially shared across multiple concurrent executions of the function,
88 : * so it must contain no execution-specific state; but its use_count must
89 : * reflect the number of SQLFunctionCache structs pointing at it.
90 : * If the function's pg_proc row is updated, we throw away and regenerate
91 : * the SQLFunctionHashEntry and subsidiary data. (Also note that if the
92 : * function is polymorphic or used as a trigger, there is a separate
93 : * SQLFunctionHashEntry for each usage, so that we need consider only one
94 : * set of relevant data types.) The struct itself is in memory managed by
95 : * funccache.c, and its subsidiary data is kept in one of two contexts:
96 : * * pcontext ("parse context") holds the raw parse trees or Query trees
97 : * that we read from the pg_proc row. These will be converted to
98 : * CachedPlanSources as they are needed. Once the last one is converted,
99 : * pcontext can be freed.
100 : * * hcontext ("hash context") holds everything else belonging to the
101 : * SQLFunctionHashEntry.
102 : *
103 : * 2. SQLFunctionCache is subsidiary data for a single FmgrInfo struct.
104 : * It is pointed to by the fn_extra field of the FmgrInfo struct, and is
105 : * always allocated in the FmgrInfo's fn_mcxt. It holds a reference to
106 : * the CachedPlan for the current query, and other execution-specific data.
107 : * A few subsidiary items such as the ParamListInfo object are also kept
108 : * directly in fn_mcxt (which is also called fcontext here). But most
109 : * subsidiary data is in jfcontext or subcontext.
110 : */
111 :
112 : typedef struct SQLFunctionHashEntry
113 : {
114 : CachedFunction cfunc; /* fields managed by funccache.c */
115 :
116 : char *fname; /* function name (for error msgs) */
117 : char *src; /* function body text (for error msgs) */
118 :
119 : SQLFunctionParseInfoPtr pinfo; /* data for parser callback hooks */
120 : int16 *argtyplen; /* lengths of the input argument types */
121 :
122 : Oid rettype; /* actual return type */
123 : int16 typlen; /* length of the return type */
124 : bool typbyval; /* true if return type is pass by value */
125 : bool returnsSet; /* true if returning multiple rows */
126 : bool returnsTuple; /* true if returning whole tuple result */
127 : bool readonly_func; /* true to run in "read only" mode */
128 : char prokind; /* prokind from pg_proc row */
129 :
130 : TupleDesc rettupdesc; /* result tuple descriptor */
131 :
132 : List *source_list; /* RawStmts or Queries read from pg_proc */
133 : int num_queries; /* original length of source_list */
134 : bool raw_source; /* true if source_list contains RawStmts */
135 :
136 : List *plansource_list; /* CachedPlanSources for fn's queries */
137 :
138 : MemoryContext pcontext; /* memory context holding source_list */
139 : MemoryContext hcontext; /* memory context holding all else */
140 : } SQLFunctionHashEntry;
141 :
142 : typedef struct SQLFunctionCache
143 : {
144 : SQLFunctionHashEntry *func; /* associated SQLFunctionHashEntry */
145 :
146 : bool lazyEvalOK; /* true if lazyEval is safe */
147 : bool shutdown_reg; /* true if registered shutdown callback */
148 : bool lazyEval; /* true if using lazyEval for result query */
149 : bool randomAccess; /* true if tstore needs random access */
150 : bool ownSubcontext; /* is subcontext really a separate context? */
151 :
152 : ParamListInfo paramLI; /* Param list representing current args */
153 :
154 : Tuplestorestate *tstore; /* where we accumulate result for a SRF */
155 : MemoryContext tscontext; /* memory context that tstore should be in */
156 :
157 : JunkFilter *junkFilter; /* will be NULL if function returns VOID */
158 : int jf_generation; /* tracks whether junkFilter is up-to-date */
159 :
160 : /*
161 : * While executing a particular query within the function, cplan is the
162 : * CachedPlan we've obtained for that query, and eslist is a chain of
163 : * execution_state records for the individual plans within the CachedPlan.
164 : * If eslist is not NULL at entry to fmgr_sql, then we are resuming
165 : * execution of a lazyEval-mode set-returning function.
166 : *
167 : * next_query_index is the 0-based index of the next CachedPlanSource to
168 : * get a CachedPlan from.
169 : */
170 : CachedPlan *cplan; /* Plan for current query, if any */
171 : ResourceOwner cowner; /* CachedPlan is registered with this owner */
172 : int next_query_index; /* index of next CachedPlanSource to run */
173 :
174 : execution_state *eslist; /* chain of execution_state records */
175 : execution_state *esarray; /* storage for eslist */
176 : int esarray_len; /* allocated length of esarray[] */
177 :
178 : /* if positive, this is the 1-based index of the query we're processing */
179 : int error_query_index;
180 :
181 : MemoryContext fcontext; /* memory context holding this struct and all
182 : * subsidiary data */
183 : MemoryContext jfcontext; /* subsidiary memory context holding
184 : * junkFilter, result slot, and related data */
185 : MemoryContext subcontext; /* subsidiary memory context for sub-executor */
186 :
187 : /* Callback to release our use-count on the SQLFunctionHashEntry */
188 : MemoryContextCallback mcb;
189 : } SQLFunctionCache;
190 :
191 : typedef SQLFunctionCache *SQLFunctionCachePtr;
192 :
193 :
194 : /* non-export function prototypes */
195 : static Node *sql_fn_param_ref(ParseState *pstate, ParamRef *pref);
196 : static Node *sql_fn_post_column_ref(ParseState *pstate,
197 : ColumnRef *cref, Node *var);
198 : static Node *sql_fn_make_param(SQLFunctionParseInfoPtr pinfo,
199 : int paramno, int location);
200 : static Node *sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo,
201 : const char *paramname, int location);
202 : static SQLFunctionCache *init_sql_fcache(FunctionCallInfo fcinfo,
203 : bool lazyEvalOK);
204 : static bool init_execution_state(SQLFunctionCachePtr fcache);
205 : static void prepare_next_query(SQLFunctionHashEntry *func);
206 : static void sql_compile_callback(FunctionCallInfo fcinfo,
207 : HeapTuple procedureTuple,
208 : const CachedFunctionHashKey *hashkey,
209 : CachedFunction *cfunc,
210 : bool forValidator);
211 : static void sql_delete_callback(CachedFunction *cfunc);
212 : static void sql_postrewrite_callback(List *querytree_list, void *arg);
213 : static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
214 : static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache);
215 : static void postquel_end(execution_state *es, SQLFunctionCachePtr fcache);
216 : static void postquel_sub_params(SQLFunctionCachePtr fcache,
217 : FunctionCallInfo fcinfo);
218 : static Datum postquel_get_single_result(TupleTableSlot *slot,
219 : FunctionCallInfo fcinfo,
220 : SQLFunctionCachePtr fcache);
221 : static void sql_compile_error_callback(void *arg);
222 : static void sql_exec_error_callback(void *arg);
223 : static void ShutdownSQLFunction(Datum arg);
224 : static void RemoveSQLFunctionCache(void *arg);
225 : static void check_sql_fn_statement(List *queryTreeList);
226 : static bool check_sql_stmt_retval(List *queryTreeList,
227 : Oid rettype, TupleDesc rettupdesc,
228 : char prokind, bool insertDroppedCols);
229 : static bool coerce_fn_result_column(TargetEntry *src_tle,
230 : Oid res_type, int32 res_typmod,
231 : bool tlist_is_modifiable,
232 : List **upper_tlist,
233 : bool *upper_tlist_nontrivial);
234 : static List *get_sql_fn_result_tlist(List *queryTreeList);
235 : static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo);
236 : static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self);
237 : static void sqlfunction_shutdown(DestReceiver *self);
238 : static void sqlfunction_destroy(DestReceiver *self);
239 :
240 :
241 : /*
242 : * Prepare the SQLFunctionParseInfo struct for parsing a SQL function body
243 : *
244 : * This includes resolving actual types of polymorphic arguments.
245 : *
246 : * call_expr can be passed as NULL, but then we will fail if there are any
247 : * polymorphic arguments.
248 : */
249 : SQLFunctionParseInfoPtr
250 7134 : prepare_sql_fn_parse_info(HeapTuple procedureTuple,
251 : Node *call_expr,
252 : Oid inputCollation)
253 : {
254 : SQLFunctionParseInfoPtr pinfo;
255 7134 : Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
256 : int nargs;
257 :
258 7134 : pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
259 :
260 : /* Function's name (only) can be used to qualify argument names */
261 7134 : pinfo->fname = pstrdup(NameStr(procedureStruct->proname));
262 :
263 : /* Save the function's input collation */
264 7134 : pinfo->collation = inputCollation;
265 :
266 : /*
267 : * Copy input argument types from the pg_proc entry, then resolve any
268 : * polymorphic types.
269 : */
270 7134 : pinfo->nargs = nargs = procedureStruct->pronargs;
271 7134 : if (nargs > 0)
272 : {
273 : Oid *argOidVect;
274 : int argnum;
275 :
276 5896 : argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
277 5896 : memcpy(argOidVect,
278 5896 : procedureStruct->proargtypes.values,
279 : nargs * sizeof(Oid));
280 :
281 15698 : for (argnum = 0; argnum < nargs; argnum++)
282 : {
283 9802 : Oid argtype = argOidVect[argnum];
284 :
285 9802 : if (IsPolymorphicType(argtype))
286 : {
287 2592 : argtype = get_call_expr_argtype(call_expr, argnum);
288 2592 : if (argtype == InvalidOid)
289 0 : ereport(ERROR,
290 : (errcode(ERRCODE_DATATYPE_MISMATCH),
291 : errmsg("could not determine actual type of argument declared %s",
292 : format_type_be(argOidVect[argnum]))));
293 2592 : argOidVect[argnum] = argtype;
294 : }
295 : }
296 :
297 5896 : pinfo->argtypes = argOidVect;
298 : }
299 :
300 : /*
301 : * Collect names of arguments, too, if any
302 : */
303 7134 : if (nargs > 0)
304 : {
305 : Datum proargnames;
306 : Datum proargmodes;
307 : int n_arg_names;
308 : bool isNull;
309 :
310 5896 : proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
311 : Anum_pg_proc_proargnames,
312 : &isNull);
313 5896 : if (isNull)
314 4004 : proargnames = PointerGetDatum(NULL); /* just to be sure */
315 :
316 5896 : proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
317 : Anum_pg_proc_proargmodes,
318 : &isNull);
319 5896 : if (isNull)
320 5262 : proargmodes = PointerGetDatum(NULL); /* just to be sure */
321 :
322 5896 : n_arg_names = get_func_input_arg_names(proargnames, proargmodes,
323 : &pinfo->argnames);
324 :
325 : /* Paranoia: ignore the result if too few array entries */
326 5896 : if (n_arg_names < nargs)
327 4004 : pinfo->argnames = NULL;
328 : }
329 : else
330 1238 : pinfo->argnames = NULL;
331 :
332 7134 : return pinfo;
333 : }
334 :
335 : /*
336 : * Parser setup hook for parsing a SQL function body.
337 : */
338 : void
339 12110 : sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
340 : {
341 12110 : pstate->p_pre_columnref_hook = NULL;
342 12110 : pstate->p_post_columnref_hook = sql_fn_post_column_ref;
343 12110 : pstate->p_paramref_hook = sql_fn_param_ref;
344 : /* no need to use p_coerce_param_hook */
345 12110 : pstate->p_ref_hook_state = pinfo;
346 12110 : }
347 :
348 : /*
349 : * sql_fn_post_column_ref parser callback for ColumnRefs
350 : */
351 : static Node *
352 8958 : sql_fn_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
353 : {
354 8958 : SQLFunctionParseInfoPtr pinfo = (SQLFunctionParseInfoPtr) pstate->p_ref_hook_state;
355 : int nnames;
356 : Node *field1;
357 8958 : Node *subfield = NULL;
358 : const char *name1;
359 8958 : const char *name2 = NULL;
360 : Node *param;
361 :
362 : /*
363 : * Never override a table-column reference. This corresponds to
364 : * considering the parameter names to appear in a scope outside the
365 : * individual SQL commands, which is what we want.
366 : */
367 8958 : if (var != NULL)
368 7528 : return NULL;
369 :
370 : /*----------
371 : * The allowed syntaxes are:
372 : *
373 : * A A = parameter name
374 : * A.B A = function name, B = parameter name
375 : * OR: A = record-typed parameter name, B = field name
376 : * (the first possibility takes precedence)
377 : * A.B.C A = function name, B = record-typed parameter name,
378 : * C = field name
379 : * A.* Whole-row reference to composite parameter A.
380 : * A.B.* Same, with A = function name, B = parameter name
381 : *
382 : * Here, it's sufficient to ignore the "*" in the last two cases --- the
383 : * main parser will take care of expanding the whole-row reference.
384 : *----------
385 : */
386 1430 : nnames = list_length(cref->fields);
387 :
388 1430 : if (nnames > 3)
389 0 : return NULL;
390 :
391 1430 : if (IsA(llast(cref->fields), A_Star))
392 42 : nnames--;
393 :
394 1430 : field1 = (Node *) linitial(cref->fields);
395 1430 : name1 = strVal(field1);
396 1430 : if (nnames > 1)
397 : {
398 156 : subfield = (Node *) lsecond(cref->fields);
399 156 : name2 = strVal(subfield);
400 : }
401 :
402 1430 : if (nnames == 3)
403 : {
404 : /*
405 : * Three-part name: if the first part doesn't match the function name,
406 : * we can fail immediately. Otherwise, look up the second part, and
407 : * take the third part to be a field reference.
408 : */
409 24 : if (strcmp(name1, pinfo->fname) != 0)
410 0 : return NULL;
411 :
412 24 : param = sql_fn_resolve_param_name(pinfo, name2, cref->location);
413 :
414 24 : subfield = (Node *) lthird(cref->fields);
415 : Assert(IsA(subfield, String));
416 : }
417 1406 : else if (nnames == 2 && strcmp(name1, pinfo->fname) == 0)
418 : {
419 : /*
420 : * Two-part name with first part matching function name: first see if
421 : * second part matches any parameter name.
422 : */
423 24 : param = sql_fn_resolve_param_name(pinfo, name2, cref->location);
424 :
425 24 : if (param)
426 : {
427 : /* Yes, so this is a parameter reference, no subfield */
428 24 : subfield = NULL;
429 : }
430 : else
431 : {
432 : /* No, so try to match as parameter name and subfield */
433 0 : param = sql_fn_resolve_param_name(pinfo, name1, cref->location);
434 : }
435 : }
436 : else
437 : {
438 : /* Single name, or parameter name followed by subfield */
439 1382 : param = sql_fn_resolve_param_name(pinfo, name1, cref->location);
440 : }
441 :
442 1430 : if (!param)
443 0 : return NULL; /* No match */
444 :
445 1430 : if (subfield)
446 : {
447 : /*
448 : * Must be a reference to a field of a composite parameter; otherwise
449 : * ParseFuncOrColumn will return NULL, and we'll fail back at the
450 : * caller.
451 : */
452 132 : param = ParseFuncOrColumn(pstate,
453 132 : list_make1(subfield),
454 132 : list_make1(param),
455 : pstate->p_last_srf,
456 : NULL,
457 : false,
458 : cref->location);
459 : }
460 :
461 1430 : return param;
462 : }
463 :
464 : /*
465 : * sql_fn_param_ref parser callback for ParamRefs ($n symbols)
466 : */
467 : static Node *
468 21816 : sql_fn_param_ref(ParseState *pstate, ParamRef *pref)
469 : {
470 21816 : SQLFunctionParseInfoPtr pinfo = (SQLFunctionParseInfoPtr) pstate->p_ref_hook_state;
471 21816 : int paramno = pref->number;
472 :
473 : /* Check parameter number is valid */
474 21816 : if (paramno <= 0 || paramno > pinfo->nargs)
475 6 : return NULL; /* unknown parameter number */
476 :
477 21810 : return sql_fn_make_param(pinfo, paramno, pref->location);
478 : }
479 :
480 : /*
481 : * sql_fn_make_param construct a Param node for the given paramno
482 : */
483 : static Node *
484 23240 : sql_fn_make_param(SQLFunctionParseInfoPtr pinfo,
485 : int paramno, int location)
486 : {
487 : Param *param;
488 :
489 23240 : param = makeNode(Param);
490 23240 : param->paramkind = PARAM_EXTERN;
491 23240 : param->paramid = paramno;
492 23240 : param->paramtype = pinfo->argtypes[paramno - 1];
493 23240 : param->paramtypmod = -1;
494 23240 : param->paramcollid = get_typcollation(param->paramtype);
495 23240 : param->location = location;
496 :
497 : /*
498 : * If we have a function input collation, allow it to override the
499 : * type-derived collation for parameter symbols. (XXX perhaps this should
500 : * not happen if the type collation is not default?)
501 : */
502 23240 : if (OidIsValid(pinfo->collation) && OidIsValid(param->paramcollid))
503 2002 : param->paramcollid = pinfo->collation;
504 :
505 23240 : return (Node *) param;
506 : }
507 :
508 : /*
509 : * Search for a function parameter of the given name; if there is one,
510 : * construct and return a Param node for it. If not, return NULL.
511 : * Helper function for sql_fn_post_column_ref.
512 : */
513 : static Node *
514 1430 : sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo,
515 : const char *paramname, int location)
516 : {
517 : int i;
518 :
519 1430 : if (pinfo->argnames == NULL)
520 0 : return NULL;
521 :
522 1962 : for (i = 0; i < pinfo->nargs; i++)
523 : {
524 1962 : if (pinfo->argnames[i] && strcmp(pinfo->argnames[i], paramname) == 0)
525 1430 : return sql_fn_make_param(pinfo, i + 1, location);
526 : }
527 :
528 0 : return NULL;
529 : }
530 :
531 : /*
532 : * Initialize the SQLFunctionCache for a SQL function
533 : */
534 : static SQLFunctionCache *
535 86946 : init_sql_fcache(FunctionCallInfo fcinfo, bool lazyEvalOK)
536 : {
537 86946 : FmgrInfo *finfo = fcinfo->flinfo;
538 : SQLFunctionHashEntry *func;
539 : SQLFunctionCache *fcache;
540 :
541 : /*
542 : * If this is the first execution for this FmgrInfo, set up a cache struct
543 : * (initially containing null pointers). The cache must live as long as
544 : * the FmgrInfo, so it goes in fn_mcxt. Also set up a memory context
545 : * callback that will be invoked when fn_mcxt is deleted.
546 : */
547 86946 : fcache = finfo->fn_extra;
548 86946 : if (fcache == NULL)
549 : {
550 : fcache = (SQLFunctionCache *)
551 34048 : MemoryContextAllocZero(finfo->fn_mcxt, sizeof(SQLFunctionCache));
552 34048 : fcache->fcontext = finfo->fn_mcxt;
553 34048 : fcache->mcb.func = RemoveSQLFunctionCache;
554 34048 : fcache->mcb.arg = fcache;
555 34048 : MemoryContextRegisterResetCallback(finfo->fn_mcxt, &fcache->mcb);
556 34048 : finfo->fn_extra = fcache;
557 : }
558 :
559 : /*
560 : * If we are resuming execution of a set-returning function, just keep
561 : * using the same cache. We do not ask funccache.c to re-validate the
562 : * SQLFunctionHashEntry: we want to run to completion using the function's
563 : * initial definition.
564 : */
565 86946 : if (fcache->eslist != NULL)
566 : {
567 : Assert(fcache->func != NULL);
568 988 : return fcache;
569 : }
570 :
571 : /*
572 : * Look up, or re-validate, the long-lived hash entry. Make the hash key
573 : * depend on the result of get_call_result_type() when that's composite,
574 : * so that we can safely assume that we'll build a new hash entry if the
575 : * composite rowtype changes.
576 : */
577 : func = (SQLFunctionHashEntry *)
578 85958 : cached_function_compile(fcinfo,
579 85958 : (CachedFunction *) fcache->func,
580 : sql_compile_callback,
581 : sql_delete_callback,
582 : sizeof(SQLFunctionHashEntry),
583 : true,
584 : false);
585 :
586 : /*
587 : * Install the hash pointer in the SQLFunctionCache, and increment its use
588 : * count to reflect that. If cached_function_compile gave us back a
589 : * different hash entry than we were using before, we must decrement that
590 : * one's use count.
591 : */
592 85952 : if (func != fcache->func)
593 : {
594 34042 : if (fcache->func != NULL)
595 : {
596 : Assert(fcache->func->cfunc.use_count > 0);
597 0 : fcache->func->cfunc.use_count--;
598 : }
599 34042 : fcache->func = func;
600 34042 : func->cfunc.use_count++;
601 : /* Assume we need to rebuild the junkFilter */
602 34042 : fcache->junkFilter = NULL;
603 : }
604 :
605 : /*
606 : * We're beginning a new execution of the function, so convert params to
607 : * appropriate format.
608 : */
609 85952 : postquel_sub_params(fcache, fcinfo);
610 :
611 : /* Also reset lazyEval state for the new execution. */
612 85952 : fcache->lazyEvalOK = lazyEvalOK;
613 85952 : fcache->lazyEval = false;
614 :
615 : /* Also reset data about where we are in the function. */
616 85952 : fcache->eslist = NULL;
617 85952 : fcache->next_query_index = 0;
618 85952 : fcache->error_query_index = 0;
619 :
620 85952 : return fcache;
621 : }
622 :
623 : /*
624 : * Set up the per-query execution_state records for the next query within
625 : * the SQL function.
626 : *
627 : * Returns true if successful, false if there are no more queries.
628 : */
629 : static bool
630 164098 : init_execution_state(SQLFunctionCachePtr fcache)
631 : {
632 : CachedPlanSource *plansource;
633 164098 : execution_state *preves = NULL;
634 164098 : execution_state *lasttages = NULL;
635 : int nstmts;
636 : ListCell *lc;
637 :
638 : /*
639 : * Clean up after previous query, if there was one.
640 : */
641 164098 : if (fcache->cplan)
642 : {
643 78146 : ReleaseCachedPlan(fcache->cplan, fcache->cowner);
644 78146 : fcache->cplan = NULL;
645 : }
646 164098 : fcache->eslist = NULL;
647 :
648 : /*
649 : * Get the next CachedPlanSource, or stop if there are no more. We might
650 : * need to create the next CachedPlanSource; if so, advance
651 : * error_query_index first, so that errors detected in prepare_next_query
652 : * are blamed on the right statement.
653 : */
654 164098 : if (fcache->next_query_index >= list_length(fcache->func->plansource_list))
655 : {
656 80258 : if (fcache->next_query_index >= fcache->func->num_queries)
657 78056 : return false;
658 2202 : fcache->error_query_index++;
659 2202 : prepare_next_query(fcache->func);
660 : }
661 : else
662 83840 : fcache->error_query_index++;
663 :
664 86036 : plansource = (CachedPlanSource *) list_nth(fcache->func->plansource_list,
665 : fcache->next_query_index);
666 86036 : fcache->next_query_index++;
667 :
668 : /*
669 : * Generate plans for the query or queries within this CachedPlanSource.
670 : * Register the CachedPlan with the current resource owner. (Saving
671 : * cowner here is mostly paranoia, but this way we needn't assume that
672 : * CurrentResourceOwner will be the same when ShutdownSQLFunction runs.)
673 : */
674 86036 : fcache->cowner = CurrentResourceOwner;
675 86036 : fcache->cplan = GetCachedPlan(plansource,
676 : fcache->paramLI,
677 : fcache->cowner,
678 : NULL);
679 :
680 : /*
681 : * If necessary, make esarray[] bigger to hold the needed state.
682 : */
683 85986 : nstmts = list_length(fcache->cplan->stmt_list);
684 85986 : if (nstmts > fcache->esarray_len)
685 : {
686 33992 : if (fcache->esarray == NULL)
687 33992 : fcache->esarray = (execution_state *)
688 33992 : MemoryContextAlloc(fcache->fcontext,
689 : sizeof(execution_state) * nstmts);
690 : else
691 0 : fcache->esarray = repalloc_array(fcache->esarray,
692 : execution_state, nstmts);
693 33992 : fcache->esarray_len = nstmts;
694 : }
695 :
696 : /*
697 : * Build execution_state list to match the number of contained plans.
698 : */
699 171978 : foreach(lc, fcache->cplan->stmt_list)
700 : {
701 85992 : PlannedStmt *stmt = lfirst_node(PlannedStmt, lc);
702 : execution_state *newes;
703 :
704 : /*
705 : * Precheck all commands for validity in a function. This should
706 : * generally match the restrictions spi.c applies.
707 : */
708 85992 : if (stmt->commandType == CMD_UTILITY)
709 : {
710 180 : if (IsA(stmt->utilityStmt, CopyStmt) &&
711 0 : ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
712 0 : ereport(ERROR,
713 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
714 : errmsg("cannot COPY to/from client in an SQL function")));
715 :
716 180 : if (IsA(stmt->utilityStmt, TransactionStmt))
717 0 : ereport(ERROR,
718 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
719 : /* translator: %s is a SQL statement name */
720 : errmsg("%s is not allowed in an SQL function",
721 : CreateCommandName(stmt->utilityStmt))));
722 : }
723 :
724 85992 : if (fcache->func->readonly_func && !CommandIsReadOnly(stmt))
725 0 : ereport(ERROR,
726 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
727 : /* translator: %s is a SQL statement name */
728 : errmsg("%s is not allowed in a non-volatile function",
729 : CreateCommandName((Node *) stmt))));
730 :
731 : /* OK, build the execution_state for this query */
732 85992 : newes = &fcache->esarray[foreach_current_index(lc)];
733 85992 : if (preves)
734 6 : preves->next = newes;
735 : else
736 85986 : fcache->eslist = newes;
737 :
738 85992 : newes->next = NULL;
739 85992 : newes->status = F_EXEC_START;
740 85992 : newes->setsResult = false; /* might change below */
741 85992 : newes->lazyEval = false; /* might change below */
742 85992 : newes->stmt = stmt;
743 85992 : newes->qd = NULL;
744 :
745 85992 : if (stmt->canSetTag)
746 85986 : lasttages = newes;
747 :
748 85992 : preves = newes;
749 : }
750 :
751 : /*
752 : * If this isn't the last CachedPlanSource, we're done here. Otherwise,
753 : * we need to prepare information about how to return the results.
754 : */
755 85986 : if (fcache->next_query_index < fcache->func->num_queries)
756 126 : return true;
757 :
758 : /*
759 : * Construct a JunkFilter we can use to coerce the returned rowtype to the
760 : * desired form, unless the result type is VOID, in which case there's
761 : * nothing to coerce to. (XXX Frequently, the JunkFilter isn't doing
762 : * anything very interesting, but much of this module expects it to be
763 : * there anyway.)
764 : *
765 : * Normally we can re-use the JunkFilter across executions, but if the
766 : * plan for the last CachedPlanSource changed, we'd better rebuild it.
767 : *
768 : * The JunkFilter, its result slot, and its tupledesc are kept in a
769 : * subsidiary memory context so that we can free them easily when needed.
770 : */
771 85860 : if (fcache->func->rettype != VOIDOID &&
772 85566 : (fcache->junkFilter == NULL ||
773 51898 : fcache->jf_generation != fcache->cplan->generation))
774 : {
775 : TupleTableSlot *slot;
776 : List *resulttlist;
777 : MemoryContext oldcontext;
778 :
779 : /* Create or reset the jfcontext */
780 35810 : if (fcache->jfcontext == NULL)
781 33668 : fcache->jfcontext = AllocSetContextCreate(fcache->fcontext,
782 : "SQL function junkfilter",
783 : ALLOCSET_SMALL_SIZES);
784 : else
785 2142 : MemoryContextReset(fcache->jfcontext);
786 35810 : oldcontext = MemoryContextSwitchTo(fcache->jfcontext);
787 :
788 35810 : slot = MakeSingleTupleTableSlot(NULL, &TTSOpsMinimalTuple);
789 :
790 : /*
791 : * Re-fetch the (possibly modified) output tlist of the final
792 : * statement. By this point, we should have thrown an error if there
793 : * is not one.
794 : */
795 35810 : resulttlist = get_sql_fn_result_tlist(plansource->query_list);
796 :
797 : /*
798 : * If the result is composite, *and* we are returning the whole tuple
799 : * result, we need to insert nulls for any dropped columns. In the
800 : * single-column-result case, there might be dropped columns within
801 : * the composite column value, but it's not our problem here. There
802 : * should be no resjunk entries in resulttlist, so in the second case
803 : * the JunkFilter is certainly a no-op.
804 : */
805 35810 : if (fcache->func->rettupdesc && fcache->func->returnsTuple)
806 1604 : fcache->junkFilter = ExecInitJunkFilterConversion(resulttlist,
807 1604 : fcache->func->rettupdesc,
808 : slot);
809 : else
810 34206 : fcache->junkFilter = ExecInitJunkFilter(resulttlist, slot);
811 :
812 : /*
813 : * The resulttlist tree belongs to the plancache and might disappear
814 : * underneath us due to plancache invalidation. While we could
815 : * forestall that by copying it, that'd just be a waste of cycles,
816 : * because the junkfilter doesn't need it anymore. (It'd only be used
817 : * by ExecFindJunkAttribute(), which we don't use here.) To ensure
818 : * there's not a dangling pointer laying about, clear the junkFilter's
819 : * pointer.
820 : */
821 35810 : fcache->junkFilter->jf_targetList = NIL;
822 :
823 : /* Make sure output rowtype is properly blessed */
824 35810 : if (fcache->func->returnsTuple)
825 1628 : BlessTupleDesc(fcache->junkFilter->jf_resultSlot->tts_tupleDescriptor);
826 :
827 : /* Mark the JunkFilter as up-to-date */
828 35810 : fcache->jf_generation = fcache->cplan->generation;
829 :
830 35810 : MemoryContextSwitchTo(oldcontext);
831 : }
832 :
833 85860 : if (fcache->func->returnsSet &&
834 4240 : !fcache->func->returnsTuple &&
835 194 : type_is_rowtype(fcache->func->rettype))
836 : {
837 : /*
838 : * Returning rowtype as if it were scalar --- materialize won't work.
839 : * Right now it's sufficient to override any caller preference for
840 : * materialize mode, but this might need more work in future.
841 : */
842 0 : fcache->lazyEvalOK = true;
843 : }
844 :
845 : /*
846 : * Mark the last canSetTag query as delivering the function result; then,
847 : * if it is a plain SELECT, mark it for lazy evaluation. If it's not a
848 : * SELECT we must always run it to completion.
849 : *
850 : * Note: at some point we might add additional criteria for whether to use
851 : * lazy eval. However, we should prefer to use it whenever the function
852 : * doesn't return set, since fetching more than one row is useless in that
853 : * case.
854 : *
855 : * Note: don't set setsResult if the function returns VOID, as evidenced
856 : * by not having made a junkfilter. This ensures we'll throw away any
857 : * output from the last statement in such a function.
858 : */
859 85860 : if (lasttages && fcache->junkFilter)
860 : {
861 85566 : lasttages->setsResult = true;
862 85566 : if (fcache->lazyEvalOK &&
863 84732 : lasttages->stmt->commandType == CMD_SELECT &&
864 84654 : !lasttages->stmt->hasModifyingCTE)
865 84654 : fcache->lazyEval = lasttages->lazyEval = true;
866 : }
867 :
868 85860 : return true;
869 : }
870 :
871 : /*
872 : * Convert the SQL function's next query from source form (RawStmt or Query)
873 : * into a CachedPlanSource. If it's the last query, also determine whether
874 : * the function returnsTuple.
875 : */
876 : static void
877 2202 : prepare_next_query(SQLFunctionHashEntry *func)
878 : {
879 : int qindex;
880 : bool islast;
881 : CachedPlanSource *plansource;
882 : List *queryTree_list;
883 : MemoryContext oldcontext;
884 :
885 : /* Which query should we process? */
886 2202 : qindex = list_length(func->plansource_list);
887 : Assert(qindex < func->num_queries); /* else caller error */
888 2202 : islast = (qindex + 1 >= func->num_queries);
889 :
890 : /*
891 : * Parse and/or rewrite the query, creating a CachedPlanSource that holds
892 : * a copy of the original parsetree. Note fine point: we make a copy of
893 : * each original parsetree to ensure that the source_list in pcontext
894 : * remains unmodified during parse analysis and rewrite. This is normally
895 : * unnecessary, but we have to do it in case an error is raised during
896 : * parse analysis. Otherwise, a fresh attempt to execute the function
897 : * will arrive back here and try to work from a corrupted source_list.
898 : */
899 2202 : if (!func->raw_source)
900 : {
901 : /* Source queries are already parse-analyzed */
902 886 : Query *parsetree = list_nth_node(Query, func->source_list, qindex);
903 :
904 886 : parsetree = copyObject(parsetree);
905 886 : plansource = CreateCachedPlanForQuery(parsetree,
906 886 : func->src,
907 : CreateCommandTag((Node *) parsetree));
908 886 : AcquireRewriteLocks(parsetree, true, false);
909 886 : queryTree_list = pg_rewrite_query(parsetree);
910 : }
911 : else
912 : {
913 : /* Source queries are raw parsetrees */
914 1316 : RawStmt *parsetree = list_nth_node(RawStmt, func->source_list, qindex);
915 :
916 1316 : parsetree = copyObject(parsetree);
917 1316 : plansource = CreateCachedPlan(parsetree,
918 1316 : func->src,
919 : CreateCommandTag(parsetree->stmt));
920 1316 : queryTree_list = pg_analyze_and_rewrite_withcb(parsetree,
921 1316 : func->src,
922 : (ParserSetupHook) sql_fn_parser_setup,
923 1316 : func->pinfo,
924 : NULL);
925 : }
926 :
927 : /*
928 : * Check that there are no statements we don't want to allow.
929 : */
930 2202 : check_sql_fn_statement(queryTree_list);
931 :
932 : /*
933 : * If this is the last query, check that the function returns the type it
934 : * claims to. Although in simple cases this was already done when the
935 : * function was defined, we have to recheck because database objects used
936 : * in the function's queries might have changed type. We'd have to
937 : * recheck anyway if the function had any polymorphic arguments. Moreover,
938 : * check_sql_stmt_retval takes care of injecting any required column type
939 : * coercions. (But we don't ask it to insert nulls for dropped columns;
940 : * the junkfilter handles that.)
941 : *
942 : * Note: we set func->returnsTuple according to whether we are returning
943 : * the whole tuple result or just a single column. In the latter case we
944 : * clear returnsTuple because we need not act different from the scalar
945 : * result case, even if it's a rowtype column. (However, we have to force
946 : * lazy eval mode in that case; otherwise we'd need extra code to expand
947 : * the rowtype column into multiple columns, since we have no way to
948 : * notify the caller that it should do that.)
949 : */
950 2202 : if (islast)
951 2126 : func->returnsTuple = check_sql_stmt_retval(queryTree_list,
952 : func->rettype,
953 : func->rettupdesc,
954 2132 : func->prokind,
955 : false);
956 :
957 : /*
958 : * Now that check_sql_stmt_retval has done its thing, we can complete plan
959 : * cache entry creation.
960 : */
961 2196 : CompleteCachedPlan(plansource,
962 : queryTree_list,
963 : NULL,
964 : NULL,
965 : 0,
966 : (ParserSetupHook) sql_fn_parser_setup,
967 2196 : func->pinfo,
968 : CURSOR_OPT_PARALLEL_OK | CURSOR_OPT_NO_SCROLL,
969 : false);
970 :
971 : /*
972 : * Install post-rewrite hook. Its arg is the hash entry if this is the
973 : * last statement, else NULL.
974 : */
975 2196 : SetPostRewriteHook(plansource,
976 : sql_postrewrite_callback,
977 : islast ? func : NULL);
978 :
979 : /*
980 : * While the CachedPlanSources can take care of themselves, our List
981 : * pointing to them had better be in the hcontext.
982 : */
983 2196 : oldcontext = MemoryContextSwitchTo(func->hcontext);
984 2196 : func->plansource_list = lappend(func->plansource_list, plansource);
985 2196 : MemoryContextSwitchTo(oldcontext);
986 :
987 : /*
988 : * As soon as we've linked the CachedPlanSource into the list, mark it as
989 : * "saved".
990 : */
991 2196 : SaveCachedPlan(plansource);
992 :
993 : /*
994 : * Finally, if this was the last statement, we can flush the pcontext with
995 : * the original query trees; they're all safely copied into
996 : * CachedPlanSources now.
997 : */
998 2196 : if (islast)
999 : {
1000 2126 : func->source_list = NIL; /* avoid dangling pointer */
1001 2126 : MemoryContextDelete(func->pcontext);
1002 2126 : func->pcontext = NULL;
1003 : }
1004 2196 : }
1005 :
1006 : /*
1007 : * Fill a new SQLFunctionHashEntry.
1008 : *
1009 : * The passed-in "cfunc" struct is expected to be zeroes, except
1010 : * for the CachedFunction fields, which we don't touch here.
1011 : *
1012 : * We expect to be called in a short-lived memory context (typically a
1013 : * query's per-tuple context). Data that is to be part of the hash entry
1014 : * must be copied into the hcontext or pcontext as appropriate.
1015 : */
1016 : static void
1017 2168 : sql_compile_callback(FunctionCallInfo fcinfo,
1018 : HeapTuple procedureTuple,
1019 : const CachedFunctionHashKey *hashkey,
1020 : CachedFunction *cfunc,
1021 : bool forValidator)
1022 : {
1023 2168 : SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) cfunc;
1024 2168 : Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
1025 : ErrorContextCallback comperrcontext;
1026 : MemoryContext hcontext;
1027 : MemoryContext pcontext;
1028 2168 : MemoryContext oldcontext = CurrentMemoryContext;
1029 : Oid rettype;
1030 : TupleDesc rettupdesc;
1031 : Datum tmp;
1032 : bool isNull;
1033 : List *source_list;
1034 :
1035 : /*
1036 : * Setup error traceback support for ereport() during compile. (This is
1037 : * mainly useful for reporting parse errors from pg_parse_query.)
1038 : */
1039 2168 : comperrcontext.callback = sql_compile_error_callback;
1040 2168 : comperrcontext.arg = func;
1041 2168 : comperrcontext.previous = error_context_stack;
1042 2168 : error_context_stack = &comperrcontext;
1043 :
1044 : /*
1045 : * Create the hash entry's memory context. For now it's a child of the
1046 : * caller's context, so that it will go away if we fail partway through.
1047 : */
1048 2168 : hcontext = AllocSetContextCreate(CurrentMemoryContext,
1049 : "SQL function",
1050 : ALLOCSET_SMALL_SIZES);
1051 :
1052 : /*
1053 : * Create the not-as-long-lived pcontext. We make this a child of
1054 : * hcontext so that it doesn't require separate deletion.
1055 : */
1056 2168 : pcontext = AllocSetContextCreate(hcontext,
1057 : "SQL function parse trees",
1058 : ALLOCSET_SMALL_SIZES);
1059 2168 : func->pcontext = pcontext;
1060 :
1061 : /*
1062 : * copy function name immediately for use by error reporting callback, and
1063 : * for use as memory context identifier
1064 : */
1065 4336 : func->fname = MemoryContextStrdup(hcontext,
1066 2168 : NameStr(procedureStruct->proname));
1067 2168 : MemoryContextSetIdentifier(hcontext, func->fname);
1068 :
1069 : /*
1070 : * Resolve any polymorphism, obtaining the actual result type, and the
1071 : * corresponding tupdesc if it's a rowtype.
1072 : */
1073 2168 : (void) get_call_result_type(fcinfo, &rettype, &rettupdesc);
1074 :
1075 2168 : func->rettype = rettype;
1076 2168 : if (rettupdesc)
1077 : {
1078 530 : MemoryContextSwitchTo(hcontext);
1079 530 : func->rettupdesc = CreateTupleDescCopy(rettupdesc);
1080 530 : MemoryContextSwitchTo(oldcontext);
1081 : }
1082 :
1083 : /* Fetch the typlen and byval info for the result type */
1084 2168 : get_typlenbyval(rettype, &func->typlen, &func->typbyval);
1085 :
1086 : /* Remember whether we're returning setof something */
1087 2168 : func->returnsSet = procedureStruct->proretset;
1088 :
1089 : /* Remember if function is STABLE/IMMUTABLE */
1090 2168 : func->readonly_func =
1091 2168 : (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
1092 :
1093 : /* Remember routine kind */
1094 2168 : func->prokind = procedureStruct->prokind;
1095 :
1096 : /*
1097 : * We need the actual argument types to pass to the parser. Also make
1098 : * sure that parameter symbols are considered to have the function's
1099 : * resolved input collation.
1100 : */
1101 2168 : MemoryContextSwitchTo(hcontext);
1102 4336 : func->pinfo = prepare_sql_fn_parse_info(procedureTuple,
1103 2168 : fcinfo->flinfo->fn_expr,
1104 : PG_GET_COLLATION());
1105 2168 : MemoryContextSwitchTo(oldcontext);
1106 :
1107 : /*
1108 : * Now that we have the resolved argument types, collect their typlens for
1109 : * use in postquel_sub_params.
1110 : */
1111 2168 : func->argtyplen = (int16 *)
1112 2168 : MemoryContextAlloc(hcontext, func->pinfo->nargs * sizeof(int16));
1113 5296 : for (int i = 0; i < func->pinfo->nargs; i++)
1114 3128 : func->argtyplen[i] = get_typlen(func->pinfo->argtypes[i]);
1115 :
1116 : /*
1117 : * And of course we need the function body text.
1118 : */
1119 2168 : tmp = SysCacheGetAttrNotNull(PROCOID, procedureTuple, Anum_pg_proc_prosrc);
1120 2168 : func->src = MemoryContextStrdup(hcontext,
1121 2168 : TextDatumGetCString(tmp));
1122 :
1123 : /* If we have prosqlbody, pay attention to that not prosrc. */
1124 2168 : tmp = SysCacheGetAttr(PROCOID,
1125 : procedureTuple,
1126 : Anum_pg_proc_prosqlbody,
1127 : &isNull);
1128 2168 : if (!isNull)
1129 : {
1130 : /* Source queries are already parse-analyzed */
1131 : Node *n;
1132 :
1133 886 : n = stringToNode(TextDatumGetCString(tmp));
1134 886 : if (IsA(n, List))
1135 656 : source_list = linitial_node(List, castNode(List, n));
1136 : else
1137 230 : source_list = list_make1(n);
1138 886 : func->raw_source = false;
1139 : }
1140 : else
1141 : {
1142 : /* Source queries are raw parsetrees */
1143 1282 : source_list = pg_parse_query(func->src);
1144 1282 : func->raw_source = true;
1145 : }
1146 :
1147 : /*
1148 : * Note: we must save the number of queries so that we'll still remember
1149 : * how many there are after we discard source_list.
1150 : */
1151 2168 : func->num_queries = list_length(source_list);
1152 :
1153 : /*
1154 : * Edge case: empty function body is OK only if it returns VOID. Normally
1155 : * we validate that the last statement returns the right thing in
1156 : * check_sql_stmt_retval, but we'll never reach that if there's no last
1157 : * statement.
1158 : */
1159 2168 : if (func->num_queries == 0 && rettype != VOIDOID)
1160 6 : ereport(ERROR,
1161 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1162 : errmsg("return type mismatch in function declared to return %s",
1163 : format_type_be(rettype)),
1164 : errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
1165 :
1166 : /* Save the source trees in pcontext for now. */
1167 2162 : MemoryContextSwitchTo(pcontext);
1168 2162 : func->source_list = copyObject(source_list);
1169 2162 : MemoryContextSwitchTo(oldcontext);
1170 :
1171 : /*
1172 : * We now have a fully valid hash entry, so reparent hcontext under
1173 : * CacheMemoryContext to make all the subsidiary data long-lived, and only
1174 : * then install the hcontext link so that sql_delete_callback will know to
1175 : * delete it.
1176 : */
1177 2162 : MemoryContextSetParent(hcontext, CacheMemoryContext);
1178 2162 : func->hcontext = hcontext;
1179 :
1180 2162 : error_context_stack = comperrcontext.previous;
1181 2162 : }
1182 :
1183 : /*
1184 : * Deletion callback used by funccache.c.
1185 : *
1186 : * Free any free-able subsidiary data of cfunc, but not the
1187 : * struct CachedFunction itself.
1188 : */
1189 : static void
1190 66 : sql_delete_callback(CachedFunction *cfunc)
1191 : {
1192 66 : SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) cfunc;
1193 : ListCell *lc;
1194 :
1195 : /* Release the CachedPlanSources */
1196 132 : foreach(lc, func->plansource_list)
1197 : {
1198 66 : CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1199 :
1200 66 : DropCachedPlan(plansource);
1201 : }
1202 66 : func->plansource_list = NIL;
1203 :
1204 : /*
1205 : * If we have an hcontext, free it, thereby getting rid of all subsidiary
1206 : * data. (If we still have a pcontext, this gets rid of that too.)
1207 : */
1208 66 : if (func->hcontext)
1209 66 : MemoryContextDelete(func->hcontext);
1210 66 : func->hcontext = NULL;
1211 66 : }
1212 :
1213 : /*
1214 : * Post-rewrite callback used by plancache.c.
1215 : *
1216 : * This must match the processing that prepare_next_query() does between
1217 : * rewriting and calling CompleteCachedPlan().
1218 : */
1219 : static void
1220 346 : sql_postrewrite_callback(List *querytree_list, void *arg)
1221 : {
1222 : /*
1223 : * Check that there are no statements we don't want to allow. (Presently,
1224 : * there's no real point in this because the result can't change from what
1225 : * we saw originally. But it's cheap and maybe someday it will matter.)
1226 : */
1227 346 : check_sql_fn_statement(querytree_list);
1228 :
1229 : /*
1230 : * If this is the last query, we must re-do what check_sql_stmt_retval did
1231 : * to its targetlist. Also check that returnsTuple didn't change (it
1232 : * probably cannot, but be cautious).
1233 : */
1234 346 : if (arg != NULL)
1235 : {
1236 346 : SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) arg;
1237 : bool returnsTuple;
1238 :
1239 346 : returnsTuple = check_sql_stmt_retval(querytree_list,
1240 : func->rettype,
1241 : func->rettupdesc,
1242 346 : func->prokind,
1243 : false);
1244 346 : if (returnsTuple != func->returnsTuple)
1245 0 : ereport(ERROR,
1246 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1247 : errmsg("cached plan must not change result type")));
1248 : }
1249 346 : }
1250 :
1251 : /* Start up execution of one execution_state node */
1252 : static void
1253 85992 : postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
1254 : {
1255 : DestReceiver *dest;
1256 85992 : MemoryContext oldcontext = CurrentMemoryContext;
1257 :
1258 : Assert(es->qd == NULL);
1259 :
1260 : /* Caller should have ensured a suitable snapshot is active */
1261 : Assert(ActiveSnapshotSet());
1262 :
1263 : /*
1264 : * In lazyEval mode for a SRF, we must run the sub-executor in a child of
1265 : * fcontext, so that it can survive across multiple calls to fmgr_sql.
1266 : * (XXX in the case of a long-lived FmgrInfo, this policy potentially
1267 : * causes memory leakage, but it's not very clear where we could keep
1268 : * stuff instead. Fortunately, there are few if any cases where
1269 : * set-returning functions are invoked via FmgrInfos that would outlive
1270 : * the calling query.) Otherwise, we're going to run it to completion
1271 : * before exiting fmgr_sql, so it can perfectly well run in the caller's
1272 : * context.
1273 : */
1274 85992 : if (es->lazyEval && fcache->func->returnsSet)
1275 : {
1276 3176 : fcache->subcontext = AllocSetContextCreate(fcache->fcontext,
1277 : "SQL function execution",
1278 : ALLOCSET_DEFAULT_SIZES);
1279 3176 : fcache->ownSubcontext = true;
1280 : }
1281 82816 : else if (es->stmt->commandType == CMD_UTILITY)
1282 : {
1283 : /*
1284 : * The code path using a sub-executor is pretty good about cleaning up
1285 : * cruft, since the executor will make its own sub-context. We don't
1286 : * really need an additional layer of sub-context in that case.
1287 : * However, if this is a utility statement, it won't make its own
1288 : * sub-context, so it seems advisable to make one that we can free on
1289 : * completion.
1290 : */
1291 180 : fcache->subcontext = AllocSetContextCreate(CurrentMemoryContext,
1292 : "SQL function execution",
1293 : ALLOCSET_DEFAULT_SIZES);
1294 180 : fcache->ownSubcontext = true;
1295 : }
1296 : else
1297 : {
1298 82636 : fcache->subcontext = CurrentMemoryContext;
1299 82636 : fcache->ownSubcontext = false;
1300 : }
1301 :
1302 : /*
1303 : * Build a tuplestore if needed, that is if it's a set-returning function
1304 : * and we're producing the function result without using lazyEval mode.
1305 : */
1306 85992 : if (es->setsResult)
1307 : {
1308 : Assert(fcache->tstore == NULL);
1309 85566 : if (fcache->func->returnsSet && !es->lazyEval)
1310 : {
1311 864 : MemoryContextSwitchTo(fcache->tscontext);
1312 864 : fcache->tstore = tuplestore_begin_heap(fcache->randomAccess,
1313 : false, work_mem);
1314 : }
1315 : }
1316 :
1317 : /* Switch into the selected subcontext (might be a no-op) */
1318 85992 : MemoryContextSwitchTo(fcache->subcontext);
1319 :
1320 : /*
1321 : * If this query produces the function result, collect its output using
1322 : * our custom DestReceiver; else discard any output.
1323 : */
1324 85992 : if (es->setsResult)
1325 : {
1326 : DR_sqlfunction *myState;
1327 :
1328 85566 : dest = CreateDestReceiver(DestSQLFunction);
1329 : /* pass down the needed info to the dest receiver routines */
1330 85566 : myState = (DR_sqlfunction *) dest;
1331 : Assert(myState->pub.mydest == DestSQLFunction);
1332 85566 : myState->tstore = fcache->tstore; /* might be NULL */
1333 85566 : myState->filter = fcache->junkFilter;
1334 :
1335 : /* Make very sure the junkfilter's result slot is empty */
1336 85566 : ExecClearTuple(fcache->junkFilter->jf_resultSlot);
1337 : }
1338 : else
1339 426 : dest = None_Receiver;
1340 :
1341 85992 : es->qd = CreateQueryDesc(es->stmt,
1342 85992 : fcache->func->src,
1343 : GetActiveSnapshot(),
1344 : InvalidSnapshot,
1345 : dest,
1346 : fcache->paramLI,
1347 85992 : es->qd ? es->qd->queryEnv : NULL,
1348 : 0);
1349 :
1350 : /* Utility commands don't need Executor. */
1351 85992 : if (es->qd->operation != CMD_UTILITY)
1352 : {
1353 : /*
1354 : * In lazyEval mode, do not let the executor set up an AfterTrigger
1355 : * context. This is necessary not just an optimization, because we
1356 : * mustn't exit from the function execution with a stacked
1357 : * AfterTrigger level still active. We are careful not to select
1358 : * lazyEval mode for any statement that could possibly queue triggers.
1359 : */
1360 : int eflags;
1361 :
1362 85812 : if (es->lazyEval)
1363 84654 : eflags = EXEC_FLAG_SKIP_TRIGGERS;
1364 : else
1365 1158 : eflags = 0; /* default run-to-completion flags */
1366 85812 : ExecutorStart(es->qd, eflags);
1367 : }
1368 :
1369 85986 : es->status = F_EXEC_RUN;
1370 :
1371 85986 : MemoryContextSwitchTo(oldcontext);
1372 85986 : }
1373 :
1374 : /* Run one execution_state; either to completion or to first result row */
1375 : /* Returns true if we ran to completion */
1376 : static bool
1377 86974 : postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
1378 : {
1379 : bool result;
1380 : MemoryContext oldcontext;
1381 :
1382 : /* Run the sub-executor in subcontext */
1383 86974 : oldcontext = MemoryContextSwitchTo(fcache->subcontext);
1384 :
1385 86974 : if (es->qd->operation == CMD_UTILITY)
1386 : {
1387 180 : ProcessUtility(es->qd->plannedstmt,
1388 180 : fcache->func->src,
1389 : true, /* protect function cache's parsetree */
1390 : PROCESS_UTILITY_QUERY,
1391 180 : es->qd->params,
1392 180 : es->qd->queryEnv,
1393 180 : es->qd->dest,
1394 : NULL);
1395 90 : result = true; /* never stops early */
1396 : }
1397 : else
1398 : {
1399 : /* Run regular commands to completion unless lazyEval */
1400 86794 : uint64 count = (es->lazyEval) ? 1 : 0;
1401 :
1402 86794 : ExecutorRun(es->qd, ForwardScanDirection, count);
1403 :
1404 : /*
1405 : * If we requested run to completion OR there was no tuple returned,
1406 : * command must be complete.
1407 : */
1408 79074 : result = (count == 0 || es->qd->estate->es_processed == 0);
1409 : }
1410 :
1411 79164 : MemoryContextSwitchTo(oldcontext);
1412 :
1413 79164 : return result;
1414 : }
1415 :
1416 : /* Shut down execution of one execution_state node */
1417 : static void
1418 78176 : postquel_end(execution_state *es, SQLFunctionCachePtr fcache)
1419 : {
1420 : MemoryContext oldcontext;
1421 :
1422 : /* Run the sub-executor in subcontext */
1423 78176 : oldcontext = MemoryContextSwitchTo(fcache->subcontext);
1424 :
1425 : /* mark status done to ensure we don't do ExecutorEnd twice */
1426 78176 : es->status = F_EXEC_DONE;
1427 :
1428 : /* Utility commands don't need Executor. */
1429 78176 : if (es->qd->operation != CMD_UTILITY)
1430 : {
1431 78086 : ExecutorFinish(es->qd);
1432 78068 : ExecutorEnd(es->qd);
1433 : }
1434 :
1435 78158 : es->qd->dest->rDestroy(es->qd->dest);
1436 :
1437 78158 : FreeQueryDesc(es->qd);
1438 78158 : es->qd = NULL;
1439 :
1440 78158 : MemoryContextSwitchTo(oldcontext);
1441 :
1442 : /* Delete the subcontext, if it's actually a separate context */
1443 78158 : if (fcache->ownSubcontext)
1444 3266 : MemoryContextDelete(fcache->subcontext);
1445 78158 : fcache->subcontext = NULL;
1446 78158 : }
1447 :
1448 : /* Build ParamListInfo array representing current arguments */
1449 : static void
1450 85952 : postquel_sub_params(SQLFunctionCachePtr fcache,
1451 : FunctionCallInfo fcinfo)
1452 : {
1453 85952 : int nargs = fcinfo->nargs;
1454 :
1455 85952 : if (nargs > 0)
1456 : {
1457 : ParamListInfo paramLI;
1458 77394 : Oid *argtypes = fcache->func->pinfo->argtypes;
1459 77394 : int16 *argtyplen = fcache->func->argtyplen;
1460 :
1461 77394 : if (fcache->paramLI == NULL)
1462 : {
1463 : /* First time through: build a persistent ParamListInfo struct */
1464 : MemoryContext oldcontext;
1465 :
1466 25520 : oldcontext = MemoryContextSwitchTo(fcache->fcontext);
1467 25520 : paramLI = makeParamList(nargs);
1468 25520 : fcache->paramLI = paramLI;
1469 25520 : MemoryContextSwitchTo(oldcontext);
1470 : }
1471 : else
1472 : {
1473 51874 : paramLI = fcache->paramLI;
1474 : Assert(paramLI->numParams == nargs);
1475 : }
1476 :
1477 228072 : for (int i = 0; i < nargs; i++)
1478 : {
1479 150678 : ParamExternData *prm = ¶mLI->params[i];
1480 :
1481 : /*
1482 : * If an incoming parameter value is a R/W expanded datum, we
1483 : * force it to R/O. We'd be perfectly entitled to scribble on it,
1484 : * but the problem is that if the parameter is referenced more
1485 : * than once in the function, earlier references might mutate the
1486 : * value seen by later references, which won't do at all. We
1487 : * could do better if we could be sure of the number of Param
1488 : * nodes in the function's plans; but we might not have planned
1489 : * all the statements yet, nor do we have plan tree walker
1490 : * infrastructure. (Examining the parse trees is not good enough,
1491 : * because of possible function inlining during planning.)
1492 : */
1493 150678 : prm->isnull = fcinfo->args[i].isnull;
1494 150678 : prm->value = MakeExpandedObjectReadOnly(fcinfo->args[i].value,
1495 : prm->isnull,
1496 : argtyplen[i]);
1497 : /* Allow the value to be substituted into custom plans */
1498 150678 : prm->pflags = PARAM_FLAG_CONST;
1499 150678 : prm->ptype = argtypes[i];
1500 : }
1501 : }
1502 : else
1503 8558 : fcache->paramLI = NULL;
1504 85952 : }
1505 :
1506 : /*
1507 : * Extract the SQL function's value from a single result row. This is used
1508 : * both for scalar (non-set) functions and for each row of a lazy-eval set
1509 : * result. We expect the current memory context to be that of the caller
1510 : * of fmgr_sql.
1511 : */
1512 : static Datum
1513 69968 : postquel_get_single_result(TupleTableSlot *slot,
1514 : FunctionCallInfo fcinfo,
1515 : SQLFunctionCachePtr fcache)
1516 : {
1517 : Datum value;
1518 :
1519 : /*
1520 : * Set up to return the function value. For pass-by-reference datatypes,
1521 : * be sure to copy the result into the current context. We can't leave
1522 : * the data in the TupleTableSlot because we must clear the slot before
1523 : * returning.
1524 : */
1525 69968 : if (fcache->func->returnsTuple)
1526 : {
1527 : /* We must return the whole tuple as a Datum. */
1528 1470 : fcinfo->isnull = false;
1529 1470 : value = ExecFetchSlotHeapTupleDatum(slot);
1530 : }
1531 : else
1532 : {
1533 : /*
1534 : * Returning a scalar, which we have to extract from the first column
1535 : * of the SELECT result, and then copy into current context if needed.
1536 : */
1537 68498 : value = slot_getattr(slot, 1, &(fcinfo->isnull));
1538 :
1539 68498 : if (!fcinfo->isnull)
1540 68104 : value = datumCopy(value, fcache->func->typbyval, fcache->func->typlen);
1541 : }
1542 :
1543 : /* Clear the slot for next time */
1544 69968 : ExecClearTuple(slot);
1545 :
1546 69968 : return value;
1547 : }
1548 :
1549 : /*
1550 : * fmgr_sql: function call manager for SQL functions
1551 : */
1552 : Datum
1553 86946 : fmgr_sql(PG_FUNCTION_ARGS)
1554 : {
1555 : SQLFunctionCachePtr fcache;
1556 : ErrorContextCallback sqlerrcontext;
1557 : MemoryContext tscontext;
1558 : bool randomAccess;
1559 : bool lazyEvalOK;
1560 : bool pushed_snapshot;
1561 : execution_state *es;
1562 : TupleTableSlot *slot;
1563 : Datum result;
1564 :
1565 : /* Check call context */
1566 86946 : if (fcinfo->flinfo->fn_retset)
1567 : {
1568 5040 : ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1569 :
1570 : /*
1571 : * For simplicity, we require callers to support both set eval modes.
1572 : * There are cases where we must use one or must use the other, and
1573 : * it's not really worthwhile to postpone the check till we know. But
1574 : * note we do not require caller to provide an expectedDesc.
1575 : */
1576 5040 : if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1577 5040 : (rsi->allowedModes & SFRM_ValuePerCall) == 0 ||
1578 5040 : (rsi->allowedModes & SFRM_Materialize) == 0)
1579 0 : ereport(ERROR,
1580 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1581 : errmsg("set-valued function called in context that cannot accept a set")));
1582 5040 : randomAccess = rsi->allowedModes & SFRM_Materialize_Random;
1583 5040 : lazyEvalOK = !(rsi->allowedModes & SFRM_Materialize_Preferred);
1584 : /* tuplestore, if used, must have query lifespan */
1585 5040 : tscontext = rsi->econtext->ecxt_per_query_memory;
1586 : }
1587 : else
1588 : {
1589 81906 : randomAccess = false;
1590 81906 : lazyEvalOK = true;
1591 : /* we won't need a tuplestore */
1592 81906 : tscontext = NULL;
1593 : }
1594 :
1595 : /*
1596 : * Initialize fcache if starting a fresh execution.
1597 : */
1598 86946 : fcache = init_sql_fcache(fcinfo, lazyEvalOK);
1599 :
1600 : /* Remember info that we might need later to construct tuplestore */
1601 86940 : fcache->tscontext = tscontext;
1602 86940 : fcache->randomAccess = randomAccess;
1603 :
1604 : /*
1605 : * Now we can set up error traceback support for ereport()
1606 : */
1607 86940 : sqlerrcontext.callback = sql_exec_error_callback;
1608 86940 : sqlerrcontext.arg = fcache;
1609 86940 : sqlerrcontext.previous = error_context_stack;
1610 86940 : error_context_stack = &sqlerrcontext;
1611 :
1612 : /*
1613 : * Find first unfinished execution_state. If none, advance to the next
1614 : * query in function.
1615 : */
1616 : do
1617 : {
1618 172830 : es = fcache->eslist;
1619 172830 : while (es && es->status == F_EXEC_DONE)
1620 0 : es = es->next;
1621 172830 : if (es)
1622 86878 : break;
1623 85952 : } while (init_execution_state(fcache));
1624 :
1625 : /*
1626 : * Execute each command in the function one after another until we either
1627 : * run out of commands or get a result row from a lazily-evaluated SELECT.
1628 : *
1629 : * Notes about snapshot management:
1630 : *
1631 : * In a read-only function, we just use the surrounding query's snapshot.
1632 : *
1633 : * In a non-read-only function, we rely on the fact that we'll never
1634 : * suspend execution between queries of the function: the only reason to
1635 : * suspend execution before completion is if we are returning a row from a
1636 : * lazily-evaluated SELECT. So, when first entering this loop, we'll
1637 : * either start a new query (and push a fresh snapshot) or re-establish
1638 : * the active snapshot from the existing query descriptor. If we need to
1639 : * start a new query in a subsequent execution of the loop, either we need
1640 : * a fresh snapshot (and pushed_snapshot is false) or the existing
1641 : * snapshot is on the active stack and we can just bump its command ID.
1642 : */
1643 86884 : pushed_snapshot = false;
1644 165036 : while (es)
1645 : {
1646 : bool completed;
1647 :
1648 86980 : if (es->status == F_EXEC_START)
1649 : {
1650 : /*
1651 : * If not read-only, be sure to advance the command counter for
1652 : * each command, so that all work to date in this transaction is
1653 : * visible. Take a new snapshot if we don't have one yet,
1654 : * otherwise just bump the command ID in the existing snapshot.
1655 : */
1656 85992 : if (!fcache->func->readonly_func)
1657 : {
1658 73338 : CommandCounterIncrement();
1659 73338 : if (!pushed_snapshot)
1660 : {
1661 73332 : PushActiveSnapshot(GetTransactionSnapshot());
1662 73332 : pushed_snapshot = true;
1663 : }
1664 : else
1665 6 : UpdateActiveSnapshotCommandId();
1666 : }
1667 :
1668 85992 : postquel_start(es, fcache);
1669 : }
1670 988 : else if (!fcache->func->readonly_func && !pushed_snapshot)
1671 : {
1672 : /* Re-establish active snapshot when re-entering function */
1673 640 : PushActiveSnapshot(es->qd->snapshot);
1674 640 : pushed_snapshot = true;
1675 : }
1676 :
1677 86974 : completed = postquel_getnext(es, fcache);
1678 :
1679 : /*
1680 : * If we ran the command to completion, we can shut it down now. Any
1681 : * row(s) we need to return are safely stashed in the result slot or
1682 : * tuplestore, and we want to be sure that, for example, AFTER
1683 : * triggers get fired before we return anything. Also, if the
1684 : * function doesn't return set, we can shut it down anyway because it
1685 : * must be a SELECT and we don't care about fetching any more result
1686 : * rows.
1687 : */
1688 79164 : if (completed || !fcache->func->returnsSet)
1689 78170 : postquel_end(es, fcache);
1690 :
1691 : /*
1692 : * Break from loop if we didn't shut down (implying we got a
1693 : * lazily-evaluated row). Otherwise we'll press on till the whole
1694 : * function is done, relying on the tuplestore to keep hold of the
1695 : * data to eventually be returned. This is necessary since an
1696 : * INSERT/UPDATE/DELETE RETURNING that sets the result might be
1697 : * followed by additional rule-inserted commands, and we want to
1698 : * finish doing all those commands before we return anything.
1699 : */
1700 79146 : if (es->status != F_EXEC_DONE)
1701 994 : break;
1702 :
1703 : /*
1704 : * Advance to next execution_state, and perhaps next query.
1705 : */
1706 78152 : es = es->next;
1707 78248 : while (!es)
1708 : {
1709 : /*
1710 : * Flush the current snapshot so that we will take a new one for
1711 : * the new query list. This ensures that new snaps are taken at
1712 : * original-query boundaries, matching the behavior of interactive
1713 : * execution.
1714 : */
1715 78146 : if (pushed_snapshot)
1716 : {
1717 65530 : PopActiveSnapshot();
1718 65530 : pushed_snapshot = false;
1719 : }
1720 :
1721 78146 : if (!init_execution_state(fcache))
1722 78050 : break; /* end of function */
1723 :
1724 96 : es = fcache->eslist;
1725 : }
1726 : }
1727 :
1728 : /*
1729 : * The result slot or tuplestore now contains whatever row(s) we are
1730 : * supposed to return.
1731 : */
1732 79050 : if (fcache->func->returnsSet)
1733 : {
1734 5034 : ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1735 :
1736 5034 : if (es)
1737 : {
1738 : /*
1739 : * If we stopped short of being done, we must have a lazy-eval
1740 : * row.
1741 : */
1742 : Assert(es->lazyEval);
1743 : /* The junkfilter's result slot contains the query result tuple */
1744 : Assert(fcache->junkFilter);
1745 994 : slot = fcache->junkFilter->jf_resultSlot;
1746 : Assert(!TTS_EMPTY(slot));
1747 : /* Extract the result as a datum, and copy out from the slot */
1748 994 : result = postquel_get_single_result(slot, fcinfo, fcache);
1749 :
1750 : /*
1751 : * Let caller know we're not finished.
1752 : */
1753 994 : rsi->isDone = ExprMultipleResult;
1754 :
1755 : /*
1756 : * Ensure we will get shut down cleanly if the exprcontext is not
1757 : * run to completion.
1758 : */
1759 994 : if (!fcache->shutdown_reg)
1760 : {
1761 726 : RegisterExprContextCallback(rsi->econtext,
1762 : ShutdownSQLFunction,
1763 : PointerGetDatum(fcache));
1764 726 : fcache->shutdown_reg = true;
1765 : }
1766 : }
1767 4040 : else if (fcache->lazyEval)
1768 : {
1769 : /*
1770 : * We are done with a lazy evaluation. Let caller know we're
1771 : * finished.
1772 : */
1773 3170 : rsi->isDone = ExprEndResult;
1774 :
1775 3170 : fcinfo->isnull = true;
1776 3170 : result = (Datum) 0;
1777 :
1778 : /* Deregister shutdown callback, if we made one */
1779 3170 : if (fcache->shutdown_reg)
1780 : {
1781 720 : UnregisterExprContextCallback(rsi->econtext,
1782 : ShutdownSQLFunction,
1783 : PointerGetDatum(fcache));
1784 720 : fcache->shutdown_reg = false;
1785 : }
1786 : }
1787 : else
1788 : {
1789 : /*
1790 : * We are done with a non-lazy evaluation. Return whatever is in
1791 : * the tuplestore. (It is now caller's responsibility to free the
1792 : * tuplestore when done.)
1793 : *
1794 : * Note an edge case: we could get here without having made a
1795 : * tuplestore if the function is declared to return SETOF VOID.
1796 : * ExecMakeTableFunctionResult will cope with null setResult.
1797 : */
1798 : Assert(fcache->tstore || fcache->func->rettype == VOIDOID);
1799 870 : rsi->returnMode = SFRM_Materialize;
1800 870 : rsi->setResult = fcache->tstore;
1801 870 : fcache->tstore = NULL;
1802 : /* must copy desc because execSRF.c will free it */
1803 870 : if (fcache->junkFilter)
1804 864 : rsi->setDesc = CreateTupleDescCopy(fcache->junkFilter->jf_cleanTupType);
1805 :
1806 870 : fcinfo->isnull = true;
1807 870 : result = (Datum) 0;
1808 :
1809 : /* Deregister shutdown callback, if we made one */
1810 870 : if (fcache->shutdown_reg)
1811 : {
1812 0 : UnregisterExprContextCallback(rsi->econtext,
1813 : ShutdownSQLFunction,
1814 : PointerGetDatum(fcache));
1815 0 : fcache->shutdown_reg = false;
1816 : }
1817 : }
1818 : }
1819 : else
1820 : {
1821 : /*
1822 : * Non-set function. If we got a row, return it; else return NULL.
1823 : */
1824 74016 : if (fcache->junkFilter)
1825 : {
1826 : /* The junkfilter's result slot contains the query result tuple */
1827 73802 : slot = fcache->junkFilter->jf_resultSlot;
1828 73802 : if (!TTS_EMPTY(slot))
1829 68974 : result = postquel_get_single_result(slot, fcinfo, fcache);
1830 : else
1831 : {
1832 4828 : fcinfo->isnull = true;
1833 4828 : result = (Datum) 0;
1834 : }
1835 : }
1836 : else
1837 : {
1838 : /* Should only get here for VOID functions and procedures */
1839 : Assert(fcache->func->rettype == VOIDOID);
1840 214 : fcinfo->isnull = true;
1841 214 : result = (Datum) 0;
1842 : }
1843 : }
1844 :
1845 : /* Pop snapshot if we have pushed one */
1846 79050 : if (pushed_snapshot)
1847 646 : PopActiveSnapshot();
1848 :
1849 : /*
1850 : * If we've gone through every command in the function, we are done. Reset
1851 : * state to start over again on next call.
1852 : */
1853 79050 : if (es == NULL)
1854 78056 : fcache->eslist = NULL;
1855 :
1856 79050 : error_context_stack = sqlerrcontext.previous;
1857 :
1858 79050 : return result;
1859 : }
1860 :
1861 :
1862 : /*
1863 : * error context callback to let us supply a traceback during compile
1864 : */
1865 : static void
1866 6 : sql_compile_error_callback(void *arg)
1867 : {
1868 6 : SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) arg;
1869 : int syntaxerrposition;
1870 :
1871 : /*
1872 : * We can do nothing useful if sql_compile_callback() didn't get as far as
1873 : * copying the function name
1874 : */
1875 6 : if (func->fname == NULL)
1876 0 : return;
1877 :
1878 : /*
1879 : * If there is a syntax error position, convert to internal syntax error
1880 : */
1881 6 : syntaxerrposition = geterrposition();
1882 6 : if (syntaxerrposition > 0 && func->src != NULL)
1883 : {
1884 0 : errposition(0);
1885 0 : internalerrposition(syntaxerrposition);
1886 0 : internalerrquery(func->src);
1887 : }
1888 :
1889 : /*
1890 : * sql_compile_callback() doesn't do any per-query processing, so just
1891 : * report the context as "during startup".
1892 : */
1893 6 : errcontext("SQL function \"%s\" during startup", func->fname);
1894 : }
1895 :
1896 : /*
1897 : * error context callback to let us supply a call-stack traceback at runtime
1898 : */
1899 : static void
1900 7928 : sql_exec_error_callback(void *arg)
1901 : {
1902 7928 : SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) arg;
1903 : int syntaxerrposition;
1904 :
1905 : /*
1906 : * If there is a syntax error position, convert to internal syntax error
1907 : */
1908 7928 : syntaxerrposition = geterrposition();
1909 7928 : if (syntaxerrposition > 0 && fcache->func->src != NULL)
1910 : {
1911 2 : errposition(0);
1912 2 : internalerrposition(syntaxerrposition);
1913 2 : internalerrquery(fcache->func->src);
1914 : }
1915 :
1916 : /*
1917 : * If we failed while executing an identifiable query within the function,
1918 : * report that. Otherwise say it was "during startup".
1919 : */
1920 7928 : if (fcache->error_query_index > 0)
1921 7928 : errcontext("SQL function \"%s\" statement %d",
1922 7928 : fcache->func->fname, fcache->error_query_index);
1923 : else
1924 0 : errcontext("SQL function \"%s\" during startup", fcache->func->fname);
1925 7928 : }
1926 :
1927 :
1928 : /*
1929 : * ExprContext callback function
1930 : *
1931 : * We register this in the active ExprContext while a set-returning SQL
1932 : * function is running, in case the function needs to be shut down before it
1933 : * has been run to completion. Note that this will not be called during an
1934 : * error abort, but we don't need it because transaction abort will take care
1935 : * of releasing executor resources.
1936 : */
1937 : static void
1938 6 : ShutdownSQLFunction(Datum arg)
1939 : {
1940 6 : SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) DatumGetPointer(arg);
1941 : execution_state *es;
1942 :
1943 6 : es = fcache->eslist;
1944 12 : while (es)
1945 : {
1946 : /* Shut down anything still running */
1947 6 : if (es->status == F_EXEC_RUN)
1948 : {
1949 : /* Re-establish active snapshot for any called functions */
1950 6 : if (!fcache->func->readonly_func)
1951 6 : PushActiveSnapshot(es->qd->snapshot);
1952 :
1953 6 : postquel_end(es, fcache);
1954 :
1955 6 : if (!fcache->func->readonly_func)
1956 6 : PopActiveSnapshot();
1957 : }
1958 6 : es = es->next;
1959 : }
1960 6 : fcache->eslist = NULL;
1961 :
1962 : /* Release tuplestore if we have one */
1963 6 : if (fcache->tstore)
1964 0 : tuplestore_end(fcache->tstore);
1965 6 : fcache->tstore = NULL;
1966 :
1967 : /* Release CachedPlan if we have one */
1968 6 : if (fcache->cplan)
1969 6 : ReleaseCachedPlan(fcache->cplan, fcache->cowner);
1970 6 : fcache->cplan = NULL;
1971 :
1972 : /* execUtils will deregister the callback... */
1973 6 : fcache->shutdown_reg = false;
1974 6 : }
1975 :
1976 : /*
1977 : * MemoryContext callback function
1978 : *
1979 : * We register this in the memory context that contains a SQLFunctionCache
1980 : * struct. When the memory context is reset or deleted, we release the
1981 : * reference count (if any) that the cache holds on the long-lived hash entry.
1982 : * Note that this will happen even during error aborts.
1983 : */
1984 : static void
1985 34048 : RemoveSQLFunctionCache(void *arg)
1986 : {
1987 34048 : SQLFunctionCache *fcache = (SQLFunctionCache *) arg;
1988 :
1989 : /* Release reference count on SQLFunctionHashEntry */
1990 34048 : if (fcache->func != NULL)
1991 : {
1992 : Assert(fcache->func->cfunc.use_count > 0);
1993 34042 : fcache->func->cfunc.use_count--;
1994 : /* This should be unnecessary, but let's just be sure: */
1995 34042 : fcache->func = NULL;
1996 : }
1997 34048 : }
1998 :
1999 : /*
2000 : * check_sql_fn_statements
2001 : *
2002 : * Check statements in an SQL function. Error out if there is anything that
2003 : * is not acceptable.
2004 : */
2005 : void
2006 7258 : check_sql_fn_statements(List *queryTreeLists)
2007 : {
2008 : ListCell *lc;
2009 :
2010 : /* We are given a list of sublists of Queries */
2011 14626 : foreach(lc, queryTreeLists)
2012 : {
2013 7374 : List *sublist = lfirst_node(List, lc);
2014 :
2015 7374 : check_sql_fn_statement(sublist);
2016 : }
2017 7252 : }
2018 :
2019 : /*
2020 : * As above, for a single sublist of Queries.
2021 : */
2022 : static void
2023 9922 : check_sql_fn_statement(List *queryTreeList)
2024 : {
2025 : ListCell *lc;
2026 :
2027 19844 : foreach(lc, queryTreeList)
2028 : {
2029 9928 : Query *query = lfirst_node(Query, lc);
2030 :
2031 : /*
2032 : * Disallow calling procedures with output arguments. The current
2033 : * implementation would just throw the output values away, unless the
2034 : * statement is the last one. Per SQL standard, we should assign the
2035 : * output values by name. By disallowing this here, we preserve an
2036 : * opportunity for future improvement.
2037 : */
2038 9928 : if (query->commandType == CMD_UTILITY &&
2039 154 : IsA(query->utilityStmt, CallStmt))
2040 : {
2041 30 : CallStmt *stmt = (CallStmt *) query->utilityStmt;
2042 :
2043 30 : if (stmt->outargs != NIL)
2044 6 : ereport(ERROR,
2045 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2046 : errmsg("calling procedures with output arguments is not supported in SQL functions")));
2047 : }
2048 : }
2049 9916 : }
2050 :
2051 : /*
2052 : * check_sql_fn_retval()
2053 : * Check return value of a list of lists of sql parse trees.
2054 : *
2055 : * The return value of a sql function is the value returned by the last
2056 : * canSetTag query in the function. We do some ad-hoc type checking and
2057 : * coercion here to ensure that the function returns what it's supposed to.
2058 : * Note that we may actually modify the last query to make it match!
2059 : *
2060 : * This function returns true if the sql function returns the entire tuple
2061 : * result of its final statement, or false if it returns just the first column
2062 : * result of that statement. It throws an error if the final statement doesn't
2063 : * return the right type at all.
2064 : *
2065 : * Note that because we allow "SELECT rowtype_expression", the result can be
2066 : * false even when the declared function return type is a rowtype.
2067 : *
2068 : * For a polymorphic function the passed rettype must be the actual resolved
2069 : * output type of the function. (This means we can't check the type during
2070 : * function definition of a polymorphic function.) If we do see a polymorphic
2071 : * rettype we'll throw an error, saying it is not a supported rettype.
2072 : *
2073 : * If the function returns composite, the passed rettupdesc should describe
2074 : * the expected output. If rettupdesc is NULL, we can't verify that the
2075 : * output matches; that should only happen in fmgr_sql_validator(), or when
2076 : * the function returns RECORD and the caller doesn't actually care which
2077 : * composite type it is.
2078 : *
2079 : * (Typically, rettype and rettupdesc are computed by get_call_result_type
2080 : * or a sibling function.)
2081 : *
2082 : * In addition to coercing individual output columns, we can modify the
2083 : * output to include dummy NULL columns for any dropped columns appearing
2084 : * in rettupdesc. This is done only if the caller asks for it.
2085 : */
2086 : bool
2087 10802 : check_sql_fn_retval(List *queryTreeLists,
2088 : Oid rettype, TupleDesc rettupdesc,
2089 : char prokind,
2090 : bool insertDroppedCols)
2091 : {
2092 : List *queryTreeList;
2093 :
2094 : /*
2095 : * We consider only the last sublist of Query nodes, so that only the last
2096 : * original statement is a candidate to produce the result. This is a
2097 : * change from pre-v18 versions, which would back up to the last statement
2098 : * that includes a canSetTag query, thus ignoring any ending statement(s)
2099 : * that rewrite to DO INSTEAD NOTHING. That behavior was undocumented and
2100 : * there seems no good reason for it, except that it was an artifact of
2101 : * the original coding.
2102 : *
2103 : * If the function body is completely empty, handle that the same as if
2104 : * the last query had rewritten to nothing.
2105 : */
2106 10802 : if (queryTreeLists != NIL)
2107 10778 : queryTreeList = llast_node(List, queryTreeLists);
2108 : else
2109 24 : queryTreeList = NIL;
2110 :
2111 10802 : return check_sql_stmt_retval(queryTreeList,
2112 : rettype, rettupdesc,
2113 : prokind, insertDroppedCols);
2114 : }
2115 :
2116 : /*
2117 : * As for check_sql_fn_retval, but we are given just the last query's
2118 : * rewritten-queries list.
2119 : */
2120 : static bool
2121 13280 : check_sql_stmt_retval(List *queryTreeList,
2122 : Oid rettype, TupleDesc rettupdesc,
2123 : char prokind, bool insertDroppedCols)
2124 : {
2125 13280 : bool is_tuple_result = false;
2126 : Query *parse;
2127 : ListCell *parse_cell;
2128 : List *tlist;
2129 : int tlistlen;
2130 : bool tlist_is_modifiable;
2131 : char fn_typtype;
2132 13280 : List *upper_tlist = NIL;
2133 13280 : bool upper_tlist_nontrivial = false;
2134 : ListCell *lc;
2135 :
2136 : /*
2137 : * If it's declared to return VOID, we don't care what's in the function.
2138 : * (This takes care of procedures with no output parameters, as well.)
2139 : */
2140 13280 : if (rettype == VOIDOID)
2141 622 : return false;
2142 :
2143 : /*
2144 : * Find the last canSetTag query in the list of Query nodes. This isn't
2145 : * necessarily the last parsetree, because rule rewriting can insert
2146 : * queries after what the user wrote.
2147 : */
2148 12658 : parse = NULL;
2149 12658 : parse_cell = NULL;
2150 25316 : foreach(lc, queryTreeList)
2151 : {
2152 12658 : Query *q = lfirst_node(Query, lc);
2153 :
2154 12658 : if (q->canSetTag)
2155 : {
2156 12652 : parse = q;
2157 12652 : parse_cell = lc;
2158 : }
2159 : }
2160 :
2161 : /*
2162 : * If it's a plain SELECT, it returns whatever the targetlist says.
2163 : * Otherwise, if it's INSERT/UPDATE/DELETE/MERGE with RETURNING, it
2164 : * returns that. Otherwise, the function return type must be VOID.
2165 : *
2166 : * Note: eventually replace this test with QueryReturnsTuples? We'd need
2167 : * a more general method of determining the output type, though. Also, it
2168 : * seems too dangerous to consider FETCH or EXECUTE as returning a
2169 : * determinable rowtype, since they depend on relatively short-lived
2170 : * entities.
2171 : */
2172 12658 : if (parse &&
2173 12652 : parse->commandType == CMD_SELECT)
2174 : {
2175 12538 : tlist = parse->targetList;
2176 : /* tlist is modifiable unless it's a dummy in a setop query */
2177 12538 : tlist_is_modifiable = (parse->setOperations == NULL);
2178 : }
2179 120 : else if (parse &&
2180 114 : (parse->commandType == CMD_INSERT ||
2181 30 : parse->commandType == CMD_UPDATE ||
2182 30 : parse->commandType == CMD_DELETE ||
2183 30 : parse->commandType == CMD_MERGE) &&
2184 114 : parse->returningList)
2185 : {
2186 114 : tlist = parse->returningList;
2187 : /* returningList can always be modified */
2188 114 : tlist_is_modifiable = true;
2189 : }
2190 : else
2191 : {
2192 : /* Last statement is a utility command, or it rewrote to nothing */
2193 6 : ereport(ERROR,
2194 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2195 : errmsg("return type mismatch in function declared to return %s",
2196 : format_type_be(rettype)),
2197 : errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));
2198 : return false; /* keep compiler quiet */
2199 : }
2200 :
2201 : /*
2202 : * OK, check that the targetlist returns something matching the declared
2203 : * type, and modify it if necessary. If possible, we insert any coercion
2204 : * steps right into the final statement's targetlist. However, that might
2205 : * risk changes in the statement's semantics --- we can't safely change
2206 : * the output type of a grouping column, for instance. In such cases we
2207 : * handle coercions by inserting an extra level of Query that effectively
2208 : * just does a projection.
2209 : */
2210 :
2211 : /*
2212 : * Count the non-junk entries in the result targetlist.
2213 : */
2214 12652 : tlistlen = ExecCleanTargetListLength(tlist);
2215 :
2216 12652 : fn_typtype = get_typtype(rettype);
2217 :
2218 12652 : if (fn_typtype == TYPTYPE_BASE ||
2219 1426 : fn_typtype == TYPTYPE_DOMAIN ||
2220 1420 : fn_typtype == TYPTYPE_ENUM ||
2221 1384 : fn_typtype == TYPTYPE_RANGE ||
2222 : fn_typtype == TYPTYPE_MULTIRANGE)
2223 11292 : {
2224 : /*
2225 : * For scalar-type returns, the target list must have exactly one
2226 : * non-junk entry, and its type must be coercible to rettype.
2227 : */
2228 : TargetEntry *tle;
2229 :
2230 11304 : if (tlistlen != 1)
2231 6 : ereport(ERROR,
2232 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2233 : errmsg("return type mismatch in function declared to return %s",
2234 : format_type_be(rettype)),
2235 : errdetail("Final statement must return exactly one column.")));
2236 :
2237 : /* We assume here that non-junk TLEs must come first in tlists */
2238 11298 : tle = (TargetEntry *) linitial(tlist);
2239 : Assert(!tle->resjunk);
2240 :
2241 11298 : if (!coerce_fn_result_column(tle, rettype, -1,
2242 : tlist_is_modifiable,
2243 : &upper_tlist,
2244 : &upper_tlist_nontrivial))
2245 6 : ereport(ERROR,
2246 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2247 : errmsg("return type mismatch in function declared to return %s",
2248 : format_type_be(rettype)),
2249 : errdetail("Actual return type is %s.",
2250 : format_type_be(exprType((Node *) tle->expr)))));
2251 : }
2252 1348 : else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
2253 1210 : {
2254 : /*
2255 : * Returns a rowtype.
2256 : *
2257 : * Note that we will not consider a domain over composite to be a
2258 : * "rowtype" return type; it goes through the scalar case above. This
2259 : * is because we only provide column-by-column implicit casting, and
2260 : * will not cast the complete record result. So the only way to
2261 : * produce a domain-over-composite result is to compute it as an
2262 : * explicit single-column result. The single-composite-column code
2263 : * path just below could handle such cases, but it won't be reached.
2264 : */
2265 : int tupnatts; /* physical number of columns in tuple */
2266 : int tuplogcols; /* # of nondeleted columns in tuple */
2267 : int colindex; /* physical column index */
2268 :
2269 : /*
2270 : * If the target list has one non-junk entry, and that expression has
2271 : * or can be coerced to the declared return type, take it as the
2272 : * result. This allows, for example, 'SELECT func2()', where func2
2273 : * has the same composite return type as the function that's calling
2274 : * it. This provision creates some ambiguity --- maybe the expression
2275 : * was meant to be the lone field of the composite result --- but it
2276 : * works well enough as long as we don't get too enthusiastic about
2277 : * inventing coercions from scalar to composite types.
2278 : *
2279 : * XXX Note that if rettype is RECORD and the expression is of a named
2280 : * composite type, or vice versa, this coercion will succeed, whether
2281 : * or not the record type really matches. For the moment we rely on
2282 : * runtime type checking to catch any discrepancy, but it'd be nice to
2283 : * do better at parse time.
2284 : *
2285 : * We must *not* do this for a procedure, however. Procedures with
2286 : * output parameter(s) have rettype RECORD, and the CALL code expects
2287 : * to get results corresponding to the list of output parameters, even
2288 : * when there's just one parameter that's composite.
2289 : */
2290 1342 : if (tlistlen == 1 && prokind != PROKIND_PROCEDURE)
2291 : {
2292 216 : TargetEntry *tle = (TargetEntry *) linitial(tlist);
2293 :
2294 : Assert(!tle->resjunk);
2295 216 : if (coerce_fn_result_column(tle, rettype, -1,
2296 : tlist_is_modifiable,
2297 : &upper_tlist,
2298 : &upper_tlist_nontrivial))
2299 : {
2300 : /* Note that we're NOT setting is_tuple_result */
2301 72 : goto tlist_coercion_finished;
2302 : }
2303 : }
2304 :
2305 : /*
2306 : * If the caller didn't provide an expected tupdesc, we can't do any
2307 : * further checking. Assume we're returning the whole tuple.
2308 : */
2309 1270 : if (rettupdesc == NULL)
2310 48 : return true;
2311 :
2312 : /*
2313 : * Verify that the targetlist matches the return tuple type. We scan
2314 : * the non-resjunk columns, and coerce them if necessary to match the
2315 : * datatypes of the non-deleted attributes. For deleted attributes,
2316 : * insert NULL result columns if the caller asked for that.
2317 : */
2318 1222 : tupnatts = rettupdesc->natts;
2319 1222 : tuplogcols = 0; /* we'll count nondeleted cols as we go */
2320 1222 : colindex = 0;
2321 :
2322 4688 : foreach(lc, tlist)
2323 : {
2324 3478 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
2325 : Form_pg_attribute attr;
2326 :
2327 : /* resjunk columns can simply be ignored */
2328 3478 : if (tle->resjunk)
2329 0 : continue;
2330 :
2331 : do
2332 : {
2333 3532 : colindex++;
2334 3532 : if (colindex > tupnatts)
2335 0 : ereport(ERROR,
2336 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2337 : errmsg("return type mismatch in function declared to return %s",
2338 : format_type_be(rettype)),
2339 : errdetail("Final statement returns too many columns.")));
2340 3532 : attr = TupleDescAttr(rettupdesc, colindex - 1);
2341 3532 : if (attr->attisdropped && insertDroppedCols)
2342 : {
2343 : Expr *null_expr;
2344 :
2345 : /* The type of the null we insert isn't important */
2346 6 : null_expr = (Expr *) makeConst(INT4OID,
2347 : -1,
2348 : InvalidOid,
2349 : sizeof(int32),
2350 : (Datum) 0,
2351 : true, /* isnull */
2352 : true /* byval */ );
2353 6 : upper_tlist = lappend(upper_tlist,
2354 6 : makeTargetEntry(null_expr,
2355 6 : list_length(upper_tlist) + 1,
2356 : NULL,
2357 : false));
2358 6 : upper_tlist_nontrivial = true;
2359 : }
2360 3532 : } while (attr->attisdropped);
2361 3478 : tuplogcols++;
2362 :
2363 3478 : if (!coerce_fn_result_column(tle,
2364 : attr->atttypid, attr->atttypmod,
2365 : tlist_is_modifiable,
2366 : &upper_tlist,
2367 : &upper_tlist_nontrivial))
2368 12 : ereport(ERROR,
2369 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2370 : errmsg("return type mismatch in function declared to return %s",
2371 : format_type_be(rettype)),
2372 : errdetail("Final statement returns %s instead of %s at column %d.",
2373 : format_type_be(exprType((Node *) tle->expr)),
2374 : format_type_be(attr->atttypid),
2375 : tuplogcols)));
2376 : }
2377 :
2378 : /* remaining columns in rettupdesc had better all be dropped */
2379 1210 : for (colindex++; colindex <= tupnatts; colindex++)
2380 : {
2381 0 : if (!TupleDescCompactAttr(rettupdesc, colindex - 1)->attisdropped)
2382 0 : ereport(ERROR,
2383 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2384 : errmsg("return type mismatch in function declared to return %s",
2385 : format_type_be(rettype)),
2386 : errdetail("Final statement returns too few columns.")));
2387 0 : if (insertDroppedCols)
2388 : {
2389 : Expr *null_expr;
2390 :
2391 : /* The type of the null we insert isn't important */
2392 0 : null_expr = (Expr *) makeConst(INT4OID,
2393 : -1,
2394 : InvalidOid,
2395 : sizeof(int32),
2396 : (Datum) 0,
2397 : true, /* isnull */
2398 : true /* byval */ );
2399 0 : upper_tlist = lappend(upper_tlist,
2400 0 : makeTargetEntry(null_expr,
2401 0 : list_length(upper_tlist) + 1,
2402 : NULL,
2403 : false));
2404 0 : upper_tlist_nontrivial = true;
2405 : }
2406 : }
2407 :
2408 : /* Report that we are returning entire tuple result */
2409 1210 : is_tuple_result = true;
2410 : }
2411 : else
2412 6 : ereport(ERROR,
2413 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
2414 : errmsg("return type %s is not supported for SQL functions",
2415 : format_type_be(rettype))));
2416 :
2417 12574 : tlist_coercion_finished:
2418 :
2419 : /*
2420 : * If necessary, modify the final Query by injecting an extra Query level
2421 : * that just performs a projection. (It'd be dubious to do this to a
2422 : * non-SELECT query, but we never have to; RETURNING lists can always be
2423 : * modified in-place.)
2424 : */
2425 12574 : if (upper_tlist_nontrivial)
2426 : {
2427 : Query *newquery;
2428 : List *colnames;
2429 : RangeTblEntry *rte;
2430 : RangeTblRef *rtr;
2431 :
2432 : Assert(parse->commandType == CMD_SELECT);
2433 :
2434 : /* Most of the upper Query struct can be left as zeroes/nulls */
2435 84 : newquery = makeNode(Query);
2436 84 : newquery->commandType = CMD_SELECT;
2437 84 : newquery->querySource = parse->querySource;
2438 84 : newquery->canSetTag = true;
2439 84 : newquery->targetList = upper_tlist;
2440 :
2441 : /* We need a moderately realistic colnames list for the subquery RTE */
2442 84 : colnames = NIL;
2443 216 : foreach(lc, parse->targetList)
2444 : {
2445 132 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
2446 :
2447 132 : if (tle->resjunk)
2448 0 : continue;
2449 132 : colnames = lappend(colnames,
2450 132 : makeString(tle->resname ? tle->resname : ""));
2451 : }
2452 :
2453 : /* Build a suitable RTE for the subquery */
2454 84 : rte = makeNode(RangeTblEntry);
2455 84 : rte->rtekind = RTE_SUBQUERY;
2456 84 : rte->subquery = parse;
2457 84 : rte->eref = rte->alias = makeAlias("*SELECT*", colnames);
2458 84 : rte->lateral = false;
2459 84 : rte->inh = false;
2460 84 : rte->inFromCl = true;
2461 84 : newquery->rtable = list_make1(rte);
2462 :
2463 84 : rtr = makeNode(RangeTblRef);
2464 84 : rtr->rtindex = 1;
2465 84 : newquery->jointree = makeFromExpr(list_make1(rtr), NULL);
2466 :
2467 : /*
2468 : * Make sure the new query is marked as having row security if the
2469 : * original one does.
2470 : */
2471 84 : newquery->hasRowSecurity = parse->hasRowSecurity;
2472 :
2473 : /* Replace original query in the correct element of the query list */
2474 84 : lfirst(parse_cell) = newquery;
2475 : }
2476 :
2477 12574 : return is_tuple_result;
2478 : }
2479 :
2480 : /*
2481 : * Process one function result column for check_sql_fn_retval
2482 : *
2483 : * Coerce the output value to the required type/typmod, and add a column
2484 : * to *upper_tlist for it. Set *upper_tlist_nontrivial to true if we
2485 : * add an upper tlist item that's not just a Var.
2486 : *
2487 : * Returns true if OK, false if could not coerce to required type
2488 : * (in which case, no changes have been made)
2489 : */
2490 : static bool
2491 14992 : coerce_fn_result_column(TargetEntry *src_tle,
2492 : Oid res_type,
2493 : int32 res_typmod,
2494 : bool tlist_is_modifiable,
2495 : List **upper_tlist,
2496 : bool *upper_tlist_nontrivial)
2497 : {
2498 : TargetEntry *new_tle;
2499 : Expr *new_tle_expr;
2500 : Node *cast_result;
2501 :
2502 : /*
2503 : * If the TLE has a sortgroupref marking, don't change it, as it probably
2504 : * is referenced by ORDER BY, DISTINCT, etc, and changing its type would
2505 : * break query semantics. Otherwise, it's safe to modify in-place unless
2506 : * the query as a whole has issues with that.
2507 : */
2508 14992 : if (tlist_is_modifiable && src_tle->ressortgroupref == 0)
2509 : {
2510 : /* OK to modify src_tle in place, if necessary */
2511 29524 : cast_result = coerce_to_target_type(NULL,
2512 14762 : (Node *) src_tle->expr,
2513 14762 : exprType((Node *) src_tle->expr),
2514 : res_type, res_typmod,
2515 : COERCION_ASSIGNMENT,
2516 : COERCE_IMPLICIT_CAST,
2517 : -1);
2518 14762 : if (cast_result == NULL)
2519 144 : return false;
2520 14618 : assign_expr_collations(NULL, cast_result);
2521 14618 : src_tle->expr = (Expr *) cast_result;
2522 : /* Make a Var referencing the possibly-modified TLE */
2523 14618 : new_tle_expr = (Expr *) makeVarFromTargetEntry(1, src_tle);
2524 : }
2525 : else
2526 : {
2527 : /* Any casting must happen in the upper tlist */
2528 230 : Var *var = makeVarFromTargetEntry(1, src_tle);
2529 :
2530 230 : cast_result = coerce_to_target_type(NULL,
2531 : (Node *) var,
2532 : var->vartype,
2533 : res_type, res_typmod,
2534 : COERCION_ASSIGNMENT,
2535 : COERCE_IMPLICIT_CAST,
2536 : -1);
2537 230 : if (cast_result == NULL)
2538 18 : return false;
2539 212 : assign_expr_collations(NULL, cast_result);
2540 : /* Did the coercion actually do anything? */
2541 212 : if (cast_result != (Node *) var)
2542 102 : *upper_tlist_nontrivial = true;
2543 212 : new_tle_expr = (Expr *) cast_result;
2544 : }
2545 29660 : new_tle = makeTargetEntry(new_tle_expr,
2546 14830 : list_length(*upper_tlist) + 1,
2547 : src_tle->resname, false);
2548 14830 : *upper_tlist = lappend(*upper_tlist, new_tle);
2549 14830 : return true;
2550 : }
2551 :
2552 : /*
2553 : * Extract the targetlist of the last canSetTag query in the given list
2554 : * of parsed-and-rewritten Queries. Returns NIL if there is none.
2555 : */
2556 : static List *
2557 35810 : get_sql_fn_result_tlist(List *queryTreeList)
2558 : {
2559 35810 : Query *parse = NULL;
2560 : ListCell *lc;
2561 :
2562 71626 : foreach(lc, queryTreeList)
2563 : {
2564 35816 : Query *q = lfirst_node(Query, lc);
2565 :
2566 35816 : if (q->canSetTag)
2567 35810 : parse = q;
2568 : }
2569 35810 : if (parse &&
2570 35810 : parse->commandType == CMD_SELECT)
2571 35714 : return parse->targetList;
2572 96 : else if (parse &&
2573 96 : (parse->commandType == CMD_INSERT ||
2574 24 : parse->commandType == CMD_UPDATE ||
2575 24 : parse->commandType == CMD_DELETE ||
2576 24 : parse->commandType == CMD_MERGE) &&
2577 96 : parse->returningList)
2578 96 : return parse->returningList;
2579 : else
2580 0 : return NIL;
2581 : }
2582 :
2583 :
2584 : /*
2585 : * CreateSQLFunctionDestReceiver -- create a suitable DestReceiver object
2586 : */
2587 : DestReceiver *
2588 85566 : CreateSQLFunctionDestReceiver(void)
2589 : {
2590 85566 : DR_sqlfunction *self = (DR_sqlfunction *) palloc0(sizeof(DR_sqlfunction));
2591 :
2592 85566 : self->pub.receiveSlot = sqlfunction_receive;
2593 85566 : self->pub.rStartup = sqlfunction_startup;
2594 85566 : self->pub.rShutdown = sqlfunction_shutdown;
2595 85566 : self->pub.rDestroy = sqlfunction_destroy;
2596 85566 : self->pub.mydest = DestSQLFunction;
2597 :
2598 : /* private fields will be set by postquel_start */
2599 :
2600 85566 : return (DestReceiver *) self;
2601 : }
2602 :
2603 : /*
2604 : * sqlfunction_startup --- executor startup
2605 : */
2606 : static void
2607 86548 : sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
2608 : {
2609 : /* no-op */
2610 86548 : }
2611 :
2612 : /*
2613 : * sqlfunction_receive --- receive one tuple
2614 : */
2615 : static bool
2616 192318 : sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)
2617 : {
2618 192318 : DR_sqlfunction *myState = (DR_sqlfunction *) self;
2619 :
2620 192318 : if (myState->tstore)
2621 : {
2622 : /* We are collecting all of a set result into the tuplestore */
2623 :
2624 : /* Filter tuple as needed */
2625 122344 : slot = ExecFilterJunk(myState->filter, slot);
2626 :
2627 : /* Store the filtered tuple into the tuplestore */
2628 122344 : tuplestore_puttupleslot(myState->tstore, slot);
2629 : }
2630 : else
2631 : {
2632 : /*
2633 : * We only want the first tuple, which we'll save in the junkfilter's
2634 : * result slot. Ignore any additional tuples passed.
2635 : */
2636 69974 : if (TTS_EMPTY(myState->filter->jf_resultSlot))
2637 : {
2638 : /* Filter tuple as needed */
2639 69968 : slot = ExecFilterJunk(myState->filter, slot);
2640 : Assert(slot == myState->filter->jf_resultSlot);
2641 :
2642 : /* Materialize the slot so it preserves pass-by-ref values */
2643 69968 : ExecMaterializeSlot(slot);
2644 : }
2645 : }
2646 :
2647 192318 : return true;
2648 : }
2649 :
2650 : /*
2651 : * sqlfunction_shutdown --- executor end
2652 : */
2653 : static void
2654 78830 : sqlfunction_shutdown(DestReceiver *self)
2655 : {
2656 : /* no-op */
2657 78830 : }
2658 :
2659 : /*
2660 : * sqlfunction_destroy --- release DestReceiver object
2661 : */
2662 : static void
2663 77842 : sqlfunction_destroy(DestReceiver *self)
2664 : {
2665 77842 : pfree(self);
2666 77842 : }
|