1 /*-------------------------------------------------------------------------
2 *
3 * functions.c
4 * Execution of SQL-language functions
5 *
6 * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/executor/functions.c
12 *
13 *-------------------------------------------------------------------------
14 */
15 #include "postgres.h"
16
17 #include "access/htup_details.h"
18 #include "access/xact.h"
19 #include "catalog/pg_proc.h"
20 #include "catalog/pg_type.h"
21 #include "executor/functions.h"
22 #include "funcapi.h"
23 #include "miscadmin.h"
24 #include "nodes/makefuncs.h"
25 #include "nodes/nodeFuncs.h"
26 #include "parser/parse_coerce.h"
27 #include "parser/parse_collate.h"
28 #include "parser/parse_func.h"
29 #include "storage/proc.h"
30 #include "tcop/utility.h"
31 #include "utils/builtins.h"
32 #include "utils/datum.h"
33 #include "utils/lsyscache.h"
34 #include "utils/memutils.h"
35 #include "utils/snapmgr.h"
36 #include "utils/syscache.h"
37
38
39 /*
40 * Specialized DestReceiver for collecting query output in a SQL function
41 */
42 typedef struct
43 {
44 DestReceiver pub; /* publicly-known function pointers */
45 Tuplestorestate *tstore; /* where to put result tuples */
46 MemoryContext cxt; /* context containing tstore */
47 JunkFilter *filter; /* filter to convert tuple type */
48 } DR_sqlfunction;
49
50 /*
51 * We have an execution_state record for each query in a function. Each
52 * record contains a plantree for its query. If the query is currently in
53 * F_EXEC_RUN state then there's a QueryDesc too.
54 *
55 * The "next" fields chain together all the execution_state records generated
56 * from a single original parsetree. (There will only be more than one in
57 * case of rule expansion of the original parsetree.)
58 */
59 typedef enum
60 {
61 F_EXEC_START, F_EXEC_RUN, F_EXEC_DONE
62 } ExecStatus;
63
64 typedef struct execution_state
65 {
66 struct execution_state *next;
67 ExecStatus status;
68 bool setsResult; /* true if this query produces func's result */
69 bool lazyEval; /* true if should fetch one row at a time */
70 PlannedStmt *stmt; /* plan for this query */
71 QueryDesc *qd; /* null unless status == RUN */
72 } execution_state;
73
74
75 /*
76 * An SQLFunctionCache record is built during the first call,
77 * and linked to from the fn_extra field of the FmgrInfo struct.
78 *
79 * Note that currently this has only the lifespan of the calling query.
80 * Someday we should rewrite this code to use plancache.c to save parse/plan
81 * results for longer than that.
82 *
83 * Physically, though, the data has the lifespan of the FmgrInfo that's used
84 * to call the function, and there are cases (particularly with indexes)
85 * where the FmgrInfo might survive across transactions. We cannot assume
86 * that the parse/plan trees are good for longer than the (sub)transaction in
87 * which parsing was done, so we must mark the record with the LXID/subxid of
88 * its creation time, and regenerate everything if that's obsolete. To avoid
89 * memory leakage when we do have to regenerate things, all the data is kept
90 * in a sub-context of the FmgrInfo's fn_mcxt.
91 */
92 typedef struct
93 {
94 char *fname; /* function name (for error msgs) */
95 char *src; /* function body text (for error msgs) */
96
tts_virtual_init(TupleTableSlot * slot)97 SQLFunctionParseInfoPtr pinfo; /* data for parser callback hooks */
98
99 Oid rettype; /* actual return type */
100 int16 typlen; /* length of the return type */
101 bool typbyval; /* true if return type is pass by value */
tts_virtual_release(TupleTableSlot * slot)102 bool returnsSet; /* true if returning multiple rows */
103 bool returnsTuple; /* true if returning whole tuple result */
104 bool shutdown_reg; /* true if registered shutdown callback */
105 bool readonly_func; /* true to run in "read only" mode */
106 bool lazyEval; /* true if using lazyEval for result query */
tts_virtual_clear(TupleTableSlot * slot)107
108 ParamListInfo paramLI; /* Param list representing current args */
109
110 Tuplestorestate *tstore; /* where we accumulate result tuples */
111
112 JunkFilter *junkFilter; /* will be NULL if function returns VOID */
113
114 /*
115 * func_state is a List of execution_state records, each of which is the
116 * first for its original parsetree, with any additional records chained
117 * to it via the "next" fields. This sublist structure is needed to keep
118 * track of where the original query boundaries are.
119 */
120 List *func_state;
121
122 MemoryContext fcontext; /* memory context holding this struct and all
123 * subsidiary data */
124
125 LocalTransactionId lxid; /* lxid in which cache was made */
126 SubTransactionId subxid; /* subxid in which cache was made */
127 } SQLFunctionCache;
128
tts_virtual_getsomeattrs(TupleTableSlot * slot,int natts)129 typedef SQLFunctionCache *SQLFunctionCachePtr;
130
131 /*
132 * Data structure needed by the parser callback hooks to resolve parameter
133 * references during parsing of a SQL function's body. This is separate from
134 * SQLFunctionCache since we sometimes do parsing separately from execution.
135 */
136 typedef struct SQLFunctionParseInfo
137 {
138 char *fname; /* function's name */
139 int nargs; /* number of input arguments */
tts_virtual_getsysattr(TupleTableSlot * slot,int attnum,bool * isnull)140 Oid *argtypes; /* resolved types of input arguments */
141 char **argnames; /* names of input arguments; NULL if none */
142 /* Note that argnames[i] can be NULL, if some args are unnamed */
143 Oid collation; /* function's input collation, if known */
144 } SQLFunctionParseInfo;
145
146
147 /* non-export function prototypes */
148 static Node *sql_fn_param_ref(ParseState *pstate, ParamRef *pref);
149 static Node *sql_fn_post_column_ref(ParseState *pstate,
150 ColumnRef *cref, Node *var);
151 static Node *sql_fn_make_param(SQLFunctionParseInfoPtr pinfo,
152 int paramno, int location);
153 static Node *sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo,
154 const char *paramname, int location);
155 static List *init_execution_state(List *queryTree_list,
156 SQLFunctionCachePtr fcache,
157 bool lazyEvalOK);
158 static void init_sql_fcache(FunctionCallInfo fcinfo, Oid collation, bool lazyEvalOK);
tts_virtual_materialize(TupleTableSlot * slot)159 static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
160 static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache);
161 static void postquel_end(execution_state *es);
162 static void postquel_sub_params(SQLFunctionCachePtr fcache,
163 FunctionCallInfo fcinfo);
164 static Datum postquel_get_single_result(TupleTableSlot *slot,
165 FunctionCallInfo fcinfo,
166 SQLFunctionCachePtr fcache,
167 MemoryContext resultcontext);
168 static void sql_exec_error_callback(void *arg);
169 static void ShutdownSQLFunction(Datum arg);
170 static bool coerce_fn_result_column(TargetEntry *src_tle,
171 Oid res_type, int32 res_typmod,
172 bool tlist_is_modifiable,
173 List **upper_tlist,
174 bool *upper_tlist_nontrivial);
175 static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo);
176 static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self);
177 static void sqlfunction_shutdown(DestReceiver *self);
178 static void sqlfunction_destroy(DestReceiver *self);
179
180
181 /*
182 * Prepare the SQLFunctionParseInfo struct for parsing a SQL function body
183 *
184 * This includes resolving actual types of polymorphic arguments.
185 *
186 * call_expr can be passed as NULL, but then we will fail if there are any
187 * polymorphic arguments.
188 */
189 SQLFunctionParseInfoPtr
190 prepare_sql_fn_parse_info(HeapTuple procedureTuple,
191 Node *call_expr,
192 Oid inputCollation)
193 {
194 SQLFunctionParseInfoPtr pinfo;
195 Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
196 int nargs;
197
198 pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
199
200 /* Function's name (only) can be used to qualify argument names */
201 pinfo->fname = pstrdup(NameStr(procedureStruct->proname));
202
203 /* Save the function's input collation */
204 pinfo->collation = inputCollation;
205
206 /*
207 * Copy input argument types from the pg_proc entry, then resolve any
208 * polymorphic types.
209 */
210 pinfo->nargs = nargs = procedureStruct->pronargs;
211 if (nargs > 0)
212 {
213 Oid *argOidVect;
214 int argnum;
215
216 argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
217 memcpy(argOidVect,
218 procedureStruct->proargtypes.values,
219 nargs * sizeof(Oid));
220
221 for (argnum = 0; argnum < nargs; argnum++)
222 {
223 Oid argtype = argOidVect[argnum];
224
225 if (IsPolymorphicType(argtype))
226 {
227 argtype = get_call_expr_argtype(call_expr, argnum);
228 if (argtype == InvalidOid)
229 ereport(ERROR,
230 (errcode(ERRCODE_DATATYPE_MISMATCH),
231 errmsg("could not determine actual type of argument declared %s",
232 format_type_be(argOidVect[argnum]))));
233 argOidVect[argnum] = argtype;
234 }
235 }
236
237 pinfo->argtypes = argOidVect;
238 }
239
240 /*
241 * Collect names of arguments, too, if any
242 */
243 if (nargs > 0)
244 {
245 Datum proargnames;
246 Datum proargmodes;
247 int n_arg_names;
248 bool isNull;
249
250 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
251 Anum_pg_proc_proargnames,
tts_virtual_copyslot(TupleTableSlot * dstslot,TupleTableSlot * srcslot)252 &isNull);
253 if (isNull)
254 proargnames = PointerGetDatum(NULL); /* just to be sure */
255
256 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
257 Anum_pg_proc_proargmodes,
258 &isNull);
259 if (isNull)
260 proargmodes = PointerGetDatum(NULL); /* just to be sure */
261
262 n_arg_names = get_func_input_arg_names(proargnames, proargmodes,
263 &pinfo->argnames);
264
265 /* Paranoia: ignore the result if too few array entries */
266 if (n_arg_names < nargs)
267 pinfo->argnames = NULL;
268 }
269 else
270 pinfo->argnames = NULL;
271
272 return pinfo;
273 }
274
275 /*
tts_virtual_copy_heap_tuple(TupleTableSlot * slot)276 * Parser setup hook for parsing a SQL function body.
277 */
278 void
279 sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
280 {
281 pstate->p_pre_columnref_hook = NULL;
282 pstate->p_post_columnref_hook = sql_fn_post_column_ref;
283 pstate->p_paramref_hook = sql_fn_param_ref;
284 /* no need to use p_coerce_param_hook */
285 pstate->p_ref_hook_state = (void *) pinfo;
286 }
287
288 /*
289 * sql_fn_post_column_ref parser callback for ColumnRefs
290 */
291 static Node *
292 sql_fn_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
293 {
294 SQLFunctionParseInfoPtr pinfo = (SQLFunctionParseInfoPtr) pstate->p_ref_hook_state;
295 int nnames;
296 Node *field1;
297 Node *subfield = NULL;
298 const char *name1;
299 const char *name2 = NULL;
300 Node *param;
tts_heap_init(TupleTableSlot * slot)301
302 /*
303 * Never override a table-column reference. This corresponds to
304 * considering the parameter names to appear in a scope outside the
305 * individual SQL commands, which is what we want.
306 */
307 if (var != NULL)
308 return NULL;
309
310 /*----------
tts_heap_clear(TupleTableSlot * slot)311 * The allowed syntaxes are:
312 *
313 * A A = parameter name
314 * A.B A = function name, B = parameter name
315 * OR: A = record-typed parameter name, B = field name
316 * (the first possibility takes precedence)
317 * A.B.C A = function name, B = record-typed parameter name,
318 * C = field name
319 * A.* Whole-row reference to composite parameter A.
320 * A.B.* Same, with A = function name, B = parameter name
321 *
322 * Here, it's sufficient to ignore the "*" in the last two cases --- the
323 * main parser will take care of expanding the whole-row reference.
324 *----------
325 */
326 nnames = list_length(cref->fields);
327
328 if (nnames > 3)
329 return NULL;
tts_heap_getsomeattrs(TupleTableSlot * slot,int natts)330
331 if (IsA(llast(cref->fields), A_Star))
332 nnames--;
333
334 field1 = (Node *) linitial(cref->fields);
335 Assert(IsA(field1, String));
336 name1 = strVal(field1);
337 if (nnames > 1)
338 {
339 subfield = (Node *) lsecond(cref->fields);
tts_heap_getsysattr(TupleTableSlot * slot,int attnum,bool * isnull)340 Assert(IsA(subfield, String));
341 name2 = strVal(subfield);
342 }
343
344 if (nnames == 3)
345 {
346 /*
347 * Three-part name: if the first part doesn't match the function name,
348 * we can fail immediately. Otherwise, look up the second part, and
349 * take the third part to be a field reference.
350 */
351 if (strcmp(name1, pinfo->fname) != 0)
352 return NULL;
353
354 param = sql_fn_resolve_param_name(pinfo, name2, cref->location);
355
356 subfield = (Node *) lthird(cref->fields);
357 Assert(IsA(subfield, String));
358 }
359 else if (nnames == 2 && strcmp(name1, pinfo->fname) == 0)
tts_heap_materialize(TupleTableSlot * slot)360 {
361 /*
362 * Two-part name with first part matching function name: first see if
363 * second part matches any parameter name.
364 */
365 param = sql_fn_resolve_param_name(pinfo, name2, cref->location);
366
367 if (param)
368 {
369 /* Yes, so this is a parameter reference, no subfield */
370 subfield = NULL;
371 }
372 else
373 {
374 /* No, so try to match as parameter name and subfield */
375 param = sql_fn_resolve_param_name(pinfo, name1, cref->location);
376 }
377 }
378 else
379 {
380 /* Single name, or parameter name followed by subfield */
381 param = sql_fn_resolve_param_name(pinfo, name1, cref->location);
382 }
383
384 if (!param)
385 return NULL; /* No match */
386
387 if (subfield)
388 {
389 /*
390 * Must be a reference to a field of a composite parameter; otherwise
391 * ParseFuncOrColumn will return NULL, and we'll fail back at the
392 * caller.
393 */
394 param = ParseFuncOrColumn(pstate,
395 list_make1(subfield),
396 list_make1(param),
397 pstate->p_last_srf,
398 NULL,
399 false,
tts_heap_copyslot(TupleTableSlot * dstslot,TupleTableSlot * srcslot)400 cref->location);
401 }
402
403 return param;
404 }
405
406 /*
407 * sql_fn_param_ref parser callback for ParamRefs ($n symbols)
408 */
409 static Node *
410 sql_fn_param_ref(ParseState *pstate, ParamRef *pref)
411 {
412 SQLFunctionParseInfoPtr pinfo = (SQLFunctionParseInfoPtr) pstate->p_ref_hook_state;
tts_heap_get_heap_tuple(TupleTableSlot * slot)413 int paramno = pref->number;
414
415 /* Check parameter number is valid */
416 if (paramno <= 0 || paramno > pinfo->nargs)
417 return NULL; /* unknown parameter number */
418
419 return sql_fn_make_param(pinfo, paramno, pref->location);
420 }
421
422 /*
423 * sql_fn_make_param construct a Param node for the given paramno
424 */
tts_heap_copy_heap_tuple(TupleTableSlot * slot)425 static Node *
426 sql_fn_make_param(SQLFunctionParseInfoPtr pinfo,
427 int paramno, int location)
428 {
429 Param *param;
430
431 param = makeNode(Param);
432 param->paramkind = PARAM_EXTERN;
433 param->paramid = paramno;
434 param->paramtype = pinfo->argtypes[paramno - 1];
435 param->paramtypmod = -1;
436 param->paramcollid = get_typcollation(param->paramtype);
437 param->location = location;
438
439 /*
440 * If we have a function input collation, allow it to override the
441 * type-derived collation for parameter symbols. (XXX perhaps this should
442 * not happen if the type collation is not default?)
443 */
444 if (OidIsValid(pinfo->collation) && OidIsValid(param->paramcollid))
445 param->paramcollid = pinfo->collation;
446
447 return (Node *) param;
448 }
449
450 /*
451 * Search for a function parameter of the given name; if there is one,
452 * construct and return a Param node for it. If not, return NULL.
453 * Helper function for sql_fn_post_column_ref.
454 */
455 static Node *
456 sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo,
457 const char *paramname, int location)
458 {
459 int i;
460
461 if (pinfo->argnames == NULL)
462 return NULL;
463
464 for (i = 0; i < pinfo->nargs; i++)
465 {
466 if (pinfo->argnames[i] && strcmp(pinfo->argnames[i], paramname) == 0)
467 return sql_fn_make_param(pinfo, i + 1, location);
468 }
469
tts_minimal_init(TupleTableSlot * slot)470 return NULL;
471 }
472
473 /*
474 * Set up the per-query execution_state records for a SQL function.
475 *
476 * The input is a List of Lists of parsed and rewritten, but not planned,
477 * querytrees. The sublist structure denotes the original query boundaries.
478 */
479 static List *
480 init_execution_state(List *queryTree_list,
481 SQLFunctionCachePtr fcache,
tts_minimal_release(TupleTableSlot * slot)482 bool lazyEvalOK)
483 {
484 List *eslist = NIL;
485 execution_state *lasttages = NULL;
486 ListCell *lc1;
487
488 foreach(lc1, queryTree_list)
489 {
490 List *qtlist = lfirst_node(List, lc1);
491 execution_state *firstes = NULL;
492 execution_state *preves = NULL;
493 ListCell *lc2;
494
495 foreach(lc2, qtlist)
496 {
497 Query *queryTree = lfirst_node(Query, lc2);
498 PlannedStmt *stmt;
499 execution_state *newes;
500
501 /* Plan the query if needed */
502 if (queryTree->commandType == CMD_UTILITY)
503 {
504 /* Utility commands require no planning. */
505 stmt = makeNode(PlannedStmt);
506 stmt->commandType = CMD_UTILITY;
507 stmt->canSetTag = queryTree->canSetTag;
508 stmt->utilityStmt = queryTree->utilityStmt;
509 stmt->stmt_location = queryTree->stmt_location;
510 stmt->stmt_len = queryTree->stmt_len;
511 }
512 else
513 stmt = pg_plan_query(queryTree,
514 fcache->src,
515 CURSOR_OPT_PARALLEL_OK,
516 NULL);
517
518 /*
519 * Precheck all commands for validity in a function. This should
520 * generally match the restrictions spi.c applies.
521 */
522 if (stmt->commandType == CMD_UTILITY)
523 {
524 if (IsA(stmt->utilityStmt, CopyStmt) &&
525 ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
526 ereport(ERROR,
527 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
528 errmsg("cannot COPY to/from client in a SQL function")));
529
530 if (IsA(stmt->utilityStmt, TransactionStmt))
531 ereport(ERROR,
532 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
533 /* translator: %s is a SQL statement name */
534 errmsg("%s is not allowed in a SQL function",
535 CreateCommandName(stmt->utilityStmt))));
536 }
537
538 if (fcache->readonly_func && !CommandIsReadOnly(stmt))
539 ereport(ERROR,
540 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
541 /* translator: %s is a SQL statement name */
542 errmsg("%s is not allowed in a non-volatile function",
543 CreateCommandName((Node *) stmt))));
544
545 /* OK, build the execution_state for this query */
546 newes = (execution_state *) palloc(sizeof(execution_state));
547 if (preves)
548 preves->next = newes;
549 else
550 firstes = newes;
551
552 newes->next = NULL;
553 newes->status = F_EXEC_START;
554 newes->setsResult = false; /* might change below */
555 newes->lazyEval = false; /* might change below */
556 newes->stmt = stmt;
557 newes->qd = NULL;
558
559 if (queryTree->canSetTag)
560 lasttages = newes;
561
562 preves = newes;
563 }
564
565 eslist = lappend(eslist, firstes);
566 }
567
568 /*
569 * Mark the last canSetTag query as delivering the function result; then,
570 * if it is a plain SELECT, mark it for lazy evaluation. If it's not a
571 * SELECT we must always run it to completion.
572 *
573 * Note: at some point we might add additional criteria for whether to use
574 * lazy eval. However, we should prefer to use it whenever the function
575 * doesn't return set, since fetching more than one row is useless in that
576 * case.
577 *
578 * Note: don't set setsResult if the function returns VOID, as evidenced
579 * by not having made a junkfilter. This ensures we'll throw away any
580 * output from the last statement in such a function.
581 */
582 if (lasttages && fcache->junkFilter)
583 {
584 lasttages->setsResult = true;
585 if (lazyEvalOK &&
586 lasttages->stmt->commandType == CMD_SELECT &&
587 !lasttages->stmt->hasModifyingCTE)
588 fcache->lazyEval = lasttages->lazyEval = true;
589 }
590
591 return eslist;
592 }
593
594 /*
595 * Initialize the SQLFunctionCache for a SQL function
596 */
597 static void
tts_minimal_copy_heap_tuple(TupleTableSlot * slot)598 init_sql_fcache(FunctionCallInfo fcinfo, Oid collation, bool lazyEvalOK)
599 {
600 FmgrInfo *finfo = fcinfo->flinfo;
601 Oid foid = finfo->fn_oid;
602 MemoryContext fcontext;
603 MemoryContext oldcontext;
604 Oid rettype;
605 TupleDesc rettupdesc;
606 HeapTuple procedureTuple;
607 Form_pg_proc procedureStruct;
608 SQLFunctionCachePtr fcache;
609 List *raw_parsetree_list;
610 List *queryTree_list;
611 List *resulttlist;
612 ListCell *lc;
613 Datum tmp;
614 bool isNull;
615
616 /*
617 * Create memory context that holds all the SQLFunctionCache data. It
618 * must be a child of whatever context holds the FmgrInfo.
619 */
620 fcontext = AllocSetContextCreate(finfo->fn_mcxt,
621 "SQL function",
622 ALLOCSET_DEFAULT_SIZES);
623
624 oldcontext = MemoryContextSwitchTo(fcontext);
625
626 /*
627 * Create the struct proper, link it to fcontext and fn_extra. Once this
628 * is done, we'll be able to recover the memory after failure, even if the
629 * FmgrInfo is long-lived.
630 */
631 fcache = (SQLFunctionCachePtr) palloc0(sizeof(SQLFunctionCache));
632 fcache->fcontext = fcontext;
633 finfo->fn_extra = (void *) fcache;
634
635 /*
636 * get the procedure tuple corresponding to the given function Oid
637 */
638 procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(foid));
639 if (!HeapTupleIsValid(procedureTuple))
640 elog(ERROR, "cache lookup failed for function %u", foid);
641 procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
642
643 /*
644 * copy function name immediately for use by error reporting callback, and
645 * for use as memory context identifier
646 */
647 fcache->fname = pstrdup(NameStr(procedureStruct->proname));
648 MemoryContextSetIdentifier(fcontext, fcache->fname);
649
650 /*
651 * Resolve any polymorphism, obtaining the actual result type, and the
652 * corresponding tupdesc if it's a rowtype.
653 */
654 (void) get_call_result_type(fcinfo, &rettype, &rettupdesc);
655
656 fcache->rettype = rettype;
657
658 /* Fetch the typlen and byval info for the result type */
659 get_typlenbyval(rettype, &fcache->typlen, &fcache->typbyval);
660
661 /* Remember whether we're returning setof something */
662 fcache->returnsSet = procedureStruct->proretset;
663
664 /* Remember if function is STABLE/IMMUTABLE */
665 fcache->readonly_func =
666 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
667
668 /*
669 * We need the actual argument types to pass to the parser. Also make
670 * sure that parameter symbols are considered to have the function's
671 * resolved input collation.
672 */
673 fcache->pinfo = prepare_sql_fn_parse_info(procedureTuple,
674 finfo->fn_expr,
675 collation);
676
677 /*
678 * And of course we need the function body text.
679 */
680 tmp = SysCacheGetAttr(PROCOID,
681 procedureTuple,
682 Anum_pg_proc_prosrc,
683 &isNull);
684 if (isNull)
685 elog(ERROR, "null prosrc for function %u", foid);
686 fcache->src = TextDatumGetCString(tmp);
687
688 /*
689 * Parse and rewrite the queries in the function text. Use sublists to
690 * keep track of the original query boundaries.
691 *
692 * Note: since parsing and planning is done in fcontext, we will generate
693 * a lot of cruft that lives as long as the fcache does. This is annoying
694 * but we'll not worry about it until the module is rewritten to use
695 * plancache.c.
696 */
697 raw_parsetree_list = pg_parse_query(fcache->src);
698
699 queryTree_list = NIL;
700 foreach(lc, raw_parsetree_list)
701 {
702 RawStmt *parsetree = lfirst_node(RawStmt, lc);
703 List *queryTree_sublist;
704
705 queryTree_sublist = pg_analyze_and_rewrite_params(parsetree,
706 fcache->src,
707 (ParserSetupHook) sql_fn_parser_setup,
708 fcache->pinfo,
709 NULL);
710 queryTree_list = lappend(queryTree_list, queryTree_sublist);
711 }
712
713 /*
714 * Check that there are no statements we don't want to allow.
715 */
716 check_sql_fn_statements(queryTree_list);
717
718 /*
719 * Check that the function returns the type it claims to. Although in
720 * simple cases this was already done when the function was defined, we
721 * have to recheck because database objects used in the function's queries
722 * might have changed type. We'd have to recheck anyway if the function
723 * had any polymorphic arguments. Moreover, check_sql_fn_retval takes
724 * care of injecting any required column type coercions. (But we don't
725 * ask it to insert nulls for dropped columns; the junkfilter handles
726 * that.)
727 *
728 * Note: we set fcache->returnsTuple according to whether we are returning
729 * the whole tuple result or just a single column. In the latter case we
730 * clear returnsTuple because we need not act different from the scalar
731 * result case, even if it's a rowtype column. (However, we have to force
732 * lazy eval mode in that case; otherwise we'd need extra code to expand
733 * the rowtype column into multiple columns, since we have no way to
734 * notify the caller that it should do that.)
735 */
736 fcache->returnsTuple = check_sql_fn_retval(queryTree_list,
737 rettype,
738 rettupdesc,
739 false,
740 &resulttlist);
741
742 /*
743 * Construct a JunkFilter we can use to coerce the returned rowtype to the
744 * desired form, unless the result type is VOID, in which case there's
745 * nothing to coerce to. (XXX Frequently, the JunkFilter isn't doing
746 * anything very interesting, but much of this module expects it to be
747 * there anyway.)
748 */
749 if (rettype != VOIDOID)
750 {
751 TupleTableSlot *slot = MakeSingleTupleTableSlot(NULL,
752 &TTSOpsMinimalTuple);
753
754 /*
755 * If the result is composite, *and* we are returning the whole tuple
756 * result, we need to insert nulls for any dropped columns. In the
757 * single-column-result case, there might be dropped columns within
758 * the composite column value, but it's not our problem here. There
759 * should be no resjunk entries in resulttlist, so in the second case
760 * the JunkFilter is certainly a no-op.
761 */
762 if (rettupdesc && fcache->returnsTuple)
763 fcache->junkFilter = ExecInitJunkFilterConversion(resulttlist,
764 rettupdesc,
765 slot);
766 else
767 fcache->junkFilter = ExecInitJunkFilter(resulttlist, slot);
768 }
769
770 if (fcache->returnsTuple)
771 {
772 /* Make sure output rowtype is properly blessed */
773 BlessTupleDesc(fcache->junkFilter->jf_resultSlot->tts_tupleDescriptor);
774 }
775 else if (fcache->returnsSet && type_is_rowtype(fcache->rettype))
776 {
777 /*
778 * Returning rowtype as if it were scalar --- materialize won't work.
779 * Right now it's sufficient to override any caller preference for
780 * materialize mode, but to add more smarts in init_execution_state
781 * about this, we'd probably need a three-way flag instead of bool.
782 */
783 lazyEvalOK = true;
784 }
785
786 /* Finally, plan the queries */
787 fcache->func_state = init_execution_state(queryTree_list,
788 fcache,
789 lazyEvalOK);
790
791 /* Mark fcache with time of creation to show it's valid */
792 fcache->lxid = MyProc->lxid;
793 fcache->subxid = GetCurrentSubTransactionId();
794
795 ReleaseSysCache(procedureTuple);
796
797 MemoryContextSwitchTo(oldcontext);
798 }
799
800 /* Start up execution of one execution_state node */
801 static void
802 postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
803 {
804 DestReceiver *dest;
805
806 Assert(es->qd == NULL);
807
808 /* Caller should have ensured a suitable snapshot is active */
809 Assert(ActiveSnapshotSet());
810
811 /*
812 * If this query produces the function result, send its output to the
813 * tuplestore; else discard any output.
814 */
815 if (es->setsResult)
816 {
817 DR_sqlfunction *myState;
818
819 dest = CreateDestReceiver(DestSQLFunction);
tts_buffer_heap_get_heap_tuple(TupleTableSlot * slot)820 /* pass down the needed info to the dest receiver routines */
821 myState = (DR_sqlfunction *) dest;
822 Assert(myState->pub.mydest == DestSQLFunction);
823 myState->tstore = fcache->tstore;
824 myState->cxt = CurrentMemoryContext;
825 myState->filter = fcache->junkFilter;
826 }
827 else
828 dest = None_Receiver;
829
830 es->qd = CreateQueryDesc(es->stmt,
831 fcache->src,
832 GetActiveSnapshot(),
tts_buffer_heap_copy_heap_tuple(TupleTableSlot * slot)833 InvalidSnapshot,
834 dest,
835 fcache->paramLI,
836 es->qd ? es->qd->queryEnv : NULL,
837 0);
838
839 /* Utility commands don't need Executor. */
840 if (es->qd->operation != CMD_UTILITY)
841 {
842 /*
843 * In lazyEval mode, do not let the executor set up an AfterTrigger
844 * context. This is necessary not just an optimization, because we
845 * mustn't exit from the function execution with a stacked
tts_buffer_heap_copy_minimal_tuple(TupleTableSlot * slot)846 * AfterTrigger level still active. We are careful not to select
847 * lazyEval mode for any statement that could possibly queue triggers.
848 */
849 int eflags;
850
851 if (es->lazyEval)
852 eflags = EXEC_FLAG_SKIP_TRIGGERS;
853 else
854 eflags = 0; /* default run-to-completion flags */
855 ExecutorStart(es->qd, eflags);
856 }
857
858 es->status = F_EXEC_RUN;
tts_buffer_heap_store_tuple(TupleTableSlot * slot,HeapTuple tuple,Buffer buffer,bool transfer_pin)859 }
860
861 /* Run one execution_state; either to completion or to first result row */
862 /* Returns true if we ran to completion */
863 static bool
864 postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
865 {
866 bool result;
867
868 if (es->qd->operation == CMD_UTILITY)
869 {
870 ProcessUtility(es->qd->plannedstmt,
871 fcache->src,
872 PROCESS_UTILITY_QUERY,
873 es->qd->params,
874 es->qd->queryEnv,
875 es->qd->dest,
876 NULL);
877 result = true; /* never stops early */
878 }
879 else
880 {
881 /* Run regular commands to completion unless lazyEval */
882 uint64 count = (es->lazyEval) ? 1 : 0;
883
884 ExecutorRun(es->qd, ForwardScanDirection, count, !fcache->returnsSet || !es->lazyEval);
885
886 /*
887 * If we requested run to completion OR there was no tuple returned,
888 * command must be complete.
889 */
890 result = (count == 0 || es->qd->estate->es_processed == 0);
891 }
892
893 return result;
894 }
895
896 /* Shut down execution of one execution_state node */
897 static void
898 postquel_end(execution_state *es)
899 {
900 /* mark status done to ensure we don't do ExecutorEnd twice */
901 es->status = F_EXEC_DONE;
902
903 /* Utility commands don't need Executor. */
904 if (es->qd->operation != CMD_UTILITY)
905 {
906 ExecutorFinish(es->qd);
907 ExecutorEnd(es->qd);
908 }
909
910 es->qd->dest->rDestroy(es->qd->dest);
911
912 FreeQueryDesc(es->qd);
913 es->qd = NULL;
914 }
915
916 /* Build ParamListInfo array representing current arguments */
917 static void
918 postquel_sub_params(SQLFunctionCachePtr fcache,
919 FunctionCallInfo fcinfo)
920 {
921 int nargs = fcinfo->nargs;
922
923 if (nargs > 0)
924 {
slot_deform_heap_tuple(TupleTableSlot * slot,HeapTuple tuple,uint32 * offp,int natts)925 ParamListInfo paramLI;
926
927 if (fcache->paramLI == NULL)
928 {
929 paramLI = makeParamList(nargs);
930 fcache->paramLI = paramLI;
931 }
932 else
933 {
934 paramLI = fcache->paramLI;
935 Assert(paramLI->numParams == nargs);
936 }
937
938 for (int i = 0; i < nargs; i++)
939 {
940 ParamExternData *prm = ¶mLI->params[i];
941
942 prm->value = fcinfo->args[i].value;
943 prm->isnull = fcinfo->args[i].isnull;
944 prm->pflags = 0;
945 prm->ptype = fcache->pinfo->argtypes[i];
946 }
947 }
948 else
949 fcache->paramLI = NULL;
950 }
951
952 /*
953 * Extract the SQL function's value from a single result row. This is used
954 * both for scalar (non-set) functions and for each row of a lazy-eval set
955 * result.
956 */
957 static Datum
958 postquel_get_single_result(TupleTableSlot *slot,
959 FunctionCallInfo fcinfo,
960 SQLFunctionCachePtr fcache,
961 MemoryContext resultcontext)
962 {
963 Datum value;
964 MemoryContext oldcontext;
965
966 /*
967 * Set up to return the function value. For pass-by-reference datatypes,
968 * be sure to allocate the result in resultcontext, not the current memory
969 * context (which has query lifespan). We can't leave the data in the
970 * TupleTableSlot because we intend to clear the slot before returning.
971 */
972 oldcontext = MemoryContextSwitchTo(resultcontext);
973
974 if (fcache->returnsTuple)
975 {
976 /* We must return the whole tuple as a Datum. */
977 fcinfo->isnull = false;
978 value = ExecFetchSlotHeapTupleDatum(slot);
979 }
980 else
981 {
982 /*
983 * Returning a scalar, which we have to extract from the first column
984 * of the SELECT result, and then copy into result context if needed.
985 */
986 value = slot_getattr(slot, 1, &(fcinfo->isnull));
987
988 if (!fcinfo->isnull)
989 value = datumCopy(value, fcache->typbyval, fcache->typlen);
990 }
991
992 MemoryContextSwitchTo(oldcontext);
993
994 return value;
995 }
996
997 /*
998 * fmgr_sql: function call manager for SQL functions
999 */
1000 Datum
1001 fmgr_sql(PG_FUNCTION_ARGS)
1002 {
1003 SQLFunctionCachePtr fcache;
1004 ErrorContextCallback sqlerrcontext;
1005 MemoryContext oldcontext;
1006 bool randomAccess;
1007 bool lazyEvalOK;
1008 bool is_first;
1009 bool pushed_snapshot;
1010 execution_state *es;
1011 TupleTableSlot *slot;
1012 Datum result;
1013 List *eslist;
1014 ListCell *eslc;
1015
1016 /*
1017 * Setup error traceback support for ereport()
1018 */
1019 sqlerrcontext.callback = sql_exec_error_callback;
1020 sqlerrcontext.arg = fcinfo->flinfo;
1021 sqlerrcontext.previous = error_context_stack;
1022 error_context_stack = &sqlerrcontext;
1023
1024 /* Check call context */
1025 if (fcinfo->flinfo->fn_retset)
1026 {
1027 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1028
1029 /*
1030 * For simplicity, we require callers to support both set eval modes.
1031 * There are cases where we must use one or must use the other, and
1032 * it's not really worthwhile to postpone the check till we know. But
1033 * note we do not require caller to provide an expectedDesc.
1034 */
1035 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1036 (rsi->allowedModes & SFRM_ValuePerCall) == 0 ||
1037 (rsi->allowedModes & SFRM_Materialize) == 0)
1038 ereport(ERROR,
1039 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1040 errmsg("set-valued function called in context that cannot accept a set")));
1041 randomAccess = rsi->allowedModes & SFRM_Materialize_Random;
1042 lazyEvalOK = !(rsi->allowedModes & SFRM_Materialize_Preferred);
1043 }
1044 else
1045 {
1046 randomAccess = false;
1047 lazyEvalOK = true;
1048 }
1049
1050 /*
1051 * Initialize fcache (build plans) if first time through; or re-initialize
1052 * if the cache is stale.
1053 */
1054 fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
1055
1056 if (fcache != NULL)
1057 {
1058 if (fcache->lxid != MyProc->lxid ||
1059 !SubTransactionIsActive(fcache->subxid))
1060 {
1061 /* It's stale; unlink and delete */
1062 fcinfo->flinfo->fn_extra = NULL;
1063 MemoryContextDelete(fcache->fcontext);
1064 fcache = NULL;
1065 }
1066 }
1067
1068 if (fcache == NULL)
1069 {
1070 init_sql_fcache(fcinfo, PG_GET_COLLATION(), lazyEvalOK);
1071 fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
1072 }
1073
1074 /*
1075 * Switch to context in which the fcache lives. This ensures that our
1076 * tuplestore etc will have sufficient lifetime. The sub-executor is
1077 * responsible for deleting per-tuple information. (XXX in the case of a
1078 * long-lived FmgrInfo, this policy represents more memory leakage, but
1079 * it's not entirely clear where to keep stuff instead.)
1080 */
1081 oldcontext = MemoryContextSwitchTo(fcache->fcontext);
1082
1083 /*
1084 * Find first unfinished query in function, and note whether it's the
1085 * first query.
1086 */
1087 eslist = fcache->func_state;
1088 es = NULL;
1089 is_first = true;
1090 foreach(eslc, eslist)
1091 {
1092 es = (execution_state *) lfirst(eslc);
1093
1094 while (es && es->status == F_EXEC_DONE)
1095 {
1096 is_first = false;
1097 es = es->next;
1098 }
1099
1100 if (es)
1101 break;
1102 }
1103
1104 /*
1105 * Convert params to appropriate format if starting a fresh execution. (If
1106 * continuing execution, we can re-use prior params.)
1107 */
1108 if (is_first && es && es->status == F_EXEC_START)
1109 postquel_sub_params(fcache, fcinfo);
1110
1111 /*
MakeTupleTableSlot(TupleDesc tupleDesc,const TupleTableSlotOps * tts_ops)1112 * Build tuplestore to hold results, if we don't have one already. Note
1113 * it's in the query-lifespan context.
1114 */
1115 if (!fcache->tstore)
1116 fcache->tstore = tuplestore_begin_heap(randomAccess, false, work_mem);
1117
1118 /*
1119 * Execute each command in the function one after another until we either
1120 * run out of commands or get a result row from a lazily-evaluated SELECT.
1121 *
1122 * Notes about snapshot management:
1123 *
1124 * In a read-only function, we just use the surrounding query's snapshot.
1125 *
1126 * In a non-read-only function, we rely on the fact that we'll never
1127 * suspend execution between queries of the function: the only reason to
1128 * suspend execution before completion is if we are returning a row from a
1129 * lazily-evaluated SELECT. So, when first entering this loop, we'll
1130 * either start a new query (and push a fresh snapshot) or re-establish
1131 * the active snapshot from the existing query descriptor. If we need to
1132 * start a new query in a subsequent execution of the loop, either we need
1133 * a fresh snapshot (and pushed_snapshot is false) or the existing
1134 * snapshot is on the active stack and we can just bump its command ID.
1135 */
1136 pushed_snapshot = false;
1137 while (es)
1138 {
1139 bool completed;
1140
1141 if (es->status == F_EXEC_START)
1142 {
1143 /*
1144 * If not read-only, be sure to advance the command counter for
1145 * each command, so that all work to date in this transaction is
1146 * visible. Take a new snapshot if we don't have one yet,
1147 * otherwise just bump the command ID in the existing snapshot.
1148 */
1149 if (!fcache->readonly_func)
1150 {
1151 CommandCounterIncrement();
1152 if (!pushed_snapshot)
1153 {
1154 PushActiveSnapshot(GetTransactionSnapshot());
1155 pushed_snapshot = true;
1156 }
1157 else
1158 UpdateActiveSnapshotCommandId();
1159 }
1160
1161 postquel_start(es, fcache);
1162 }
1163 else if (!fcache->readonly_func && !pushed_snapshot)
1164 {
1165 /* Re-establish active snapshot when re-entering function */
1166 PushActiveSnapshot(es->qd->snapshot);
1167 pushed_snapshot = true;
1168 }
1169
1170 completed = postquel_getnext(es, fcache);
ExecAllocTableSlot(List ** tupleTable,TupleDesc desc,const TupleTableSlotOps * tts_ops)1171
1172 /*
1173 * If we ran the command to completion, we can shut it down now. Any
1174 * row(s) we need to return are safely stashed in the tuplestore, and
1175 * we want to be sure that, for example, AFTER triggers get fired
1176 * before we return anything. Also, if the function doesn't return
1177 * set, we can shut it down anyway because it must be a SELECT and we
1178 * don't care about fetching any more result rows.
1179 */
1180 if (completed || !fcache->returnsSet)
1181 postquel_end(es);
1182
1183 /*
1184 * Break from loop if we didn't shut down (implying we got a
1185 * lazily-evaluated row). Otherwise we'll press on till the whole
1186 * function is done, relying on the tuplestore to keep hold of the
1187 * data to eventually be returned. This is necessary since an
1188 * INSERT/UPDATE/DELETE RETURNING that sets the result might be
1189 * followed by additional rule-inserted commands, and we want to
1190 * finish doing all those commands before we return anything.
ExecResetTupleTable(List * tupleTable,bool shouldFree)1191 */
1192 if (es->status != F_EXEC_DONE)
1193 break;
1194
1195 /*
1196 * Advance to next execution_state, which might be in the next list.
1197 */
1198 es = es->next;
1199 while (!es)
1200 {
1201 eslc = lnext(eslist, eslc);
1202 if (!eslc)
1203 break; /* end of function */
1204
1205 es = (execution_state *) lfirst(eslc);
1206
1207 /*
1208 * Flush the current snapshot so that we will take a new one for
1209 * the new query list. This ensures that new snaps are taken at
1210 * original-query boundaries, matching the behavior of interactive
1211 * execution.
1212 */
1213 if (pushed_snapshot)
1214 {
1215 PopActiveSnapshot();
1216 pushed_snapshot = false;
1217 }
1218 }
1219 }
1220
1221 /*
1222 * The tuplestore now contains whatever row(s) we are supposed to return.
1223 */
1224 if (fcache->returnsSet)
1225 {
1226 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1227
1228 if (es)
1229 {
1230 /*
1231 * If we stopped short of being done, we must have a lazy-eval
1232 * row.
1233 */
1234 Assert(es->lazyEval);
1235 /* Re-use the junkfilter's output slot to fetch back the tuple */
1236 Assert(fcache->junkFilter);
1237 slot = fcache->junkFilter->jf_resultSlot;
MakeSingleTupleTableSlot(TupleDesc tupdesc,const TupleTableSlotOps * tts_ops)1238 if (!tuplestore_gettupleslot(fcache->tstore, true, false, slot))
1239 elog(ERROR, "failed to fetch lazy-eval tuple");
1240 /* Extract the result as a datum, and copy out from the slot */
1241 result = postquel_get_single_result(slot, fcinfo,
1242 fcache, oldcontext);
1243 /* Clear the tuplestore, but keep it for next time */
1244 /* NB: this might delete the slot's content, but we don't care */
1245 tuplestore_clear(fcache->tstore);
1246
1247 /*
1248 * Let caller know we're not finished.
1249 */
1250 rsi->isDone = ExprMultipleResult;
1251
1252 /*
1253 * Ensure we will get shut down cleanly if the exprcontext is not
ExecDropSingleTupleTableSlot(TupleTableSlot * slot)1254 * run to completion.
1255 */
1256 if (!fcache->shutdown_reg)
1257 {
1258 RegisterExprContextCallback(rsi->econtext,
1259 ShutdownSQLFunction,
1260 PointerGetDatum(fcache));
1261 fcache->shutdown_reg = true;
1262 }
1263 }
1264 else if (fcache->lazyEval)
1265 {
1266 /*
1267 * We are done with a lazy evaluation. Clean up.
1268 */
1269 tuplestore_clear(fcache->tstore);
1270
1271 /*
1272 * Let caller know we're finished.
1273 */
1274 rsi->isDone = ExprEndResult;
1275
1276 fcinfo->isnull = true;
1277 result = (Datum) 0;
1278
1279 /* Deregister shutdown callback, if we made one */
1280 if (fcache->shutdown_reg)
1281 {
1282 UnregisterExprContextCallback(rsi->econtext,
1283 ShutdownSQLFunction,
1284 PointerGetDatum(fcache));
1285 fcache->shutdown_reg = false;
1286 }
1287 }
1288 else
ExecSetSlotDescriptor(TupleTableSlot * slot,TupleDesc tupdesc)1289 {
1290 /*
1291 * We are done with a non-lazy evaluation. Return whatever is in
1292 * the tuplestore. (It is now caller's responsibility to free the
1293 * tuplestore when done.)
1294 */
1295 rsi->returnMode = SFRM_Materialize;
1296 rsi->setResult = fcache->tstore;
1297 fcache->tstore = NULL;
1298 /* must copy desc because execSRF.c will free it */
1299 if (fcache->junkFilter)
1300 rsi->setDesc = CreateTupleDescCopy(fcache->junkFilter->jf_cleanTupType);
1301
1302 fcinfo->isnull = true;
1303 result = (Datum) 0;
1304
1305 /* Deregister shutdown callback, if we made one */
1306 if (fcache->shutdown_reg)
1307 {
1308 UnregisterExprContextCallback(rsi->econtext,
1309 ShutdownSQLFunction,
1310 PointerGetDatum(fcache));
1311 fcache->shutdown_reg = false;
1312 }
1313 }
1314 }
1315 else
1316 {
1317 /*
1318 * Non-set function. If we got a row, return it; else return NULL.
1319 */
1320 if (fcache->junkFilter)
1321 {
1322 /* Re-use the junkfilter's output slot to fetch back the tuple */
1323 slot = fcache->junkFilter->jf_resultSlot;
1324 if (tuplestore_gettupleslot(fcache->tstore, true, false, slot))
1325 result = postquel_get_single_result(slot, fcinfo,
1326 fcache, oldcontext);
1327 else
1328 {
1329 fcinfo->isnull = true;
1330 result = (Datum) 0;
1331 }
1332 }
1333 else
1334 {
1335 /* Should only get here for VOID functions and procedures */
1336 Assert(fcache->rettype == VOIDOID);
1337 fcinfo->isnull = true;
1338 result = (Datum) 0;
1339 }
1340
1341 /* Clear the tuplestore, but keep it for next time */
1342 tuplestore_clear(fcache->tstore);
1343 }
1344
1345 /* Pop snapshot if we have pushed one */
1346 if (pushed_snapshot)
1347 PopActiveSnapshot();
1348
1349 /*
1350 * If we've gone through every command in the function, we are done. Reset
1351 * the execution states to start over again on next call.
ExecStoreHeapTuple(HeapTuple tuple,TupleTableSlot * slot,bool shouldFree)1352 */
1353 if (es == NULL)
1354 {
1355 foreach(eslc, fcache->func_state)
1356 {
1357 es = (execution_state *) lfirst(eslc);
1358 while (es)
1359 {
1360 es->status = F_EXEC_START;
1361 es = es->next;
1362 }
1363 }
1364 }
1365
1366 error_context_stack = sqlerrcontext.previous;
1367
1368 MemoryContextSwitchTo(oldcontext);
1369
1370 return result;
1371 }
1372
1373
1374 /*
1375 * error context callback to let us supply a call-stack traceback
1376 */
1377 static void
1378 sql_exec_error_callback(void *arg)
1379 {
1380 FmgrInfo *flinfo = (FmgrInfo *) arg;
1381 SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) flinfo->fn_extra;
1382 int syntaxerrposition;
1383
1384 /*
1385 * We can do nothing useful if init_sql_fcache() didn't get as far as
1386 * saving the function name
1387 */
1388 if (fcache == NULL || fcache->fname == NULL)
1389 return;
1390
1391 /*
ExecStoreBufferHeapTuple(HeapTuple tuple,TupleTableSlot * slot,Buffer buffer)1392 * If there is a syntax error position, convert to internal syntax error
1393 */
1394 syntaxerrposition = geterrposition();
1395 if (syntaxerrposition > 0 && fcache->src != NULL)
1396 {
1397 errposition(0);
1398 internalerrposition(syntaxerrposition);
1399 internalerrquery(fcache->src);
1400 }
1401
1402 /*
1403 * Try to determine where in the function we failed. If there is a query
1404 * with non-null QueryDesc, finger it. (We check this rather than looking
1405 * for F_EXEC_RUN state, so that errors during ExecutorStart or
1406 * ExecutorEnd are blamed on the appropriate query; see postquel_start and
1407 * postquel_end.)
1408 */
1409 if (fcache->func_state)
1410 {
1411 execution_state *es;
1412 int query_num;
1413 ListCell *lc;
1414
1415 es = NULL;
1416 query_num = 1;
1417 foreach(lc, fcache->func_state)
ExecStorePinnedBufferHeapTuple(HeapTuple tuple,TupleTableSlot * slot,Buffer buffer)1418 {
1419 es = (execution_state *) lfirst(lc);
1420 while (es)
1421 {
1422 if (es->qd)
1423 {
1424 errcontext("SQL function \"%s\" statement %d",
1425 fcache->fname, query_num);
1426 break;
1427 }
1428 es = es->next;
1429 }
1430 if (es)
1431 break;
1432 query_num++;
1433 }
1434 if (es == NULL)
1435 {
1436 /*
1437 * couldn't identify a running query; might be function entry,
1438 * function exit, or between queries.
1439 */
1440 errcontext("SQL function \"%s\"", fcache->fname);
1441 }
1442 }
1443 else
1444 {
1445 /*
ExecStoreMinimalTuple(MinimalTuple mtup,TupleTableSlot * slot,bool shouldFree)1446 * Assume we failed during init_sql_fcache(). (It's possible that the
1447 * function actually has an empty body, but in that case we may as
1448 * well report all errors as being "during startup".)
1449 */
1450 errcontext("SQL function \"%s\" during startup", fcache->fname);
1451 }
1452 }
1453
1454
1455 /*
1456 * callback function in case a function-returning-set needs to be shut down
1457 * before it has been run to completion
1458 */
1459 static void
1460 ShutdownSQLFunction(Datum arg)
1461 {
1462 SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) DatumGetPointer(arg);
1463 execution_state *es;
1464 ListCell *lc;
1465
1466 foreach(lc, fcache->func_state)
1467 {
1468 es = (execution_state *) lfirst(lc);
ExecForceStoreHeapTuple(HeapTuple tuple,TupleTableSlot * slot,bool shouldFree)1469 while (es)
1470 {
1471 /* Shut down anything still running */
1472 if (es->status == F_EXEC_RUN)
1473 {
1474 /* Re-establish active snapshot for any called functions */
1475 if (!fcache->readonly_func)
1476 PushActiveSnapshot(es->qd->snapshot);
1477
1478 postquel_end(es);
1479
1480 if (!fcache->readonly_func)
1481 PopActiveSnapshot();
1482 }
1483
1484 /* Reset states to START in case we're called again */
1485 es->status = F_EXEC_START;
1486 es = es->next;
1487 }
1488 }
1489
1490 /* Release tuplestore if we have one */
1491 if (fcache->tstore)
1492 tuplestore_end(fcache->tstore);
1493 fcache->tstore = NULL;
1494
1495 /* execUtils will deregister the callback... */
1496 fcache->shutdown_reg = false;
1497 }
1498
1499 /*
1500 * check_sql_fn_statements
1501 *
1502 * Check statements in an SQL function. Error out if there is anything that
1503 * is not acceptable.
1504 */
1505 void
1506 check_sql_fn_statements(List *queryTreeLists)
1507 {
1508 ListCell *lc;
1509
1510 /* We are given a list of sublists of Queries */
1511 foreach(lc, queryTreeLists)
ExecForceStoreMinimalTuple(MinimalTuple mtup,TupleTableSlot * slot,bool shouldFree)1512 {
1513 List *sublist = lfirst_node(List, lc);
1514 ListCell *lc2;
1515
1516 foreach(lc2, sublist)
1517 {
1518 Query *query = lfirst_node(Query, lc2);
1519
1520 /*
1521 * Disallow procedures with output arguments. The current
1522 * implementation would just throw the output values away, unless
1523 * the statement is the last one. Per SQL standard, we should
1524 * assign the output values by name. By disallowing this here, we
1525 * preserve an opportunity for future improvement.
1526 */
1527 if (query->commandType == CMD_UTILITY &&
1528 IsA(query->utilityStmt, CallStmt))
1529 {
1530 CallStmt *stmt = castNode(CallStmt, query->utilityStmt);
1531 HeapTuple tuple;
1532 int numargs;
1533 Oid *argtypes;
1534 char **argnames;
1535 char *argmodes;
1536 int i;
1537
1538 tuple = SearchSysCache1(PROCOID,
1539 ObjectIdGetDatum(stmt->funcexpr->funcid));
1540 if (!HeapTupleIsValid(tuple))
1541 elog(ERROR, "cache lookup failed for function %u",
1542 stmt->funcexpr->funcid);
1543 numargs = get_func_arg_info(tuple,
1544 &argtypes, &argnames, &argmodes);
1545 ReleaseSysCache(tuple);
1546
1547 for (i = 0; i < numargs; i++)
1548 {
1549 if (argmodes && (argmodes[i] == PROARGMODE_INOUT ||
1550 argmodes[i] == PROARGMODE_OUT))
1551 ereport(ERROR,
1552 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1553 errmsg("calling procedures with output arguments is not supported in SQL functions")));
1554 }
1555 }
1556 }
1557 }
1558 }
1559
1560 /*
1561 * check_sql_fn_retval()
1562 * Check return value of a list of lists of sql parse trees.
1563 *
1564 * The return value of a sql function is the value returned by the last
1565 * canSetTag query in the function. We do some ad-hoc type checking and
1566 * coercion here to ensure that the function returns what it's supposed to.
1567 * Note that we may actually modify the last query to make it match!
1568 *
1569 * This function returns true if the sql function returns the entire tuple
1570 * result of its final statement, or false if it returns just the first column
1571 * result of that statement. It throws an error if the final statement doesn't
1572 * return the right type at all.
1573 *
1574 * Note that because we allow "SELECT rowtype_expression", the result can be
1575 * false even when the declared function return type is a rowtype.
ExecStoreAllNullTuple(TupleTableSlot * slot)1576 *
1577 * For a polymorphic function the passed rettype must be the actual resolved
1578 * output type of the function. (This means we can't check the type during
1579 * function definition of a polymorphic function.) If we do see a polymorphic
1580 * rettype we'll throw an error, saying it is not a supported rettype.
1581 *
1582 * If the function returns composite, the passed rettupdesc should describe
1583 * the expected output. If rettupdesc is NULL, we can't verify that the
1584 * output matches; that should only happen in fmgr_sql_validator(), or when
1585 * the function returns RECORD and the caller doesn't actually care which
1586 * composite type it is.
1587 *
1588 * (Typically, rettype and rettupdesc are computed by get_call_result_type
1589 * or a sibling function.)
1590 *
1591 * In addition to coercing individual output columns, we can modify the
1592 * output to include dummy NULL columns for any dropped columns appearing
1593 * in rettupdesc. This is done only if the caller asks for it.
1594 *
1595 * If resultTargetList isn't NULL, then *resultTargetList is set to the
1596 * targetlist that defines the final statement's result. Exception: if the
1597 * function is defined to return VOID then *resultTargetList is set to NIL.
1598 */
1599 bool
1600 check_sql_fn_retval(List *queryTreeLists,
1601 Oid rettype, TupleDesc rettupdesc,
1602 bool insertDroppedCols,
1603 List **resultTargetList)
1604 {
1605 bool is_tuple_result = false;
1606 Query *parse;
1607 ListCell *parse_cell;
1608 List *tlist;
1609 int tlistlen;
1610 bool tlist_is_modifiable;
1611 char fn_typtype;
1612 List *upper_tlist = NIL;
1613 bool upper_tlist_nontrivial = false;
1614 ListCell *lc;
1615
1616 if (resultTargetList)
1617 *resultTargetList = NIL; /* initialize in case of VOID result */
1618
1619 /*
1620 * If it's declared to return VOID, we don't care what's in the function.
1621 * (This takes care of the procedure case, as well.)
1622 */
1623 if (rettype == VOIDOID)
1624 return false;
1625
1626 /*
1627 * Find the last canSetTag query in the function body (which is presented
1628 * to us as a list of sublists of Query nodes). This isn't necessarily
1629 * the last parsetree, because rule rewriting can insert queries after
1630 * what the user wrote. Note that it might not even be in the last
1631 * sublist, for example if the last query rewrites to DO INSTEAD NOTHING.
1632 * (It might not be unreasonable to throw an error in such a case, but
1633 * this is the historical behavior and it doesn't seem worth changing.)
1634 */
1635 parse = NULL;
1636 parse_cell = NULL;
1637 foreach(lc, queryTreeLists)
1638 {
1639 List *sublist = lfirst_node(List, lc);
1640 ListCell *lc2;
1641
1642 foreach(lc2, sublist)
1643 {
1644 Query *q = lfirst_node(Query, lc2);
1645
1646 if (q->canSetTag)
1647 {
1648 parse = q;
1649 parse_cell = lc2;
1650 }
1651 }
1652 }
1653
1654 /*
1655 * If it's a plain SELECT, it returns whatever the targetlist says.
1656 * Otherwise, if it's INSERT/UPDATE/DELETE with RETURNING, it returns
1657 * that. Otherwise, the function return type must be VOID.
1658 *
1659 * Note: eventually replace this test with QueryReturnsTuples? We'd need
1660 * a more general method of determining the output type, though. Also, it
1661 * seems too dangerous to consider FETCH or EXECUTE as returning a
1662 * determinable rowtype, since they depend on relatively short-lived
1663 * entities.
1664 */
1665 if (parse &&
1666 parse->commandType == CMD_SELECT)
1667 {
1668 tlist = parse->targetList;
1669 /* tlist is modifiable unless it's a dummy in a setop query */
1670 tlist_is_modifiable = (parse->setOperations == NULL);
1671 }
1672 else if (parse &&
1673 (parse->commandType == CMD_INSERT ||
1674 parse->commandType == CMD_UPDATE ||
1675 parse->commandType == CMD_DELETE) &&
1676 parse->returningList)
1677 {
1678 tlist = parse->returningList;
1679 /* returningList can always be modified */
1680 tlist_is_modifiable = true;
1681 }
1682 else
1683 {
1684 /* Empty function body, or last statement is a utility command */
1685 ereport(ERROR,
1686 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1687 errmsg("return type mismatch in function declared to return %s",
1688 format_type_be(rettype)),
1689 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING.")));
1690 return false; /* keep compiler quiet */
1691 }
1692
1693 /*
1694 * OK, check that the targetlist returns something matching the declared
1695 * type, and modify it if necessary. If possible, we insert any coercion
1696 * steps right into the final statement's targetlist. However, that might
1697 * risk changes in the statement's semantics --- we can't safely change
1698 * the output type of a grouping column, for instance. In such cases we
1699 * handle coercions by inserting an extra level of Query that effectively
1700 * just does a projection.
1701 */
1702
1703 /*
1704 * Count the non-junk entries in the result targetlist.
1705 */
1706 tlistlen = ExecCleanTargetListLength(tlist);
1707
1708 fn_typtype = get_typtype(rettype);
1709
1710 if (fn_typtype == TYPTYPE_BASE ||
1711 fn_typtype == TYPTYPE_DOMAIN ||
1712 fn_typtype == TYPTYPE_ENUM ||
1713 fn_typtype == TYPTYPE_RANGE)
1714 {
1715 /*
1716 * For scalar-type returns, the target list must have exactly one
1717 * non-junk entry, and its type must be coercible to rettype.
1718 */
1719 TargetEntry *tle;
1720
1721 if (tlistlen != 1)
1722 ereport(ERROR,
1723 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1724 errmsg("return type mismatch in function declared to return %s",
1725 format_type_be(rettype)),
1726 errdetail("Final statement must return exactly one column.")));
1727
1728 /* We assume here that non-junk TLEs must come first in tlists */
1729 tle = (TargetEntry *) linitial(tlist);
1730 Assert(!tle->resjunk);
1731
1732 if (!coerce_fn_result_column(tle, rettype, -1,
1733 tlist_is_modifiable,
1734 &upper_tlist,
1735 &upper_tlist_nontrivial))
1736 ereport(ERROR,
1737 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1738 errmsg("return type mismatch in function declared to return %s",
1739 format_type_be(rettype)),
1740 errdetail("Actual return type is %s.",
1741 format_type_be(exprType((Node *) tle->expr)))));
1742 }
1743 else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
1744 {
1745 /*
1746 * Returns a rowtype.
1747 *
1748 * Note that we will not consider a domain over composite to be a
1749 * "rowtype" return type; it goes through the scalar case above. This
1750 * is because we only provide column-by-column implicit casting, and
1751 * will not cast the complete record result. So the only way to
1752 * produce a domain-over-composite result is to compute it as an
1753 * explicit single-column result. The single-composite-column code
1754 * path just below could handle such cases, but it won't be reached.
1755 */
1756 int tupnatts; /* physical number of columns in tuple */
1757 int tuplogcols; /* # of nondeleted columns in tuple */
1758 int colindex; /* physical column index */
1759
1760 /*
1761 * If the target list has one non-junk entry, and that expression has
1762 * or can be coerced to the declared return type, take it as the
1763 * result. This allows, for example, 'SELECT func2()', where func2
1764 * has the same composite return type as the function that's calling
1765 * it. This provision creates some ambiguity --- maybe the expression
1766 * was meant to be the lone field of the composite result --- but it
1767 * works well enough as long as we don't get too enthusiastic about
1768 * inventing coercions from scalar to composite types.
1769 *
1770 * XXX Note that if rettype is RECORD and the expression is of a named
1771 * composite type, or vice versa, this coercion will succeed, whether
1772 * or not the record type really matches. For the moment we rely on
1773 * runtime type checking to catch any discrepancy, but it'd be nice to
1774 * do better at parse time.
1775 */
1776 if (tlistlen == 1)
1777 {
1778 TargetEntry *tle = (TargetEntry *) linitial(tlist);
1779
1780 Assert(!tle->resjunk);
1781 if (coerce_fn_result_column(tle, rettype, -1,
1782 tlist_is_modifiable,
1783 &upper_tlist,
1784 &upper_tlist_nontrivial))
1785 {
1786 /* Note that we're NOT setting is_tuple_result */
1787 goto tlist_coercion_finished;
1788 }
1789 }
1790
1791 /*
1792 * If the caller didn't provide an expected tupdesc, we can't do any
1793 * further checking. Assume we're returning the whole tuple.
1794 */
1795 if (rettupdesc == NULL)
1796 {
1797 /* Return tlist if requested */
1798 if (resultTargetList)
1799 *resultTargetList = tlist;
1800 return true;
1801 }
1802
1803 /*
1804 * Verify that the targetlist matches the return tuple type. We scan
1805 * the non-resjunk columns, and coerce them if necessary to match the
1806 * datatypes of the non-deleted attributes. For deleted attributes,
1807 * insert NULL result columns if the caller asked for that.
1808 */
1809 tupnatts = rettupdesc->natts;
1810 tuplogcols = 0; /* we'll count nondeleted cols as we go */
1811 colindex = 0;
1812
1813 foreach(lc, tlist)
1814 {
1815 TargetEntry *tle = (TargetEntry *) lfirst(lc);
1816 Form_pg_attribute attr;
1817
1818 /* resjunk columns can simply be ignored */
1819 if (tle->resjunk)
1820 continue;
1821
1822 do
1823 {
1824 colindex++;
1825 if (colindex > tupnatts)
1826 ereport(ERROR,
1827 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1828 errmsg("return type mismatch in function declared to return %s",
1829 format_type_be(rettype)),
1830 errdetail("Final statement returns too many columns.")));
1831 attr = TupleDescAttr(rettupdesc, colindex - 1);
1832 if (attr->attisdropped && insertDroppedCols)
1833 {
1834 Expr *null_expr;
1835
1836 /* The type of the null we insert isn't important */
1837 null_expr = (Expr *) makeConst(INT4OID,
1838 -1,
1839 InvalidOid,
1840 sizeof(int32),
1841 (Datum) 0,
1842 true, /* isnull */
1843 true /* byval */ );
1844 upper_tlist = lappend(upper_tlist,
1845 makeTargetEntry(null_expr,
1846 list_length(upper_tlist) + 1,
1847 NULL,
1848 false));
1849 upper_tlist_nontrivial = true;
1850 }
1851 } while (attr->attisdropped);
1852 tuplogcols++;
1853
1854 if (!coerce_fn_result_column(tle,
1855 attr->atttypid, attr->atttypmod,
1856 tlist_is_modifiable,
1857 &upper_tlist,
1858 &upper_tlist_nontrivial))
1859 ereport(ERROR,
1860 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1861 errmsg("return type mismatch in function declared to return %s",
1862 format_type_be(rettype)),
1863 errdetail("Final statement returns %s instead of %s at column %d.",
1864 format_type_be(exprType((Node *) tle->expr)),
1865 format_type_be(attr->atttypid),
1866 tuplogcols)));
1867 }
1868
1869 /* remaining columns in rettupdesc had better all be dropped */
1870 for (colindex++; colindex <= tupnatts; colindex++)
1871 {
1872 if (!TupleDescAttr(rettupdesc, colindex - 1)->attisdropped)
1873 ereport(ERROR,
1874 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1875 errmsg("return type mismatch in function declared to return %s",
1876 format_type_be(rettype)),
1877 errdetail("Final statement returns too few columns.")));
1878 if (insertDroppedCols)
1879 {
1880 Expr *null_expr;
1881
1882 /* The type of the null we insert isn't important */
1883 null_expr = (Expr *) makeConst(INT4OID,
1884 -1,
1885 InvalidOid,
1886 sizeof(int32),
1887 (Datum) 0,
1888 true, /* isnull */
1889 true /* byval */ );
1890 upper_tlist = lappend(upper_tlist,
1891 makeTargetEntry(null_expr,
1892 list_length(upper_tlist) + 1,
1893 NULL,
1894 false));
1895 upper_tlist_nontrivial = true;
1896 }
1897 }
1898
1899 /* Report that we are returning entire tuple result */
1900 is_tuple_result = true;
1901 }
1902 else
1903 ereport(ERROR,
1904 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1905 errmsg("return type %s is not supported for SQL functions",
1906 format_type_be(rettype))));
1907
1908 tlist_coercion_finished:
1909
1910 /*
1911 * If necessary, modify the final Query by injecting an extra Query level
1912 * that just performs a projection. (It'd be dubious to do this to a
1913 * non-SELECT query, but we never have to; RETURNING lists can always be
1914 * modified in-place.)
1915 */
1916 if (upper_tlist_nontrivial)
1917 {
1918 Query *newquery;
1919 List *colnames;
1920 RangeTblEntry *rte;
1921 RangeTblRef *rtr;
1922
1923 Assert(parse->commandType == CMD_SELECT);
1924
1925 /* Most of the upper Query struct can be left as zeroes/nulls */
1926 newquery = makeNode(Query);
1927 newquery->commandType = CMD_SELECT;
1928 newquery->querySource = parse->querySource;
1929 newquery->canSetTag = true;
1930 newquery->targetList = upper_tlist;
1931
1932 /* We need a moderately realistic colnames list for the subquery RTE */
1933 colnames = NIL;
1934 foreach(lc, parse->targetList)
1935 {
1936 TargetEntry *tle = (TargetEntry *) lfirst(lc);
1937
1938 if (tle->resjunk)
1939 continue;
1940 colnames = lappend(colnames,
1941 makeString(tle->resname ? tle->resname : ""));
1942 }
1943
1944 /* Build a suitable RTE for the subquery */
1945 rte = makeNode(RangeTblEntry);
1946 rte->rtekind = RTE_SUBQUERY;
1947 rte->subquery = parse;
1948 rte->eref = rte->alias = makeAlias("*SELECT*", colnames);
1949 rte->lateral = false;
1950 rte->inh = false;
1951 rte->inFromCl = true;
1952 newquery->rtable = list_make1(rte);
1953
1954 rtr = makeNode(RangeTblRef);
1955 rtr->rtindex = 1;
1956 newquery->jointree = makeFromExpr(list_make1(rtr), NULL);
1957
1958 /* Replace original query in the correct element of the query list */
1959 lfirst(parse_cell) = newquery;
1960 }
1961
1962 /* Return tlist (possibly modified) if requested */
1963 if (resultTargetList)
1964 *resultTargetList = upper_tlist;
1965
1966 return is_tuple_result;
1967 }
1968
1969 /*
1970 * Process one function result column for check_sql_fn_retval
1971 *
1972 * Coerce the output value to the required type/typmod, and add a column
1973 * to *upper_tlist for it. Set *upper_tlist_nontrivial to true if we
1974 * add an upper tlist item that's not just a Var.
1975 *
1976 * Returns true if OK, false if could not coerce to required type
1977 * (in which case, no changes have been made)
1978 */
1979 static bool
1980 coerce_fn_result_column(TargetEntry *src_tle,
1981 Oid res_type,
1982 int32 res_typmod,
1983 bool tlist_is_modifiable,
1984 List **upper_tlist,
1985 bool *upper_tlist_nontrivial)
1986 {
1987 TargetEntry *new_tle;
1988 Expr *new_tle_expr;
1989 Node *cast_result;
1990
1991 /*
1992 * If the TLE has a sortgroupref marking, don't change it, as it probably
1993 * is referenced by ORDER BY, DISTINCT, etc, and changing its type would
1994 * break query semantics. Otherwise, it's safe to modify in-place unless
1995 * the query as a whole has issues with that.
1996 */
ExecTypeFromExprList(List * exprList)1997 if (tlist_is_modifiable && src_tle->ressortgroupref == 0)
1998 {
1999 /* OK to modify src_tle in place, if necessary */
2000 cast_result = coerce_to_target_type(NULL,
2001 (Node *) src_tle->expr,
2002 exprType((Node *) src_tle->expr),
2003 res_type, res_typmod,
2004 COERCION_ASSIGNMENT,
2005 COERCE_IMPLICIT_CAST,
2006 -1);
2007 if (cast_result == NULL)
2008 return false;
2009 assign_expr_collations(NULL, cast_result);
2010 src_tle->expr = (Expr *) cast_result;
2011 /* Make a Var referencing the possibly-modified TLE */
2012 new_tle_expr = (Expr *) makeVarFromTargetEntry(1, src_tle);
2013 }
2014 else
2015 {
2016 /* Any casting must happen in the upper tlist */
2017 Var *var = makeVarFromTargetEntry(1, src_tle);
2018
2019 cast_result = coerce_to_target_type(NULL,
2020 (Node *) var,
2021 var->vartype,
2022 res_type, res_typmod,
2023 COERCION_ASSIGNMENT,
2024 COERCE_IMPLICIT_CAST,
2025 -1);
2026 if (cast_result == NULL)
2027 return false;
2028 assign_expr_collations(NULL, cast_result);
2029 /* Did the coercion actually do anything? */
2030 if (cast_result != (Node *) var)
2031 *upper_tlist_nontrivial = true;
2032 new_tle_expr = (Expr *) cast_result;
2033 }
2034 new_tle = makeTargetEntry(new_tle_expr,
2035 list_length(*upper_tlist) + 1,
ExecTypeSetColNames(TupleDesc typeInfo,List * namesList)2036 src_tle->resname, false);
2037 *upper_tlist = lappend(*upper_tlist, new_tle);
2038 return true;
2039 }
2040
2041
2042 /*
2043 * CreateSQLFunctionDestReceiver -- create a suitable DestReceiver object
2044 */
2045 DestReceiver *
2046 CreateSQLFunctionDestReceiver(void)
2047 {
2048 DR_sqlfunction *self = (DR_sqlfunction *) palloc0(sizeof(DR_sqlfunction));
2049
2050 self->pub.receiveSlot = sqlfunction_receive;
2051 self->pub.rStartup = sqlfunction_startup;
2052 self->pub.rShutdown = sqlfunction_shutdown;
2053 self->pub.rDestroy = sqlfunction_destroy;
2054 self->pub.mydest = DestSQLFunction;
2055
2056 /* private fields will be set by postquel_start */
2057
2058 return (DestReceiver *) self;
2059 }
2060
2061 /*
2062 * sqlfunction_startup --- executor startup
2063 */
2064 static void
2065 sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
2066 {
2067 /* no-op */
2068 }
2069
2070 /*
2071 * sqlfunction_receive --- receive one tuple
2072 */
2073 static bool
2074 sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)
2075 {
2076 DR_sqlfunction *myState = (DR_sqlfunction *) self;
2077
2078 /* Filter tuple as needed */
2079 slot = ExecFilterJunk(myState->filter, slot);
2080
2081 /* Store the filtered tuple into the tuplestore */
BlessTupleDesc(TupleDesc tupdesc)2082 tuplestore_puttupleslot(myState->tstore, slot);
2083
2084 return true;
2085 }
2086
2087 /*
2088 * sqlfunction_shutdown --- executor end
2089 */
2090 static void
2091 sqlfunction_shutdown(DestReceiver *self)
2092 {
2093 /* no-op */
2094 }
2095
2096 /*
TupleDescGetAttInMetadata(TupleDesc tupdesc)2097 * sqlfunction_destroy --- release DestReceiver object
2098 */
2099 static void
2100 sqlfunction_destroy(DestReceiver *self)
2101 {
2102 pfree(self);
2103 }
2104