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