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