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