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