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