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