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