Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pl_exec.c - Executor for the PL/pgSQL
4 : * procedural language
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/pl/plpgsql/src/pl_exec.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include <ctype.h>
19 :
20 : #include "access/htup_details.h"
21 : #include "access/transam.h"
22 : #include "access/tupconvert.h"
23 : #include "catalog/pg_proc.h"
24 : #include "catalog/pg_type.h"
25 : #include "executor/spi.h"
26 : #include "funcapi.h"
27 : #include "miscadmin.h"
28 : #include "nodes/nodeFuncs.h"
29 : #include "optimizer/planner.h"
30 : #include "parser/parse_coerce.h"
31 : #include "parser/scansup.h"
32 : #include "storage/proc.h"
33 : #include "tcop/tcopprot.h"
34 : #include "utils/array.h"
35 : #include "utils/builtins.h"
36 : #include "utils/datum.h"
37 : #include "utils/fmgroids.h"
38 : #include "utils/lsyscache.h"
39 : #include "utils/memutils.h"
40 : #include "utils/rel.h"
41 : #include "utils/snapmgr.h"
42 : #include "utils/typcache.h"
43 :
44 : #include "plpgsql.h"
45 :
46 :
47 : typedef struct
48 : {
49 : int nargs; /* number of arguments */
50 : Oid *types; /* types of arguments */
51 : Datum *values; /* evaluated argument values */
52 : char *nulls; /* null markers (' '/'n' style) */
53 : } PreparedParamsData;
54 :
55 : /*
56 : * All plpgsql function executions within a single transaction share the same
57 : * executor EState for evaluating "simple" expressions. Each function call
58 : * creates its own "eval_econtext" ExprContext within this estate for
59 : * per-evaluation workspace. eval_econtext is freed at normal function exit,
60 : * and the EState is freed at transaction end (in case of error, we assume
61 : * that the abort mechanisms clean it all up). Furthermore, any exception
62 : * block within a function has to have its own eval_econtext separate from
63 : * the containing function's, so that we can clean up ExprContext callbacks
64 : * properly at subtransaction exit. We maintain a stack that tracks the
65 : * individual econtexts so that we can clean up correctly at subxact exit.
66 : *
67 : * This arrangement is a bit tedious to maintain, but it's worth the trouble
68 : * so that we don't have to re-prepare simple expressions on each trip through
69 : * a function. (We assume the case to optimize is many repetitions of a
70 : * function within a transaction.)
71 : *
72 : * However, there's no value in trying to amortize simple expression setup
73 : * across multiple executions of a DO block (inline code block), since there
74 : * can never be any. If we use the shared EState for a DO block, the expr
75 : * state trees are effectively leaked till end of transaction, and that can
76 : * add up if the user keeps on submitting DO blocks. Therefore, each DO block
77 : * has its own simple-expression EState, which is cleaned up at exit from
78 : * plpgsql_inline_handler(). DO blocks still use the simple_econtext_stack,
79 : * though, so that subxact abort cleanup does the right thing.
80 : */
81 : typedef struct SimpleEcontextStackEntry
82 : {
83 : ExprContext *stack_econtext; /* a stacked econtext */
84 : SubTransactionId xact_subxid; /* ID for current subxact */
85 : struct SimpleEcontextStackEntry *next; /* next stack entry up */
86 : } SimpleEcontextStackEntry;
87 :
88 : static EState *shared_simple_eval_estate = NULL;
89 : static SimpleEcontextStackEntry *simple_econtext_stack = NULL;
90 :
91 : /*
92 : * Memory management within a plpgsql function generally works with three
93 : * contexts:
94 : *
95 : * 1. Function-call-lifespan data, such as variable values, is kept in the
96 : * "main" context, a/k/a the "SPI Proc" context established by SPI_connect().
97 : * This is usually the CurrentMemoryContext while running code in this module
98 : * (which is not good, because careless coding can easily cause
99 : * function-lifespan memory leaks, but we live with it for now).
100 : *
101 : * 2. Some statement-execution routines need statement-lifespan workspace.
102 : * A suitable context is created on-demand by get_stmt_mcontext(), and must
103 : * be reset at the end of the requesting routine. Error recovery will clean
104 : * it up automatically. Nested statements requiring statement-lifespan
105 : * workspace will result in a stack of such contexts, see push_stmt_mcontext().
106 : *
107 : * 3. We use the eval_econtext's per-tuple memory context for expression
108 : * evaluation, and as a general-purpose workspace for short-lived allocations.
109 : * Such allocations usually aren't explicitly freed, but are left to be
110 : * cleaned up by a context reset, typically done by exec_eval_cleanup().
111 : *
112 : * These macros are for use in making short-lived allocations:
113 : */
114 : #define get_eval_mcontext(estate) \
115 : ((estate)->eval_econtext->ecxt_per_tuple_memory)
116 : #define eval_mcontext_alloc(estate, sz) \
117 : MemoryContextAlloc(get_eval_mcontext(estate), sz)
118 : #define eval_mcontext_alloc0(estate, sz) \
119 : MemoryContextAllocZero(get_eval_mcontext(estate), sz)
120 :
121 : /*
122 : * We use a session-wide hash table for caching cast information.
123 : *
124 : * Once built, the compiled expression trees (cast_expr fields) survive for
125 : * the life of the session. At some point it might be worth invalidating
126 : * those after pg_cast changes, but for the moment we don't bother.
127 : *
128 : * The evaluation state trees (cast_exprstate) are managed in the same way as
129 : * simple expressions (i.e., we assume cast expressions are always simple).
130 : *
131 : * As with simple expressions, DO blocks don't use the shared hash table but
132 : * must have their own. This isn't ideal, but we don't want to deal with
133 : * multiple simple_eval_estates within a DO block.
134 : */
135 : typedef struct /* lookup key for cast info */
136 : {
137 : /* NB: we assume this struct contains no padding bytes */
138 : Oid srctype; /* source type for cast */
139 : Oid dsttype; /* destination type for cast */
140 : int32 srctypmod; /* source typmod for cast */
141 : int32 dsttypmod; /* destination typmod for cast */
142 : } plpgsql_CastHashKey;
143 :
144 : typedef struct /* cast_hash table entry */
145 : {
146 : plpgsql_CastHashKey key; /* hash key --- MUST BE FIRST */
147 : Expr *cast_expr; /* cast expression, or NULL if no-op cast */
148 : /* ExprState is valid only when cast_lxid matches current LXID */
149 : ExprState *cast_exprstate; /* expression's eval tree */
150 : bool cast_in_use; /* true while we're executing eval tree */
151 : LocalTransactionId cast_lxid;
152 : } plpgsql_CastHashEntry;
153 :
154 : static MemoryContext shared_cast_context = NULL;
155 : static HTAB *shared_cast_hash = NULL;
156 :
157 : /************************************************************
158 : * Local function forward declarations
159 : ************************************************************/
160 : static void plpgsql_exec_error_callback(void *arg);
161 : static PLpgSQL_datum *copy_plpgsql_datum(PLpgSQL_datum *datum);
162 : static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate);
163 : static void push_stmt_mcontext(PLpgSQL_execstate *estate);
164 : static void pop_stmt_mcontext(PLpgSQL_execstate *estate);
165 :
166 : static int exec_stmt_block(PLpgSQL_execstate *estate,
167 : PLpgSQL_stmt_block *block);
168 : static int exec_stmts(PLpgSQL_execstate *estate,
169 : List *stmts);
170 : static int exec_stmt(PLpgSQL_execstate *estate,
171 : PLpgSQL_stmt *stmt);
172 : static int exec_stmt_assign(PLpgSQL_execstate *estate,
173 : PLpgSQL_stmt_assign *stmt);
174 : static int exec_stmt_perform(PLpgSQL_execstate *estate,
175 : PLpgSQL_stmt_perform *stmt);
176 : static int exec_stmt_getdiag(PLpgSQL_execstate *estate,
177 : PLpgSQL_stmt_getdiag *stmt);
178 : static int exec_stmt_if(PLpgSQL_execstate *estate,
179 : PLpgSQL_stmt_if *stmt);
180 : static int exec_stmt_case(PLpgSQL_execstate *estate,
181 : PLpgSQL_stmt_case *stmt);
182 : static int exec_stmt_loop(PLpgSQL_execstate *estate,
183 : PLpgSQL_stmt_loop *stmt);
184 : static int exec_stmt_while(PLpgSQL_execstate *estate,
185 : PLpgSQL_stmt_while *stmt);
186 : static int exec_stmt_fori(PLpgSQL_execstate *estate,
187 : PLpgSQL_stmt_fori *stmt);
188 : static int exec_stmt_fors(PLpgSQL_execstate *estate,
189 : PLpgSQL_stmt_fors *stmt);
190 : static int exec_stmt_forc(PLpgSQL_execstate *estate,
191 : PLpgSQL_stmt_forc *stmt);
192 : static int exec_stmt_foreach_a(PLpgSQL_execstate *estate,
193 : PLpgSQL_stmt_foreach_a *stmt);
194 : static int exec_stmt_open(PLpgSQL_execstate *estate,
195 : PLpgSQL_stmt_open *stmt);
196 : static int exec_stmt_fetch(PLpgSQL_execstate *estate,
197 : PLpgSQL_stmt_fetch *stmt);
198 : static int exec_stmt_close(PLpgSQL_execstate *estate,
199 : PLpgSQL_stmt_close *stmt);
200 : static int exec_stmt_exit(PLpgSQL_execstate *estate,
201 : PLpgSQL_stmt_exit *stmt);
202 : static int exec_stmt_return(PLpgSQL_execstate *estate,
203 : PLpgSQL_stmt_return *stmt);
204 : static int exec_stmt_return_next(PLpgSQL_execstate *estate,
205 : PLpgSQL_stmt_return_next *stmt);
206 : static int exec_stmt_return_query(PLpgSQL_execstate *estate,
207 : PLpgSQL_stmt_return_query *stmt);
208 : static int exec_stmt_raise(PLpgSQL_execstate *estate,
209 : PLpgSQL_stmt_raise *stmt);
210 : static int exec_stmt_assert(PLpgSQL_execstate *estate,
211 : PLpgSQL_stmt_assert *stmt);
212 : static int exec_stmt_execsql(PLpgSQL_execstate *estate,
213 : PLpgSQL_stmt_execsql *stmt);
214 : static int exec_stmt_dynexecute(PLpgSQL_execstate *estate,
215 : PLpgSQL_stmt_dynexecute *stmt);
216 : static int exec_stmt_dynfors(PLpgSQL_execstate *estate,
217 : PLpgSQL_stmt_dynfors *stmt);
218 :
219 : static void plpgsql_estate_setup(PLpgSQL_execstate *estate,
220 : PLpgSQL_function *func,
221 : ReturnSetInfo *rsi,
222 : EState *simple_eval_estate);
223 : static void exec_eval_cleanup(PLpgSQL_execstate *estate);
224 :
225 : static void exec_prepare_plan(PLpgSQL_execstate *estate,
226 : PLpgSQL_expr *expr, int cursorOptions);
227 : static void exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr);
228 : static void exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan);
229 : static void exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno);
230 : static bool contains_target_param(Node *node, int *target_dno);
231 : static bool exec_eval_simple_expr(PLpgSQL_execstate *estate,
232 : PLpgSQL_expr *expr,
233 : Datum *result,
234 : bool *isNull,
235 : Oid *rettype,
236 : int32 *rettypmod);
237 :
238 : static void exec_assign_expr(PLpgSQL_execstate *estate,
239 : PLpgSQL_datum *target,
240 : PLpgSQL_expr *expr);
241 : static void exec_assign_c_string(PLpgSQL_execstate *estate,
242 : PLpgSQL_datum *target,
243 : const char *str);
244 : static void exec_assign_value(PLpgSQL_execstate *estate,
245 : PLpgSQL_datum *target,
246 : Datum value, bool isNull,
247 : Oid valtype, int32 valtypmod);
248 : static void exec_eval_datum(PLpgSQL_execstate *estate,
249 : PLpgSQL_datum *datum,
250 : Oid *typeid,
251 : int32 *typetypmod,
252 : Datum *value,
253 : bool *isnull);
254 : static int exec_eval_integer(PLpgSQL_execstate *estate,
255 : PLpgSQL_expr *expr,
256 : bool *isNull);
257 : static bool exec_eval_boolean(PLpgSQL_execstate *estate,
258 : PLpgSQL_expr *expr,
259 : bool *isNull);
260 : static Datum exec_eval_expr(PLpgSQL_execstate *estate,
261 : PLpgSQL_expr *expr,
262 : bool *isNull,
263 : Oid *rettype,
264 : int32 *rettypmod);
265 : static int exec_run_select(PLpgSQL_execstate *estate,
266 : PLpgSQL_expr *expr, long maxtuples, Portal *portalP);
267 : static int exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
268 : Portal portal, bool prefetch_ok);
269 : static ParamListInfo setup_param_list(PLpgSQL_execstate *estate,
270 : PLpgSQL_expr *expr);
271 : static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate,
272 : PLpgSQL_expr *expr);
273 : static void plpgsql_param_fetch(ParamListInfo params, int paramid);
274 : static void exec_move_row(PLpgSQL_execstate *estate,
275 : PLpgSQL_rec *rec,
276 : PLpgSQL_row *row,
277 : HeapTuple tup, TupleDesc tupdesc);
278 : static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
279 : PLpgSQL_row *row,
280 : TupleDesc tupdesc);
281 : static HeapTuple get_tuple_from_datum(Datum value);
282 : static TupleDesc get_tupdesc_from_datum(Datum value);
283 : static void exec_move_row_from_datum(PLpgSQL_execstate *estate,
284 : PLpgSQL_rec *rec,
285 : PLpgSQL_row *row,
286 : Datum value);
287 : static char *convert_value_to_string(PLpgSQL_execstate *estate,
288 : Datum value, Oid valtype);
289 : static Datum exec_cast_value(PLpgSQL_execstate *estate,
290 : Datum value, bool *isnull,
291 : Oid valtype, int32 valtypmod,
292 : Oid reqtype, int32 reqtypmod);
293 : static plpgsql_CastHashEntry *get_cast_hashentry(PLpgSQL_execstate *estate,
294 : Oid srctype, int32 srctypmod,
295 : Oid dsttype, int32 dsttypmod);
296 : static void exec_init_tuple_store(PLpgSQL_execstate *estate);
297 : static void exec_set_found(PLpgSQL_execstate *estate, bool state);
298 : static void plpgsql_create_econtext(PLpgSQL_execstate *estate);
299 : static void plpgsql_destroy_econtext(PLpgSQL_execstate *estate);
300 : static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
301 : Datum newvalue, bool isnull, bool freeable);
302 : static void assign_text_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
303 : const char *str);
304 : static PreparedParamsData *exec_eval_using_params(PLpgSQL_execstate *estate,
305 : List *params);
306 : static Portal exec_dynquery_with_params(PLpgSQL_execstate *estate,
307 : PLpgSQL_expr *dynquery, List *params,
308 : const char *portalname, int cursorOptions);
309 : static char *format_expr_params(PLpgSQL_execstate *estate,
310 : const PLpgSQL_expr *expr);
311 : static char *format_preparedparamsdata(PLpgSQL_execstate *estate,
312 : const PreparedParamsData *ppd);
313 :
314 :
315 : /* ----------
316 : * plpgsql_exec_function Called by the call handler for
317 : * function execution.
318 : *
319 : * This is also used to execute inline code blocks (DO blocks). The only
320 : * difference that this code is aware of is that for a DO block, we want
321 : * to use a private simple_eval_estate, which is created and passed in by
322 : * the caller. For regular functions, pass NULL, which implies using
323 : * shared_simple_eval_estate. (When using a private simple_eval_estate,
324 : * we must also use a private cast hashtable, but that's taken care of
325 : * within plpgsql_estate_setup.)
326 : * ----------
327 : */
328 : Datum
329 10450 : plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
330 : EState *simple_eval_estate)
331 : {
332 : PLpgSQL_execstate estate;
333 : ErrorContextCallback plerrcontext;
334 : int i;
335 : int rc;
336 :
337 : /*
338 : * Setup the execution state
339 : */
340 10450 : plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo,
341 : simple_eval_estate);
342 :
343 : /*
344 : * Setup error traceback support for ereport()
345 : */
346 10450 : plerrcontext.callback = plpgsql_exec_error_callback;
347 10450 : plerrcontext.arg = &estate;
348 10450 : plerrcontext.previous = error_context_stack;
349 10450 : error_context_stack = &plerrcontext;
350 :
351 : /*
352 : * Make local execution copies of all the datums
353 : */
354 10450 : estate.err_text = gettext_noop("during initialization of execution state");
355 39990 : for (i = 0; i < estate.ndatums; i++)
356 29540 : estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
357 :
358 : /*
359 : * Store the actual call argument values into the appropriate variables
360 : */
361 10450 : estate.err_text = gettext_noop("while storing call arguments into local variables");
362 26268 : for (i = 0; i < func->fn_nargs; i++)
363 : {
364 15818 : int n = func->fn_argvarnos[i];
365 :
366 15818 : switch (estate.datums[n]->dtype)
367 : {
368 : case PLPGSQL_DTYPE_VAR:
369 : {
370 15777 : PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
371 :
372 15777 : assign_simple_var(&estate, var,
373 : fcinfo->arg[i],
374 15777 : fcinfo->argnull[i],
375 : false);
376 :
377 : /*
378 : * Force any array-valued parameter to be stored in
379 : * expanded form in our local variable, in hopes of
380 : * improving efficiency of uses of the variable. (This is
381 : * a hack, really: why only arrays? Need more thought
382 : * about which cases are likely to win. See also
383 : * typisarray-specific heuristic in exec_assign_value.)
384 : *
385 : * Special cases: If passed a R/W expanded pointer, assume
386 : * we can commandeer the object rather than having to copy
387 : * it. If passed a R/O expanded pointer, just keep it as
388 : * the value of the variable for the moment. (We'll force
389 : * it to R/W if the variable gets modified, but that may
390 : * very well never happen.)
391 : */
392 15777 : if (!var->isnull && var->datatype->typisarray)
393 : {
394 40 : if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(var->value)))
395 : {
396 : /* take ownership of R/W object */
397 0 : assign_simple_var(&estate, var,
398 : TransferExpandedObject(var->value,
399 : CurrentMemoryContext),
400 : false,
401 : true);
402 : }
403 40 : else if (VARATT_IS_EXTERNAL_EXPANDED_RO(DatumGetPointer(var->value)))
404 : {
405 : /* R/O pointer, keep it as-is until assigned to */
406 : }
407 : else
408 : {
409 : /* flat array, so force to expanded form */
410 32 : assign_simple_var(&estate, var,
411 : expand_array(var->value,
412 : CurrentMemoryContext,
413 : NULL),
414 : false,
415 : true);
416 : }
417 : }
418 : }
419 15777 : break;
420 :
421 : case PLPGSQL_DTYPE_ROW:
422 : {
423 41 : PLpgSQL_row *row = (PLpgSQL_row *) estate.datums[n];
424 :
425 41 : if (!fcinfo->argnull[i])
426 : {
427 : /* Assign row value from composite datum */
428 32 : exec_move_row_from_datum(&estate, NULL, row,
429 : fcinfo->arg[i]);
430 : }
431 : else
432 : {
433 : /* If arg is null, treat it as an empty row */
434 9 : exec_move_row(&estate, NULL, row, NULL, NULL);
435 : }
436 : /* clean up after exec_move_row() */
437 41 : exec_eval_cleanup(&estate);
438 : }
439 41 : break;
440 :
441 : default:
442 0 : elog(ERROR, "unrecognized dtype: %d", func->datums[i]->dtype);
443 : }
444 : }
445 :
446 10450 : estate.err_text = gettext_noop("during function entry");
447 :
448 : /*
449 : * Set the magic variable FOUND to false
450 : */
451 10450 : exec_set_found(&estate, false);
452 :
453 : /*
454 : * Let the instrumentation plugin peek at this function
455 : */
456 10450 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
457 0 : ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
458 :
459 : /*
460 : * Now call the toplevel block of statements
461 : */
462 10450 : estate.err_text = NULL;
463 10450 : estate.err_stmt = (PLpgSQL_stmt *) (func->action);
464 10450 : rc = exec_stmt_block(&estate, func->action);
465 10364 : if (rc != PLPGSQL_RC_RETURN)
466 : {
467 1 : estate.err_stmt = NULL;
468 1 : estate.err_text = NULL;
469 1 : ereport(ERROR,
470 : (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
471 : errmsg("control reached end of function without RETURN")));
472 : }
473 :
474 : /*
475 : * We got a return value - process it
476 : */
477 10363 : estate.err_stmt = NULL;
478 10363 : estate.err_text = gettext_noop("while casting return value to function's return type");
479 :
480 10363 : fcinfo->isnull = estate.retisnull;
481 :
482 10363 : if (estate.retisset)
483 : {
484 77 : ReturnSetInfo *rsi = estate.rsi;
485 :
486 : /* Check caller can handle a set result */
487 154 : if (!rsi || !IsA(rsi, ReturnSetInfo) ||
488 77 : (rsi->allowedModes & SFRM_Materialize) == 0)
489 0 : ereport(ERROR,
490 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
491 : errmsg("set-valued function called in context that cannot accept a set")));
492 77 : rsi->returnMode = SFRM_Materialize;
493 :
494 : /* If we produced any tuples, send back the result */
495 77 : if (estate.tuple_store)
496 : {
497 74 : rsi->setResult = estate.tuple_store;
498 74 : if (estate.rettupdesc)
499 : {
500 : MemoryContext oldcxt;
501 :
502 74 : oldcxt = MemoryContextSwitchTo(estate.tuple_store_cxt);
503 74 : rsi->setDesc = CreateTupleDescCopy(estate.rettupdesc);
504 74 : MemoryContextSwitchTo(oldcxt);
505 : }
506 : }
507 77 : estate.retval = (Datum) 0;
508 77 : fcinfo->isnull = true;
509 : }
510 10286 : else if (!estate.retisnull)
511 : {
512 10282 : if (estate.retistuple)
513 : {
514 : /*
515 : * We have to check that the returned tuple actually matches the
516 : * expected result type. XXX would be better to cache the tupdesc
517 : * instead of repeating get_call_result_type()
518 : */
519 51 : HeapTuple rettup = (HeapTuple) DatumGetPointer(estate.retval);
520 : TupleDesc tupdesc;
521 : TupleConversionMap *tupmap;
522 :
523 51 : switch (get_call_result_type(fcinfo, NULL, &tupdesc))
524 : {
525 : case TYPEFUNC_COMPOSITE:
526 : /* got the expected result rowtype, now check it */
527 43 : tupmap = convert_tuples_by_position(estate.rettupdesc,
528 : tupdesc,
529 : gettext_noop("returned record type does not match expected record type"));
530 : /* it might need conversion */
531 42 : if (tupmap)
532 0 : rettup = do_convert_tuple(rettup, tupmap);
533 : /* no need to free map, we're about to return anyway */
534 42 : break;
535 : case TYPEFUNC_RECORD:
536 :
537 : /*
538 : * Failed to determine actual type of RECORD. We could
539 : * raise an error here, but what this means in practice is
540 : * that the caller is expecting any old generic rowtype,
541 : * so we don't really need to be restrictive. Pass back
542 : * the generated result type, instead.
543 : */
544 8 : tupdesc = estate.rettupdesc;
545 8 : if (tupdesc == NULL) /* shouldn't happen */
546 0 : elog(ERROR, "return type must be a row type");
547 8 : break;
548 : default:
549 : /* shouldn't get here if retistuple is true ... */
550 0 : elog(ERROR, "return type must be a row type");
551 : break;
552 : }
553 :
554 : /*
555 : * Copy tuple to upper executor memory, as a tuple Datum. Make
556 : * sure it is labeled with the caller-supplied tuple type.
557 : */
558 50 : estate.retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
559 : }
560 : else
561 : {
562 : /* Cast value to proper type */
563 10231 : estate.retval = exec_cast_value(&estate,
564 : estate.retval,
565 : &fcinfo->isnull,
566 : estate.rettype,
567 : -1,
568 : func->fn_rettype,
569 : -1);
570 :
571 : /*
572 : * If the function's return type isn't by value, copy the value
573 : * into upper executor memory context. However, if we have a R/W
574 : * expanded datum, we can just transfer its ownership out to the
575 : * upper executor context.
576 : */
577 10227 : if (!fcinfo->isnull && !func->fn_retbyval)
578 162 : estate.retval = SPI_datumTransfer(estate.retval,
579 : false,
580 : func->fn_rettyplen);
581 : }
582 : }
583 :
584 10358 : estate.err_text = gettext_noop("during function exit");
585 :
586 : /*
587 : * Let the instrumentation plugin peek at this function
588 : */
589 10358 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
590 0 : ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
591 :
592 : /* Clean up any leftover temporary memory */
593 10358 : plpgsql_destroy_econtext(&estate);
594 10358 : exec_eval_cleanup(&estate);
595 : /* stmt_mcontext will be destroyed when function's main context is */
596 :
597 : /*
598 : * Pop the error context stack
599 : */
600 10358 : error_context_stack = plerrcontext.previous;
601 :
602 : /*
603 : * Return the function's result
604 : */
605 10358 : return estate.retval;
606 : }
607 :
608 :
609 : /* ----------
610 : * plpgsql_exec_trigger Called by the call handler for
611 : * trigger execution.
612 : * ----------
613 : */
614 : HeapTuple
615 1831 : plpgsql_exec_trigger(PLpgSQL_function *func,
616 : TriggerData *trigdata)
617 : {
618 : PLpgSQL_execstate estate;
619 : ErrorContextCallback plerrcontext;
620 : int i;
621 : int rc;
622 : PLpgSQL_var *var;
623 : PLpgSQL_rec *rec_new,
624 : *rec_old;
625 : HeapTuple rettup;
626 :
627 : /*
628 : * Setup the execution state
629 : */
630 1831 : plpgsql_estate_setup(&estate, func, NULL, NULL);
631 :
632 : /*
633 : * Setup error traceback support for ereport()
634 : */
635 1831 : plerrcontext.callback = plpgsql_exec_error_callback;
636 1831 : plerrcontext.arg = &estate;
637 1831 : plerrcontext.previous = error_context_stack;
638 1831 : error_context_stack = &plerrcontext;
639 :
640 : /*
641 : * Make local execution copies of all the datums
642 : */
643 1831 : estate.err_text = gettext_noop("during initialization of execution state");
644 38636 : for (i = 0; i < estate.ndatums; i++)
645 36805 : estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
646 :
647 : /*
648 : * Put the OLD and NEW tuples into record variables
649 : *
650 : * We make the tupdescs available in both records even though only one may
651 : * have a value. This allows parsing of record references to succeed in
652 : * functions that are used for multiple trigger types. For example, we
653 : * might have a test like "if (TG_OP = 'INSERT' and NEW.foo = 'xyz')",
654 : * which should parse regardless of the current trigger type.
655 : */
656 1831 : rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
657 1831 : rec_new->freetup = false;
658 1831 : rec_new->tupdesc = trigdata->tg_relation->rd_att;
659 1831 : rec_new->freetupdesc = false;
660 1831 : rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
661 1831 : rec_old->freetup = false;
662 1831 : rec_old->tupdesc = trigdata->tg_relation->rd_att;
663 1831 : rec_old->freetupdesc = false;
664 :
665 1831 : if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
666 : {
667 : /*
668 : * Per-statement triggers don't use OLD/NEW variables
669 : */
670 128 : rec_new->tup = NULL;
671 128 : rec_old->tup = NULL;
672 : }
673 1703 : else if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
674 : {
675 911 : rec_new->tup = trigdata->tg_trigtuple;
676 911 : rec_old->tup = NULL;
677 : }
678 792 : else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
679 : {
680 768 : rec_new->tup = trigdata->tg_newtuple;
681 768 : rec_old->tup = trigdata->tg_trigtuple;
682 : }
683 24 : else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
684 : {
685 24 : rec_new->tup = NULL;
686 24 : rec_old->tup = trigdata->tg_trigtuple;
687 : }
688 : else
689 0 : elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
690 :
691 : /* Make transition tables visible to this SPI connection */
692 1831 : rc = SPI_register_trigger_data(trigdata);
693 1831 : Assert(rc >= 0);
694 :
695 : /*
696 : * Assign the special tg_ variables
697 : */
698 :
699 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_op_varno]);
700 1831 : if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
701 970 : assign_text_var(&estate, var, "INSERT");
702 861 : else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
703 813 : assign_text_var(&estate, var, "UPDATE");
704 48 : else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
705 46 : assign_text_var(&estate, var, "DELETE");
706 2 : else if (TRIGGER_FIRED_BY_TRUNCATE(trigdata->tg_event))
707 2 : assign_text_var(&estate, var, "TRUNCATE");
708 : else
709 0 : elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, UPDATE, or TRUNCATE");
710 :
711 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_name_varno]);
712 1831 : assign_simple_var(&estate, var,
713 1831 : DirectFunctionCall1(namein,
714 : CStringGetDatum(trigdata->tg_trigger->tgname)),
715 : false, true);
716 :
717 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_when_varno]);
718 1831 : if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
719 1133 : assign_text_var(&estate, var, "BEFORE");
720 698 : else if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
721 657 : assign_text_var(&estate, var, "AFTER");
722 41 : else if (TRIGGER_FIRED_INSTEAD(trigdata->tg_event))
723 41 : assign_text_var(&estate, var, "INSTEAD OF");
724 : else
725 0 : elog(ERROR, "unrecognized trigger execution time: not BEFORE, AFTER, or INSTEAD OF");
726 :
727 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_level_varno]);
728 1831 : if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
729 1703 : assign_text_var(&estate, var, "ROW");
730 128 : else if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
731 128 : assign_text_var(&estate, var, "STATEMENT");
732 : else
733 0 : elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
734 :
735 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_relid_varno]);
736 1831 : assign_simple_var(&estate, var,
737 1831 : ObjectIdGetDatum(trigdata->tg_relation->rd_id),
738 : false, false);
739 :
740 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_relname_varno]);
741 1831 : assign_simple_var(&estate, var,
742 1831 : DirectFunctionCall1(namein,
743 : CStringGetDatum(RelationGetRelationName(trigdata->tg_relation))),
744 : false, true);
745 :
746 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_table_name_varno]);
747 1831 : assign_simple_var(&estate, var,
748 1831 : DirectFunctionCall1(namein,
749 : CStringGetDatum(RelationGetRelationName(trigdata->tg_relation))),
750 : false, true);
751 :
752 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_table_schema_varno]);
753 1831 : assign_simple_var(&estate, var,
754 1831 : DirectFunctionCall1(namein,
755 : CStringGetDatum(get_namespace_name(
756 : RelationGetNamespace(
757 : trigdata->tg_relation)))),
758 : false, true);
759 :
760 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_nargs_varno]);
761 1831 : assign_simple_var(&estate, var,
762 1831 : Int16GetDatum(trigdata->tg_trigger->tgnargs),
763 : false, false);
764 :
765 1831 : var = (PLpgSQL_var *) (estate.datums[func->tg_argv_varno]);
766 1831 : if (trigdata->tg_trigger->tgnargs > 0)
767 : {
768 : /*
769 : * For historical reasons, tg_argv[] subscripts start at zero not one.
770 : * So we can't use construct_array().
771 : */
772 730 : int nelems = trigdata->tg_trigger->tgnargs;
773 : Datum *elems;
774 : int dims[1];
775 : int lbs[1];
776 :
777 730 : elems = palloc(sizeof(Datum) * nelems);
778 1463 : for (i = 0; i < nelems; i++)
779 733 : elems[i] = CStringGetTextDatum(trigdata->tg_trigger->tgargs[i]);
780 730 : dims[0] = nelems;
781 730 : lbs[0] = 0;
782 :
783 730 : assign_simple_var(&estate, var,
784 730 : PointerGetDatum(construct_md_array(elems, NULL,
785 : 1, dims, lbs,
786 : TEXTOID,
787 : -1, false, 'i')),
788 : false, true);
789 : }
790 : else
791 : {
792 1101 : assign_simple_var(&estate, var, (Datum) 0, true, false);
793 : }
794 :
795 1831 : estate.err_text = gettext_noop("during function entry");
796 :
797 : /*
798 : * Set the magic variable FOUND to false
799 : */
800 1831 : exec_set_found(&estate, false);
801 :
802 : /*
803 : * Let the instrumentation plugin peek at this function
804 : */
805 1831 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
806 0 : ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
807 :
808 : /*
809 : * Now call the toplevel block of statements
810 : */
811 1831 : estate.err_text = NULL;
812 1831 : estate.err_stmt = (PLpgSQL_stmt *) (func->action);
813 1831 : rc = exec_stmt_block(&estate, func->action);
814 1810 : if (rc != PLPGSQL_RC_RETURN)
815 : {
816 0 : estate.err_stmt = NULL;
817 0 : estate.err_text = NULL;
818 0 : ereport(ERROR,
819 : (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
820 : errmsg("control reached end of trigger procedure without RETURN")));
821 : }
822 :
823 1810 : estate.err_stmt = NULL;
824 1810 : estate.err_text = gettext_noop("during function exit");
825 :
826 1810 : if (estate.retisset)
827 0 : ereport(ERROR,
828 : (errcode(ERRCODE_DATATYPE_MISMATCH),
829 : errmsg("trigger procedure cannot return a set")));
830 :
831 : /*
832 : * Check that the returned tuple structure has the same attributes, the
833 : * relation that fired the trigger has. A per-statement trigger always
834 : * needs to return NULL, so we ignore any return value the function itself
835 : * produces (XXX: is this a good idea?)
836 : *
837 : * XXX This way it is possible, that the trigger returns a tuple where
838 : * attributes don't have the correct atttypmod's length. It's up to the
839 : * trigger's programmer to ensure that this doesn't happen. Jan
840 : */
841 1810 : if (estate.retisnull || !TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
842 213 : rettup = NULL;
843 : else
844 : {
845 : TupleConversionMap *tupmap;
846 :
847 1597 : rettup = (HeapTuple) DatumGetPointer(estate.retval);
848 : /* check rowtype compatibility */
849 1597 : tupmap = convert_tuples_by_position(estate.rettupdesc,
850 1597 : trigdata->tg_relation->rd_att,
851 : gettext_noop("returned row structure does not match the structure of the triggering table"));
852 : /* it might need conversion */
853 1597 : if (tupmap)
854 0 : rettup = do_convert_tuple(rettup, tupmap);
855 : /* no need to free map, we're about to return anyway */
856 :
857 : /* Copy tuple to upper executor memory */
858 1597 : rettup = SPI_copytuple(rettup);
859 : }
860 :
861 : /*
862 : * Let the instrumentation plugin peek at this function
863 : */
864 1810 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
865 0 : ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
866 :
867 : /* Clean up any leftover temporary memory */
868 1810 : plpgsql_destroy_econtext(&estate);
869 1810 : exec_eval_cleanup(&estate);
870 : /* stmt_mcontext will be destroyed when function's main context is */
871 :
872 : /*
873 : * Pop the error context stack
874 : */
875 1810 : error_context_stack = plerrcontext.previous;
876 :
877 : /*
878 : * Return the trigger's result
879 : */
880 1810 : return rettup;
881 : }
882 :
883 : /* ----------
884 : * plpgsql_exec_event_trigger Called by the call handler for
885 : * event trigger execution.
886 : * ----------
887 : */
888 : void
889 45 : plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
890 : {
891 : PLpgSQL_execstate estate;
892 : ErrorContextCallback plerrcontext;
893 : int i;
894 : int rc;
895 : PLpgSQL_var *var;
896 :
897 : /*
898 : * Setup the execution state
899 : */
900 45 : plpgsql_estate_setup(&estate, func, NULL, NULL);
901 :
902 : /*
903 : * Setup error traceback support for ereport()
904 : */
905 45 : plerrcontext.callback = plpgsql_exec_error_callback;
906 45 : plerrcontext.arg = &estate;
907 45 : plerrcontext.previous = error_context_stack;
908 45 : error_context_stack = &plerrcontext;
909 :
910 : /*
911 : * Make local execution copies of all the datums
912 : */
913 45 : estate.err_text = gettext_noop("during initialization of execution state");
914 317 : for (i = 0; i < estate.ndatums; i++)
915 272 : estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
916 :
917 : /*
918 : * Assign the special tg_ variables
919 : */
920 45 : var = (PLpgSQL_var *) (estate.datums[func->tg_event_varno]);
921 45 : assign_text_var(&estate, var, trigdata->event);
922 :
923 45 : var = (PLpgSQL_var *) (estate.datums[func->tg_tag_varno]);
924 45 : assign_text_var(&estate, var, trigdata->tag);
925 :
926 : /*
927 : * Let the instrumentation plugin peek at this function
928 : */
929 45 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
930 0 : ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
931 :
932 : /*
933 : * Now call the toplevel block of statements
934 : */
935 45 : estate.err_text = NULL;
936 45 : estate.err_stmt = (PLpgSQL_stmt *) (func->action);
937 45 : rc = exec_stmt_block(&estate, func->action);
938 40 : if (rc != PLPGSQL_RC_RETURN)
939 : {
940 0 : estate.err_stmt = NULL;
941 0 : estate.err_text = NULL;
942 0 : ereport(ERROR,
943 : (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
944 : errmsg("control reached end of trigger procedure without RETURN")));
945 : }
946 :
947 40 : estate.err_stmt = NULL;
948 40 : estate.err_text = gettext_noop("during function exit");
949 :
950 : /*
951 : * Let the instrumentation plugin peek at this function
952 : */
953 40 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
954 0 : ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
955 :
956 : /* Clean up any leftover temporary memory */
957 40 : plpgsql_destroy_econtext(&estate);
958 40 : exec_eval_cleanup(&estate);
959 : /* stmt_mcontext will be destroyed when function's main context is */
960 :
961 : /*
962 : * Pop the error context stack
963 : */
964 40 : error_context_stack = plerrcontext.previous;
965 :
966 40 : return;
967 : }
968 :
969 : /*
970 : * error context callback to let us supply a call-stack traceback
971 : */
972 : static void
973 1752 : plpgsql_exec_error_callback(void *arg)
974 : {
975 1752 : PLpgSQL_execstate *estate = (PLpgSQL_execstate *) arg;
976 :
977 1752 : if (estate->err_text != NULL)
978 : {
979 : /*
980 : * We don't expend the cycles to run gettext() on err_text unless we
981 : * actually need it. Therefore, places that set up err_text should
982 : * use gettext_noop() to ensure the strings get recorded in the
983 : * message dictionary.
984 : *
985 : * If both err_text and err_stmt are set, use the err_text as
986 : * description, but report the err_stmt's line number. When err_stmt
987 : * is not set, we're in function entry/exit, or some such place not
988 : * attached to a specific line number.
989 : */
990 7 : if (estate->err_stmt != NULL)
991 : {
992 : /*
993 : * translator: last %s is a phrase such as "during statement block
994 : * local variable initialization"
995 : */
996 6 : errcontext("PL/pgSQL function %s line %d %s",
997 2 : estate->func->fn_signature,
998 2 : estate->err_stmt->lineno,
999 : _(estate->err_text));
1000 : }
1001 : else
1002 : {
1003 : /*
1004 : * translator: last %s is a phrase such as "while storing call
1005 : * arguments into local variables"
1006 : */
1007 10 : errcontext("PL/pgSQL function %s %s",
1008 5 : estate->func->fn_signature,
1009 : _(estate->err_text));
1010 : }
1011 : }
1012 1745 : else if (estate->err_stmt != NULL)
1013 : {
1014 : /* translator: last %s is a plpgsql statement type name */
1015 5232 : errcontext("PL/pgSQL function %s line %d at %s",
1016 1744 : estate->func->fn_signature,
1017 1744 : estate->err_stmt->lineno,
1018 : plpgsql_stmt_typename(estate->err_stmt));
1019 : }
1020 : else
1021 2 : errcontext("PL/pgSQL function %s",
1022 1 : estate->func->fn_signature);
1023 1752 : }
1024 :
1025 :
1026 : /* ----------
1027 : * Support function for initializing local execution variables
1028 : * ----------
1029 : */
1030 : static PLpgSQL_datum *
1031 66617 : copy_plpgsql_datum(PLpgSQL_datum *datum)
1032 : {
1033 : PLpgSQL_datum *result;
1034 :
1035 66617 : switch (datum->dtype)
1036 : {
1037 : case PLPGSQL_DTYPE_VAR:
1038 : {
1039 48409 : PLpgSQL_var *new = palloc(sizeof(PLpgSQL_var));
1040 :
1041 48409 : memcpy(new, datum, sizeof(PLpgSQL_var));
1042 : /* should be preset to null/non-freeable */
1043 48409 : Assert(new->isnull);
1044 48409 : Assert(!new->freeval);
1045 :
1046 48409 : result = (PLpgSQL_datum *) new;
1047 : }
1048 48409 : break;
1049 :
1050 : case PLPGSQL_DTYPE_REC:
1051 : {
1052 4180 : PLpgSQL_rec *new = palloc(sizeof(PLpgSQL_rec));
1053 :
1054 4180 : memcpy(new, datum, sizeof(PLpgSQL_rec));
1055 : /* should be preset to null/non-freeable */
1056 4180 : Assert(new->tup == NULL);
1057 4180 : Assert(new->tupdesc == NULL);
1058 4180 : Assert(!new->freetup);
1059 4180 : Assert(!new->freetupdesc);
1060 :
1061 4180 : result = (PLpgSQL_datum *) new;
1062 : }
1063 4180 : break;
1064 :
1065 : case PLPGSQL_DTYPE_ROW:
1066 : case PLPGSQL_DTYPE_RECFIELD:
1067 : case PLPGSQL_DTYPE_ARRAYELEM:
1068 :
1069 : /*
1070 : * These datum records are read-only at runtime, so no need to
1071 : * copy them (well, ARRAYELEM contains some cached type data, but
1072 : * we'd just as soon centralize the caching anyway)
1073 : */
1074 14028 : result = datum;
1075 14028 : break;
1076 :
1077 : default:
1078 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
1079 : result = NULL; /* keep compiler quiet */
1080 : break;
1081 : }
1082 :
1083 66617 : return result;
1084 : }
1085 :
1086 : /*
1087 : * Create a memory context for statement-lifespan variables, if we don't
1088 : * have one already. It will be a child of stmt_mcontext_parent, which is
1089 : * either the function's main context or a pushed-down outer stmt_mcontext.
1090 : */
1091 : static MemoryContext
1092 2718 : get_stmt_mcontext(PLpgSQL_execstate *estate)
1093 : {
1094 2718 : if (estate->stmt_mcontext == NULL)
1095 : {
1096 1142 : estate->stmt_mcontext =
1097 1142 : AllocSetContextCreate(estate->stmt_mcontext_parent,
1098 : "PLpgSQL per-statement data",
1099 : ALLOCSET_DEFAULT_SIZES);
1100 : }
1101 2718 : return estate->stmt_mcontext;
1102 : }
1103 :
1104 : /*
1105 : * Push down the current stmt_mcontext so that called statements won't use it.
1106 : * This is needed by statements that have statement-lifespan data and need to
1107 : * preserve it across some inner statements. The caller should eventually do
1108 : * pop_stmt_mcontext().
1109 : */
1110 : static void
1111 15 : push_stmt_mcontext(PLpgSQL_execstate *estate)
1112 : {
1113 : /* Should have done get_stmt_mcontext() first */
1114 15 : Assert(estate->stmt_mcontext != NULL);
1115 : /* Assert we've not messed up the stack linkage */
1116 15 : Assert(MemoryContextGetParent(estate->stmt_mcontext) == estate->stmt_mcontext_parent);
1117 : /* Push it down to become the parent of any nested stmt mcontext */
1118 15 : estate->stmt_mcontext_parent = estate->stmt_mcontext;
1119 : /* And make it not available for use directly */
1120 15 : estate->stmt_mcontext = NULL;
1121 15 : }
1122 :
1123 : /*
1124 : * Undo push_stmt_mcontext(). We assume this is done just before or after
1125 : * resetting the caller's stmt_mcontext; since that action will also delete
1126 : * any child contexts, there's no need to explicitly delete whatever context
1127 : * might currently be estate->stmt_mcontext.
1128 : */
1129 : static void
1130 247 : pop_stmt_mcontext(PLpgSQL_execstate *estate)
1131 : {
1132 : /* We need only pop the stack */
1133 247 : estate->stmt_mcontext = estate->stmt_mcontext_parent;
1134 247 : estate->stmt_mcontext_parent = MemoryContextGetParent(estate->stmt_mcontext);
1135 247 : }
1136 :
1137 :
1138 : /*
1139 : * Subroutine for exec_stmt_block: does any condition in the condition list
1140 : * match the current exception?
1141 : */
1142 : static bool
1143 249 : exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond)
1144 : {
1145 259 : for (; cond != NULL; cond = cond->next)
1146 : {
1147 250 : int sqlerrstate = cond->sqlerrstate;
1148 :
1149 : /*
1150 : * OTHERS matches everything *except* query-canceled and
1151 : * assert-failure. If you're foolish enough, you can match those
1152 : * explicitly.
1153 : */
1154 250 : if (sqlerrstate == 0)
1155 : {
1156 413 : if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED &&
1157 206 : edata->sqlerrcode != ERRCODE_ASSERT_FAILURE)
1158 205 : return true;
1159 : }
1160 : /* Exact match? */
1161 43 : else if (edata->sqlerrcode == sqlerrstate)
1162 33 : return true;
1163 : /* Category match? */
1164 13 : else if (ERRCODE_IS_CATEGORY(sqlerrstate) &&
1165 3 : ERRCODE_TO_CATEGORY(edata->sqlerrcode) == sqlerrstate)
1166 2 : return true;
1167 : }
1168 9 : return false;
1169 : }
1170 :
1171 :
1172 : /* ----------
1173 : * exec_stmt_block Execute a block of statements
1174 : * ----------
1175 : */
1176 : static int
1177 12607 : exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
1178 : {
1179 12607 : volatile int rc = -1;
1180 : int i;
1181 : int n;
1182 :
1183 : /*
1184 : * First initialize all variables declared in this block
1185 : */
1186 12607 : estate->err_text = gettext_noop("during statement block local variable initialization");
1187 :
1188 14071 : for (i = 0; i < block->n_initvars; i++)
1189 : {
1190 1466 : n = block->initvarnos[i];
1191 :
1192 1466 : switch (estate->datums[n]->dtype)
1193 : {
1194 : case PLPGSQL_DTYPE_VAR:
1195 : {
1196 1466 : PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]);
1197 :
1198 : /*
1199 : * Free any old value, in case re-entering block, and
1200 : * initialize to NULL
1201 : */
1202 1466 : assign_simple_var(estate, var, (Datum) 0, true, false);
1203 :
1204 1466 : if (var->default_val == NULL)
1205 : {
1206 : /*
1207 : * If needed, give the datatype a chance to reject
1208 : * NULLs, by assigning a NULL to the variable. We
1209 : * claim the value is of type UNKNOWN, not the var's
1210 : * datatype, else coercion will be skipped. (Do this
1211 : * before the notnull check to be consistent with
1212 : * exec_assign_value.)
1213 : */
1214 1343 : if (var->datatype->typtype == TYPTYPE_DOMAIN)
1215 15 : exec_assign_value(estate,
1216 : (PLpgSQL_datum *) var,
1217 : (Datum) 0,
1218 : true,
1219 : UNKNOWNOID,
1220 : -1);
1221 :
1222 1342 : if (var->notnull)
1223 0 : ereport(ERROR,
1224 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1225 : errmsg("variable \"%s\" declared NOT NULL cannot default to NULL",
1226 : var->refname)));
1227 : }
1228 : else
1229 : {
1230 123 : exec_assign_expr(estate, (PLpgSQL_datum *) var,
1231 : var->default_val);
1232 : }
1233 : }
1234 1464 : break;
1235 :
1236 : case PLPGSQL_DTYPE_REC:
1237 : {
1238 0 : PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[n]);
1239 :
1240 0 : if (rec->freetup)
1241 : {
1242 0 : heap_freetuple(rec->tup);
1243 0 : rec->freetup = false;
1244 : }
1245 0 : if (rec->freetupdesc)
1246 : {
1247 0 : FreeTupleDesc(rec->tupdesc);
1248 0 : rec->freetupdesc = false;
1249 : }
1250 0 : rec->tup = NULL;
1251 0 : rec->tupdesc = NULL;
1252 : }
1253 0 : break;
1254 :
1255 : case PLPGSQL_DTYPE_RECFIELD:
1256 : case PLPGSQL_DTYPE_ARRAYELEM:
1257 0 : break;
1258 :
1259 : default:
1260 0 : elog(ERROR, "unrecognized dtype: %d",
1261 : estate->datums[n]->dtype);
1262 : }
1263 : }
1264 :
1265 12605 : if (block->exceptions)
1266 : {
1267 : /*
1268 : * Execute the statements in the block's body inside a sub-transaction
1269 : */
1270 252 : MemoryContext oldcontext = CurrentMemoryContext;
1271 252 : ResourceOwner oldowner = CurrentResourceOwner;
1272 252 : ExprContext *old_eval_econtext = estate->eval_econtext;
1273 252 : ErrorData *save_cur_error = estate->cur_error;
1274 : MemoryContext stmt_mcontext;
1275 :
1276 252 : estate->err_text = gettext_noop("during statement block entry");
1277 :
1278 : /*
1279 : * We will need a stmt_mcontext to hold the error data if an error
1280 : * occurs. It seems best to force it to exist before entering the
1281 : * subtransaction, so that we reduce the risk of out-of-memory during
1282 : * error recovery, and because this greatly simplifies restoring the
1283 : * stmt_mcontext stack to the correct state after an error. We can
1284 : * ameliorate the cost of this by allowing the called statements to
1285 : * use this mcontext too; so we don't push it down here.
1286 : */
1287 252 : stmt_mcontext = get_stmt_mcontext(estate);
1288 :
1289 252 : BeginInternalSubTransaction(NULL);
1290 : /* Want to run statements inside function's memory context */
1291 252 : MemoryContextSwitchTo(oldcontext);
1292 :
1293 252 : PG_TRY();
1294 : {
1295 : /*
1296 : * We need to run the block's statements with a new eval_econtext
1297 : * that belongs to the current subtransaction; if we try to use
1298 : * the outer econtext then ExprContext shutdown callbacks will be
1299 : * called at the wrong times.
1300 : */
1301 252 : plpgsql_create_econtext(estate);
1302 :
1303 252 : estate->err_text = NULL;
1304 :
1305 : /* Run the block's statements */
1306 252 : rc = exec_stmts(estate, block->body);
1307 :
1308 9 : estate->err_text = gettext_noop("during statement block exit");
1309 :
1310 : /*
1311 : * If the block ended with RETURN, we may need to copy the return
1312 : * value out of the subtransaction eval_context. This is
1313 : * currently only needed for scalar result types --- rowtype
1314 : * values will always exist in the function's main memory context,
1315 : * cf. exec_stmt_return(). We can avoid a physical copy if the
1316 : * value happens to be a R/W expanded object.
1317 : */
1318 9 : if (rc == PLPGSQL_RC_RETURN &&
1319 0 : !estate->retisset &&
1320 0 : !estate->retisnull &&
1321 0 : estate->rettupdesc == NULL)
1322 : {
1323 : int16 resTypLen;
1324 : bool resTypByVal;
1325 :
1326 0 : get_typlenbyval(estate->rettype, &resTypLen, &resTypByVal);
1327 0 : estate->retval = datumTransfer(estate->retval,
1328 : resTypByVal, resTypLen);
1329 : }
1330 :
1331 : /* Commit the inner transaction, return to outer xact context */
1332 9 : ReleaseCurrentSubTransaction();
1333 9 : MemoryContextSwitchTo(oldcontext);
1334 9 : CurrentResourceOwner = oldowner;
1335 :
1336 : /* Assert that the stmt_mcontext stack is unchanged */
1337 9 : Assert(stmt_mcontext == estate->stmt_mcontext);
1338 :
1339 : /*
1340 : * Revert to outer eval_econtext. (The inner one was
1341 : * automatically cleaned up during subxact exit.)
1342 : */
1343 9 : estate->eval_econtext = old_eval_econtext;
1344 : }
1345 243 : PG_CATCH();
1346 : {
1347 : ErrorData *edata;
1348 : ListCell *e;
1349 :
1350 243 : estate->err_text = gettext_noop("during exception cleanup");
1351 :
1352 : /* Save error info in our stmt_mcontext */
1353 243 : MemoryContextSwitchTo(stmt_mcontext);
1354 243 : edata = CopyErrorData();
1355 243 : FlushErrorState();
1356 :
1357 : /* Abort the inner transaction */
1358 243 : RollbackAndReleaseCurrentSubTransaction();
1359 243 : MemoryContextSwitchTo(oldcontext);
1360 243 : CurrentResourceOwner = oldowner;
1361 :
1362 : /*
1363 : * Set up the stmt_mcontext stack as though we had restored our
1364 : * previous state and then done push_stmt_mcontext(). The push is
1365 : * needed so that statements in the exception handler won't
1366 : * clobber the error data that's in our stmt_mcontext.
1367 : */
1368 243 : estate->stmt_mcontext_parent = stmt_mcontext;
1369 243 : estate->stmt_mcontext = NULL;
1370 :
1371 : /*
1372 : * Now we can delete any nested stmt_mcontexts that might have
1373 : * been created as children of ours. (Note: we do not immediately
1374 : * release any statement-lifespan data that might have been left
1375 : * behind in stmt_mcontext itself. We could attempt that by doing
1376 : * a MemoryContextReset on it before collecting the error data
1377 : * above, but it seems too risky to do any significant amount of
1378 : * work before collecting the error.)
1379 : */
1380 243 : MemoryContextDeleteChildren(stmt_mcontext);
1381 :
1382 : /* Revert to outer eval_econtext */
1383 243 : estate->eval_econtext = old_eval_econtext;
1384 :
1385 : /*
1386 : * Must clean up the econtext too. However, any tuple table made
1387 : * in the subxact will have been thrown away by SPI during subxact
1388 : * abort, so we don't need to (and mustn't try to) free the
1389 : * eval_tuptable.
1390 : */
1391 243 : estate->eval_tuptable = NULL;
1392 243 : exec_eval_cleanup(estate);
1393 :
1394 : /* Look for a matching exception handler */
1395 252 : foreach(e, block->exceptions->exc_list)
1396 : {
1397 249 : PLpgSQL_exception *exception = (PLpgSQL_exception *) lfirst(e);
1398 :
1399 249 : if (exception_matches_conditions(edata, exception->conditions))
1400 : {
1401 : /*
1402 : * Initialize the magic SQLSTATE and SQLERRM variables for
1403 : * the exception block; this also frees values from any
1404 : * prior use of the same exception. We needn't do this
1405 : * until we have found a matching exception.
1406 : */
1407 : PLpgSQL_var *state_var;
1408 : PLpgSQL_var *errm_var;
1409 :
1410 240 : state_var = (PLpgSQL_var *)
1411 240 : estate->datums[block->exceptions->sqlstate_varno];
1412 240 : errm_var = (PLpgSQL_var *)
1413 240 : estate->datums[block->exceptions->sqlerrm_varno];
1414 :
1415 240 : assign_text_var(estate, state_var,
1416 240 : unpack_sql_state(edata->sqlerrcode));
1417 240 : assign_text_var(estate, errm_var, edata->message);
1418 :
1419 : /*
1420 : * Also set up cur_error so the error data is accessible
1421 : * inside the handler.
1422 : */
1423 240 : estate->cur_error = edata;
1424 :
1425 240 : estate->err_text = NULL;
1426 :
1427 240 : rc = exec_stmts(estate, exception->action);
1428 :
1429 235 : break;
1430 : }
1431 : }
1432 :
1433 : /*
1434 : * Restore previous state of cur_error, whether or not we executed
1435 : * a handler. This is needed in case an error got thrown from
1436 : * some inner block's exception handler.
1437 : */
1438 238 : estate->cur_error = save_cur_error;
1439 :
1440 : /* If no match found, re-throw the error */
1441 238 : if (e == NULL)
1442 3 : ReThrowError(edata);
1443 :
1444 : /* Restore stmt_mcontext stack and release the error data */
1445 235 : pop_stmt_mcontext(estate);
1446 235 : MemoryContextReset(stmt_mcontext);
1447 : }
1448 244 : PG_END_TRY();
1449 :
1450 244 : Assert(save_cur_error == estate->cur_error);
1451 : }
1452 : else
1453 : {
1454 : /*
1455 : * Just execute the statements in the block's body
1456 : */
1457 12353 : estate->err_text = NULL;
1458 :
1459 12353 : rc = exec_stmts(estate, block->body);
1460 : }
1461 :
1462 12485 : estate->err_text = NULL;
1463 :
1464 : /*
1465 : * Handle the return code.
1466 : */
1467 12485 : switch (rc)
1468 : {
1469 : case PLPGSQL_RC_OK:
1470 : case PLPGSQL_RC_RETURN:
1471 : case PLPGSQL_RC_CONTINUE:
1472 12484 : return rc;
1473 :
1474 : case PLPGSQL_RC_EXIT:
1475 :
1476 : /*
1477 : * This is intentionally different from the handling of RC_EXIT
1478 : * for loops: to match a block, we require a match by label.
1479 : */
1480 1 : if (estate->exitlabel == NULL)
1481 0 : return PLPGSQL_RC_EXIT;
1482 1 : if (block->label == NULL)
1483 0 : return PLPGSQL_RC_EXIT;
1484 1 : if (strcmp(block->label, estate->exitlabel) != 0)
1485 0 : return PLPGSQL_RC_EXIT;
1486 1 : estate->exitlabel = NULL;
1487 1 : return PLPGSQL_RC_OK;
1488 :
1489 : default:
1490 0 : elog(ERROR, "unrecognized rc: %d", rc);
1491 : }
1492 :
1493 : return PLPGSQL_RC_OK;
1494 : }
1495 :
1496 :
1497 : /* ----------
1498 : * exec_stmts Iterate over a list of statements
1499 : * as long as their return code is OK
1500 : * ----------
1501 : */
1502 : static int
1503 30575 : exec_stmts(PLpgSQL_execstate *estate, List *stmts)
1504 : {
1505 : ListCell *s;
1506 :
1507 30575 : if (stmts == NIL)
1508 : {
1509 : /*
1510 : * Ensure we do a CHECK_FOR_INTERRUPTS() even though there is no
1511 : * statement. This prevents hangup in a tight loop if, for instance,
1512 : * there is a LOOP construct with an empty body.
1513 : */
1514 7459 : CHECK_FOR_INTERRUPTS();
1515 7459 : return PLPGSQL_RC_OK;
1516 : }
1517 :
1518 39734 : foreach(s, stmts)
1519 : {
1520 35038 : PLpgSQL_stmt *stmt = (PLpgSQL_stmt *) lfirst(s);
1521 35038 : int rc = exec_stmt(estate, stmt);
1522 :
1523 34643 : if (rc != PLPGSQL_RC_OK)
1524 18025 : return rc;
1525 : }
1526 :
1527 4696 : return PLPGSQL_RC_OK;
1528 : }
1529 :
1530 :
1531 : /* ----------
1532 : * exec_stmt Distribute one statement to the statements
1533 : * type specific execution function.
1534 : * ----------
1535 : */
1536 : static int
1537 35038 : exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
1538 : {
1539 : PLpgSQL_stmt *save_estmt;
1540 35038 : int rc = -1;
1541 :
1542 35038 : save_estmt = estate->err_stmt;
1543 35038 : estate->err_stmt = stmt;
1544 :
1545 : /* Let the plugin know that we are about to execute this statement */
1546 35038 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
1547 0 : ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
1548 :
1549 35038 : CHECK_FOR_INTERRUPTS();
1550 :
1551 35038 : switch (stmt->cmd_type)
1552 : {
1553 : case PLPGSQL_STMT_BLOCK:
1554 281 : rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
1555 271 : break;
1556 :
1557 : case PLPGSQL_STMT_ASSIGN:
1558 2656 : rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
1559 2626 : break;
1560 :
1561 : case PLPGSQL_STMT_PERFORM:
1562 236 : rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
1563 28 : break;
1564 :
1565 : case PLPGSQL_STMT_GETDIAG:
1566 16 : rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
1567 15 : break;
1568 :
1569 : case PLPGSQL_STMT_IF:
1570 14528 : rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
1571 14496 : break;
1572 :
1573 : case PLPGSQL_STMT_CASE:
1574 15 : rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
1575 12 : break;
1576 :
1577 : case PLPGSQL_STMT_LOOP:
1578 17 : rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
1579 17 : break;
1580 :
1581 : case PLPGSQL_STMT_WHILE:
1582 7 : rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
1583 7 : break;
1584 :
1585 : case PLPGSQL_STMT_FORI:
1586 83 : rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
1587 83 : break;
1588 :
1589 : case PLPGSQL_STMT_FORS:
1590 174 : rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
1591 169 : break;
1592 :
1593 : case PLPGSQL_STMT_FORC:
1594 6 : rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
1595 6 : break;
1596 :
1597 : case PLPGSQL_STMT_FOREACH_A:
1598 15 : rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
1599 12 : break;
1600 :
1601 : case PLPGSQL_STMT_EXIT:
1602 190 : rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
1603 190 : break;
1604 :
1605 : case PLPGSQL_STMT_RETURN:
1606 12221 : rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
1607 12213 : break;
1608 :
1609 : case PLPGSQL_STMT_RETURN_NEXT:
1610 156 : rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
1611 156 : break;
1612 :
1613 : case PLPGSQL_STMT_RETURN_QUERY:
1614 25 : rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
1615 25 : break;
1616 :
1617 : case PLPGSQL_STMT_RAISE:
1618 1334 : rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
1619 1281 : break;
1620 :
1621 : case PLPGSQL_STMT_ASSERT:
1622 6 : rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
1623 2 : break;
1624 :
1625 : case PLPGSQL_STMT_EXECSQL:
1626 1899 : rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
1627 1882 : break;
1628 :
1629 : case PLPGSQL_STMT_DYNEXECUTE:
1630 583 : rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
1631 564 : break;
1632 :
1633 : case PLPGSQL_STMT_DYNFORS:
1634 503 : rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
1635 503 : break;
1636 :
1637 : case PLPGSQL_STMT_OPEN:
1638 19 : rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
1639 18 : break;
1640 :
1641 : case PLPGSQL_STMT_FETCH:
1642 56 : rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
1643 55 : break;
1644 :
1645 : case PLPGSQL_STMT_CLOSE:
1646 12 : rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
1647 12 : break;
1648 :
1649 : default:
1650 0 : estate->err_stmt = save_estmt;
1651 0 : elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);
1652 : }
1653 :
1654 : /* Let the plugin know that we have finished executing this statement */
1655 34643 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
1656 0 : ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
1657 :
1658 34643 : estate->err_stmt = save_estmt;
1659 :
1660 34643 : return rc;
1661 : }
1662 :
1663 :
1664 : /* ----------
1665 : * exec_stmt_assign Evaluate an expression and
1666 : * put the result into a variable.
1667 : * ----------
1668 : */
1669 : static int
1670 2656 : exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
1671 : {
1672 2656 : Assert(stmt->varno >= 0);
1673 :
1674 2656 : exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
1675 :
1676 2626 : return PLPGSQL_RC_OK;
1677 : }
1678 :
1679 : /* ----------
1680 : * exec_stmt_perform Evaluate query and discard result (but set
1681 : * FOUND depending on whether at least one row
1682 : * was returned).
1683 : * ----------
1684 : */
1685 : static int
1686 236 : exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
1687 : {
1688 236 : PLpgSQL_expr *expr = stmt->expr;
1689 :
1690 236 : (void) exec_run_select(estate, expr, 0, NULL);
1691 28 : exec_set_found(estate, (estate->eval_processed != 0));
1692 28 : exec_eval_cleanup(estate);
1693 :
1694 28 : return PLPGSQL_RC_OK;
1695 : }
1696 :
1697 : /* ----------
1698 : * exec_stmt_getdiag Put internal PG information into
1699 : * specified variables.
1700 : * ----------
1701 : */
1702 : static int
1703 16 : exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
1704 : {
1705 : ListCell *lc;
1706 :
1707 : /*
1708 : * GET STACKED DIAGNOSTICS is only valid inside an exception handler.
1709 : *
1710 : * Note: we trust the grammar to have disallowed the relevant item kinds
1711 : * if not is_stacked, otherwise we'd dump core below.
1712 : */
1713 16 : if (stmt->is_stacked && estate->cur_error == NULL)
1714 1 : ereport(ERROR,
1715 : (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
1716 : errmsg("GET STACKED DIAGNOSTICS cannot be used outside an exception handler")));
1717 :
1718 38 : foreach(lc, stmt->diag_items)
1719 : {
1720 23 : PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
1721 23 : PLpgSQL_datum *var = estate->datums[diag_item->target];
1722 :
1723 23 : switch (diag_item->kind)
1724 : {
1725 : case PLPGSQL_GETDIAG_ROW_COUNT:
1726 4 : exec_assign_value(estate, var,
1727 4 : UInt64GetDatum(estate->eval_processed),
1728 : false, INT8OID, -1);
1729 4 : break;
1730 :
1731 : case PLPGSQL_GETDIAG_RESULT_OID:
1732 0 : exec_assign_value(estate, var,
1733 : ObjectIdGetDatum(estate->eval_lastoid),
1734 : false, OIDOID, -1);
1735 0 : break;
1736 :
1737 : case PLPGSQL_GETDIAG_ERROR_CONTEXT:
1738 1 : exec_assign_c_string(estate, var,
1739 1 : estate->cur_error->context);
1740 1 : break;
1741 :
1742 : case PLPGSQL_GETDIAG_ERROR_DETAIL:
1743 1 : exec_assign_c_string(estate, var,
1744 1 : estate->cur_error->detail);
1745 1 : break;
1746 :
1747 : case PLPGSQL_GETDIAG_ERROR_HINT:
1748 1 : exec_assign_c_string(estate, var,
1749 1 : estate->cur_error->hint);
1750 1 : break;
1751 :
1752 : case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
1753 1 : exec_assign_c_string(estate, var,
1754 1 : unpack_sql_state(estate->cur_error->sqlerrcode));
1755 1 : break;
1756 :
1757 : case PLPGSQL_GETDIAG_COLUMN_NAME:
1758 1 : exec_assign_c_string(estate, var,
1759 1 : estate->cur_error->column_name);
1760 1 : break;
1761 :
1762 : case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
1763 1 : exec_assign_c_string(estate, var,
1764 1 : estate->cur_error->constraint_name);
1765 1 : break;
1766 :
1767 : case PLPGSQL_GETDIAG_DATATYPE_NAME:
1768 1 : exec_assign_c_string(estate, var,
1769 1 : estate->cur_error->datatype_name);
1770 1 : break;
1771 :
1772 : case PLPGSQL_GETDIAG_MESSAGE_TEXT:
1773 2 : exec_assign_c_string(estate, var,
1774 2 : estate->cur_error->message);
1775 2 : break;
1776 :
1777 : case PLPGSQL_GETDIAG_TABLE_NAME:
1778 1 : exec_assign_c_string(estate, var,
1779 1 : estate->cur_error->table_name);
1780 1 : break;
1781 :
1782 : case PLPGSQL_GETDIAG_SCHEMA_NAME:
1783 1 : exec_assign_c_string(estate, var,
1784 1 : estate->cur_error->schema_name);
1785 1 : break;
1786 :
1787 : case PLPGSQL_GETDIAG_CONTEXT:
1788 : {
1789 : char *contextstackstr;
1790 : MemoryContext oldcontext;
1791 :
1792 : /* Use eval_mcontext for short-lived string */
1793 8 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
1794 8 : contextstackstr = GetErrorContextStack();
1795 8 : MemoryContextSwitchTo(oldcontext);
1796 :
1797 8 : exec_assign_c_string(estate, var, contextstackstr);
1798 : }
1799 8 : break;
1800 :
1801 : default:
1802 0 : elog(ERROR, "unrecognized diagnostic item kind: %d",
1803 : diag_item->kind);
1804 : }
1805 : }
1806 :
1807 15 : exec_eval_cleanup(estate);
1808 :
1809 15 : return PLPGSQL_RC_OK;
1810 : }
1811 :
1812 : /* ----------
1813 : * exec_stmt_if Evaluate a bool expression and
1814 : * execute the true or false body
1815 : * conditionally.
1816 : * ----------
1817 : */
1818 : static int
1819 14528 : exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
1820 : {
1821 : bool value;
1822 : bool isnull;
1823 : ListCell *lc;
1824 :
1825 14528 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
1826 14528 : exec_eval_cleanup(estate);
1827 14528 : if (!isnull && value)
1828 6612 : return exec_stmts(estate, stmt->then_body);
1829 :
1830 7917 : foreach(lc, stmt->elsif_list)
1831 : {
1832 35 : PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(lc);
1833 :
1834 35 : value = exec_eval_boolean(estate, elif->cond, &isnull);
1835 35 : exec_eval_cleanup(estate);
1836 35 : if (!isnull && value)
1837 34 : return exec_stmts(estate, elif->stmts);
1838 : }
1839 :
1840 7882 : return exec_stmts(estate, stmt->else_body);
1841 : }
1842 :
1843 :
1844 : /*-----------
1845 : * exec_stmt_case
1846 : *-----------
1847 : */
1848 : static int
1849 15 : exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
1850 : {
1851 15 : PLpgSQL_var *t_var = NULL;
1852 : bool isnull;
1853 : ListCell *l;
1854 :
1855 15 : if (stmt->t_expr != NULL)
1856 : {
1857 : /* simple case */
1858 : Datum t_val;
1859 : Oid t_typoid;
1860 : int32 t_typmod;
1861 :
1862 11 : t_val = exec_eval_expr(estate, stmt->t_expr,
1863 : &isnull, &t_typoid, &t_typmod);
1864 :
1865 11 : t_var = (PLpgSQL_var *) estate->datums[stmt->t_varno];
1866 :
1867 : /*
1868 : * When expected datatype is different from real, change it. Note that
1869 : * what we're modifying here is an execution copy of the datum, so
1870 : * this doesn't affect the originally stored function parse tree. (In
1871 : * theory, if the expression datatype keeps changing during execution,
1872 : * this could cause a function-lifespan memory leak. Doesn't seem
1873 : * worth worrying about though.)
1874 : */
1875 11 : if (t_var->datatype->typoid != t_typoid ||
1876 0 : t_var->datatype->atttypmod != t_typmod)
1877 11 : t_var->datatype = plpgsql_build_datatype(t_typoid,
1878 : t_typmod,
1879 11 : estate->func->fn_input_collation);
1880 :
1881 : /* now we can assign to the variable */
1882 11 : exec_assign_value(estate,
1883 : (PLpgSQL_datum *) t_var,
1884 : t_val,
1885 : isnull,
1886 : t_typoid,
1887 : t_typmod);
1888 :
1889 11 : exec_eval_cleanup(estate);
1890 : }
1891 :
1892 : /* Now search for a successful WHEN clause */
1893 53 : foreach(l, stmt->case_when_list)
1894 : {
1895 48 : PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
1896 : bool value;
1897 :
1898 48 : value = exec_eval_boolean(estate, cwt->expr, &isnull);
1899 48 : exec_eval_cleanup(estate);
1900 48 : if (!isnull && value)
1901 : {
1902 : /* Found it */
1903 :
1904 : /* We can now discard any value we had for the temp variable */
1905 10 : if (t_var != NULL)
1906 8 : assign_simple_var(estate, t_var, (Datum) 0, true, false);
1907 :
1908 : /* Evaluate the statement(s), and we're done */
1909 10 : return exec_stmts(estate, cwt->stmts);
1910 : }
1911 : }
1912 :
1913 : /* We can now discard any value we had for the temp variable */
1914 5 : if (t_var != NULL)
1915 3 : assign_simple_var(estate, t_var, (Datum) 0, true, false);
1916 :
1917 : /* SQL2003 mandates this error if there was no ELSE clause */
1918 5 : if (!stmt->have_else)
1919 3 : ereport(ERROR,
1920 : (errcode(ERRCODE_CASE_NOT_FOUND),
1921 : errmsg("case not found"),
1922 : errhint("CASE statement is missing ELSE part.")));
1923 :
1924 : /* Evaluate the ELSE statements, and we're done */
1925 2 : return exec_stmts(estate, stmt->else_stmts);
1926 : }
1927 :
1928 :
1929 : /* ----------
1930 : * exec_stmt_loop Loop over statements until
1931 : * an exit occurs.
1932 : * ----------
1933 : */
1934 : static int
1935 102 : exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
1936 : {
1937 : for (;;)
1938 : {
1939 102 : int rc = exec_stmts(estate, stmt->body);
1940 :
1941 102 : switch (rc)
1942 : {
1943 : case PLPGSQL_RC_OK:
1944 67 : break;
1945 :
1946 : case PLPGSQL_RC_EXIT:
1947 8 : if (estate->exitlabel == NULL)
1948 5 : return PLPGSQL_RC_OK;
1949 3 : if (stmt->label == NULL)
1950 2 : return PLPGSQL_RC_EXIT;
1951 1 : if (strcmp(stmt->label, estate->exitlabel) != 0)
1952 0 : return PLPGSQL_RC_EXIT;
1953 1 : estate->exitlabel = NULL;
1954 1 : return PLPGSQL_RC_OK;
1955 :
1956 : case PLPGSQL_RC_CONTINUE:
1957 27 : if (estate->exitlabel == NULL)
1958 : /* anonymous continue, so re-run the loop */
1959 9 : break;
1960 27 : else if (stmt->label != NULL &&
1961 9 : strcmp(stmt->label, estate->exitlabel) == 0)
1962 : /* label matches named continue, so re-run loop */
1963 9 : estate->exitlabel = NULL;
1964 : else
1965 : /* label doesn't match named continue, so propagate upward */
1966 9 : return PLPGSQL_RC_CONTINUE;
1967 9 : break;
1968 :
1969 : case PLPGSQL_RC_RETURN:
1970 0 : return rc;
1971 :
1972 : default:
1973 0 : elog(ERROR, "unrecognized rc: %d", rc);
1974 : }
1975 85 : }
1976 : }
1977 :
1978 :
1979 : /* ----------
1980 : * exec_stmt_while Loop over statements as long
1981 : * as an expression evaluates to
1982 : * true or an exit occurs.
1983 : * ----------
1984 : */
1985 : static int
1986 38 : exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
1987 : {
1988 : for (;;)
1989 : {
1990 : int rc;
1991 : bool value;
1992 : bool isnull;
1993 :
1994 38 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
1995 38 : exec_eval_cleanup(estate);
1996 :
1997 38 : if (isnull || !value)
1998 : break;
1999 :
2000 31 : rc = exec_stmts(estate, stmt->body);
2001 :
2002 31 : switch (rc)
2003 : {
2004 : case PLPGSQL_RC_OK:
2005 25 : break;
2006 :
2007 : case PLPGSQL_RC_EXIT:
2008 0 : if (estate->exitlabel == NULL)
2009 0 : return PLPGSQL_RC_OK;
2010 0 : if (stmt->label == NULL)
2011 0 : return PLPGSQL_RC_EXIT;
2012 0 : if (strcmp(stmt->label, estate->exitlabel) != 0)
2013 0 : return PLPGSQL_RC_EXIT;
2014 0 : estate->exitlabel = NULL;
2015 0 : return PLPGSQL_RC_OK;
2016 :
2017 : case PLPGSQL_RC_CONTINUE:
2018 6 : if (estate->exitlabel == NULL)
2019 : /* anonymous continue, so re-run loop */
2020 1 : break;
2021 10 : else if (stmt->label != NULL &&
2022 5 : strcmp(stmt->label, estate->exitlabel) == 0)
2023 : /* label matches named continue, so re-run loop */
2024 5 : estate->exitlabel = NULL;
2025 : else
2026 : /* label doesn't match named continue, propagate upward */
2027 0 : return PLPGSQL_RC_CONTINUE;
2028 5 : break;
2029 :
2030 : case PLPGSQL_RC_RETURN:
2031 0 : return rc;
2032 :
2033 : default:
2034 0 : elog(ERROR, "unrecognized rc: %d", rc);
2035 : }
2036 31 : }
2037 :
2038 7 : return PLPGSQL_RC_OK;
2039 : }
2040 :
2041 :
2042 : /* ----------
2043 : * exec_stmt_fori Iterate an integer variable
2044 : * from a lower to an upper value
2045 : * incrementing or decrementing by the BY value
2046 : * ----------
2047 : */
2048 : static int
2049 83 : exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
2050 : {
2051 : PLpgSQL_var *var;
2052 : Datum value;
2053 : bool isnull;
2054 : Oid valtype;
2055 : int32 valtypmod;
2056 : int32 loop_value;
2057 : int32 end_value;
2058 : int32 step_value;
2059 83 : bool found = false;
2060 83 : int rc = PLPGSQL_RC_OK;
2061 :
2062 83 : var = (PLpgSQL_var *) (estate->datums[stmt->var->dno]);
2063 :
2064 : /*
2065 : * Get the value of the lower bound
2066 : */
2067 83 : value = exec_eval_expr(estate, stmt->lower,
2068 : &isnull, &valtype, &valtypmod);
2069 166 : value = exec_cast_value(estate, value, &isnull,
2070 : valtype, valtypmod,
2071 83 : var->datatype->typoid,
2072 83 : var->datatype->atttypmod);
2073 83 : if (isnull)
2074 0 : ereport(ERROR,
2075 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2076 : errmsg("lower bound of FOR loop cannot be null")));
2077 83 : loop_value = DatumGetInt32(value);
2078 83 : exec_eval_cleanup(estate);
2079 :
2080 : /*
2081 : * Get the value of the upper bound
2082 : */
2083 83 : value = exec_eval_expr(estate, stmt->upper,
2084 : &isnull, &valtype, &valtypmod);
2085 166 : value = exec_cast_value(estate, value, &isnull,
2086 : valtype, valtypmod,
2087 83 : var->datatype->typoid,
2088 83 : var->datatype->atttypmod);
2089 83 : if (isnull)
2090 0 : ereport(ERROR,
2091 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2092 : errmsg("upper bound of FOR loop cannot be null")));
2093 83 : end_value = DatumGetInt32(value);
2094 83 : exec_eval_cleanup(estate);
2095 :
2096 : /*
2097 : * Get the step value
2098 : */
2099 83 : if (stmt->step)
2100 : {
2101 0 : value = exec_eval_expr(estate, stmt->step,
2102 : &isnull, &valtype, &valtypmod);
2103 0 : value = exec_cast_value(estate, value, &isnull,
2104 : valtype, valtypmod,
2105 0 : var->datatype->typoid,
2106 0 : var->datatype->atttypmod);
2107 0 : if (isnull)
2108 0 : ereport(ERROR,
2109 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2110 : errmsg("BY value of FOR loop cannot be null")));
2111 0 : step_value = DatumGetInt32(value);
2112 0 : exec_eval_cleanup(estate);
2113 0 : if (step_value <= 0)
2114 0 : ereport(ERROR,
2115 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2116 : errmsg("BY value of FOR loop must be greater than zero")));
2117 : }
2118 : else
2119 83 : step_value = 1;
2120 :
2121 : /*
2122 : * Now do the loop
2123 : */
2124 : for (;;)
2125 : {
2126 : /*
2127 : * Check against upper bound
2128 : */
2129 282 : if (stmt->reverse)
2130 : {
2131 0 : if (loop_value < end_value)
2132 0 : break;
2133 : }
2134 : else
2135 : {
2136 282 : if (loop_value > end_value)
2137 80 : break;
2138 : }
2139 :
2140 202 : found = true; /* looped at least once */
2141 :
2142 : /*
2143 : * Assign current value to loop var
2144 : */
2145 202 : assign_simple_var(estate, var, Int32GetDatum(loop_value), false, false);
2146 :
2147 : /*
2148 : * Execute the statements
2149 : */
2150 202 : rc = exec_stmts(estate, stmt->body);
2151 :
2152 202 : if (rc == PLPGSQL_RC_RETURN)
2153 0 : break; /* break out of the loop */
2154 202 : else if (rc == PLPGSQL_RC_EXIT)
2155 : {
2156 3 : if (estate->exitlabel == NULL)
2157 : /* unlabelled exit, finish the current loop */
2158 1 : rc = PLPGSQL_RC_OK;
2159 4 : else if (stmt->label != NULL &&
2160 2 : strcmp(stmt->label, estate->exitlabel) == 0)
2161 : {
2162 : /* labelled exit, matches the current stmt's label */
2163 2 : estate->exitlabel = NULL;
2164 2 : rc = PLPGSQL_RC_OK;
2165 : }
2166 :
2167 : /*
2168 : * otherwise, this is a labelled exit that does not match the
2169 : * current statement's label, if any: return RC_EXIT so that the
2170 : * EXIT continues to propagate up the stack.
2171 : */
2172 3 : break;
2173 : }
2174 199 : else if (rc == PLPGSQL_RC_CONTINUE)
2175 : {
2176 5 : if (estate->exitlabel == NULL)
2177 : /* unlabelled continue, so re-run the current loop */
2178 5 : rc = PLPGSQL_RC_OK;
2179 0 : else if (stmt->label != NULL &&
2180 0 : strcmp(stmt->label, estate->exitlabel) == 0)
2181 : {
2182 : /* label matches named continue, so re-run loop */
2183 0 : estate->exitlabel = NULL;
2184 0 : rc = PLPGSQL_RC_OK;
2185 : }
2186 : else
2187 : {
2188 : /*
2189 : * otherwise, this is a named continue that does not match the
2190 : * current statement's label, if any: return RC_CONTINUE so
2191 : * that the CONTINUE will propagate up the stack.
2192 : */
2193 : break;
2194 : }
2195 : }
2196 :
2197 : /*
2198 : * Increase/decrease loop value, unless it would overflow, in which
2199 : * case exit the loop.
2200 : */
2201 199 : if (stmt->reverse)
2202 : {
2203 0 : if ((int32) (loop_value - step_value) > loop_value)
2204 0 : break;
2205 0 : loop_value -= step_value;
2206 : }
2207 : else
2208 : {
2209 199 : if ((int32) (loop_value + step_value) < loop_value)
2210 0 : break;
2211 199 : loop_value += step_value;
2212 : }
2213 199 : }
2214 :
2215 : /*
2216 : * Set the FOUND variable to indicate the result of executing the loop
2217 : * (namely, whether we looped one or more times). This must be set here so
2218 : * that it does not interfere with the value of the FOUND variable inside
2219 : * the loop processing itself.
2220 : */
2221 83 : exec_set_found(estate, found);
2222 :
2223 83 : return rc;
2224 : }
2225 :
2226 :
2227 : /* ----------
2228 : * exec_stmt_fors Execute a query, assign each
2229 : * tuple to a record or row and
2230 : * execute a group of statements
2231 : * for it.
2232 : * ----------
2233 : */
2234 : static int
2235 174 : exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
2236 : {
2237 : Portal portal;
2238 : int rc;
2239 :
2240 : /*
2241 : * Open the implicit cursor for the statement using exec_run_select
2242 : */
2243 174 : exec_run_select(estate, stmt->query, 0, &portal);
2244 :
2245 : /*
2246 : * Execute the loop
2247 : */
2248 172 : rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
2249 :
2250 : /*
2251 : * Close the implicit cursor
2252 : */
2253 169 : SPI_cursor_close(portal);
2254 :
2255 169 : return rc;
2256 : }
2257 :
2258 :
2259 : /* ----------
2260 : * exec_stmt_forc Execute a loop for each row from a cursor.
2261 : * ----------
2262 : */
2263 : static int
2264 6 : exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
2265 : {
2266 : PLpgSQL_var *curvar;
2267 6 : MemoryContext stmt_mcontext = NULL;
2268 6 : char *curname = NULL;
2269 : PLpgSQL_expr *query;
2270 : ParamListInfo paramLI;
2271 : Portal portal;
2272 : int rc;
2273 :
2274 : /* ----------
2275 : * Get the cursor variable and if it has an assigned name, check
2276 : * that it's not in use currently.
2277 : * ----------
2278 : */
2279 6 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
2280 6 : if (!curvar->isnull)
2281 : {
2282 : MemoryContext oldcontext;
2283 :
2284 : /* We only need stmt_mcontext to hold the cursor name string */
2285 5 : stmt_mcontext = get_stmt_mcontext(estate);
2286 5 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
2287 5 : curname = TextDatumGetCString(curvar->value);
2288 5 : MemoryContextSwitchTo(oldcontext);
2289 :
2290 5 : if (SPI_cursor_find(curname) != NULL)
2291 0 : ereport(ERROR,
2292 : (errcode(ERRCODE_DUPLICATE_CURSOR),
2293 : errmsg("cursor \"%s\" already in use", curname)));
2294 : }
2295 :
2296 : /* ----------
2297 : * Open the cursor just like an OPEN command
2298 : *
2299 : * Note: parser should already have checked that statement supplies
2300 : * args iff cursor needs them, but we check again to be safe.
2301 : * ----------
2302 : */
2303 6 : if (stmt->argquery != NULL)
2304 : {
2305 : /* ----------
2306 : * OPEN CURSOR with args. We fake a SELECT ... INTO ...
2307 : * statement to evaluate the args and put 'em into the
2308 : * internal row.
2309 : * ----------
2310 : */
2311 : PLpgSQL_stmt_execsql set_args;
2312 :
2313 2 : if (curvar->cursor_explicit_argrow < 0)
2314 0 : ereport(ERROR,
2315 : (errcode(ERRCODE_SYNTAX_ERROR),
2316 : errmsg("arguments given for cursor without arguments")));
2317 :
2318 2 : memset(&set_args, 0, sizeof(set_args));
2319 2 : set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
2320 2 : set_args.lineno = stmt->lineno;
2321 2 : set_args.sqlstmt = stmt->argquery;
2322 2 : set_args.into = true;
2323 : /* XXX historically this has not been STRICT */
2324 2 : set_args.row = (PLpgSQL_row *)
2325 2 : (estate->datums[curvar->cursor_explicit_argrow]);
2326 :
2327 2 : if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
2328 0 : elog(ERROR, "open cursor failed during argument processing");
2329 : }
2330 : else
2331 : {
2332 4 : if (curvar->cursor_explicit_argrow >= 0)
2333 0 : ereport(ERROR,
2334 : (errcode(ERRCODE_SYNTAX_ERROR),
2335 : errmsg("arguments required for cursor")));
2336 : }
2337 :
2338 6 : query = curvar->cursor_explicit_expr;
2339 6 : Assert(query);
2340 :
2341 6 : if (query->plan == NULL)
2342 3 : exec_prepare_plan(estate, query, curvar->cursor_options);
2343 :
2344 : /*
2345 : * Set up short-lived ParamListInfo
2346 : */
2347 6 : paramLI = setup_unshared_param_list(estate, query);
2348 :
2349 : /*
2350 : * Open the cursor (the paramlist will get copied into the portal)
2351 : */
2352 6 : portal = SPI_cursor_open_with_paramlist(curname, query->plan,
2353 : paramLI,
2354 6 : estate->readonly_func);
2355 6 : if (portal == NULL)
2356 0 : elog(ERROR, "could not open cursor: %s",
2357 : SPI_result_code_string(SPI_result));
2358 :
2359 : /*
2360 : * If cursor variable was NULL, store the generated portal name in it
2361 : */
2362 6 : if (curname == NULL)
2363 1 : assign_text_var(estate, curvar, portal->name);
2364 :
2365 : /*
2366 : * Clean up before entering exec_for_query
2367 : */
2368 6 : exec_eval_cleanup(estate);
2369 6 : if (stmt_mcontext)
2370 5 : MemoryContextReset(stmt_mcontext);
2371 :
2372 : /*
2373 : * Execute the loop. We can't prefetch because the cursor is accessible
2374 : * to the user, for instance via UPDATE WHERE CURRENT OF within the loop.
2375 : */
2376 6 : rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, false);
2377 :
2378 : /* ----------
2379 : * Close portal, and restore cursor variable if it was initially NULL.
2380 : * ----------
2381 : */
2382 6 : SPI_cursor_close(portal);
2383 :
2384 6 : if (curname == NULL)
2385 1 : assign_simple_var(estate, curvar, (Datum) 0, true, false);
2386 :
2387 6 : return rc;
2388 : }
2389 :
2390 :
2391 : /* ----------
2392 : * exec_stmt_foreach_a Loop over elements or slices of an array
2393 : *
2394 : * When looping over elements, the loop variable is the same type that the
2395 : * array stores (eg: integer), when looping through slices, the loop variable
2396 : * is an array of size and dimensions to match the size of the slice.
2397 : * ----------
2398 : */
2399 : static int
2400 15 : exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
2401 : {
2402 : ArrayType *arr;
2403 : Oid arrtype;
2404 : int32 arrtypmod;
2405 : PLpgSQL_datum *loop_var;
2406 : Oid loop_var_elem_type;
2407 15 : bool found = false;
2408 15 : int rc = PLPGSQL_RC_OK;
2409 : MemoryContext stmt_mcontext;
2410 : MemoryContext oldcontext;
2411 : ArrayIterator array_iterator;
2412 : Oid iterator_result_type;
2413 : int32 iterator_result_typmod;
2414 : Datum value;
2415 : bool isnull;
2416 :
2417 : /* get the value of the array expression */
2418 15 : value = exec_eval_expr(estate, stmt->expr, &isnull, &arrtype, &arrtypmod);
2419 15 : if (isnull)
2420 0 : ereport(ERROR,
2421 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2422 : errmsg("FOREACH expression must not be null")));
2423 :
2424 : /*
2425 : * Do as much as possible of the code below in stmt_mcontext, to avoid any
2426 : * leaks from called subroutines. We need a private stmt_mcontext since
2427 : * we'll be calling arbitrary statement code.
2428 : */
2429 15 : stmt_mcontext = get_stmt_mcontext(estate);
2430 15 : push_stmt_mcontext(estate);
2431 15 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
2432 :
2433 : /* check the type of the expression - must be an array */
2434 15 : if (!OidIsValid(get_element_type(arrtype)))
2435 0 : ereport(ERROR,
2436 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2437 : errmsg("FOREACH expression must yield an array, not type %s",
2438 : format_type_be(arrtype))));
2439 :
2440 : /*
2441 : * We must copy the array into stmt_mcontext, else it will disappear in
2442 : * exec_eval_cleanup. This is annoying, but cleanup will certainly happen
2443 : * while running the loop body, so we have little choice.
2444 : */
2445 15 : arr = DatumGetArrayTypePCopy(value);
2446 :
2447 : /* Clean up any leftover temporary memory */
2448 15 : exec_eval_cleanup(estate);
2449 :
2450 : /* Slice dimension must be less than or equal to array dimension */
2451 15 : if (stmt->slice < 0 || stmt->slice > ARR_NDIM(arr))
2452 1 : ereport(ERROR,
2453 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2454 : errmsg("slice dimension (%d) is out of the valid range 0..%d",
2455 : stmt->slice, ARR_NDIM(arr))));
2456 :
2457 : /* Set up the loop variable and see if it is of an array type */
2458 14 : loop_var = estate->datums[stmt->varno];
2459 26 : if (loop_var->dtype == PLPGSQL_DTYPE_REC ||
2460 12 : loop_var->dtype == PLPGSQL_DTYPE_ROW)
2461 : {
2462 : /*
2463 : * Record/row variable is certainly not of array type, and might not
2464 : * be initialized at all yet, so don't try to get its type
2465 : */
2466 4 : loop_var_elem_type = InvalidOid;
2467 : }
2468 : else
2469 10 : loop_var_elem_type = get_element_type(plpgsql_exec_get_datum_type(estate,
2470 : loop_var));
2471 :
2472 : /*
2473 : * Sanity-check the loop variable type. We don't try very hard here, and
2474 : * should not be too picky since it's possible that exec_assign_value can
2475 : * coerce values of different types. But it seems worthwhile to complain
2476 : * if the array-ness of the loop variable is not right.
2477 : */
2478 14 : if (stmt->slice > 0 && loop_var_elem_type == InvalidOid)
2479 2 : ereport(ERROR,
2480 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2481 : errmsg("FOREACH ... SLICE loop variable must be of an array type")));
2482 12 : if (stmt->slice == 0 && loop_var_elem_type != InvalidOid)
2483 0 : ereport(ERROR,
2484 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2485 : errmsg("FOREACH loop variable must not be of an array type")));
2486 :
2487 : /* Create an iterator to step through the array */
2488 12 : array_iterator = array_create_iterator(arr, stmt->slice, NULL);
2489 :
2490 : /* Identify iterator result type */
2491 12 : if (stmt->slice > 0)
2492 : {
2493 : /* When slicing, nominal type of result is same as array type */
2494 6 : iterator_result_type = arrtype;
2495 6 : iterator_result_typmod = arrtypmod;
2496 : }
2497 : else
2498 : {
2499 : /* Without slicing, results are individual array elements */
2500 6 : iterator_result_type = ARR_ELEMTYPE(arr);
2501 6 : iterator_result_typmod = arrtypmod;
2502 : }
2503 :
2504 : /* Iterate over the array elements or slices */
2505 55 : while (array_iterate(array_iterator, &value, &isnull))
2506 : {
2507 31 : found = true; /* looped at least once */
2508 :
2509 : /* exec_assign_value and exec_stmts must run in the main context */
2510 31 : MemoryContextSwitchTo(oldcontext);
2511 :
2512 : /* Assign current element/slice to the loop variable */
2513 31 : exec_assign_value(estate, loop_var, value, isnull,
2514 : iterator_result_type, iterator_result_typmod);
2515 :
2516 : /* In slice case, value is temporary; must free it to avoid leakage */
2517 31 : if (stmt->slice > 0)
2518 9 : pfree(DatumGetPointer(value));
2519 :
2520 : /*
2521 : * Execute the statements
2522 : */
2523 31 : rc = exec_stmts(estate, stmt->body);
2524 :
2525 : /* Handle the return code */
2526 31 : if (rc == PLPGSQL_RC_RETURN)
2527 0 : break; /* break out of the loop */
2528 31 : else if (rc == PLPGSQL_RC_EXIT)
2529 : {
2530 0 : if (estate->exitlabel == NULL)
2531 : /* unlabelled exit, finish the current loop */
2532 0 : rc = PLPGSQL_RC_OK;
2533 0 : else if (stmt->label != NULL &&
2534 0 : strcmp(stmt->label, estate->exitlabel) == 0)
2535 : {
2536 : /* labelled exit, matches the current stmt's label */
2537 0 : estate->exitlabel = NULL;
2538 0 : rc = PLPGSQL_RC_OK;
2539 : }
2540 :
2541 : /*
2542 : * otherwise, this is a labelled exit that does not match the
2543 : * current statement's label, if any: return RC_EXIT so that the
2544 : * EXIT continues to propagate up the stack.
2545 : */
2546 0 : break;
2547 : }
2548 31 : else if (rc == PLPGSQL_RC_CONTINUE)
2549 : {
2550 0 : if (estate->exitlabel == NULL)
2551 : /* unlabelled continue, so re-run the current loop */
2552 0 : rc = PLPGSQL_RC_OK;
2553 0 : else if (stmt->label != NULL &&
2554 0 : strcmp(stmt->label, estate->exitlabel) == 0)
2555 : {
2556 : /* label matches named continue, so re-run loop */
2557 0 : estate->exitlabel = NULL;
2558 0 : rc = PLPGSQL_RC_OK;
2559 : }
2560 : else
2561 : {
2562 : /*
2563 : * otherwise, this is a named continue that does not match the
2564 : * current statement's label, if any: return RC_CONTINUE so
2565 : * that the CONTINUE will propagate up the stack.
2566 : */
2567 : break;
2568 : }
2569 : }
2570 :
2571 31 : MemoryContextSwitchTo(stmt_mcontext);
2572 : }
2573 :
2574 : /* Restore memory context state */
2575 12 : MemoryContextSwitchTo(oldcontext);
2576 12 : pop_stmt_mcontext(estate);
2577 :
2578 : /* Release temporary memory, including the array value */
2579 12 : MemoryContextReset(stmt_mcontext);
2580 :
2581 : /*
2582 : * Set the FOUND variable to indicate the result of executing the loop
2583 : * (namely, whether we looped one or more times). This must be set here so
2584 : * that it does not interfere with the value of the FOUND variable inside
2585 : * the loop processing itself.
2586 : */
2587 12 : exec_set_found(estate, found);
2588 :
2589 12 : return rc;
2590 : }
2591 :
2592 :
2593 : /* ----------
2594 : * exec_stmt_exit Implements EXIT and CONTINUE
2595 : *
2596 : * This begins the process of exiting / restarting a loop.
2597 : * ----------
2598 : */
2599 : static int
2600 190 : exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
2601 : {
2602 : /*
2603 : * If the exit / continue has a condition, evaluate it
2604 : */
2605 190 : if (stmt->cond != NULL)
2606 : {
2607 : bool value;
2608 : bool isnull;
2609 :
2610 165 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
2611 165 : exec_eval_cleanup(estate);
2612 165 : if (isnull || value == false)
2613 113 : return PLPGSQL_RC_OK;
2614 : }
2615 :
2616 77 : estate->exitlabel = stmt->label;
2617 77 : if (stmt->is_exit)
2618 10 : return PLPGSQL_RC_EXIT;
2619 : else
2620 67 : return PLPGSQL_RC_CONTINUE;
2621 : }
2622 :
2623 :
2624 : /* ----------
2625 : * exec_stmt_return Evaluate an expression and start
2626 : * returning from the function.
2627 : *
2628 : * Note: in the retistuple code paths, the returned tuple is always in the
2629 : * function's main context, whereas for non-tuple data types the result may
2630 : * be in the eval_mcontext. The former case is not a memory leak since we're
2631 : * about to exit the function anyway. (If you want to change it, note that
2632 : * exec_stmt_block() knows about this behavior.) The latter case means that
2633 : * we must not do exec_eval_cleanup while unwinding the control stack.
2634 : * ----------
2635 : */
2636 : static int
2637 12221 : exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
2638 : {
2639 : /*
2640 : * If processing a set-returning PL/pgSQL function, the final RETURN
2641 : * indicates that the function is finished producing tuples. The rest of
2642 : * the work will be done at the top level.
2643 : */
2644 12221 : if (estate->retisset)
2645 77 : return PLPGSQL_RC_RETURN;
2646 :
2647 : /* initialize for null result (possibly a tuple) */
2648 12144 : estate->retval = (Datum) 0;
2649 12144 : estate->rettupdesc = NULL;
2650 12144 : estate->retisnull = true;
2651 12144 : estate->rettype = InvalidOid;
2652 :
2653 : /*
2654 : * Special case path when the RETURN expression is a simple variable
2655 : * reference; in particular, this path is always taken in functions with
2656 : * one or more OUT parameters.
2657 : *
2658 : * This special case is especially efficient for returning variables that
2659 : * have R/W expanded values: we can put the R/W pointer directly into
2660 : * estate->retval, leading to transferring the value to the caller's
2661 : * context cheaply. If we went through exec_eval_expr we'd end up with a
2662 : * R/O pointer. It's okay to skip MakeExpandedObjectReadOnly here since
2663 : * we know we won't need the variable's value within the function anymore.
2664 : */
2665 12144 : if (stmt->retvarno >= 0)
2666 : {
2667 5778 : PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
2668 :
2669 5778 : switch (retvar->dtype)
2670 : {
2671 : case PLPGSQL_DTYPE_VAR:
2672 : {
2673 4129 : PLpgSQL_var *var = (PLpgSQL_var *) retvar;
2674 :
2675 4129 : estate->retval = var->value;
2676 4129 : estate->retisnull = var->isnull;
2677 4129 : estate->rettype = var->datatype->typoid;
2678 :
2679 : /*
2680 : * Cope with retistuple case. A PLpgSQL_var could not be
2681 : * of composite type, so we needn't make any effort to
2682 : * convert. However, for consistency with the expression
2683 : * code path, don't throw error if the result is NULL.
2684 : */
2685 4129 : if (estate->retistuple && !estate->retisnull)
2686 1 : ereport(ERROR,
2687 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2688 : errmsg("cannot return non-composite value from function returning composite type")));
2689 : }
2690 4128 : break;
2691 :
2692 : case PLPGSQL_DTYPE_REC:
2693 : {
2694 1610 : PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
2695 : int32 rettypmod;
2696 :
2697 1610 : if (HeapTupleIsValid(rec->tup))
2698 : {
2699 1601 : if (estate->retistuple)
2700 : {
2701 1601 : estate->retval = PointerGetDatum(rec->tup);
2702 1601 : estate->rettupdesc = rec->tupdesc;
2703 1601 : estate->retisnull = false;
2704 : }
2705 : else
2706 0 : exec_eval_datum(estate,
2707 : retvar,
2708 : &estate->rettype,
2709 : &rettypmod,
2710 : &estate->retval,
2711 : &estate->retisnull);
2712 : }
2713 : }
2714 1610 : break;
2715 :
2716 : case PLPGSQL_DTYPE_ROW:
2717 : {
2718 39 : PLpgSQL_row *row = (PLpgSQL_row *) retvar;
2719 : int32 rettypmod;
2720 :
2721 39 : if (estate->retistuple)
2722 : {
2723 : HeapTuple tup;
2724 :
2725 38 : if (!row->rowtupdesc) /* should not happen */
2726 0 : elog(ERROR, "row variable has no tupdesc");
2727 38 : tup = make_tuple_from_row(estate, row, row->rowtupdesc);
2728 38 : if (tup == NULL) /* should not happen */
2729 0 : elog(ERROR, "row not compatible with its own tupdesc");
2730 38 : estate->retval = PointerGetDatum(tup);
2731 38 : estate->rettupdesc = row->rowtupdesc;
2732 38 : estate->retisnull = false;
2733 : }
2734 : else
2735 1 : exec_eval_datum(estate,
2736 : retvar,
2737 : &estate->rettype,
2738 : &rettypmod,
2739 : &estate->retval,
2740 : &estate->retisnull);
2741 : }
2742 39 : break;
2743 :
2744 : default:
2745 0 : elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
2746 : }
2747 :
2748 5777 : return PLPGSQL_RC_RETURN;
2749 : }
2750 :
2751 6366 : if (stmt->expr != NULL)
2752 : {
2753 : int32 rettypmod;
2754 :
2755 6263 : estate->retval = exec_eval_expr(estate, stmt->expr,
2756 : &(estate->retisnull),
2757 : &(estate->rettype),
2758 : &rettypmod);
2759 :
2760 6257 : if (estate->retistuple && !estate->retisnull)
2761 : {
2762 : /* Convert composite datum to a HeapTuple and TupleDesc */
2763 : HeapTuple tuple;
2764 : TupleDesc tupdesc;
2765 :
2766 : /* Source must be of RECORD or composite type */
2767 10 : if (!type_is_rowtype(estate->rettype))
2768 1 : ereport(ERROR,
2769 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2770 : errmsg("cannot return non-composite value from function returning composite type")));
2771 9 : tuple = get_tuple_from_datum(estate->retval);
2772 9 : tupdesc = get_tupdesc_from_datum(estate->retval);
2773 9 : estate->retval = PointerGetDatum(tuple);
2774 9 : estate->rettupdesc = CreateTupleDescCopy(tupdesc);
2775 9 : ReleaseTupleDesc(tupdesc);
2776 : }
2777 :
2778 6256 : return PLPGSQL_RC_RETURN;
2779 : }
2780 :
2781 : /*
2782 : * Special hack for function returning VOID: instead of NULL, return a
2783 : * non-null VOID value. This is of dubious importance but is kept for
2784 : * backwards compatibility.
2785 : */
2786 103 : if (estate->fn_rettype == VOIDOID)
2787 : {
2788 103 : estate->retval = (Datum) 0;
2789 103 : estate->retisnull = false;
2790 103 : estate->rettype = VOIDOID;
2791 : }
2792 :
2793 103 : return PLPGSQL_RC_RETURN;
2794 : }
2795 :
2796 : /* ----------
2797 : * exec_stmt_return_next Evaluate an expression and add it to the
2798 : * list of tuples returned by the current
2799 : * SRF.
2800 : * ----------
2801 : */
2802 : static int
2803 156 : exec_stmt_return_next(PLpgSQL_execstate *estate,
2804 : PLpgSQL_stmt_return_next *stmt)
2805 : {
2806 : TupleDesc tupdesc;
2807 : int natts;
2808 : HeapTuple tuple;
2809 : MemoryContext oldcontext;
2810 :
2811 156 : if (!estate->retisset)
2812 0 : ereport(ERROR,
2813 : (errcode(ERRCODE_SYNTAX_ERROR),
2814 : errmsg("cannot use RETURN NEXT in a non-SETOF function")));
2815 :
2816 156 : if (estate->tuple_store == NULL)
2817 58 : exec_init_tuple_store(estate);
2818 :
2819 : /* rettupdesc will be filled by exec_init_tuple_store */
2820 156 : tupdesc = estate->rettupdesc;
2821 156 : natts = tupdesc->natts;
2822 :
2823 : /*
2824 : * Special case path when the RETURN NEXT expression is a simple variable
2825 : * reference; in particular, this path is always taken in functions with
2826 : * one or more OUT parameters.
2827 : *
2828 : * Unlike exec_statement_return, there's no special win here for R/W
2829 : * expanded values, since they'll have to get flattened to go into the
2830 : * tuplestore. Indeed, we'd better make them R/O to avoid any risk of the
2831 : * casting step changing them in-place.
2832 : */
2833 156 : if (stmt->retvarno >= 0)
2834 : {
2835 66 : PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
2836 :
2837 66 : switch (retvar->dtype)
2838 : {
2839 : case PLPGSQL_DTYPE_VAR:
2840 : {
2841 29 : PLpgSQL_var *var = (PLpgSQL_var *) retvar;
2842 29 : Datum retval = var->value;
2843 29 : bool isNull = var->isnull;
2844 29 : Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
2845 :
2846 29 : if (natts != 1)
2847 0 : ereport(ERROR,
2848 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2849 : errmsg("wrong result type supplied in RETURN NEXT")));
2850 :
2851 : /* let's be very paranoid about the cast step */
2852 29 : retval = MakeExpandedObjectReadOnly(retval,
2853 : isNull,
2854 : var->datatype->typlen);
2855 :
2856 : /* coerce type if needed */
2857 87 : retval = exec_cast_value(estate,
2858 : retval,
2859 : &isNull,
2860 29 : var->datatype->typoid,
2861 29 : var->datatype->atttypmod,
2862 : attr->atttypid,
2863 : attr->atttypmod);
2864 :
2865 29 : tuplestore_putvalues(estate->tuple_store, tupdesc,
2866 : &retval, &isNull);
2867 : }
2868 29 : break;
2869 :
2870 : case PLPGSQL_DTYPE_REC:
2871 : {
2872 25 : PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
2873 : TupleConversionMap *tupmap;
2874 :
2875 25 : if (!HeapTupleIsValid(rec->tup))
2876 0 : ereport(ERROR,
2877 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2878 : errmsg("record \"%s\" is not assigned yet",
2879 : rec->refname),
2880 : errdetail("The tuple structure of a not-yet-assigned"
2881 : " record is indeterminate.")));
2882 :
2883 : /* Use eval_mcontext for tuple conversion work */
2884 25 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2885 25 : tupmap = convert_tuples_by_position(rec->tupdesc,
2886 : tupdesc,
2887 : gettext_noop("wrong record type supplied in RETURN NEXT"));
2888 25 : tuple = rec->tup;
2889 25 : if (tupmap)
2890 5 : tuple = do_convert_tuple(tuple, tupmap);
2891 25 : tuplestore_puttuple(estate->tuple_store, tuple);
2892 25 : MemoryContextSwitchTo(oldcontext);
2893 : }
2894 25 : break;
2895 :
2896 : case PLPGSQL_DTYPE_ROW:
2897 : {
2898 12 : PLpgSQL_row *row = (PLpgSQL_row *) retvar;
2899 :
2900 : /* Use eval_mcontext for tuple conversion work */
2901 12 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2902 12 : tuple = make_tuple_from_row(estate, row, tupdesc);
2903 12 : if (tuple == NULL)
2904 0 : ereport(ERROR,
2905 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2906 : errmsg("wrong record type supplied in RETURN NEXT")));
2907 12 : tuplestore_puttuple(estate->tuple_store, tuple);
2908 12 : MemoryContextSwitchTo(oldcontext);
2909 : }
2910 12 : break;
2911 :
2912 : default:
2913 0 : elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
2914 : break;
2915 : }
2916 : }
2917 90 : else if (stmt->expr)
2918 : {
2919 : Datum retval;
2920 : bool isNull;
2921 : Oid rettype;
2922 : int32 rettypmod;
2923 :
2924 90 : retval = exec_eval_expr(estate,
2925 : stmt->expr,
2926 : &isNull,
2927 : &rettype,
2928 : &rettypmod);
2929 :
2930 90 : if (estate->retistuple)
2931 : {
2932 : /* Expression should be of RECORD or composite type */
2933 80 : if (!isNull)
2934 : {
2935 : TupleDesc retvaldesc;
2936 : TupleConversionMap *tupmap;
2937 :
2938 79 : if (!type_is_rowtype(rettype))
2939 0 : ereport(ERROR,
2940 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2941 : errmsg("cannot return non-composite value from function returning composite type")));
2942 :
2943 : /* Use eval_mcontext for tuple conversion work */
2944 79 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2945 79 : tuple = get_tuple_from_datum(retval);
2946 79 : retvaldesc = get_tupdesc_from_datum(retval);
2947 79 : tupmap = convert_tuples_by_position(retvaldesc, tupdesc,
2948 : gettext_noop("returned record type does not match expected record type"));
2949 79 : if (tupmap)
2950 0 : tuple = do_convert_tuple(tuple, tupmap);
2951 79 : tuplestore_puttuple(estate->tuple_store, tuple);
2952 79 : ReleaseTupleDesc(retvaldesc);
2953 79 : MemoryContextSwitchTo(oldcontext);
2954 : }
2955 : else
2956 : {
2957 : /* Composite NULL --- store a row of nulls */
2958 : Datum *nulldatums;
2959 : bool *nullflags;
2960 :
2961 1 : nulldatums = (Datum *)
2962 1 : eval_mcontext_alloc0(estate, natts * sizeof(Datum));
2963 1 : nullflags = (bool *)
2964 1 : eval_mcontext_alloc(estate, natts * sizeof(bool));
2965 1 : memset(nullflags, true, natts * sizeof(bool));
2966 1 : tuplestore_putvalues(estate->tuple_store, tupdesc,
2967 : nulldatums, nullflags);
2968 : }
2969 : }
2970 : else
2971 : {
2972 10 : Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
2973 :
2974 : /* Simple scalar result */
2975 10 : if (natts != 1)
2976 0 : ereport(ERROR,
2977 : (errcode(ERRCODE_DATATYPE_MISMATCH),
2978 : errmsg("wrong result type supplied in RETURN NEXT")));
2979 :
2980 : /* coerce type if needed */
2981 10 : retval = exec_cast_value(estate,
2982 : retval,
2983 : &isNull,
2984 : rettype,
2985 : rettypmod,
2986 : attr->atttypid,
2987 : attr->atttypmod);
2988 :
2989 10 : tuplestore_putvalues(estate->tuple_store, tupdesc,
2990 : &retval, &isNull);
2991 : }
2992 : }
2993 : else
2994 : {
2995 0 : ereport(ERROR,
2996 : (errcode(ERRCODE_SYNTAX_ERROR),
2997 : errmsg("RETURN NEXT must have a parameter")));
2998 : }
2999 :
3000 156 : exec_eval_cleanup(estate);
3001 :
3002 156 : return PLPGSQL_RC_OK;
3003 : }
3004 :
3005 : /* ----------
3006 : * exec_stmt_return_query Evaluate a query and add it to the
3007 : * list of tuples returned by the current
3008 : * SRF.
3009 : * ----------
3010 : */
3011 : static int
3012 25 : exec_stmt_return_query(PLpgSQL_execstate *estate,
3013 : PLpgSQL_stmt_return_query *stmt)
3014 : {
3015 : Portal portal;
3016 25 : uint64 processed = 0;
3017 : TupleConversionMap *tupmap;
3018 : MemoryContext oldcontext;
3019 :
3020 25 : if (!estate->retisset)
3021 0 : ereport(ERROR,
3022 : (errcode(ERRCODE_SYNTAX_ERROR),
3023 : errmsg("cannot use RETURN QUERY in a non-SETOF function")));
3024 :
3025 25 : if (estate->tuple_store == NULL)
3026 16 : exec_init_tuple_store(estate);
3027 :
3028 25 : if (stmt->query != NULL)
3029 : {
3030 : /* static query */
3031 17 : exec_run_select(estate, stmt->query, 0, &portal);
3032 : }
3033 : else
3034 : {
3035 : /* RETURN QUERY EXECUTE */
3036 8 : Assert(stmt->dynquery != NULL);
3037 8 : portal = exec_dynquery_with_params(estate, stmt->dynquery,
3038 : stmt->params, NULL,
3039 : 0);
3040 : }
3041 :
3042 : /* Use eval_mcontext for tuple conversion work */
3043 25 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3044 :
3045 25 : tupmap = convert_tuples_by_position(portal->tupDesc,
3046 : estate->rettupdesc,
3047 : gettext_noop("structure of query does not match function result type"));
3048 :
3049 : while (true)
3050 : {
3051 : uint64 i;
3052 :
3053 48 : SPI_cursor_fetch(portal, true, 50);
3054 :
3055 : /* SPI will have changed CurrentMemoryContext */
3056 48 : MemoryContextSwitchTo(get_eval_mcontext(estate));
3057 :
3058 48 : if (SPI_processed == 0)
3059 25 : break;
3060 :
3061 96 : for (i = 0; i < SPI_processed; i++)
3062 : {
3063 73 : HeapTuple tuple = SPI_tuptable->vals[i];
3064 :
3065 73 : if (tupmap)
3066 12 : tuple = do_convert_tuple(tuple, tupmap);
3067 73 : tuplestore_puttuple(estate->tuple_store, tuple);
3068 73 : if (tupmap)
3069 12 : heap_freetuple(tuple);
3070 73 : processed++;
3071 : }
3072 :
3073 23 : SPI_freetuptable(SPI_tuptable);
3074 23 : }
3075 :
3076 25 : SPI_freetuptable(SPI_tuptable);
3077 25 : SPI_cursor_close(portal);
3078 :
3079 25 : MemoryContextSwitchTo(oldcontext);
3080 25 : exec_eval_cleanup(estate);
3081 :
3082 25 : estate->eval_processed = processed;
3083 25 : exec_set_found(estate, processed != 0);
3084 :
3085 25 : return PLPGSQL_RC_OK;
3086 : }
3087 :
3088 : static void
3089 74 : exec_init_tuple_store(PLpgSQL_execstate *estate)
3090 : {
3091 74 : ReturnSetInfo *rsi = estate->rsi;
3092 : MemoryContext oldcxt;
3093 : ResourceOwner oldowner;
3094 :
3095 : /*
3096 : * Check caller can handle a set result in the way we want
3097 : */
3098 148 : if (!rsi || !IsA(rsi, ReturnSetInfo) ||
3099 148 : (rsi->allowedModes & SFRM_Materialize) == 0 ||
3100 74 : rsi->expectedDesc == NULL)
3101 0 : ereport(ERROR,
3102 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3103 : errmsg("set-valued function called in context that cannot accept a set")));
3104 :
3105 : /*
3106 : * Switch to the right memory context and resource owner for storing the
3107 : * tuplestore for return set. If we're within a subtransaction opened for
3108 : * an exception-block, for example, we must still create the tuplestore in
3109 : * the resource owner that was active when this function was entered, and
3110 : * not in the subtransaction resource owner.
3111 : */
3112 74 : oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
3113 74 : oldowner = CurrentResourceOwner;
3114 74 : CurrentResourceOwner = estate->tuple_store_owner;
3115 :
3116 74 : estate->tuple_store =
3117 74 : tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
3118 : false, work_mem);
3119 :
3120 74 : CurrentResourceOwner = oldowner;
3121 74 : MemoryContextSwitchTo(oldcxt);
3122 :
3123 74 : estate->rettupdesc = rsi->expectedDesc;
3124 74 : }
3125 :
3126 : #define SET_RAISE_OPTION_TEXT(opt, name) \
3127 : do { \
3128 : if (opt) \
3129 : ereport(ERROR, \
3130 : (errcode(ERRCODE_SYNTAX_ERROR), \
3131 : errmsg("RAISE option already specified: %s", \
3132 : name))); \
3133 : opt = MemoryContextStrdup(stmt_mcontext, extval); \
3134 : } while (0)
3135 :
3136 : /* ----------
3137 : * exec_stmt_raise Build a message and throw it with elog()
3138 : * ----------
3139 : */
3140 : static int
3141 1334 : exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
3142 : {
3143 1334 : int err_code = 0;
3144 1334 : char *condname = NULL;
3145 1334 : char *err_message = NULL;
3146 1334 : char *err_detail = NULL;
3147 1334 : char *err_hint = NULL;
3148 1334 : char *err_column = NULL;
3149 1334 : char *err_constraint = NULL;
3150 1334 : char *err_datatype = NULL;
3151 1334 : char *err_table = NULL;
3152 1334 : char *err_schema = NULL;
3153 : MemoryContext stmt_mcontext;
3154 : ListCell *lc;
3155 :
3156 : /* RAISE with no parameters: re-throw current exception */
3157 1343 : if (stmt->condname == NULL && stmt->message == NULL &&
3158 9 : stmt->options == NIL)
3159 : {
3160 6 : if (estate->cur_error != NULL)
3161 5 : ReThrowError(estate->cur_error);
3162 : /* oops, we're not inside a handler */
3163 1 : ereport(ERROR,
3164 : (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
3165 : errmsg("RAISE without parameters cannot be used outside an exception handler")));
3166 : }
3167 :
3168 : /* We'll need to accumulate the various strings in stmt_mcontext */
3169 1328 : stmt_mcontext = get_stmt_mcontext(estate);
3170 :
3171 1328 : if (stmt->condname)
3172 : {
3173 9 : err_code = plpgsql_recognize_err_condition(stmt->condname, true);
3174 9 : condname = MemoryContextStrdup(stmt_mcontext, stmt->condname);
3175 : }
3176 :
3177 1328 : if (stmt->message)
3178 : {
3179 : StringInfoData ds;
3180 : ListCell *current_param;
3181 : char *cp;
3182 : MemoryContext oldcontext;
3183 :
3184 : /* build string in stmt_mcontext */
3185 1316 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3186 1316 : initStringInfo(&ds);
3187 1316 : MemoryContextSwitchTo(oldcontext);
3188 :
3189 1316 : current_param = list_head(stmt->params);
3190 :
3191 23747 : for (cp = stmt->message; *cp; cp++)
3192 : {
3193 : /*
3194 : * Occurrences of a single % are replaced by the next parameter's
3195 : * external representation. Double %'s are converted to one %.
3196 : */
3197 22435 : if (cp[0] == '%')
3198 : {
3199 : Oid paramtypeid;
3200 : int32 paramtypmod;
3201 : Datum paramvalue;
3202 : bool paramisnull;
3203 : char *extval;
3204 :
3205 2550 : if (cp[1] == '%')
3206 : {
3207 1 : appendStringInfoChar(&ds, '%');
3208 1 : cp++;
3209 1 : continue;
3210 : }
3211 :
3212 : /* should have been checked at compile time */
3213 2549 : if (current_param == NULL)
3214 0 : elog(ERROR, "unexpected RAISE parameter list length");
3215 :
3216 2549 : paramvalue = exec_eval_expr(estate,
3217 2549 : (PLpgSQL_expr *) lfirst(current_param),
3218 : ¶misnull,
3219 : ¶mtypeid,
3220 : ¶mtypmod);
3221 :
3222 2545 : if (paramisnull)
3223 5 : extval = "<NULL>";
3224 : else
3225 2540 : extval = convert_value_to_string(estate,
3226 : paramvalue,
3227 : paramtypeid);
3228 2545 : appendStringInfoString(&ds, extval);
3229 2545 : current_param = lnext(current_param);
3230 2545 : exec_eval_cleanup(estate);
3231 : }
3232 : else
3233 19885 : appendStringInfoChar(&ds, cp[0]);
3234 : }
3235 :
3236 : /* should have been checked at compile time */
3237 1312 : if (current_param != NULL)
3238 0 : elog(ERROR, "unexpected RAISE parameter list length");
3239 :
3240 1312 : err_message = ds.data;
3241 : }
3242 :
3243 1349 : foreach(lc, stmt->options)
3244 : {
3245 27 : PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
3246 : Datum optionvalue;
3247 : bool optionisnull;
3248 : Oid optiontypeid;
3249 : int32 optiontypmod;
3250 : char *extval;
3251 :
3252 27 : optionvalue = exec_eval_expr(estate, opt->expr,
3253 : &optionisnull,
3254 : &optiontypeid,
3255 : &optiontypmod);
3256 27 : if (optionisnull)
3257 0 : ereport(ERROR,
3258 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3259 : errmsg("RAISE statement option cannot be null")));
3260 :
3261 27 : extval = convert_value_to_string(estate, optionvalue, optiontypeid);
3262 :
3263 27 : switch (opt->opt_type)
3264 : {
3265 : case PLPGSQL_RAISEOPTION_ERRCODE:
3266 7 : if (err_code)
3267 1 : ereport(ERROR,
3268 : (errcode(ERRCODE_SYNTAX_ERROR),
3269 : errmsg("RAISE option already specified: %s",
3270 : "ERRCODE")));
3271 6 : err_code = plpgsql_recognize_err_condition(extval, true);
3272 6 : condname = MemoryContextStrdup(stmt_mcontext, extval);
3273 6 : break;
3274 : case PLPGSQL_RAISEOPTION_MESSAGE:
3275 6 : SET_RAISE_OPTION_TEXT(err_message, "MESSAGE");
3276 5 : break;
3277 : case PLPGSQL_RAISEOPTION_DETAIL:
3278 7 : SET_RAISE_OPTION_TEXT(err_detail, "DETAIL");
3279 7 : break;
3280 : case PLPGSQL_RAISEOPTION_HINT:
3281 2 : SET_RAISE_OPTION_TEXT(err_hint, "HINT");
3282 2 : break;
3283 : case PLPGSQL_RAISEOPTION_COLUMN:
3284 1 : SET_RAISE_OPTION_TEXT(err_column, "COLUMN");
3285 1 : break;
3286 : case PLPGSQL_RAISEOPTION_CONSTRAINT:
3287 1 : SET_RAISE_OPTION_TEXT(err_constraint, "CONSTRAINT");
3288 1 : break;
3289 : case PLPGSQL_RAISEOPTION_DATATYPE:
3290 1 : SET_RAISE_OPTION_TEXT(err_datatype, "DATATYPE");
3291 1 : break;
3292 : case PLPGSQL_RAISEOPTION_TABLE:
3293 1 : SET_RAISE_OPTION_TEXT(err_table, "TABLE");
3294 1 : break;
3295 : case PLPGSQL_RAISEOPTION_SCHEMA:
3296 1 : SET_RAISE_OPTION_TEXT(err_schema, "SCHEMA");
3297 1 : break;
3298 : default:
3299 0 : elog(ERROR, "unrecognized raise option: %d", opt->opt_type);
3300 : }
3301 :
3302 25 : exec_eval_cleanup(estate);
3303 : }
3304 :
3305 : /* Default code if nothing specified */
3306 1322 : if (err_code == 0 && stmt->elog_level >= ERROR)
3307 28 : err_code = ERRCODE_RAISE_EXCEPTION;
3308 :
3309 : /* Default error message if nothing specified */
3310 1322 : if (err_message == NULL)
3311 : {
3312 7 : if (condname)
3313 : {
3314 6 : err_message = condname;
3315 6 : condname = NULL;
3316 : }
3317 : else
3318 1 : err_message = MemoryContextStrdup(stmt_mcontext,
3319 1 : unpack_sql_state(err_code));
3320 : }
3321 :
3322 : /*
3323 : * Throw the error (may or may not come back)
3324 : */
3325 1322 : ereport(stmt->elog_level,
3326 : (err_code ? errcode(err_code) : 0,
3327 : errmsg_internal("%s", err_message),
3328 : (err_detail != NULL) ? errdetail_internal("%s", err_detail) : 0,
3329 : (err_hint != NULL) ? errhint("%s", err_hint) : 0,
3330 : (err_column != NULL) ?
3331 : err_generic_string(PG_DIAG_COLUMN_NAME, err_column) : 0,
3332 : (err_constraint != NULL) ?
3333 : err_generic_string(PG_DIAG_CONSTRAINT_NAME, err_constraint) : 0,
3334 : (err_datatype != NULL) ?
3335 : err_generic_string(PG_DIAG_DATATYPE_NAME, err_datatype) : 0,
3336 : (err_table != NULL) ?
3337 : err_generic_string(PG_DIAG_TABLE_NAME, err_table) : 0,
3338 : (err_schema != NULL) ?
3339 : err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema) : 0));
3340 :
3341 : /* Clean up transient strings */
3342 1281 : MemoryContextReset(stmt_mcontext);
3343 :
3344 1281 : return PLPGSQL_RC_OK;
3345 : }
3346 :
3347 : /* ----------
3348 : * exec_stmt_assert Assert statement
3349 : * ----------
3350 : */
3351 : static int
3352 6 : exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
3353 : {
3354 : bool value;
3355 : bool isnull;
3356 :
3357 : /* do nothing when asserts are not enabled */
3358 6 : if (!plpgsql_check_asserts)
3359 1 : return PLPGSQL_RC_OK;
3360 :
3361 5 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
3362 5 : exec_eval_cleanup(estate);
3363 :
3364 5 : if (isnull || !value)
3365 : {
3366 4 : char *message = NULL;
3367 :
3368 4 : if (stmt->message != NULL)
3369 : {
3370 : Datum val;
3371 : Oid typeid;
3372 : int32 typmod;
3373 :
3374 2 : val = exec_eval_expr(estate, stmt->message,
3375 : &isnull, &typeid, &typmod);
3376 2 : if (!isnull)
3377 2 : message = convert_value_to_string(estate, val, typeid);
3378 : /* we mustn't do exec_eval_cleanup here */
3379 : }
3380 :
3381 4 : ereport(ERROR,
3382 : (errcode(ERRCODE_ASSERT_FAILURE),
3383 : message ? errmsg_internal("%s", message) :
3384 : errmsg("assertion failed")));
3385 : }
3386 :
3387 1 : return PLPGSQL_RC_OK;
3388 : }
3389 :
3390 : /* ----------
3391 : * Initialize a mostly empty execution state
3392 : * ----------
3393 : */
3394 : static void
3395 12326 : plpgsql_estate_setup(PLpgSQL_execstate *estate,
3396 : PLpgSQL_function *func,
3397 : ReturnSetInfo *rsi,
3398 : EState *simple_eval_estate)
3399 : {
3400 : HASHCTL ctl;
3401 :
3402 : /* this link will be restored at exit from plpgsql_call_handler */
3403 12326 : func->cur_estate = estate;
3404 :
3405 12326 : estate->func = func;
3406 :
3407 12326 : estate->retval = (Datum) 0;
3408 12326 : estate->retisnull = true;
3409 12326 : estate->rettype = InvalidOid;
3410 :
3411 12326 : estate->fn_rettype = func->fn_rettype;
3412 12326 : estate->retistuple = func->fn_retistuple;
3413 12326 : estate->retisset = func->fn_retset;
3414 :
3415 12326 : estate->readonly_func = func->fn_readonly;
3416 :
3417 12326 : estate->rettupdesc = NULL;
3418 12326 : estate->exitlabel = NULL;
3419 12326 : estate->cur_error = NULL;
3420 :
3421 12326 : estate->tuple_store = NULL;
3422 12326 : if (rsi)
3423 : {
3424 105 : estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
3425 105 : estate->tuple_store_owner = CurrentResourceOwner;
3426 : }
3427 : else
3428 : {
3429 12221 : estate->tuple_store_cxt = NULL;
3430 12221 : estate->tuple_store_owner = NULL;
3431 : }
3432 12326 : estate->rsi = rsi;
3433 :
3434 12326 : estate->found_varno = func->found_varno;
3435 12326 : estate->ndatums = func->ndatums;
3436 12326 : estate->datums = palloc(sizeof(PLpgSQL_datum *) * estate->ndatums);
3437 : /* caller is expected to fill the datums array */
3438 :
3439 : /* initialize ParamListInfo with one entry per datum, all invalid */
3440 12326 : estate->paramLI = (ParamListInfo)
3441 12326 : palloc0(offsetof(ParamListInfoData, params) +
3442 12326 : estate->ndatums * sizeof(ParamExternData));
3443 12326 : estate->paramLI->paramFetch = plpgsql_param_fetch;
3444 12326 : estate->paramLI->paramFetchArg = (void *) estate;
3445 12326 : estate->paramLI->parserSetup = (ParserSetupHook) plpgsql_parser_setup;
3446 12326 : estate->paramLI->parserSetupArg = NULL; /* filled during use */
3447 12326 : estate->paramLI->numParams = estate->ndatums;
3448 12326 : estate->paramLI->paramMask = NULL;
3449 12326 : estate->params_dirty = false;
3450 :
3451 : /* set up for use of appropriate simple-expression EState and cast hash */
3452 12326 : if (simple_eval_estate)
3453 : {
3454 39 : estate->simple_eval_estate = simple_eval_estate;
3455 : /* Private cast hash just lives in function's main context */
3456 39 : memset(&ctl, 0, sizeof(ctl));
3457 39 : ctl.keysize = sizeof(plpgsql_CastHashKey);
3458 39 : ctl.entrysize = sizeof(plpgsql_CastHashEntry);
3459 39 : ctl.hcxt = CurrentMemoryContext;
3460 39 : estate->cast_hash = hash_create("PLpgSQL private cast cache",
3461 : 16, /* start small and extend */
3462 : &ctl,
3463 : HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
3464 39 : estate->cast_hash_context = CurrentMemoryContext;
3465 : }
3466 : else
3467 : {
3468 12287 : estate->simple_eval_estate = shared_simple_eval_estate;
3469 : /* Create the session-wide cast-info hash table if we didn't already */
3470 12287 : if (shared_cast_hash == NULL)
3471 : {
3472 32 : shared_cast_context = AllocSetContextCreate(TopMemoryContext,
3473 : "PLpgSQL cast info",
3474 : ALLOCSET_DEFAULT_SIZES);
3475 32 : memset(&ctl, 0, sizeof(ctl));
3476 32 : ctl.keysize = sizeof(plpgsql_CastHashKey);
3477 32 : ctl.entrysize = sizeof(plpgsql_CastHashEntry);
3478 32 : ctl.hcxt = shared_cast_context;
3479 32 : shared_cast_hash = hash_create("PLpgSQL cast cache",
3480 : 16, /* start small and extend */
3481 : &ctl,
3482 : HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
3483 : }
3484 12287 : estate->cast_hash = shared_cast_hash;
3485 12287 : estate->cast_hash_context = shared_cast_context;
3486 : }
3487 :
3488 : /*
3489 : * We start with no stmt_mcontext; one will be created only if needed.
3490 : * That context will be a direct child of the function's main execution
3491 : * context. Additional stmt_mcontexts might be created as children of it.
3492 : */
3493 12326 : estate->stmt_mcontext = NULL;
3494 12326 : estate->stmt_mcontext_parent = CurrentMemoryContext;
3495 :
3496 12326 : estate->eval_tuptable = NULL;
3497 12326 : estate->eval_processed = 0;
3498 12326 : estate->eval_lastoid = InvalidOid;
3499 12326 : estate->eval_econtext = NULL;
3500 :
3501 12326 : estate->err_stmt = NULL;
3502 12326 : estate->err_text = NULL;
3503 :
3504 12326 : estate->plugin_info = NULL;
3505 :
3506 : /*
3507 : * Create an EState and ExprContext for evaluation of simple expressions.
3508 : */
3509 12326 : plpgsql_create_econtext(estate);
3510 :
3511 : /*
3512 : * Let the plugin see this function before we initialize any local
3513 : * PL/pgSQL variables - note that we also give the plugin a few function
3514 : * pointers so it can call back into PL/pgSQL for doing things like
3515 : * variable assignments and stack traces
3516 : */
3517 12326 : if (*plpgsql_plugin_ptr)
3518 : {
3519 0 : (*plpgsql_plugin_ptr)->error_callback = plpgsql_exec_error_callback;
3520 0 : (*plpgsql_plugin_ptr)->assign_expr = exec_assign_expr;
3521 :
3522 0 : if ((*plpgsql_plugin_ptr)->func_setup)
3523 0 : ((*plpgsql_plugin_ptr)->func_setup) (estate, func);
3524 : }
3525 12326 : }
3526 :
3527 : /* ----------
3528 : * Release temporary memory used by expression/subselect evaluation
3529 : *
3530 : * NB: the result of the evaluation is no longer valid after this is done,
3531 : * unless it is a pass-by-value datatype.
3532 : *
3533 : * NB: if you change this code, see also the hacks in exec_assign_value's
3534 : * PLPGSQL_DTYPE_ARRAYELEM case for partial cleanup after subscript evals.
3535 : * ----------
3536 : */
3537 : static void
3538 38366 : exec_eval_cleanup(PLpgSQL_execstate *estate)
3539 : {
3540 : /* Clear result of a full SPI_execute */
3541 38366 : if (estate->eval_tuptable != NULL)
3542 726 : SPI_freetuptable(estate->eval_tuptable);
3543 38366 : estate->eval_tuptable = NULL;
3544 :
3545 : /*
3546 : * Clear result of exec_eval_simple_expr (but keep the econtext). This
3547 : * also clears any short-lived allocations done via get_eval_mcontext.
3548 : */
3549 38366 : if (estate->eval_econtext != NULL)
3550 26158 : ResetExprContext(estate->eval_econtext);
3551 38366 : }
3552 :
3553 :
3554 : /* ----------
3555 : * Generate a prepared plan
3556 : * ----------
3557 : */
3558 : static void
3559 1589 : exec_prepare_plan(PLpgSQL_execstate *estate,
3560 : PLpgSQL_expr *expr, int cursorOptions)
3561 : {
3562 : SPIPlanPtr plan;
3563 :
3564 : /*
3565 : * The grammar can't conveniently set expr->func while building the parse
3566 : * tree, so make sure it's set before parser hooks need it.
3567 : */
3568 1589 : expr->func = estate->func;
3569 :
3570 : /*
3571 : * Generate and save the plan
3572 : */
3573 1589 : plan = SPI_prepare_params(expr->query,
3574 : (ParserSetupHook) plpgsql_parser_setup,
3575 : (void *) expr,
3576 : cursorOptions);
3577 1584 : if (plan == NULL)
3578 : {
3579 : /* Some SPI errors deserve specific error messages */
3580 0 : switch (SPI_result)
3581 : {
3582 : case SPI_ERROR_COPY:
3583 0 : ereport(ERROR,
3584 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3585 : errmsg("cannot COPY to/from client in PL/pgSQL")));
3586 : case SPI_ERROR_TRANSACTION:
3587 0 : ereport(ERROR,
3588 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3589 : errmsg("cannot begin/end transactions in PL/pgSQL"),
3590 : errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
3591 : default:
3592 0 : elog(ERROR, "SPI_prepare_params failed for \"%s\": %s",
3593 : expr->query, SPI_result_code_string(SPI_result));
3594 : }
3595 : }
3596 1584 : SPI_keepplan(plan);
3597 1584 : expr->plan = plan;
3598 :
3599 : /* Check to see if it's a simple expression */
3600 1584 : exec_simple_check_plan(estate, expr);
3601 :
3602 : /*
3603 : * Mark expression as not using a read-write param. exec_assign_value has
3604 : * to take steps to override this if appropriate; that seems cleaner than
3605 : * adding parameters to all other callers.
3606 : */
3607 1579 : expr->rwparam = -1;
3608 1579 : }
3609 :
3610 :
3611 : /* ----------
3612 : * exec_stmt_execsql Execute an SQL statement (possibly with INTO).
3613 : *
3614 : * Note: some callers rely on this not touching stmt_mcontext. If it ever
3615 : * needs to use that, fix those callers to push/pop stmt_mcontext.
3616 : * ----------
3617 : */
3618 : static int
3619 1909 : exec_stmt_execsql(PLpgSQL_execstate *estate,
3620 : PLpgSQL_stmt_execsql *stmt)
3621 : {
3622 : ParamListInfo paramLI;
3623 : long tcount;
3624 : int rc;
3625 1909 : PLpgSQL_expr *expr = stmt->sqlstmt;
3626 :
3627 : /*
3628 : * On the first call for this statement generate the plan, and detect
3629 : * whether the statement is INSERT/UPDATE/DELETE
3630 : */
3631 1909 : if (expr->plan == NULL)
3632 : {
3633 : ListCell *l;
3634 :
3635 146 : exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
3636 145 : stmt->mod_stmt = false;
3637 290 : foreach(l, SPI_plan_get_plan_sources(expr->plan))
3638 : {
3639 145 : CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l);
3640 : ListCell *l2;
3641 :
3642 290 : foreach(l2, plansource->query_list)
3643 : {
3644 145 : Query *q = lfirst_node(Query, l2);
3645 :
3646 145 : if (q->canSetTag)
3647 : {
3648 257 : if (q->commandType == CMD_INSERT ||
3649 201 : q->commandType == CMD_UPDATE ||
3650 89 : q->commandType == CMD_DELETE)
3651 64 : stmt->mod_stmt = true;
3652 : }
3653 : }
3654 : }
3655 : }
3656 :
3657 : /*
3658 : * Set up ParamListInfo to pass to executor
3659 : */
3660 1908 : paramLI = setup_param_list(estate, expr);
3661 :
3662 : /*
3663 : * If we have INTO, then we only need one row back ... but if we have INTO
3664 : * STRICT, ask for two rows, so that we can verify the statement returns
3665 : * only one. INSERT/UPDATE/DELETE are always treated strictly. Without
3666 : * INTO, just run the statement to completion (tcount = 0).
3667 : *
3668 : * We could just ask for two rows always when using INTO, but there are
3669 : * some cases where demanding the extra row costs significant time, eg by
3670 : * forcing completion of a sequential scan. So don't do it unless we need
3671 : * to enforce strictness.
3672 : */
3673 1908 : if (stmt->into)
3674 : {
3675 583 : if (stmt->strict || stmt->mod_stmt)
3676 63 : tcount = 2;
3677 : else
3678 520 : tcount = 1;
3679 : }
3680 : else
3681 1325 : tcount = 0;
3682 :
3683 : /*
3684 : * Execute the plan
3685 : */
3686 1908 : rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
3687 1908 : estate->readonly_func, tcount);
3688 :
3689 : /*
3690 : * Check for error, and set FOUND if appropriate (for historical reasons
3691 : * we set FOUND only for certain query types). Also Assert that we
3692 : * identified the statement type the same as SPI did.
3693 : */
3694 1899 : switch (rc)
3695 : {
3696 : case SPI_OK_SELECT:
3697 525 : Assert(!stmt->mod_stmt);
3698 525 : exec_set_found(estate, (SPI_processed != 0));
3699 525 : break;
3700 :
3701 : case SPI_OK_INSERT:
3702 : case SPI_OK_UPDATE:
3703 : case SPI_OK_DELETE:
3704 : case SPI_OK_INSERT_RETURNING:
3705 : case SPI_OK_UPDATE_RETURNING:
3706 : case SPI_OK_DELETE_RETURNING:
3707 359 : Assert(stmt->mod_stmt);
3708 359 : exec_set_found(estate, (SPI_processed != 0));
3709 359 : break;
3710 :
3711 : case SPI_OK_SELINTO:
3712 : case SPI_OK_UTILITY:
3713 1015 : Assert(!stmt->mod_stmt);
3714 1015 : break;
3715 :
3716 : case SPI_OK_REWRITTEN:
3717 0 : Assert(!stmt->mod_stmt);
3718 :
3719 : /*
3720 : * The command was rewritten into another kind of command. It's
3721 : * not clear what FOUND would mean in that case (and SPI doesn't
3722 : * return the row count either), so just set it to false.
3723 : */
3724 0 : exec_set_found(estate, false);
3725 0 : break;
3726 :
3727 : /* Some SPI errors deserve specific error messages */
3728 : case SPI_ERROR_COPY:
3729 0 : ereport(ERROR,
3730 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3731 : errmsg("cannot COPY to/from client in PL/pgSQL")));
3732 : case SPI_ERROR_TRANSACTION:
3733 0 : ereport(ERROR,
3734 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3735 : errmsg("cannot begin/end transactions in PL/pgSQL"),
3736 : errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
3737 :
3738 : default:
3739 0 : elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s",
3740 : expr->query, SPI_result_code_string(rc));
3741 : }
3742 :
3743 : /* All variants should save result info for GET DIAGNOSTICS */
3744 1899 : estate->eval_processed = SPI_processed;
3745 1899 : estate->eval_lastoid = SPI_lastoid;
3746 :
3747 : /* Process INTO if present */
3748 1899 : if (stmt->into)
3749 : {
3750 580 : SPITupleTable *tuptab = SPI_tuptable;
3751 580 : uint64 n = SPI_processed;
3752 580 : PLpgSQL_rec *rec = NULL;
3753 580 : PLpgSQL_row *row = NULL;
3754 :
3755 : /* If the statement did not return a tuple table, complain */
3756 580 : if (tuptab == NULL)
3757 0 : ereport(ERROR,
3758 : (errcode(ERRCODE_SYNTAX_ERROR),
3759 : errmsg("INTO used with a command that cannot return data")));
3760 :
3761 : /* Determine if we assign to a record or a row */
3762 580 : if (stmt->rec != NULL)
3763 458 : rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
3764 122 : else if (stmt->row != NULL)
3765 122 : row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
3766 : else
3767 0 : elog(ERROR, "unsupported target");
3768 :
3769 : /*
3770 : * If SELECT ... INTO specified STRICT, and the query didn't find
3771 : * exactly one row, throw an error. If STRICT was not specified, then
3772 : * allow the query to find any number of rows.
3773 : */
3774 580 : if (n == 0)
3775 : {
3776 10 : if (stmt->strict)
3777 : {
3778 : char *errdetail;
3779 :
3780 2 : if (estate->func->print_strict_params)
3781 1 : errdetail = format_expr_params(estate, expr);
3782 : else
3783 1 : errdetail = NULL;
3784 :
3785 2 : ereport(ERROR,
3786 : (errcode(ERRCODE_NO_DATA_FOUND),
3787 : errmsg("query returned no rows"),
3788 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3789 : }
3790 : /* set the target to NULL(s) */
3791 8 : exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
3792 : }
3793 : else
3794 : {
3795 570 : if (n > 1 && (stmt->strict || stmt->mod_stmt))
3796 : {
3797 : char *errdetail;
3798 :
3799 6 : if (estate->func->print_strict_params)
3800 3 : errdetail = format_expr_params(estate, expr);
3801 : else
3802 3 : errdetail = NULL;
3803 :
3804 6 : ereport(ERROR,
3805 : (errcode(ERRCODE_TOO_MANY_ROWS),
3806 : errmsg("query returned more than one row"),
3807 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3808 : }
3809 : /* Put the first result row into the target */
3810 564 : exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
3811 : }
3812 :
3813 : /* Clean up */
3814 572 : exec_eval_cleanup(estate);
3815 572 : SPI_freetuptable(SPI_tuptable);
3816 : }
3817 : else
3818 : {
3819 : /* If the statement returned a tuple table, complain */
3820 1319 : if (SPI_tuptable != NULL)
3821 0 : ereport(ERROR,
3822 : (errcode(ERRCODE_SYNTAX_ERROR),
3823 : errmsg("query has no destination for result data"),
3824 : (rc == SPI_OK_SELECT) ? errhint("If you want to discard the results of a SELECT, use PERFORM instead.") : 0));
3825 : }
3826 :
3827 1891 : return PLPGSQL_RC_OK;
3828 : }
3829 :
3830 :
3831 : /* ----------
3832 : * exec_stmt_dynexecute Execute a dynamic SQL query
3833 : * (possibly with INTO).
3834 : * ----------
3835 : */
3836 : static int
3837 583 : exec_stmt_dynexecute(PLpgSQL_execstate *estate,
3838 : PLpgSQL_stmt_dynexecute *stmt)
3839 : {
3840 : Datum query;
3841 : bool isnull;
3842 : Oid restype;
3843 : int32 restypmod;
3844 : char *querystr;
3845 : int exec_res;
3846 583 : PreparedParamsData *ppd = NULL;
3847 583 : MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
3848 :
3849 : /*
3850 : * First we evaluate the string expression after the EXECUTE keyword. Its
3851 : * result is the querystring we have to execute.
3852 : */
3853 583 : query = exec_eval_expr(estate, stmt->query, &isnull, &restype, &restypmod);
3854 583 : if (isnull)
3855 0 : ereport(ERROR,
3856 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3857 : errmsg("query string argument of EXECUTE is null")));
3858 :
3859 : /* Get the C-String representation */
3860 583 : querystr = convert_value_to_string(estate, query, restype);
3861 :
3862 : /* copy it into the stmt_mcontext before we clean up */
3863 583 : querystr = MemoryContextStrdup(stmt_mcontext, querystr);
3864 :
3865 583 : exec_eval_cleanup(estate);
3866 :
3867 : /*
3868 : * Execute the query without preparing a saved plan.
3869 : */
3870 583 : if (stmt->params)
3871 : {
3872 3 : ppd = exec_eval_using_params(estate, stmt->params);
3873 6 : exec_res = SPI_execute_with_args(querystr,
3874 : ppd->nargs, ppd->types,
3875 3 : ppd->values, ppd->nulls,
3876 3 : estate->readonly_func, 0);
3877 : }
3878 : else
3879 580 : exec_res = SPI_execute(querystr, estate->readonly_func, 0);
3880 :
3881 569 : switch (exec_res)
3882 : {
3883 : case SPI_OK_SELECT:
3884 : case SPI_OK_INSERT:
3885 : case SPI_OK_UPDATE:
3886 : case SPI_OK_DELETE:
3887 : case SPI_OK_INSERT_RETURNING:
3888 : case SPI_OK_UPDATE_RETURNING:
3889 : case SPI_OK_DELETE_RETURNING:
3890 : case SPI_OK_UTILITY:
3891 : case SPI_OK_REWRITTEN:
3892 569 : break;
3893 :
3894 : case 0:
3895 :
3896 : /*
3897 : * Also allow a zero return, which implies the querystring
3898 : * contained no commands.
3899 : */
3900 0 : break;
3901 :
3902 : case SPI_OK_SELINTO:
3903 :
3904 : /*
3905 : * We want to disallow SELECT INTO for now, because its behavior
3906 : * is not consistent with SELECT INTO in a normal plpgsql context.
3907 : * (We need to reimplement EXECUTE to parse the string as a
3908 : * plpgsql command, not just feed it to SPI_execute.) This is not
3909 : * a functional limitation because CREATE TABLE AS is allowed.
3910 : */
3911 0 : ereport(ERROR,
3912 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3913 : errmsg("EXECUTE of SELECT ... INTO is not implemented"),
3914 : errhint("You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.")));
3915 : break;
3916 :
3917 : /* Some SPI errors deserve specific error messages */
3918 : case SPI_ERROR_COPY:
3919 0 : ereport(ERROR,
3920 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3921 : errmsg("cannot COPY to/from client in PL/pgSQL")));
3922 : case SPI_ERROR_TRANSACTION:
3923 0 : ereport(ERROR,
3924 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3925 : errmsg("cannot begin/end transactions in PL/pgSQL"),
3926 : errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
3927 :
3928 : default:
3929 0 : elog(ERROR, "SPI_execute failed executing query \"%s\": %s",
3930 : querystr, SPI_result_code_string(exec_res));
3931 : break;
3932 : }
3933 :
3934 : /* Save result info for GET DIAGNOSTICS */
3935 569 : estate->eval_processed = SPI_processed;
3936 569 : estate->eval_lastoid = SPI_lastoid;
3937 :
3938 : /* Process INTO if present */
3939 569 : if (stmt->into)
3940 : {
3941 550 : SPITupleTable *tuptab = SPI_tuptable;
3942 550 : uint64 n = SPI_processed;
3943 550 : PLpgSQL_rec *rec = NULL;
3944 550 : PLpgSQL_row *row = NULL;
3945 :
3946 : /* If the statement did not return a tuple table, complain */
3947 550 : if (tuptab == NULL)
3948 0 : ereport(ERROR,
3949 : (errcode(ERRCODE_SYNTAX_ERROR),
3950 : errmsg("INTO used with a command that cannot return data")));
3951 :
3952 : /* Determine if we assign to a record or a row */
3953 550 : if (stmt->rec != NULL)
3954 9 : rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
3955 541 : else if (stmt->row != NULL)
3956 541 : row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
3957 : else
3958 0 : elog(ERROR, "unsupported target");
3959 :
3960 : /*
3961 : * If SELECT ... INTO specified STRICT, and the query didn't find
3962 : * exactly one row, throw an error. If STRICT was not specified, then
3963 : * allow the query to find any number of rows.
3964 : */
3965 550 : if (n == 0)
3966 : {
3967 2 : if (stmt->strict)
3968 : {
3969 : char *errdetail;
3970 :
3971 2 : if (estate->func->print_strict_params)
3972 1 : errdetail = format_preparedparamsdata(estate, ppd);
3973 : else
3974 1 : errdetail = NULL;
3975 :
3976 2 : ereport(ERROR,
3977 : (errcode(ERRCODE_NO_DATA_FOUND),
3978 : errmsg("query returned no rows"),
3979 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3980 : }
3981 : /* set the target to NULL(s) */
3982 0 : exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
3983 : }
3984 : else
3985 : {
3986 548 : if (n > 1 && stmt->strict)
3987 : {
3988 : char *errdetail;
3989 :
3990 3 : if (estate->func->print_strict_params)
3991 2 : errdetail = format_preparedparamsdata(estate, ppd);
3992 : else
3993 1 : errdetail = NULL;
3994 :
3995 3 : ereport(ERROR,
3996 : (errcode(ERRCODE_TOO_MANY_ROWS),
3997 : errmsg("query returned more than one row"),
3998 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3999 : }
4000 :
4001 : /* Put the first result row into the target */
4002 545 : exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
4003 : }
4004 : /* clean up after exec_move_row() */
4005 545 : exec_eval_cleanup(estate);
4006 : }
4007 : else
4008 : {
4009 : /*
4010 : * It might be a good idea to raise an error if the query returned
4011 : * tuples that are being ignored, but historically we have not done
4012 : * that.
4013 : */
4014 : }
4015 :
4016 : /* Release any result from SPI_execute, as well as transient data */
4017 564 : SPI_freetuptable(SPI_tuptable);
4018 564 : MemoryContextReset(stmt_mcontext);
4019 :
4020 564 : return PLPGSQL_RC_OK;
4021 : }
4022 :
4023 :
4024 : /* ----------
4025 : * exec_stmt_dynfors Execute a dynamic query, assign each
4026 : * tuple to a record or row and
4027 : * execute a group of statements
4028 : * for it.
4029 : * ----------
4030 : */
4031 : static int
4032 503 : exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
4033 : {
4034 : Portal portal;
4035 : int rc;
4036 :
4037 503 : portal = exec_dynquery_with_params(estate, stmt->query, stmt->params,
4038 : NULL, 0);
4039 :
4040 : /*
4041 : * Execute the loop
4042 : */
4043 503 : rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
4044 :
4045 : /*
4046 : * Close the implicit cursor
4047 : */
4048 503 : SPI_cursor_close(portal);
4049 :
4050 503 : return rc;
4051 : }
4052 :
4053 :
4054 : /* ----------
4055 : * exec_stmt_open Execute an OPEN cursor statement
4056 : * ----------
4057 : */
4058 : static int
4059 19 : exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
4060 : {
4061 : PLpgSQL_var *curvar;
4062 19 : MemoryContext stmt_mcontext = NULL;
4063 19 : char *curname = NULL;
4064 : PLpgSQL_expr *query;
4065 : Portal portal;
4066 : ParamListInfo paramLI;
4067 :
4068 : /* ----------
4069 : * Get the cursor variable and if it has an assigned name, check
4070 : * that it's not in use currently.
4071 : * ----------
4072 : */
4073 19 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4074 19 : if (!curvar->isnull)
4075 : {
4076 : MemoryContext oldcontext;
4077 :
4078 : /* We only need stmt_mcontext to hold the cursor name string */
4079 15 : stmt_mcontext = get_stmt_mcontext(estate);
4080 15 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
4081 15 : curname = TextDatumGetCString(curvar->value);
4082 15 : MemoryContextSwitchTo(oldcontext);
4083 :
4084 15 : if (SPI_cursor_find(curname) != NULL)
4085 0 : ereport(ERROR,
4086 : (errcode(ERRCODE_DUPLICATE_CURSOR),
4087 : errmsg("cursor \"%s\" already in use", curname)));
4088 : }
4089 :
4090 : /* ----------
4091 : * Process the OPEN according to it's type.
4092 : * ----------
4093 : */
4094 19 : if (stmt->query != NULL)
4095 : {
4096 : /* ----------
4097 : * This is an OPEN refcursor FOR SELECT ...
4098 : *
4099 : * We just make sure the query is planned. The real work is
4100 : * done downstairs.
4101 : * ----------
4102 : */
4103 4 : query = stmt->query;
4104 4 : if (query->plan == NULL)
4105 3 : exec_prepare_plan(estate, query, stmt->cursor_options);
4106 : }
4107 15 : else if (stmt->dynquery != NULL)
4108 : {
4109 : /* ----------
4110 : * This is an OPEN refcursor FOR EXECUTE ...
4111 : * ----------
4112 : */
4113 3 : portal = exec_dynquery_with_params(estate,
4114 : stmt->dynquery,
4115 : stmt->params,
4116 : curname,
4117 : stmt->cursor_options);
4118 :
4119 : /*
4120 : * If cursor variable was NULL, store the generated portal name in it.
4121 : * Note: exec_dynquery_with_params already reset the stmt_mcontext, so
4122 : * curname is a dangling pointer here; but testing it for nullness is
4123 : * OK.
4124 : */
4125 3 : if (curname == NULL)
4126 3 : assign_text_var(estate, curvar, portal->name);
4127 :
4128 3 : return PLPGSQL_RC_OK;
4129 : }
4130 : else
4131 : {
4132 : /* ----------
4133 : * This is an OPEN cursor
4134 : *
4135 : * Note: parser should already have checked that statement supplies
4136 : * args iff cursor needs them, but we check again to be safe.
4137 : * ----------
4138 : */
4139 12 : if (stmt->argquery != NULL)
4140 : {
4141 : /* ----------
4142 : * OPEN CURSOR with args. We fake a SELECT ... INTO ...
4143 : * statement to evaluate the args and put 'em into the
4144 : * internal row.
4145 : * ----------
4146 : */
4147 : PLpgSQL_stmt_execsql set_args;
4148 :
4149 8 : if (curvar->cursor_explicit_argrow < 0)
4150 0 : ereport(ERROR,
4151 : (errcode(ERRCODE_SYNTAX_ERROR),
4152 : errmsg("arguments given for cursor without arguments")));
4153 :
4154 8 : memset(&set_args, 0, sizeof(set_args));
4155 8 : set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
4156 8 : set_args.lineno = stmt->lineno;
4157 8 : set_args.sqlstmt = stmt->argquery;
4158 8 : set_args.into = true;
4159 : /* XXX historically this has not been STRICT */
4160 8 : set_args.row = (PLpgSQL_row *)
4161 8 : (estate->datums[curvar->cursor_explicit_argrow]);
4162 :
4163 8 : if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
4164 0 : elog(ERROR, "open cursor failed during argument processing");
4165 : }
4166 : else
4167 : {
4168 4 : if (curvar->cursor_explicit_argrow >= 0)
4169 0 : ereport(ERROR,
4170 : (errcode(ERRCODE_SYNTAX_ERROR),
4171 : errmsg("arguments required for cursor")));
4172 : }
4173 :
4174 11 : query = curvar->cursor_explicit_expr;
4175 11 : if (query->plan == NULL)
4176 9 : exec_prepare_plan(estate, query, curvar->cursor_options);
4177 : }
4178 :
4179 : /*
4180 : * Set up short-lived ParamListInfo
4181 : */
4182 15 : paramLI = setup_unshared_param_list(estate, query);
4183 :
4184 : /*
4185 : * Open the cursor
4186 : */
4187 15 : portal = SPI_cursor_open_with_paramlist(curname, query->plan,
4188 : paramLI,
4189 15 : estate->readonly_func);
4190 15 : if (portal == NULL)
4191 0 : elog(ERROR, "could not open cursor: %s",
4192 : SPI_result_code_string(SPI_result));
4193 :
4194 : /*
4195 : * If cursor variable was NULL, store the generated portal name in it
4196 : */
4197 15 : if (curname == NULL)
4198 1 : assign_text_var(estate, curvar, portal->name);
4199 :
4200 : /* If we had any transient data, clean it up */
4201 15 : exec_eval_cleanup(estate);
4202 15 : if (stmt_mcontext)
4203 14 : MemoryContextReset(stmt_mcontext);
4204 :
4205 15 : return PLPGSQL_RC_OK;
4206 : }
4207 :
4208 :
4209 : /* ----------
4210 : * exec_stmt_fetch Fetch from a cursor into a target, or just
4211 : * move the current position of the cursor
4212 : * ----------
4213 : */
4214 : static int
4215 56 : exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
4216 : {
4217 : PLpgSQL_var *curvar;
4218 56 : PLpgSQL_rec *rec = NULL;
4219 56 : PLpgSQL_row *row = NULL;
4220 56 : long how_many = stmt->how_many;
4221 : SPITupleTable *tuptab;
4222 : Portal portal;
4223 : char *curname;
4224 : uint64 n;
4225 : MemoryContext oldcontext;
4226 :
4227 : /* ----------
4228 : * Get the portal of the cursor by name
4229 : * ----------
4230 : */
4231 56 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4232 56 : if (curvar->isnull)
4233 0 : ereport(ERROR,
4234 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4235 : errmsg("cursor variable \"%s\" is null", curvar->refname)));
4236 :
4237 : /* Use eval_mcontext for short-lived string */
4238 56 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4239 56 : curname = TextDatumGetCString(curvar->value);
4240 56 : MemoryContextSwitchTo(oldcontext);
4241 :
4242 56 : portal = SPI_cursor_find(curname);
4243 56 : if (portal == NULL)
4244 0 : ereport(ERROR,
4245 : (errcode(ERRCODE_UNDEFINED_CURSOR),
4246 : errmsg("cursor \"%s\" does not exist", curname)));
4247 :
4248 : /* Calculate position for FETCH_RELATIVE or FETCH_ABSOLUTE */
4249 56 : if (stmt->expr)
4250 : {
4251 : bool isnull;
4252 :
4253 : /* XXX should be doing this in LONG not INT width */
4254 11 : how_many = exec_eval_integer(estate, stmt->expr, &isnull);
4255 :
4256 11 : if (isnull)
4257 0 : ereport(ERROR,
4258 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4259 : errmsg("relative or absolute cursor position is null")));
4260 :
4261 11 : exec_eval_cleanup(estate);
4262 : }
4263 :
4264 56 : if (!stmt->is_move)
4265 : {
4266 : /* ----------
4267 : * Determine if we fetch into a record or a row
4268 : * ----------
4269 : */
4270 49 : if (stmt->rec != NULL)
4271 16 : rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
4272 33 : else if (stmt->row != NULL)
4273 33 : row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
4274 : else
4275 0 : elog(ERROR, "unsupported target");
4276 :
4277 : /* ----------
4278 : * Fetch 1 tuple from the cursor
4279 : * ----------
4280 : */
4281 49 : SPI_scroll_cursor_fetch(portal, stmt->direction, how_many);
4282 48 : tuptab = SPI_tuptable;
4283 48 : n = SPI_processed;
4284 :
4285 : /* ----------
4286 : * Set the target appropriately.
4287 : * ----------
4288 : */
4289 48 : if (n == 0)
4290 8 : exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
4291 : else
4292 40 : exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
4293 :
4294 48 : exec_eval_cleanup(estate);
4295 48 : SPI_freetuptable(tuptab);
4296 : }
4297 : else
4298 : {
4299 : /* Move the cursor */
4300 7 : SPI_scroll_cursor_move(portal, stmt->direction, how_many);
4301 7 : n = SPI_processed;
4302 : }
4303 :
4304 : /* Set the ROW_COUNT and the global FOUND variable appropriately. */
4305 55 : estate->eval_processed = n;
4306 55 : exec_set_found(estate, n != 0);
4307 :
4308 55 : return PLPGSQL_RC_OK;
4309 : }
4310 :
4311 : /* ----------
4312 : * exec_stmt_close Close a cursor
4313 : * ----------
4314 : */
4315 : static int
4316 12 : exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
4317 : {
4318 : PLpgSQL_var *curvar;
4319 : Portal portal;
4320 : char *curname;
4321 : MemoryContext oldcontext;
4322 :
4323 : /* ----------
4324 : * Get the portal of the cursor by name
4325 : * ----------
4326 : */
4327 12 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4328 12 : if (curvar->isnull)
4329 0 : ereport(ERROR,
4330 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4331 : errmsg("cursor variable \"%s\" is null", curvar->refname)));
4332 :
4333 : /* Use eval_mcontext for short-lived string */
4334 12 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4335 12 : curname = TextDatumGetCString(curvar->value);
4336 12 : MemoryContextSwitchTo(oldcontext);
4337 :
4338 12 : portal = SPI_cursor_find(curname);
4339 12 : if (portal == NULL)
4340 0 : ereport(ERROR,
4341 : (errcode(ERRCODE_UNDEFINED_CURSOR),
4342 : errmsg("cursor \"%s\" does not exist", curname)));
4343 :
4344 : /* ----------
4345 : * And close it.
4346 : * ----------
4347 : */
4348 12 : SPI_cursor_close(portal);
4349 :
4350 12 : return PLPGSQL_RC_OK;
4351 : }
4352 :
4353 :
4354 : /* ----------
4355 : * exec_assign_expr Put an expression's result into a variable.
4356 : * ----------
4357 : */
4358 : static void
4359 2779 : exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
4360 : PLpgSQL_expr *expr)
4361 : {
4362 : Datum value;
4363 : bool isnull;
4364 : Oid valtype;
4365 : int32 valtypmod;
4366 :
4367 : /*
4368 : * If first time through, create a plan for this expression, and then see
4369 : * if we can pass the target variable as a read-write parameter to the
4370 : * expression. (This is a bit messy, but it seems cleaner than modifying
4371 : * the API of exec_eval_expr for the purpose.)
4372 : */
4373 2779 : if (expr->plan == NULL)
4374 : {
4375 273 : exec_prepare_plan(estate, expr, 0);
4376 273 : if (target->dtype == PLPGSQL_DTYPE_VAR)
4377 246 : exec_check_rw_parameter(expr, target->dno);
4378 : }
4379 :
4380 2779 : value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
4381 2762 : exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
4382 2748 : exec_eval_cleanup(estate);
4383 2748 : }
4384 :
4385 :
4386 : /* ----------
4387 : * exec_assign_c_string Put a C string into a text variable.
4388 : *
4389 : * We take a NULL pointer as signifying empty string, not SQL null.
4390 : *
4391 : * As with the underlying exec_assign_value, caller is expected to do
4392 : * exec_eval_cleanup later.
4393 : * ----------
4394 : */
4395 : static void
4396 19 : exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
4397 : const char *str)
4398 : {
4399 : text *value;
4400 : MemoryContext oldcontext;
4401 :
4402 : /* Use eval_mcontext for short-lived text value */
4403 19 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4404 19 : if (str != NULL)
4405 19 : value = cstring_to_text(str);
4406 : else
4407 0 : value = cstring_to_text("");
4408 19 : MemoryContextSwitchTo(oldcontext);
4409 :
4410 19 : exec_assign_value(estate, target, PointerGetDatum(value), false,
4411 : TEXTOID, -1);
4412 19 : }
4413 :
4414 :
4415 : /* ----------
4416 : * exec_assign_value Put a value into a target datum
4417 : *
4418 : * Note: in some code paths, this will leak memory in the eval_mcontext;
4419 : * we assume that will be cleaned up later by exec_eval_cleanup. We cannot
4420 : * call exec_eval_cleanup here for fear of destroying the input Datum value.
4421 : * ----------
4422 : */
4423 : static void
4424 6186 : exec_assign_value(PLpgSQL_execstate *estate,
4425 : PLpgSQL_datum *target,
4426 : Datum value, bool isNull,
4427 : Oid valtype, int32 valtypmod)
4428 : {
4429 6186 : switch (target->dtype)
4430 : {
4431 : case PLPGSQL_DTYPE_VAR:
4432 : {
4433 : /*
4434 : * Target is a variable
4435 : */
4436 6047 : PLpgSQL_var *var = (PLpgSQL_var *) target;
4437 : Datum newvalue;
4438 :
4439 12094 : newvalue = exec_cast_value(estate,
4440 : value,
4441 : &isNull,
4442 : valtype,
4443 : valtypmod,
4444 6047 : var->datatype->typoid,
4445 6047 : var->datatype->atttypmod);
4446 :
4447 6036 : if (isNull && var->notnull)
4448 1 : ereport(ERROR,
4449 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4450 : errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
4451 : var->refname)));
4452 :
4453 : /*
4454 : * If type is by-reference, copy the new value (which is
4455 : * probably in the eval_mcontext) into the procedure's main
4456 : * memory context. But if it's a read/write reference to an
4457 : * expanded object, no physical copy needs to happen; at most
4458 : * we need to reparent the object's memory context.
4459 : *
4460 : * If it's an array, we force the value to be stored in R/W
4461 : * expanded form. This wins if the function later does, say,
4462 : * a lot of array subscripting operations on the variable, and
4463 : * otherwise might lose. We might need to use a different
4464 : * heuristic, but it's too soon to tell. Also, are there
4465 : * cases where it'd be useful to force non-array values into
4466 : * expanded form?
4467 : */
4468 6035 : if (!var->datatype->typbyval && !isNull)
4469 : {
4470 4924 : if (var->datatype->typisarray &&
4471 830 : !VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(newvalue)))
4472 : {
4473 : /* array and not already R/W, so apply expand_array */
4474 818 : newvalue = expand_array(newvalue,
4475 : CurrentMemoryContext,
4476 : NULL);
4477 : }
4478 : else
4479 : {
4480 : /* else transfer value if R/W, else just datumCopy */
4481 3282 : newvalue = datumTransfer(newvalue,
4482 : false,
4483 3282 : var->datatype->typlen);
4484 : }
4485 : }
4486 :
4487 : /*
4488 : * Now free the old value, if any, and assign the new one. But
4489 : * skip the assignment if old and new values are the same.
4490 : * Note that for expanded objects, this test is necessary and
4491 : * cannot reliably be made any earlier; we have to be looking
4492 : * at the object's standard R/W pointer to be sure pointer
4493 : * equality is meaningful.
4494 : */
4495 6035 : if (var->value != newvalue || var->isnull || isNull)
4496 5860 : assign_simple_var(estate, var, newvalue, isNull,
4497 5860 : (!var->datatype->typbyval && !isNull));
4498 6035 : break;
4499 : }
4500 :
4501 : case PLPGSQL_DTYPE_ROW:
4502 : {
4503 : /*
4504 : * Target is a row variable
4505 : */
4506 9 : PLpgSQL_row *row = (PLpgSQL_row *) target;
4507 :
4508 9 : if (isNull)
4509 : {
4510 : /* If source is null, just assign nulls to the row */
4511 0 : exec_move_row(estate, NULL, row, NULL, NULL);
4512 : }
4513 : else
4514 : {
4515 : /* Source must be of RECORD or composite type */
4516 9 : if (!type_is_rowtype(valtype))
4517 0 : ereport(ERROR,
4518 : (errcode(ERRCODE_DATATYPE_MISMATCH),
4519 : errmsg("cannot assign non-composite value to a row variable")));
4520 9 : exec_move_row_from_datum(estate, NULL, row, value);
4521 : }
4522 9 : break;
4523 : }
4524 :
4525 : case PLPGSQL_DTYPE_REC:
4526 : {
4527 : /*
4528 : * Target is a record variable
4529 : */
4530 28 : PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
4531 :
4532 28 : if (isNull)
4533 : {
4534 : /* If source is null, just assign nulls to the record */
4535 0 : exec_move_row(estate, rec, NULL, NULL, NULL);
4536 : }
4537 : else
4538 : {
4539 : /* Source must be of RECORD or composite type */
4540 28 : if (!type_is_rowtype(valtype))
4541 0 : ereport(ERROR,
4542 : (errcode(ERRCODE_DATATYPE_MISMATCH),
4543 : errmsg("cannot assign non-composite value to a record variable")));
4544 28 : exec_move_row_from_datum(estate, rec, NULL, value);
4545 : }
4546 28 : break;
4547 : }
4548 :
4549 : case PLPGSQL_DTYPE_RECFIELD:
4550 : {
4551 : /*
4552 : * Target is a field of a record
4553 : */
4554 86 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) target;
4555 : PLpgSQL_rec *rec;
4556 : int fno;
4557 : HeapTuple newtup;
4558 : int colnums[1];
4559 : Datum values[1];
4560 : bool nulls[1];
4561 : Oid atttype;
4562 : int32 atttypmod;
4563 :
4564 86 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
4565 :
4566 : /*
4567 : * Check that there is already a tuple in the record. We need
4568 : * that because records don't have any predefined field
4569 : * structure.
4570 : */
4571 86 : if (!HeapTupleIsValid(rec->tup))
4572 0 : ereport(ERROR,
4573 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4574 : errmsg("record \"%s\" is not assigned yet",
4575 : rec->refname),
4576 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4577 :
4578 : /*
4579 : * Get the number of the record field to change. Disallow
4580 : * system columns because the code below won't cope.
4581 : */
4582 86 : fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
4583 86 : if (fno <= 0)
4584 0 : ereport(ERROR,
4585 : (errcode(ERRCODE_UNDEFINED_COLUMN),
4586 : errmsg("record \"%s\" has no field \"%s\"",
4587 : rec->refname, recfield->fieldname)));
4588 86 : colnums[0] = fno;
4589 :
4590 : /*
4591 : * Now insert the new value, being careful to cast it to the
4592 : * right type.
4593 : */
4594 86 : atttype = TupleDescAttr(rec->tupdesc, fno - 1)->atttypid;
4595 86 : atttypmod = TupleDescAttr(rec->tupdesc, fno - 1)->atttypmod;
4596 86 : values[0] = exec_cast_value(estate,
4597 : value,
4598 : &isNull,
4599 : valtype,
4600 : valtypmod,
4601 : atttype,
4602 : atttypmod);
4603 86 : nulls[0] = isNull;
4604 :
4605 86 : newtup = heap_modify_tuple_by_cols(rec->tup, rec->tupdesc,
4606 : 1, colnums, values, nulls);
4607 :
4608 86 : if (rec->freetup)
4609 10 : heap_freetuple(rec->tup);
4610 :
4611 86 : rec->tup = newtup;
4612 86 : rec->freetup = true;
4613 :
4614 86 : break;
4615 : }
4616 :
4617 : case PLPGSQL_DTYPE_ARRAYELEM:
4618 : {
4619 : /*
4620 : * Target is an element of an array
4621 : */
4622 : PLpgSQL_arrayelem *arrayelem;
4623 : int nsubscripts;
4624 : int i;
4625 : PLpgSQL_expr *subscripts[MAXDIM];
4626 : int subscriptvals[MAXDIM];
4627 : Datum oldarraydatum,
4628 : newarraydatum,
4629 : coerced_value;
4630 : bool oldarrayisnull;
4631 : Oid parenttypoid;
4632 : int32 parenttypmod;
4633 : SPITupleTable *save_eval_tuptable;
4634 : MemoryContext oldcontext;
4635 :
4636 : /*
4637 : * We need to do subscript evaluation, which might require
4638 : * evaluating general expressions; and the caller might have
4639 : * done that too in order to prepare the input Datum. We have
4640 : * to save and restore the caller's SPI_execute result, if
4641 : * any.
4642 : */
4643 16 : save_eval_tuptable = estate->eval_tuptable;
4644 16 : estate->eval_tuptable = NULL;
4645 :
4646 : /*
4647 : * To handle constructs like x[1][2] := something, we have to
4648 : * be prepared to deal with a chain of arrayelem datums. Chase
4649 : * back to find the base array datum, and save the subscript
4650 : * expressions as we go. (We are scanning right to left here,
4651 : * but want to evaluate the subscripts left-to-right to
4652 : * minimize surprises.) Note that arrayelem is left pointing
4653 : * to the leftmost arrayelem datum, where we will cache the
4654 : * array element type data.
4655 : */
4656 16 : nsubscripts = 0;
4657 : do
4658 : {
4659 17 : arrayelem = (PLpgSQL_arrayelem *) target;
4660 17 : if (nsubscripts >= MAXDIM)
4661 0 : ereport(ERROR,
4662 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
4663 : errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
4664 : nsubscripts + 1, MAXDIM)));
4665 17 : subscripts[nsubscripts++] = arrayelem->subscript;
4666 17 : target = estate->datums[arrayelem->arrayparentno];
4667 17 : } while (target->dtype == PLPGSQL_DTYPE_ARRAYELEM);
4668 :
4669 : /* Fetch current value of array datum */
4670 16 : exec_eval_datum(estate, target,
4671 : &parenttypoid, &parenttypmod,
4672 : &oldarraydatum, &oldarrayisnull);
4673 :
4674 : /* Update cached type data if necessary */
4675 23 : if (arrayelem->parenttypoid != parenttypoid ||
4676 7 : arrayelem->parenttypmod != parenttypmod)
4677 : {
4678 : Oid arraytypoid;
4679 9 : int32 arraytypmod = parenttypmod;
4680 : int16 arraytyplen;
4681 : Oid elemtypoid;
4682 : int16 elemtyplen;
4683 : bool elemtypbyval;
4684 : char elemtypalign;
4685 :
4686 : /* If target is domain over array, reduce to base type */
4687 9 : arraytypoid = getBaseTypeAndTypmod(parenttypoid,
4688 : &arraytypmod);
4689 :
4690 : /* ... and identify the element type */
4691 9 : elemtypoid = get_element_type(arraytypoid);
4692 9 : if (!OidIsValid(elemtypoid))
4693 0 : ereport(ERROR,
4694 : (errcode(ERRCODE_DATATYPE_MISMATCH),
4695 : errmsg("subscripted object is not an array")));
4696 :
4697 : /* Collect needed data about the types */
4698 9 : arraytyplen = get_typlen(arraytypoid);
4699 :
4700 9 : get_typlenbyvalalign(elemtypoid,
4701 : &elemtyplen,
4702 : &elemtypbyval,
4703 : &elemtypalign);
4704 :
4705 : /* Now safe to update the cached data */
4706 9 : arrayelem->parenttypoid = parenttypoid;
4707 9 : arrayelem->parenttypmod = parenttypmod;
4708 9 : arrayelem->arraytypoid = arraytypoid;
4709 9 : arrayelem->arraytypmod = arraytypmod;
4710 9 : arrayelem->arraytyplen = arraytyplen;
4711 9 : arrayelem->elemtypoid = elemtypoid;
4712 9 : arrayelem->elemtyplen = elemtyplen;
4713 9 : arrayelem->elemtypbyval = elemtypbyval;
4714 9 : arrayelem->elemtypalign = elemtypalign;
4715 : }
4716 :
4717 : /*
4718 : * Evaluate the subscripts, switch into left-to-right order.
4719 : * Like the expression built by ExecInitArrayRef(), complain
4720 : * if any subscript is null.
4721 : */
4722 33 : for (i = 0; i < nsubscripts; i++)
4723 : {
4724 : bool subisnull;
4725 :
4726 17 : subscriptvals[i] =
4727 17 : exec_eval_integer(estate,
4728 17 : subscripts[nsubscripts - 1 - i],
4729 : &subisnull);
4730 17 : if (subisnull)
4731 0 : ereport(ERROR,
4732 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4733 : errmsg("array subscript in assignment must not be null")));
4734 :
4735 : /*
4736 : * Clean up in case the subscript expression wasn't
4737 : * simple. We can't do exec_eval_cleanup, but we can do
4738 : * this much (which is safe because the integer subscript
4739 : * value is surely pass-by-value), and we must do it in
4740 : * case the next subscript expression isn't simple either.
4741 : */
4742 17 : if (estate->eval_tuptable != NULL)
4743 2 : SPI_freetuptable(estate->eval_tuptable);
4744 17 : estate->eval_tuptable = NULL;
4745 : }
4746 :
4747 : /* Now we can restore caller's SPI_execute result if any. */
4748 16 : Assert(estate->eval_tuptable == NULL);
4749 16 : estate->eval_tuptable = save_eval_tuptable;
4750 :
4751 : /* Coerce source value to match array element type. */
4752 16 : coerced_value = exec_cast_value(estate,
4753 : value,
4754 : &isNull,
4755 : valtype,
4756 : valtypmod,
4757 : arrayelem->elemtypoid,
4758 : arrayelem->arraytypmod);
4759 :
4760 : /*
4761 : * If the original array is null, cons up an empty array so
4762 : * that the assignment can proceed; we'll end with a
4763 : * one-element array containing just the assigned-to
4764 : * subscript. This only works for varlena arrays, though; for
4765 : * fixed-length array types we skip the assignment. We can't
4766 : * support assignment of a null entry into a fixed-length
4767 : * array, either, so that's a no-op too. This is all ugly but
4768 : * corresponds to the current behavior of execExpr*.c.
4769 : */
4770 13 : if (arrayelem->arraytyplen > 0 && /* fixed-length array? */
4771 0 : (oldarrayisnull || isNull))
4772 6169 : return;
4773 :
4774 : /* empty array, if any, and newarraydatum are short-lived */
4775 13 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4776 :
4777 13 : if (oldarrayisnull)
4778 4 : oldarraydatum = PointerGetDatum(construct_empty_array(arrayelem->elemtypoid));
4779 :
4780 : /*
4781 : * Build the modified array value.
4782 : */
4783 52 : newarraydatum = array_set_element(oldarraydatum,
4784 : nsubscripts,
4785 : subscriptvals,
4786 : coerced_value,
4787 : isNull,
4788 13 : arrayelem->arraytyplen,
4789 13 : arrayelem->elemtyplen,
4790 13 : arrayelem->elemtypbyval,
4791 13 : arrayelem->elemtypalign);
4792 :
4793 13 : MemoryContextSwitchTo(oldcontext);
4794 :
4795 : /*
4796 : * Assign the new array to the base variable. It's never NULL
4797 : * at this point. Note that if the target is a domain,
4798 : * coercing the base array type back up to the domain will
4799 : * happen within exec_assign_value.
4800 : */
4801 13 : exec_assign_value(estate, target,
4802 : newarraydatum,
4803 : false,
4804 : arrayelem->arraytypoid,
4805 : arrayelem->arraytypmod);
4806 11 : break;
4807 : }
4808 :
4809 : default:
4810 0 : elog(ERROR, "unrecognized dtype: %d", target->dtype);
4811 : }
4812 : }
4813 :
4814 : /*
4815 : * exec_eval_datum Get current value of a PLpgSQL_datum
4816 : *
4817 : * The type oid, typmod, value in Datum format, and null flag are returned.
4818 : *
4819 : * At present this doesn't handle PLpgSQL_expr or PLpgSQL_arrayelem datums;
4820 : * that's not needed because we never pass references to such datums to SPI.
4821 : *
4822 : * NOTE: the returned Datum points right at the stored value in the case of
4823 : * pass-by-reference datatypes. Generally callers should take care not to
4824 : * modify the stored value. Some callers intentionally manipulate variables
4825 : * referenced by R/W expanded pointers, though; it is those callers'
4826 : * responsibility that the results are semantically OK.
4827 : *
4828 : * In some cases we have to palloc a return value, and in such cases we put
4829 : * it into the estate's eval_mcontext.
4830 : */
4831 : static void
4832 5796 : exec_eval_datum(PLpgSQL_execstate *estate,
4833 : PLpgSQL_datum *datum,
4834 : Oid *typeid,
4835 : int32 *typetypmod,
4836 : Datum *value,
4837 : bool *isnull)
4838 : {
4839 : MemoryContext oldcontext;
4840 :
4841 5796 : switch (datum->dtype)
4842 : {
4843 : case PLPGSQL_DTYPE_VAR:
4844 : {
4845 205 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
4846 :
4847 205 : *typeid = var->datatype->typoid;
4848 205 : *typetypmod = var->datatype->atttypmod;
4849 205 : *value = var->value;
4850 205 : *isnull = var->isnull;
4851 205 : break;
4852 : }
4853 :
4854 : case PLPGSQL_DTYPE_ROW:
4855 : {
4856 45 : PLpgSQL_row *row = (PLpgSQL_row *) datum;
4857 : HeapTuple tup;
4858 :
4859 45 : if (!row->rowtupdesc) /* should not happen */
4860 0 : elog(ERROR, "row variable has no tupdesc");
4861 : /* Make sure we have a valid type/typmod setting */
4862 45 : BlessTupleDesc(row->rowtupdesc);
4863 45 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4864 45 : tup = make_tuple_from_row(estate, row, row->rowtupdesc);
4865 45 : if (tup == NULL) /* should not happen */
4866 0 : elog(ERROR, "row not compatible with its own tupdesc");
4867 45 : *typeid = row->rowtupdesc->tdtypeid;
4868 45 : *typetypmod = row->rowtupdesc->tdtypmod;
4869 45 : *value = HeapTupleGetDatum(tup);
4870 45 : *isnull = false;
4871 45 : MemoryContextSwitchTo(oldcontext);
4872 45 : break;
4873 : }
4874 :
4875 : case PLPGSQL_DTYPE_REC:
4876 : {
4877 105 : PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
4878 :
4879 105 : if (!HeapTupleIsValid(rec->tup))
4880 0 : ereport(ERROR,
4881 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4882 : errmsg("record \"%s\" is not assigned yet",
4883 : rec->refname),
4884 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4885 105 : Assert(rec->tupdesc != NULL);
4886 : /* Make sure we have a valid type/typmod setting */
4887 105 : BlessTupleDesc(rec->tupdesc);
4888 :
4889 105 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4890 105 : *typeid = rec->tupdesc->tdtypeid;
4891 105 : *typetypmod = rec->tupdesc->tdtypmod;
4892 105 : *value = heap_copy_tuple_as_datum(rec->tup, rec->tupdesc);
4893 105 : *isnull = false;
4894 105 : MemoryContextSwitchTo(oldcontext);
4895 105 : break;
4896 : }
4897 :
4898 : case PLPGSQL_DTYPE_RECFIELD:
4899 : {
4900 5441 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
4901 : PLpgSQL_rec *rec;
4902 : int fno;
4903 :
4904 5441 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
4905 5441 : if (!HeapTupleIsValid(rec->tup))
4906 0 : ereport(ERROR,
4907 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4908 : errmsg("record \"%s\" is not assigned yet",
4909 : rec->refname),
4910 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4911 5441 : fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
4912 5441 : if (fno == SPI_ERROR_NOATTRIBUTE)
4913 0 : ereport(ERROR,
4914 : (errcode(ERRCODE_UNDEFINED_COLUMN),
4915 : errmsg("record \"%s\" has no field \"%s\"",
4916 : rec->refname, recfield->fieldname)));
4917 5441 : *typeid = SPI_gettypeid(rec->tupdesc, fno);
4918 5441 : if (fno > 0)
4919 : {
4920 5441 : Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1);
4921 :
4922 5441 : *typetypmod = attr->atttypmod;
4923 : }
4924 : else
4925 0 : *typetypmod = -1;
4926 5441 : *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
4927 5441 : break;
4928 : }
4929 :
4930 : default:
4931 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
4932 : }
4933 5796 : }
4934 :
4935 : /*
4936 : * plpgsql_exec_get_datum_type Get datatype of a PLpgSQL_datum
4937 : *
4938 : * This is the same logic as in exec_eval_datum, except that it can handle
4939 : * some cases where exec_eval_datum has to fail; specifically, we may have
4940 : * a tupdesc but no row value for a record variable. (This currently can
4941 : * happen only for a trigger's NEW/OLD records.)
4942 : */
4943 : Oid
4944 10 : plpgsql_exec_get_datum_type(PLpgSQL_execstate *estate,
4945 : PLpgSQL_datum *datum)
4946 : {
4947 : Oid typeid;
4948 :
4949 10 : switch (datum->dtype)
4950 : {
4951 : case PLPGSQL_DTYPE_VAR:
4952 : {
4953 10 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
4954 :
4955 10 : typeid = var->datatype->typoid;
4956 10 : break;
4957 : }
4958 :
4959 : case PLPGSQL_DTYPE_ROW:
4960 : {
4961 0 : PLpgSQL_row *row = (PLpgSQL_row *) datum;
4962 :
4963 0 : if (!row->rowtupdesc) /* should not happen */
4964 0 : elog(ERROR, "row variable has no tupdesc");
4965 : /* Make sure we have a valid type/typmod setting */
4966 0 : BlessTupleDesc(row->rowtupdesc);
4967 0 : typeid = row->rowtupdesc->tdtypeid;
4968 0 : break;
4969 : }
4970 :
4971 : case PLPGSQL_DTYPE_REC:
4972 : {
4973 0 : PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
4974 :
4975 0 : if (rec->tupdesc == NULL)
4976 0 : ereport(ERROR,
4977 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4978 : errmsg("record \"%s\" is not assigned yet",
4979 : rec->refname),
4980 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4981 : /* Make sure we have a valid type/typmod setting */
4982 0 : BlessTupleDesc(rec->tupdesc);
4983 0 : typeid = rec->tupdesc->tdtypeid;
4984 0 : break;
4985 : }
4986 :
4987 : case PLPGSQL_DTYPE_RECFIELD:
4988 : {
4989 0 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
4990 : PLpgSQL_rec *rec;
4991 : int fno;
4992 :
4993 0 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
4994 0 : if (rec->tupdesc == NULL)
4995 0 : ereport(ERROR,
4996 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4997 : errmsg("record \"%s\" is not assigned yet",
4998 : rec->refname),
4999 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
5000 0 : fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
5001 0 : if (fno == SPI_ERROR_NOATTRIBUTE)
5002 0 : ereport(ERROR,
5003 : (errcode(ERRCODE_UNDEFINED_COLUMN),
5004 : errmsg("record \"%s\" has no field \"%s\"",
5005 : rec->refname, recfield->fieldname)));
5006 0 : typeid = SPI_gettypeid(rec->tupdesc, fno);
5007 0 : break;
5008 : }
5009 :
5010 : default:
5011 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5012 : typeid = InvalidOid; /* keep compiler quiet */
5013 : break;
5014 : }
5015 :
5016 10 : return typeid;
5017 : }
5018 :
5019 : /*
5020 : * plpgsql_exec_get_datum_type_info Get datatype etc of a PLpgSQL_datum
5021 : *
5022 : * An extended version of plpgsql_exec_get_datum_type, which also retrieves the
5023 : * typmod and collation of the datum.
5024 : */
5025 : void
5026 1911 : plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate,
5027 : PLpgSQL_datum *datum,
5028 : Oid *typeid, int32 *typmod, Oid *collation)
5029 : {
5030 1911 : switch (datum->dtype)
5031 : {
5032 : case PLPGSQL_DTYPE_VAR:
5033 : {
5034 1395 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
5035 :
5036 1395 : *typeid = var->datatype->typoid;
5037 1395 : *typmod = var->datatype->atttypmod;
5038 1395 : *collation = var->datatype->collation;
5039 1395 : break;
5040 : }
5041 :
5042 : case PLPGSQL_DTYPE_ROW:
5043 : {
5044 5 : PLpgSQL_row *row = (PLpgSQL_row *) datum;
5045 :
5046 5 : if (!row->rowtupdesc) /* should not happen */
5047 0 : elog(ERROR, "row variable has no tupdesc");
5048 : /* Make sure we have a valid type/typmod setting */
5049 5 : BlessTupleDesc(row->rowtupdesc);
5050 5 : *typeid = row->rowtupdesc->tdtypeid;
5051 : /* do NOT return the mutable typmod of a RECORD variable */
5052 5 : *typmod = -1;
5053 : /* composite types are never collatable */
5054 5 : *collation = InvalidOid;
5055 5 : break;
5056 : }
5057 :
5058 : case PLPGSQL_DTYPE_REC:
5059 : {
5060 25 : PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5061 :
5062 25 : if (rec->tupdesc == NULL)
5063 0 : ereport(ERROR,
5064 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
5065 : errmsg("record \"%s\" is not assigned yet",
5066 : rec->refname),
5067 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
5068 : /* Make sure we have a valid type/typmod setting */
5069 25 : BlessTupleDesc(rec->tupdesc);
5070 25 : *typeid = rec->tupdesc->tdtypeid;
5071 : /* do NOT return the mutable typmod of a RECORD variable */
5072 25 : *typmod = -1;
5073 : /* composite types are never collatable */
5074 25 : *collation = InvalidOid;
5075 25 : break;
5076 : }
5077 :
5078 : case PLPGSQL_DTYPE_RECFIELD:
5079 : {
5080 486 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
5081 : PLpgSQL_rec *rec;
5082 : int fno;
5083 :
5084 486 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5085 486 : if (rec->tupdesc == NULL)
5086 0 : ereport(ERROR,
5087 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
5088 : errmsg("record \"%s\" is not assigned yet",
5089 : rec->refname),
5090 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
5091 486 : fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
5092 486 : if (fno == SPI_ERROR_NOATTRIBUTE)
5093 0 : ereport(ERROR,
5094 : (errcode(ERRCODE_UNDEFINED_COLUMN),
5095 : errmsg("record \"%s\" has no field \"%s\"",
5096 : rec->refname, recfield->fieldname)));
5097 486 : *typeid = SPI_gettypeid(rec->tupdesc, fno);
5098 486 : if (fno > 0)
5099 : {
5100 486 : Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1);
5101 :
5102 486 : *typmod = attr->atttypmod;
5103 : }
5104 : else
5105 0 : *typmod = -1;
5106 486 : if (fno > 0)
5107 : {
5108 486 : Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1);
5109 :
5110 486 : *collation = attr->attcollation;
5111 : }
5112 : else /* no system column types have collation */
5113 0 : *collation = InvalidOid;
5114 486 : break;
5115 : }
5116 :
5117 : default:
5118 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5119 : *typeid = InvalidOid; /* keep compiler quiet */
5120 : *typmod = -1;
5121 : *collation = InvalidOid;
5122 : break;
5123 : }
5124 1911 : }
5125 :
5126 : /* ----------
5127 : * exec_eval_integer Evaluate an expression, coerce result to int4
5128 : *
5129 : * Note we do not do exec_eval_cleanup here; the caller must do it at
5130 : * some later point. (We do this because the caller may be holding the
5131 : * results of other, pass-by-reference, expression evaluations, such as
5132 : * an array value to be subscripted.)
5133 : * ----------
5134 : */
5135 : static int
5136 28 : exec_eval_integer(PLpgSQL_execstate *estate,
5137 : PLpgSQL_expr *expr,
5138 : bool *isNull)
5139 : {
5140 : Datum exprdatum;
5141 : Oid exprtypeid;
5142 : int32 exprtypmod;
5143 :
5144 28 : exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5145 28 : exprdatum = exec_cast_value(estate, exprdatum, isNull,
5146 : exprtypeid, exprtypmod,
5147 : INT4OID, -1);
5148 28 : return DatumGetInt32(exprdatum);
5149 : }
5150 :
5151 : /* ----------
5152 : * exec_eval_boolean Evaluate an expression, coerce result to bool
5153 : *
5154 : * Note we do not do exec_eval_cleanup here; the caller must do it at
5155 : * some later point.
5156 : * ----------
5157 : */
5158 : static bool
5159 14819 : exec_eval_boolean(PLpgSQL_execstate *estate,
5160 : PLpgSQL_expr *expr,
5161 : bool *isNull)
5162 : {
5163 : Datum exprdatum;
5164 : Oid exprtypeid;
5165 : int32 exprtypmod;
5166 :
5167 14819 : exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5168 14819 : exprdatum = exec_cast_value(estate, exprdatum, isNull,
5169 : exprtypeid, exprtypmod,
5170 : BOOLOID, -1);
5171 14819 : return DatumGetBool(exprdatum);
5172 : }
5173 :
5174 : /* ----------
5175 : * exec_eval_expr Evaluate an expression and return
5176 : * the result Datum, along with data type/typmod.
5177 : *
5178 : * NOTE: caller must do exec_eval_cleanup when done with the Datum.
5179 : * ----------
5180 : */
5181 : static Datum
5182 27855 : exec_eval_expr(PLpgSQL_execstate *estate,
5183 : PLpgSQL_expr *expr,
5184 : bool *isNull,
5185 : Oid *rettype,
5186 : int32 *rettypmod)
5187 : {
5188 27855 : Datum result = 0;
5189 : int rc;
5190 : Form_pg_attribute attr;
5191 :
5192 : /*
5193 : * If first time through, create a plan for this expression.
5194 : */
5195 27855 : if (expr->plan == NULL)
5196 1101 : exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
5197 :
5198 : /*
5199 : * If this is a simple expression, bypass SPI and use the executor
5200 : * directly
5201 : */
5202 27851 : if (exec_eval_simple_expr(estate, expr,
5203 : &result, isNull, rettype, rettypmod))
5204 27127 : return result;
5205 :
5206 : /*
5207 : * Else do it the hard way via exec_run_select
5208 : */
5209 703 : rc = exec_run_select(estate, expr, 2, NULL);
5210 701 : if (rc != SPI_OK_SELECT)
5211 0 : ereport(ERROR,
5212 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5213 : errmsg("query \"%s\" did not return data", expr->query)));
5214 :
5215 : /*
5216 : * Check that the expression returns exactly one column...
5217 : */
5218 701 : if (estate->eval_tuptable->tupdesc->natts != 1)
5219 0 : ereport(ERROR,
5220 : (errcode(ERRCODE_SYNTAX_ERROR),
5221 : errmsg_plural("query \"%s\" returned %d column",
5222 : "query \"%s\" returned %d columns",
5223 : estate->eval_tuptable->tupdesc->natts,
5224 : expr->query,
5225 : estate->eval_tuptable->tupdesc->natts)));
5226 :
5227 : /*
5228 : * ... and get the column's datatype.
5229 : */
5230 701 : attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0);
5231 701 : *rettype = attr->atttypid;
5232 701 : *rettypmod = attr->atttypmod;
5233 :
5234 : /*
5235 : * If there are no rows selected, the result is a NULL of that type.
5236 : */
5237 701 : if (estate->eval_processed == 0)
5238 : {
5239 0 : *isNull = true;
5240 0 : return (Datum) 0;
5241 : }
5242 :
5243 : /*
5244 : * Check that the expression returned no more than one row.
5245 : */
5246 701 : if (estate->eval_processed != 1)
5247 0 : ereport(ERROR,
5248 : (errcode(ERRCODE_CARDINALITY_VIOLATION),
5249 : errmsg("query \"%s\" returned more than one row",
5250 : expr->query)));
5251 :
5252 : /*
5253 : * Return the single result Datum.
5254 : */
5255 701 : return SPI_getbinval(estate->eval_tuptable->vals[0],
5256 701 : estate->eval_tuptable->tupdesc, 1, isNull);
5257 : }
5258 :
5259 :
5260 : /* ----------
5261 : * exec_run_select Execute a select query
5262 : * ----------
5263 : */
5264 : static int
5265 1130 : exec_run_select(PLpgSQL_execstate *estate,
5266 : PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
5267 : {
5268 : ParamListInfo paramLI;
5269 : int rc;
5270 :
5271 : /*
5272 : * On the first call for this expression generate the plan.
5273 : *
5274 : * If we don't need to return a portal, then we're just going to execute
5275 : * the query once, which means it's OK to use a parallel plan, even if the
5276 : * number of rows being fetched is limited. If we do need to return a
5277 : * portal, the caller might do cursor operations, which parallel query
5278 : * can't support.
5279 : */
5280 1130 : if (expr->plan == NULL)
5281 54 : exec_prepare_plan(estate, expr,
5282 : portalP == NULL ? CURSOR_OPT_PARALLEL_OK : 0);
5283 :
5284 : /*
5285 : * If a portal was requested, put the query into the portal
5286 : */
5287 1125 : if (portalP != NULL)
5288 : {
5289 : /*
5290 : * Set up short-lived ParamListInfo
5291 : */
5292 189 : paramLI = setup_unshared_param_list(estate, expr);
5293 :
5294 189 : *portalP = SPI_cursor_open_with_paramlist(NULL, expr->plan,
5295 : paramLI,
5296 189 : estate->readonly_func);
5297 189 : if (*portalP == NULL)
5298 0 : elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
5299 : expr->query, SPI_result_code_string(SPI_result));
5300 189 : exec_eval_cleanup(estate);
5301 189 : return SPI_OK_CURSOR;
5302 : }
5303 :
5304 : /*
5305 : * Set up ParamListInfo to pass to executor
5306 : */
5307 936 : paramLI = setup_param_list(estate, expr);
5308 :
5309 : /*
5310 : * Execute the query
5311 : */
5312 936 : rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
5313 936 : estate->readonly_func, maxtuples);
5314 729 : if (rc != SPI_OK_SELECT)
5315 0 : ereport(ERROR,
5316 : (errcode(ERRCODE_SYNTAX_ERROR),
5317 : errmsg("query \"%s\" is not a SELECT", expr->query)));
5318 :
5319 : /* Save query results for eventual cleanup */
5320 729 : Assert(estate->eval_tuptable == NULL);
5321 729 : estate->eval_tuptable = SPI_tuptable;
5322 729 : estate->eval_processed = SPI_processed;
5323 729 : estate->eval_lastoid = SPI_lastoid;
5324 :
5325 729 : return rc;
5326 : }
5327 :
5328 :
5329 : /*
5330 : * exec_for_query --- execute body of FOR loop for each row from a portal
5331 : *
5332 : * Used by exec_stmt_fors, exec_stmt_forc and exec_stmt_dynfors
5333 : */
5334 : static int
5335 681 : exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
5336 : Portal portal, bool prefetch_ok)
5337 : {
5338 681 : PLpgSQL_rec *rec = NULL;
5339 681 : PLpgSQL_row *row = NULL;
5340 : SPITupleTable *tuptab;
5341 681 : bool found = false;
5342 681 : int rc = PLPGSQL_RC_OK;
5343 : uint64 n;
5344 :
5345 : /*
5346 : * Determine if we assign to a record or a row
5347 : */
5348 681 : if (stmt->rec != NULL)
5349 42 : rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
5350 639 : else if (stmt->row != NULL)
5351 639 : row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
5352 : else
5353 0 : elog(ERROR, "unsupported target");
5354 :
5355 : /*
5356 : * Make sure the portal doesn't get closed by the user statements we
5357 : * execute.
5358 : */
5359 681 : PinPortal(portal);
5360 :
5361 : /*
5362 : * Fetch the initial tuple(s). If prefetching is allowed then we grab a
5363 : * few more rows to avoid multiple trips through executor startup
5364 : * overhead.
5365 : */
5366 681 : SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1);
5367 681 : tuptab = SPI_tuptable;
5368 681 : n = SPI_processed;
5369 :
5370 : /*
5371 : * If the query didn't return any rows, set the target to NULL and fall
5372 : * through with found = false.
5373 : */
5374 681 : if (n == 0)
5375 : {
5376 5 : exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
5377 5 : exec_eval_cleanup(estate);
5378 : }
5379 : else
5380 676 : found = true; /* processed at least one tuple */
5381 :
5382 : /*
5383 : * Now do the loop
5384 : */
5385 2063 : while (n > 0)
5386 : {
5387 : uint64 i;
5388 :
5389 3525 : for (i = 0; i < n; i++)
5390 : {
5391 : /*
5392 : * Assign the tuple to the target
5393 : */
5394 2824 : exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);
5395 2824 : exec_eval_cleanup(estate);
5396 :
5397 : /*
5398 : * Execute the statements
5399 : */
5400 2824 : rc = exec_stmts(estate, stmt->body);
5401 :
5402 2821 : if (rc != PLPGSQL_RC_OK)
5403 : {
5404 38 : if (rc == PLPGSQL_RC_EXIT)
5405 : {
5406 0 : if (estate->exitlabel == NULL)
5407 : {
5408 : /* unlabelled exit, so exit the current loop */
5409 0 : rc = PLPGSQL_RC_OK;
5410 : }
5411 0 : else if (stmt->label != NULL &&
5412 0 : strcmp(stmt->label, estate->exitlabel) == 0)
5413 : {
5414 : /* label matches this loop, so exit loop */
5415 0 : estate->exitlabel = NULL;
5416 0 : rc = PLPGSQL_RC_OK;
5417 : }
5418 :
5419 : /*
5420 : * otherwise, we processed a labelled exit that does not
5421 : * match the current statement's label, if any; return
5422 : * RC_EXIT so that the EXIT continues to recurse upward.
5423 : */
5424 : }
5425 38 : else if (rc == PLPGSQL_RC_CONTINUE)
5426 : {
5427 38 : if (estate->exitlabel == NULL)
5428 : {
5429 : /* unlabelled continue, so re-run the current loop */
5430 38 : rc = PLPGSQL_RC_OK;
5431 38 : continue;
5432 : }
5433 0 : else if (stmt->label != NULL &&
5434 0 : strcmp(stmt->label, estate->exitlabel) == 0)
5435 : {
5436 : /* label matches this loop, so re-run loop */
5437 0 : estate->exitlabel = NULL;
5438 0 : rc = PLPGSQL_RC_OK;
5439 0 : continue;
5440 : }
5441 :
5442 : /*
5443 : * otherwise, we process a labelled continue that does not
5444 : * match the current statement's label, if any; return
5445 : * RC_CONTINUE so that the CONTINUE will propagate up the
5446 : * stack.
5447 : */
5448 : }
5449 :
5450 : /*
5451 : * We're aborting the loop. Need a goto to get out of two
5452 : * levels of loop...
5453 : */
5454 0 : goto loop_exit;
5455 : }
5456 : }
5457 :
5458 701 : SPI_freetuptable(tuptab);
5459 :
5460 : /*
5461 : * Fetch more tuples. If prefetching is allowed, grab 50 at a time.
5462 : */
5463 701 : SPI_cursor_fetch(portal, true, prefetch_ok ? 50 : 1);
5464 701 : tuptab = SPI_tuptable;
5465 701 : n = SPI_processed;
5466 : }
5467 :
5468 : loop_exit:
5469 :
5470 : /*
5471 : * Release last group of tuples (if any)
5472 : */
5473 678 : SPI_freetuptable(tuptab);
5474 :
5475 678 : UnpinPortal(portal);
5476 :
5477 : /*
5478 : * Set the FOUND variable to indicate the result of executing the loop
5479 : * (namely, whether we looped one or more times). This must be set last so
5480 : * that it does not interfere with the value of the FOUND variable inside
5481 : * the loop processing itself.
5482 : */
5483 678 : exec_set_found(estate, found);
5484 :
5485 678 : return rc;
5486 : }
5487 :
5488 :
5489 : /* ----------
5490 : * exec_eval_simple_expr - Evaluate a simple expression returning
5491 : * a Datum by directly calling ExecEvalExpr().
5492 : *
5493 : * If successful, store results into *result, *isNull, *rettype, *rettypmod
5494 : * and return TRUE. If the expression cannot be handled by simple evaluation,
5495 : * return FALSE.
5496 : *
5497 : * Because we only store one execution tree for a simple expression, we
5498 : * can't handle recursion cases. So, if we see the tree is already busy
5499 : * with an evaluation in the current xact, we just return FALSE and let the
5500 : * caller run the expression the hard way. (Other alternatives such as
5501 : * creating a new tree for a recursive call either introduce memory leaks,
5502 : * or add enough bookkeeping to be doubtful wins anyway.) Another case that
5503 : * is covered by the expr_simple_in_use test is where a previous execution
5504 : * of the tree was aborted by an error: the tree may contain bogus state
5505 : * so we dare not re-use it.
5506 : *
5507 : * It is possible that we'd need to replan a simple expression; for example,
5508 : * someone might redefine a SQL function that had been inlined into the simple
5509 : * expression. That cannot cause a simple expression to become non-simple (or
5510 : * vice versa), but we do have to handle replacing the expression tree.
5511 : * Fortunately it's normally inexpensive to call SPI_plan_get_cached_plan for
5512 : * a simple expression.
5513 : *
5514 : * Note: if pass-by-reference, the result is in the eval_mcontext.
5515 : * It will be freed when exec_eval_cleanup is done.
5516 : * ----------
5517 : */
5518 : static bool
5519 27851 : exec_eval_simple_expr(PLpgSQL_execstate *estate,
5520 : PLpgSQL_expr *expr,
5521 : Datum *result,
5522 : bool *isNull,
5523 : Oid *rettype,
5524 : int32 *rettypmod)
5525 : {
5526 27851 : ExprContext *econtext = estate->eval_econtext;
5527 27851 : LocalTransactionId curlxid = MyProc->lxid;
5528 : CachedPlan *cplan;
5529 : ParamListInfo paramLI;
5530 : void *save_setup_arg;
5531 : MemoryContext oldcontext;
5532 :
5533 : /*
5534 : * Forget it if expression wasn't simple before.
5535 : */
5536 27851 : if (expr->expr_simple_expr == NULL)
5537 684 : return false;
5538 :
5539 : /*
5540 : * If expression is in use in current xact, don't touch it.
5541 : */
5542 27167 : if (expr->expr_simple_in_use && expr->expr_simple_lxid == curlxid)
5543 19 : return false;
5544 :
5545 : /*
5546 : * Revalidate cached plan, so that we will notice if it became stale. (We
5547 : * need to hold a refcount while using the plan, anyway.) If replanning
5548 : * is needed, do that work in the eval_mcontext.
5549 : */
5550 27148 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5551 27148 : cplan = SPI_plan_get_cached_plan(expr->plan);
5552 27148 : MemoryContextSwitchTo(oldcontext);
5553 :
5554 : /*
5555 : * We can't get a failure here, because the number of CachedPlanSources in
5556 : * the SPI plan can't change from what exec_simple_check_plan saw; it's a
5557 : * property of the raw parsetree generated from the query text.
5558 : */
5559 27148 : Assert(cplan != NULL);
5560 :
5561 : /* If it got replanned, update our copy of the simple expression */
5562 27148 : if (cplan->generation != expr->expr_simple_generation)
5563 : {
5564 509 : exec_save_simple_expr(expr, cplan);
5565 : /* better recheck r/w safety, as it could change due to inlining */
5566 509 : if (expr->rwparam >= 0)
5567 0 : exec_check_rw_parameter(expr, expr->rwparam);
5568 : }
5569 :
5570 : /*
5571 : * Pass back previously-determined result type.
5572 : */
5573 27148 : *rettype = expr->expr_simple_type;
5574 27148 : *rettypmod = expr->expr_simple_typmod;
5575 :
5576 : /*
5577 : * Prepare the expression for execution, if it's not been done already in
5578 : * the current transaction. (This will be forced to happen if we called
5579 : * exec_save_simple_expr above.)
5580 : */
5581 27148 : if (expr->expr_simple_lxid != curlxid)
5582 : {
5583 6122 : oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
5584 6122 : expr->expr_simple_state = ExecInitExpr(expr->expr_simple_expr, NULL);
5585 6122 : expr->expr_simple_in_use = false;
5586 6122 : expr->expr_simple_lxid = curlxid;
5587 6122 : MemoryContextSwitchTo(oldcontext);
5588 : }
5589 :
5590 : /*
5591 : * We have to do some of the things SPI_execute_plan would do, in
5592 : * particular advance the snapshot if we are in a non-read-only function.
5593 : * Without this, stable functions within the expression would fail to see
5594 : * updates made so far by our own function.
5595 : */
5596 27148 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5597 27148 : if (!estate->readonly_func)
5598 : {
5599 15152 : CommandCounterIncrement();
5600 15152 : PushActiveSnapshot(GetTransactionSnapshot());
5601 : }
5602 :
5603 : /*
5604 : * Set up ParamListInfo to pass to executor. We need an unshared list if
5605 : * it's going to include any R/W expanded-object pointer. For safety,
5606 : * save and restore estate->paramLI->parserSetupArg around our use of the
5607 : * param list.
5608 : */
5609 27148 : save_setup_arg = estate->paramLI->parserSetupArg;
5610 :
5611 27148 : if (expr->rwparam >= 0)
5612 0 : paramLI = setup_unshared_param_list(estate, expr);
5613 : else
5614 27148 : paramLI = setup_param_list(estate, expr);
5615 :
5616 27148 : econtext->ecxt_param_list_info = paramLI;
5617 :
5618 : /*
5619 : * Mark expression as busy for the duration of the ExecEvalExpr call.
5620 : */
5621 27148 : expr->expr_simple_in_use = true;
5622 :
5623 : /*
5624 : * Finally we can call the executor to evaluate the expression
5625 : */
5626 27148 : *result = ExecEvalExpr(expr->expr_simple_state,
5627 : econtext,
5628 : isNull);
5629 :
5630 : /* Assorted cleanup */
5631 27127 : expr->expr_simple_in_use = false;
5632 :
5633 27127 : econtext->ecxt_param_list_info = NULL;
5634 :
5635 27127 : estate->paramLI->parserSetupArg = save_setup_arg;
5636 :
5637 27127 : if (!estate->readonly_func)
5638 15131 : PopActiveSnapshot();
5639 :
5640 27127 : MemoryContextSwitchTo(oldcontext);
5641 :
5642 : /*
5643 : * Now we can release our refcount on the cached plan.
5644 : */
5645 27127 : ReleaseCachedPlan(cplan, true);
5646 :
5647 : /*
5648 : * That's it.
5649 : */
5650 27127 : return true;
5651 : }
5652 :
5653 :
5654 : /*
5655 : * Create a ParamListInfo to pass to SPI
5656 : *
5657 : * We share a single ParamListInfo array across all SPI calls made from this
5658 : * estate, except calls creating cursors, which use setup_unshared_param_list
5659 : * (see its comments for reasons why), and calls that pass a R/W expanded
5660 : * object pointer. A shared array is generally OK since any given slot in
5661 : * the array would need to contain the same current datum value no matter
5662 : * which query or expression we're evaluating; but of course that doesn't
5663 : * hold when a specific variable is being passed as a R/W pointer, because
5664 : * other expressions in the same function probably don't want to do that.
5665 : *
5666 : * Note that paramLI->parserSetupArg points to the specific PLpgSQL_expr
5667 : * being evaluated. This is not an issue for statement-level callers, but
5668 : * lower-level callers must save and restore estate->paramLI->parserSetupArg
5669 : * just in case there's an active evaluation at an outer call level.
5670 : *
5671 : * The general plan for passing parameters to SPI is that plain VAR datums
5672 : * always have valid images in the shared param list. This is ensured by
5673 : * assign_simple_var(), which also marks those params as PARAM_FLAG_CONST,
5674 : * allowing the planner to use those values in custom plans. However, non-VAR
5675 : * datums cannot conveniently be managed that way. For one thing, they could
5676 : * throw errors (for example "no such record field") and we do not want that
5677 : * to happen in a part of the expression that might never be evaluated at
5678 : * runtime. For another thing, exec_eval_datum() may return short-lived
5679 : * values stored in the estate's eval_mcontext, which will not necessarily
5680 : * survive to the next SPI operation. And for a third thing, ROW
5681 : * and RECFIELD datums' values depend on other datums, and we don't have a
5682 : * cheap way to track that. Therefore, param slots for non-VAR datum types
5683 : * are always reset here and then filled on-demand by plpgsql_param_fetch().
5684 : * We can save a few cycles by not bothering with the reset loop unless at
5685 : * least one such param has actually been filled by plpgsql_param_fetch().
5686 : */
5687 : static ParamListInfo
5688 29992 : setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
5689 : {
5690 : ParamListInfo paramLI;
5691 :
5692 : /*
5693 : * We must have created the SPIPlan already (hence, query text has been
5694 : * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
5695 : */
5696 29992 : Assert(expr->plan != NULL);
5697 :
5698 : /*
5699 : * Expressions with R/W parameters can't use the shared param list.
5700 : */
5701 29992 : Assert(expr->rwparam == -1);
5702 :
5703 : /*
5704 : * We only need a ParamListInfo if the expression has parameters. In
5705 : * principle we should test with bms_is_empty(), but we use a not-null
5706 : * test because it's faster. In current usage bits are never removed from
5707 : * expr->paramnos, only added, so this test is correct anyway.
5708 : */
5709 29992 : if (expr->paramnos)
5710 : {
5711 : /* Use the common ParamListInfo */
5712 21264 : paramLI = estate->paramLI;
5713 :
5714 : /*
5715 : * If any resettable parameters have been passed to the executor since
5716 : * last time, we need to reset those param slots to "invalid", for the
5717 : * reasons mentioned in the comment above.
5718 : */
5719 21264 : if (estate->params_dirty)
5720 : {
5721 2325 : Bitmapset *resettable_datums = estate->func->resettable_datums;
5722 2325 : int dno = -1;
5723 :
5724 36557 : while ((dno = bms_next_member(resettable_datums, dno)) >= 0)
5725 : {
5726 31907 : ParamExternData *prm = ¶mLI->params[dno];
5727 :
5728 31907 : prm->ptype = InvalidOid;
5729 : }
5730 2325 : estate->params_dirty = false;
5731 : }
5732 :
5733 : /*
5734 : * Set up link to active expr where the hook functions can find it.
5735 : * Callers must save and restore parserSetupArg if there is any chance
5736 : * that they are interrupting an active use of parameters.
5737 : */
5738 21264 : paramLI->parserSetupArg = (void *) expr;
5739 :
5740 : /*
5741 : * Allow parameters that aren't needed by this expression to be
5742 : * ignored.
5743 : */
5744 21264 : paramLI->paramMask = expr->paramnos;
5745 :
5746 : /*
5747 : * Also make sure this is set before parser hooks need it. There is
5748 : * no need to save and restore, since the value is always correct once
5749 : * set. (Should be set already, but let's be sure.)
5750 : */
5751 21264 : expr->func = estate->func;
5752 : }
5753 : else
5754 : {
5755 : /*
5756 : * Expression requires no parameters. Be sure we represent this case
5757 : * as a NULL ParamListInfo, so that plancache.c knows there is no
5758 : * point in a custom plan.
5759 : */
5760 8728 : paramLI = NULL;
5761 : }
5762 29992 : return paramLI;
5763 : }
5764 :
5765 : /*
5766 : * Create an unshared, short-lived ParamListInfo to pass to SPI
5767 : *
5768 : * When creating a cursor, we do not use the shared ParamListInfo array
5769 : * but create a short-lived one that will contain only params actually
5770 : * referenced by the query. The reason for this is that copyParamList() will
5771 : * be used to copy the parameters into cursor-lifespan storage, and we don't
5772 : * want it to copy anything that's not used by the specific cursor; that
5773 : * could result in uselessly copying some large values.
5774 : *
5775 : * We also use this for expressions that are passing a R/W object pointer
5776 : * to some trusted function. We don't want the R/W pointer to get into the
5777 : * shared param list, where it could get passed to some less-trusted function.
5778 : *
5779 : * The result, if not NULL, is in the estate's eval_mcontext.
5780 : *
5781 : * XXX. Could we use ParamListInfo's new paramMask to avoid creating unshared
5782 : * parameter lists?
5783 : */
5784 : static ParamListInfo
5785 210 : setup_unshared_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
5786 : {
5787 : ParamListInfo paramLI;
5788 :
5789 : /*
5790 : * We must have created the SPIPlan already (hence, query text has been
5791 : * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
5792 : */
5793 210 : Assert(expr->plan != NULL);
5794 :
5795 : /*
5796 : * We only need a ParamListInfo if the expression has parameters. In
5797 : * principle we should test with bms_is_empty(), but we use a not-null
5798 : * test because it's faster. In current usage bits are never removed from
5799 : * expr->paramnos, only added, so this test is correct anyway.
5800 : */
5801 210 : if (expr->paramnos)
5802 : {
5803 : int dno;
5804 :
5805 : /* initialize ParamListInfo with one entry per datum, all invalid */
5806 20 : paramLI = (ParamListInfo)
5807 20 : eval_mcontext_alloc0(estate,
5808 : offsetof(ParamListInfoData, params) +
5809 : estate->ndatums * sizeof(ParamExternData));
5810 20 : paramLI->paramFetch = plpgsql_param_fetch;
5811 20 : paramLI->paramFetchArg = (void *) estate;
5812 20 : paramLI->parserSetup = (ParserSetupHook) plpgsql_parser_setup;
5813 20 : paramLI->parserSetupArg = (void *) expr;
5814 20 : paramLI->numParams = estate->ndatums;
5815 20 : paramLI->paramMask = NULL;
5816 :
5817 : /*
5818 : * Instantiate values for "safe" parameters of the expression. We
5819 : * could skip this and leave them to be filled by plpgsql_param_fetch;
5820 : * but then the values would not be available for query planning,
5821 : * since the planner doesn't call the paramFetch hook.
5822 : */
5823 20 : dno = -1;
5824 70 : while ((dno = bms_next_member(expr->paramnos, dno)) >= 0)
5825 : {
5826 30 : PLpgSQL_datum *datum = estate->datums[dno];
5827 :
5828 30 : if (datum->dtype == PLPGSQL_DTYPE_VAR)
5829 : {
5830 30 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
5831 30 : ParamExternData *prm = ¶mLI->params[dno];
5832 :
5833 30 : if (dno == expr->rwparam)
5834 0 : prm->value = var->value;
5835 : else
5836 30 : prm->value = MakeExpandedObjectReadOnly(var->value,
5837 : var->isnull,
5838 : var->datatype->typlen);
5839 30 : prm->isnull = var->isnull;
5840 30 : prm->pflags = PARAM_FLAG_CONST;
5841 30 : prm->ptype = var->datatype->typoid;
5842 : }
5843 : }
5844 :
5845 : /*
5846 : * Also make sure this is set before parser hooks need it. There is
5847 : * no need to save and restore, since the value is always correct once
5848 : * set. (Should be set already, but let's be sure.)
5849 : */
5850 20 : expr->func = estate->func;
5851 : }
5852 : else
5853 : {
5854 : /*
5855 : * Expression requires no parameters. Be sure we represent this case
5856 : * as a NULL ParamListInfo, so that plancache.c knows there is no
5857 : * point in a custom plan.
5858 : */
5859 190 : paramLI = NULL;
5860 : }
5861 210 : return paramLI;
5862 : }
5863 :
5864 : /*
5865 : * plpgsql_param_fetch paramFetch callback for dynamic parameter fetch
5866 : */
5867 : static void
5868 5697 : plpgsql_param_fetch(ParamListInfo params, int paramid)
5869 : {
5870 : int dno;
5871 : PLpgSQL_execstate *estate;
5872 : PLpgSQL_expr *expr;
5873 : PLpgSQL_datum *datum;
5874 : ParamExternData *prm;
5875 : int32 prmtypmod;
5876 :
5877 : /* paramid's are 1-based, but dnos are 0-based */
5878 5697 : dno = paramid - 1;
5879 5697 : Assert(dno >= 0 && dno < params->numParams);
5880 :
5881 : /* fetch back the hook data */
5882 5697 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
5883 5697 : expr = (PLpgSQL_expr *) params->parserSetupArg;
5884 5697 : Assert(params->numParams == estate->ndatums);
5885 :
5886 : /* now we can access the target datum */
5887 5697 : datum = estate->datums[dno];
5888 :
5889 : /*
5890 : * Since copyParamList() or SerializeParamList() will try to materialize
5891 : * every single parameter slot, it's important to do nothing when asked
5892 : * for a datum that's not supposed to be used by this SQL expression.
5893 : * Otherwise we risk failures in exec_eval_datum(), or copying a lot more
5894 : * data than necessary.
5895 : */
5896 5697 : if (!bms_is_member(dno, expr->paramnos))
5897 5806 : return;
5898 :
5899 5588 : if (params == estate->paramLI)
5900 : {
5901 : /*
5902 : * We need to mark the shared params array dirty if we're about to
5903 : * evaluate a resettable datum.
5904 : */
5905 5588 : switch (datum->dtype)
5906 : {
5907 : case PLPGSQL_DTYPE_ROW:
5908 : case PLPGSQL_DTYPE_REC:
5909 : case PLPGSQL_DTYPE_RECFIELD:
5910 5588 : estate->params_dirty = true;
5911 5588 : break;
5912 :
5913 : default:
5914 0 : break;
5915 : }
5916 : }
5917 :
5918 : /* OK, evaluate the value and store into the appropriate paramlist slot */
5919 5588 : prm = ¶ms->params[dno];
5920 5588 : exec_eval_datum(estate, datum,
5921 : &prm->ptype, &prmtypmod,
5922 : &prm->value, &prm->isnull);
5923 : /* We can always mark params as "const" for executor's purposes */
5924 5588 : prm->pflags = PARAM_FLAG_CONST;
5925 :
5926 : /*
5927 : * If it's a read/write expanded datum, convert reference to read-only,
5928 : * unless it's safe to pass as read-write.
5929 : */
5930 5588 : if (datum->dtype == PLPGSQL_DTYPE_VAR && dno != expr->rwparam)
5931 0 : prm->value = MakeExpandedObjectReadOnly(prm->value,
5932 : prm->isnull,
5933 : ((PLpgSQL_var *) datum)->datatype->typlen);
5934 : }
5935 :
5936 :
5937 : /* ----------
5938 : * exec_move_row Move one tuple's values into a record or row
5939 : *
5940 : * Since this uses exec_assign_value, caller should eventually call
5941 : * exec_eval_cleanup to prevent long-term memory leaks.
5942 : * ----------
5943 : */
5944 : static void
5945 4072 : exec_move_row(PLpgSQL_execstate *estate,
5946 : PLpgSQL_rec *rec,
5947 : PLpgSQL_row *row,
5948 : HeapTuple tup, TupleDesc tupdesc)
5949 : {
5950 : /*
5951 : * Record is simple - just copy the tuple and its descriptor into the
5952 : * record variable
5953 : */
5954 4072 : if (rec != NULL)
5955 : {
5956 : /*
5957 : * Copy input first, just in case it is pointing at variable's value
5958 : */
5959 927 : if (HeapTupleIsValid(tup))
5960 916 : tup = heap_copytuple(tup);
5961 11 : else if (tupdesc)
5962 : {
5963 : /* If we have a tupdesc but no data, form an all-nulls tuple */
5964 : bool *nulls;
5965 :
5966 11 : nulls = (bool *)
5967 11 : eval_mcontext_alloc(estate, tupdesc->natts * sizeof(bool));
5968 11 : memset(nulls, true, tupdesc->natts * sizeof(bool));
5969 :
5970 11 : tup = heap_form_tuple(tupdesc, NULL, nulls);
5971 : }
5972 :
5973 927 : if (tupdesc)
5974 927 : tupdesc = CreateTupleDescCopy(tupdesc);
5975 :
5976 : /* Free the old value ... */
5977 927 : if (rec->freetup)
5978 : {
5979 435 : heap_freetuple(rec->tup);
5980 435 : rec->freetup = false;
5981 : }
5982 927 : if (rec->freetupdesc)
5983 : {
5984 435 : FreeTupleDesc(rec->tupdesc);
5985 435 : rec->freetupdesc = false;
5986 : }
5987 :
5988 : /* ... and install the new */
5989 927 : if (HeapTupleIsValid(tup))
5990 : {
5991 927 : rec->tup = tup;
5992 927 : rec->freetup = true;
5993 : }
5994 : else
5995 0 : rec->tup = NULL;
5996 :
5997 927 : if (tupdesc)
5998 : {
5999 927 : rec->tupdesc = tupdesc;
6000 927 : rec->freetupdesc = true;
6001 : }
6002 : else
6003 0 : rec->tupdesc = NULL;
6004 :
6005 927 : return;
6006 : }
6007 :
6008 : /*
6009 : * Row is a bit more complicated in that we assign the individual
6010 : * attributes of the tuple to the variables the row points to.
6011 : *
6012 : * NOTE: this code used to demand row->nfields ==
6013 : * HeapTupleHeaderGetNatts(tup->t_data), but that's wrong. The tuple
6014 : * might have more fields than we expected if it's from an
6015 : * inheritance-child table of the current table, or it might have fewer if
6016 : * the table has had columns added by ALTER TABLE. Ignore extra columns
6017 : * and assume NULL for missing columns, the same as heap_getattr would do.
6018 : * We also have to skip over dropped columns in either the source or
6019 : * destination.
6020 : *
6021 : * If we have no tuple data at all, we'll assign NULL to all columns of
6022 : * the row variable.
6023 : */
6024 3145 : if (row != NULL)
6025 : {
6026 3145 : int td_natts = tupdesc ? tupdesc->natts : 0;
6027 : int t_natts;
6028 : int fnum;
6029 : int anum;
6030 :
6031 3145 : if (HeapTupleIsValid(tup))
6032 3126 : t_natts = HeapTupleHeaderGetNatts(tup->t_data);
6033 : else
6034 19 : t_natts = 0;
6035 :
6036 3145 : anum = 0;
6037 6476 : for (fnum = 0; fnum < row->nfields; fnum++)
6038 : {
6039 : PLpgSQL_var *var;
6040 : Datum value;
6041 : bool isnull;
6042 : Oid valtype;
6043 : int32 valtypmod;
6044 :
6045 3331 : if (row->varnos[fnum] < 0)
6046 0 : continue; /* skip dropped column in row struct */
6047 :
6048 3331 : var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
6049 :
6050 9975 : while (anum < td_natts &&
6051 3313 : TupleDescAttr(tupdesc, anum)->attisdropped)
6052 0 : anum++; /* skip dropped column in tuple */
6053 :
6054 3331 : if (anum < td_natts)
6055 : {
6056 3313 : if (anum < t_natts)
6057 3302 : value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
6058 : else
6059 : {
6060 11 : value = (Datum) 0;
6061 11 : isnull = true;
6062 : }
6063 3313 : valtype = TupleDescAttr(tupdesc, anum)->atttypid;
6064 3313 : valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
6065 3313 : anum++;
6066 : }
6067 : else
6068 : {
6069 18 : value = (Datum) 0;
6070 18 : isnull = true;
6071 18 : valtype = UNKNOWNOID;
6072 18 : valtypmod = -1;
6073 : }
6074 :
6075 3331 : exec_assign_value(estate, (PLpgSQL_datum *) var,
6076 : value, isnull, valtype, valtypmod);
6077 : }
6078 :
6079 3145 : return;
6080 : }
6081 :
6082 0 : elog(ERROR, "unsupported target");
6083 : }
6084 :
6085 : /* ----------
6086 : * make_tuple_from_row Make a tuple from the values of a row object
6087 : *
6088 : * A NULL return indicates rowtype mismatch; caller must raise suitable error
6089 : *
6090 : * The result tuple is freshly palloc'd in caller's context. Some junk
6091 : * may be left behind in eval_mcontext, too.
6092 : * ----------
6093 : */
6094 : static HeapTuple
6095 95 : make_tuple_from_row(PLpgSQL_execstate *estate,
6096 : PLpgSQL_row *row,
6097 : TupleDesc tupdesc)
6098 : {
6099 95 : int natts = tupdesc->natts;
6100 : HeapTuple tuple;
6101 : Datum *dvalues;
6102 : bool *nulls;
6103 : int i;
6104 :
6105 95 : if (natts != row->nfields)
6106 0 : return NULL;
6107 :
6108 95 : dvalues = (Datum *) eval_mcontext_alloc0(estate, natts * sizeof(Datum));
6109 95 : nulls = (bool *) eval_mcontext_alloc(estate, natts * sizeof(bool));
6110 :
6111 280 : for (i = 0; i < natts; i++)
6112 : {
6113 : Oid fieldtypeid;
6114 : int32 fieldtypmod;
6115 :
6116 185 : if (TupleDescAttr(tupdesc, i)->attisdropped)
6117 : {
6118 0 : nulls[i] = true; /* leave the column as null */
6119 0 : continue;
6120 : }
6121 185 : if (row->varnos[i] < 0) /* should not happen */
6122 0 : elog(ERROR, "dropped rowtype entry for non-dropped column");
6123 :
6124 370 : exec_eval_datum(estate, estate->datums[row->varnos[i]],
6125 : &fieldtypeid, &fieldtypmod,
6126 185 : &dvalues[i], &nulls[i]);
6127 185 : if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid)
6128 0 : return NULL;
6129 : /* XXX should we insist on typmod match, too? */
6130 : }
6131 :
6132 95 : tuple = heap_form_tuple(tupdesc, dvalues, nulls);
6133 :
6134 95 : return tuple;
6135 : }
6136 :
6137 : /* ----------
6138 : * get_tuple_from_datum extract a tuple from a composite Datum
6139 : *
6140 : * Returns a HeapTuple, freshly palloc'd in caller's context.
6141 : *
6142 : * Note: it's caller's responsibility to be sure value is of composite type.
6143 : * ----------
6144 : */
6145 : static HeapTuple
6146 88 : get_tuple_from_datum(Datum value)
6147 : {
6148 88 : HeapTupleHeader td = DatumGetHeapTupleHeader(value);
6149 : HeapTupleData tmptup;
6150 :
6151 : /* Build a temporary HeapTuple control structure */
6152 88 : tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
6153 88 : ItemPointerSetInvalid(&(tmptup.t_self));
6154 88 : tmptup.t_tableOid = InvalidOid;
6155 88 : tmptup.t_data = td;
6156 :
6157 : /* Build a copy and return it */
6158 88 : return heap_copytuple(&tmptup);
6159 : }
6160 :
6161 : /* ----------
6162 : * get_tupdesc_from_datum get a tuple descriptor for a composite Datum
6163 : *
6164 : * Returns a pointer to the TupleDesc of the tuple's rowtype.
6165 : * Caller is responsible for calling ReleaseTupleDesc when done with it.
6166 : *
6167 : * Note: it's caller's responsibility to be sure value is of composite type.
6168 : * ----------
6169 : */
6170 : static TupleDesc
6171 88 : get_tupdesc_from_datum(Datum value)
6172 : {
6173 88 : HeapTupleHeader td = DatumGetHeapTupleHeader(value);
6174 : Oid tupType;
6175 : int32 tupTypmod;
6176 :
6177 : /* Extract rowtype info and find a tupdesc */
6178 88 : tupType = HeapTupleHeaderGetTypeId(td);
6179 88 : tupTypmod = HeapTupleHeaderGetTypMod(td);
6180 88 : return lookup_rowtype_tupdesc(tupType, tupTypmod);
6181 : }
6182 :
6183 : /* ----------
6184 : * exec_move_row_from_datum Move a composite Datum into a record or row
6185 : *
6186 : * This is equivalent to get_tuple_from_datum() followed by exec_move_row(),
6187 : * but we avoid constructing an intermediate physical copy of the tuple.
6188 : * ----------
6189 : */
6190 : static void
6191 69 : exec_move_row_from_datum(PLpgSQL_execstate *estate,
6192 : PLpgSQL_rec *rec,
6193 : PLpgSQL_row *row,
6194 : Datum value)
6195 : {
6196 69 : HeapTupleHeader td = DatumGetHeapTupleHeader(value);
6197 : Oid tupType;
6198 : int32 tupTypmod;
6199 : TupleDesc tupdesc;
6200 : HeapTupleData tmptup;
6201 :
6202 : /* Extract rowtype info and find a tupdesc */
6203 69 : tupType = HeapTupleHeaderGetTypeId(td);
6204 69 : tupTypmod = HeapTupleHeaderGetTypMod(td);
6205 69 : tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
6206 :
6207 : /* Build a temporary HeapTuple control structure */
6208 69 : tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
6209 69 : ItemPointerSetInvalid(&(tmptup.t_self));
6210 69 : tmptup.t_tableOid = InvalidOid;
6211 69 : tmptup.t_data = td;
6212 :
6213 : /* Do the move */
6214 69 : exec_move_row(estate, rec, row, &tmptup, tupdesc);
6215 :
6216 : /* Release tupdesc usage count */
6217 69 : ReleaseTupleDesc(tupdesc);
6218 69 : }
6219 :
6220 : /* ----------
6221 : * convert_value_to_string Convert a non-null Datum to C string
6222 : *
6223 : * Note: the result is in the estate's eval_mcontext, and will be cleared
6224 : * by the next exec_eval_cleanup() call. The invoked output function might
6225 : * leave additional cruft there as well, so just pfree'ing the result string
6226 : * would not be enough to avoid memory leaks if we did not do it like this.
6227 : * In most usages the Datum being passed in is also in that context (if
6228 : * pass-by-reference) and so an exec_eval_cleanup() call is needed anyway.
6229 : *
6230 : * Note: not caching the conversion function lookup is bad for performance.
6231 : * However, this function isn't currently used in any places where an extra
6232 : * catalog lookup or two seems like a big deal.
6233 : * ----------
6234 : */
6235 : static char *
6236 3675 : convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
6237 : {
6238 : char *result;
6239 : MemoryContext oldcontext;
6240 : Oid typoutput;
6241 : bool typIsVarlena;
6242 :
6243 3675 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6244 3675 : getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
6245 3675 : result = OidOutputFunctionCall(typoutput, value);
6246 3675 : MemoryContextSwitchTo(oldcontext);
6247 :
6248 3675 : return result;
6249 : }
6250 :
6251 : /* ----------
6252 : * exec_cast_value Cast a value if required
6253 : *
6254 : * Note that *isnull is an input and also an output parameter. While it's
6255 : * unlikely that a cast operation would produce null from non-null or vice
6256 : * versa, that could happen in principle.
6257 : *
6258 : * Note: the estate's eval_mcontext is used for temporary storage, and may
6259 : * also contain the result Datum if we have to do a conversion to a pass-
6260 : * by-reference data type. Be sure to do an exec_eval_cleanup() call when
6261 : * done with the result.
6262 : * ----------
6263 : */
6264 : static Datum
6265 31432 : exec_cast_value(PLpgSQL_execstate *estate,
6266 : Datum value, bool *isnull,
6267 : Oid valtype, int32 valtypmod,
6268 : Oid reqtype, int32 reqtypmod)
6269 : {
6270 : /*
6271 : * If the type of the given value isn't what's requested, convert it.
6272 : */
6273 31432 : if (valtype != reqtype ||
6274 6 : (valtypmod != reqtypmod && reqtypmod != -1))
6275 : {
6276 : plpgsql_CastHashEntry *cast_entry;
6277 :
6278 886 : cast_entry = get_cast_hashentry(estate,
6279 : valtype, valtypmod,
6280 : reqtype, reqtypmod);
6281 886 : if (cast_entry)
6282 : {
6283 869 : ExprContext *econtext = estate->eval_econtext;
6284 : MemoryContext oldcontext;
6285 :
6286 869 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6287 :
6288 869 : econtext->caseValue_datum = value;
6289 869 : econtext->caseValue_isNull = *isnull;
6290 :
6291 869 : cast_entry->cast_in_use = true;
6292 :
6293 869 : value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
6294 : isnull);
6295 :
6296 851 : cast_entry->cast_in_use = false;
6297 :
6298 851 : MemoryContextSwitchTo(oldcontext);
6299 : }
6300 : }
6301 :
6302 31414 : return value;
6303 : }
6304 :
6305 : /* ----------
6306 : * get_cast_hashentry Look up how to perform a type cast
6307 : *
6308 : * Returns a plpgsql_CastHashEntry if an expression has to be evaluated,
6309 : * or NULL if the cast is a mere no-op relabeling. If there's work to be
6310 : * done, the cast_exprstate field contains an expression evaluation tree
6311 : * based on a CaseTestExpr input, and the cast_in_use field should be set
6312 : * TRUE while executing it.
6313 : * ----------
6314 : */
6315 : static plpgsql_CastHashEntry *
6316 886 : get_cast_hashentry(PLpgSQL_execstate *estate,
6317 : Oid srctype, int32 srctypmod,
6318 : Oid dsttype, int32 dsttypmod)
6319 : {
6320 : plpgsql_CastHashKey cast_key;
6321 : plpgsql_CastHashEntry *cast_entry;
6322 : bool found;
6323 : LocalTransactionId curlxid;
6324 : MemoryContext oldcontext;
6325 :
6326 : /* Look for existing entry */
6327 886 : cast_key.srctype = srctype;
6328 886 : cast_key.dsttype = dsttype;
6329 886 : cast_key.srctypmod = srctypmod;
6330 886 : cast_key.dsttypmod = dsttypmod;
6331 886 : cast_entry = (plpgsql_CastHashEntry *) hash_search(estate->cast_hash,
6332 : (void *) &cast_key,
6333 : HASH_FIND, NULL);
6334 :
6335 886 : if (cast_entry == NULL)
6336 : {
6337 : /* We've not looked up this coercion before */
6338 : Node *cast_expr;
6339 : CaseTestExpr *placeholder;
6340 :
6341 : /*
6342 : * Since we could easily fail (no such coercion), construct a
6343 : * temporary coercion expression tree in the short-lived
6344 : * eval_mcontext, then if successful copy it to cast_hash_context.
6345 : */
6346 46 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6347 :
6348 : /*
6349 : * We use a CaseTestExpr as the base of the coercion tree, since it's
6350 : * very cheap to insert the source value for that.
6351 : */
6352 46 : placeholder = makeNode(CaseTestExpr);
6353 46 : placeholder->typeId = srctype;
6354 46 : placeholder->typeMod = srctypmod;
6355 46 : placeholder->collation = get_typcollation(srctype);
6356 :
6357 : /*
6358 : * Apply coercion. We use ASSIGNMENT coercion because that's the
6359 : * closest match to plpgsql's historical behavior; in particular,
6360 : * EXPLICIT coercion would allow silent truncation to a destination
6361 : * varchar/bpchar's length, which we do not want.
6362 : *
6363 : * If source type is UNKNOWN, coerce_to_target_type will fail (it only
6364 : * expects to see that for Const input nodes), so don't call it; we'll
6365 : * apply CoerceViaIO instead. Likewise, it doesn't currently work for
6366 : * coercing RECORD to some other type, so skip for that too.
6367 : */
6368 46 : if (srctype == UNKNOWNOID || srctype == RECORDOID)
6369 10 : cast_expr = NULL;
6370 : else
6371 36 : cast_expr = coerce_to_target_type(NULL,
6372 : (Node *) placeholder, srctype,
6373 : dsttype, dsttypmod,
6374 : COERCION_ASSIGNMENT,
6375 : COERCE_IMPLICIT_CAST,
6376 : -1);
6377 :
6378 : /*
6379 : * If there's no cast path according to the parser, fall back to using
6380 : * an I/O coercion; this is semantically dubious but matches plpgsql's
6381 : * historical behavior. We would need something of the sort for
6382 : * UNKNOWN literals in any case.
6383 : */
6384 46 : if (cast_expr == NULL)
6385 : {
6386 17 : CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
6387 :
6388 17 : iocoerce->arg = (Expr *) placeholder;
6389 17 : iocoerce->resulttype = dsttype;
6390 17 : iocoerce->resultcollid = InvalidOid;
6391 17 : iocoerce->coerceformat = COERCE_IMPLICIT_CAST;
6392 17 : iocoerce->location = -1;
6393 17 : cast_expr = (Node *) iocoerce;
6394 17 : if (dsttypmod != -1)
6395 0 : cast_expr = coerce_to_target_type(NULL,
6396 : cast_expr, dsttype,
6397 : dsttype, dsttypmod,
6398 : COERCION_ASSIGNMENT,
6399 : COERCE_IMPLICIT_CAST,
6400 : -1);
6401 : }
6402 :
6403 : /* Note: we don't bother labeling the expression tree with collation */
6404 :
6405 : /* Detect whether we have a no-op (RelabelType) coercion */
6406 47 : if (IsA(cast_expr, RelabelType) &&
6407 1 : ((RelabelType *) cast_expr)->arg == (Expr *) placeholder)
6408 1 : cast_expr = NULL;
6409 :
6410 46 : if (cast_expr)
6411 : {
6412 : /* ExecInitExpr assumes we've planned the expression */
6413 45 : cast_expr = (Node *) expression_planner((Expr *) cast_expr);
6414 :
6415 : /* Now copy the tree into cast_hash_context */
6416 45 : MemoryContextSwitchTo(estate->cast_hash_context);
6417 :
6418 45 : cast_expr = copyObject(cast_expr);
6419 : }
6420 :
6421 46 : MemoryContextSwitchTo(oldcontext);
6422 :
6423 : /* Now we can fill in a hashtable entry. */
6424 46 : cast_entry = (plpgsql_CastHashEntry *) hash_search(estate->cast_hash,
6425 : (void *) &cast_key,
6426 : HASH_ENTER, &found);
6427 46 : Assert(!found); /* wasn't there a moment ago */
6428 46 : cast_entry->cast_expr = (Expr *) cast_expr;
6429 46 : cast_entry->cast_exprstate = NULL;
6430 46 : cast_entry->cast_in_use = false;
6431 46 : cast_entry->cast_lxid = InvalidLocalTransactionId;
6432 : }
6433 :
6434 : /* Done if we have determined that this is a no-op cast. */
6435 886 : if (cast_entry->cast_expr == NULL)
6436 17 : return NULL;
6437 :
6438 : /*
6439 : * Prepare the expression for execution, if it's not been done already in
6440 : * the current transaction; also, if it's marked busy in the current
6441 : * transaction, abandon that expression tree and build a new one, so as to
6442 : * avoid potential problems with recursive cast expressions and failed
6443 : * executions. (We will leak some memory intra-transaction if that
6444 : * happens a lot, but we don't expect it to.) It's okay to update the
6445 : * hash table with the new tree because all plpgsql functions within a
6446 : * given transaction share the same simple_eval_estate. (Well, regular
6447 : * functions do; DO blocks have private simple_eval_estates, and private
6448 : * cast hash tables to go with them.)
6449 : */
6450 869 : curlxid = MyProc->lxid;
6451 869 : if (cast_entry->cast_lxid != curlxid || cast_entry->cast_in_use)
6452 : {
6453 246 : oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
6454 246 : cast_entry->cast_exprstate = ExecInitExpr(cast_entry->cast_expr, NULL);
6455 246 : cast_entry->cast_in_use = false;
6456 246 : cast_entry->cast_lxid = curlxid;
6457 246 : MemoryContextSwitchTo(oldcontext);
6458 : }
6459 :
6460 869 : return cast_entry;
6461 : }
6462 :
6463 :
6464 : /* ----------
6465 : * exec_simple_check_plan - Check if a plan is simple enough to
6466 : * be evaluated by ExecEvalExpr() instead
6467 : * of SPI.
6468 : * ----------
6469 : */
6470 : static void
6471 1584 : exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
6472 : {
6473 : List *plansources;
6474 : CachedPlanSource *plansource;
6475 : Query *query;
6476 : CachedPlan *cplan;
6477 : MemoryContext oldcontext;
6478 :
6479 : /*
6480 : * Initialize to "not simple".
6481 : */
6482 1584 : expr->expr_simple_expr = NULL;
6483 :
6484 : /*
6485 : * Check the analyzed-and-rewritten form of the query to see if we will be
6486 : * able to treat it as a simple expression. Since this function is only
6487 : * called immediately after creating the CachedPlanSource, we need not
6488 : * worry about the query being stale.
6489 : */
6490 :
6491 : /*
6492 : * We can only test queries that resulted in exactly one CachedPlanSource
6493 : */
6494 1584 : plansources = SPI_plan_get_plan_sources(expr->plan);
6495 1584 : if (list_length(plansources) != 1)
6496 0 : return;
6497 1584 : plansource = (CachedPlanSource *) linitial(plansources);
6498 :
6499 : /*
6500 : * 1. There must be one single querytree.
6501 : */
6502 1584 : if (list_length(plansource->query_list) != 1)
6503 0 : return;
6504 1584 : query = (Query *) linitial(plansource->query_list);
6505 :
6506 : /*
6507 : * 2. It must be a plain SELECT query without any input tables
6508 : */
6509 1584 : if (!IsA(query, Query))
6510 0 : return;
6511 1584 : if (query->commandType != CMD_SELECT)
6512 87 : return;
6513 1497 : if (query->rtable != NIL)
6514 102 : return;
6515 :
6516 : /*
6517 : * 3. Can't have any subplans, aggregates, qual clauses either. (These
6518 : * tests should generally match what inline_function() checks before
6519 : * inlining a SQL function; otherwise, inlining could change our
6520 : * conclusion about whether an expression is simple, which we don't want.)
6521 : */
6522 2790 : if (query->hasAggs ||
6523 2790 : query->hasWindowFuncs ||
6524 2790 : query->hasTargetSRFs ||
6525 2750 : query->hasSubLinks ||
6526 2710 : query->cteList ||
6527 2710 : query->jointree->fromlist ||
6528 2710 : query->jointree->quals ||
6529 2710 : query->groupClause ||
6530 2710 : query->groupingSets ||
6531 2710 : query->havingQual ||
6532 2710 : query->windowClause ||
6533 2710 : query->distinctClause ||
6534 2710 : query->sortClause ||
6535 2710 : query->limitOffset ||
6536 2710 : query->limitCount ||
6537 1355 : query->setOperations)
6538 40 : return;
6539 :
6540 : /*
6541 : * 4. The query must have a single attribute as result
6542 : */
6543 1355 : if (list_length(query->targetList) != 1)
6544 12 : return;
6545 :
6546 : /*
6547 : * OK, we can treat it as a simple plan.
6548 : *
6549 : * Get the generic plan for the query. If replanning is needed, do that
6550 : * work in the eval_mcontext.
6551 : */
6552 1343 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6553 1343 : cplan = SPI_plan_get_cached_plan(expr->plan);
6554 1338 : MemoryContextSwitchTo(oldcontext);
6555 :
6556 : /* Can't fail, because we checked for a single CachedPlanSource above */
6557 1338 : Assert(cplan != NULL);
6558 :
6559 : /* Share the remaining work with replan code path */
6560 1338 : exec_save_simple_expr(expr, cplan);
6561 :
6562 : /* Release our plan refcount */
6563 1338 : ReleaseCachedPlan(cplan, true);
6564 : }
6565 :
6566 : /*
6567 : * exec_save_simple_expr --- extract simple expression from CachedPlan
6568 : */
6569 : static void
6570 1847 : exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
6571 : {
6572 : PlannedStmt *stmt;
6573 : Plan *plan;
6574 : Expr *tle_expr;
6575 :
6576 : /*
6577 : * Given the checks that exec_simple_check_plan did, none of the Asserts
6578 : * here should ever fail.
6579 : */
6580 :
6581 : /* Extract the single PlannedStmt */
6582 1847 : Assert(list_length(cplan->stmt_list) == 1);
6583 1847 : stmt = linitial_node(PlannedStmt, cplan->stmt_list);
6584 1847 : Assert(stmt->commandType == CMD_SELECT);
6585 :
6586 : /*
6587 : * Ordinarily, the plan node should be a simple Result. However, if
6588 : * force_parallel_mode is on, the planner might've stuck a Gather node
6589 : * atop that. The simplest way to deal with this is to look through the
6590 : * Gather node. The Gather node's tlist would normally contain a Var
6591 : * referencing the child node's output ... but setrefs.c might also have
6592 : * copied a Const as-is.
6593 : */
6594 1847 : plan = stmt->planTree;
6595 : for (;;)
6596 : {
6597 : /* Extract the single tlist expression */
6598 1847 : Assert(list_length(plan->targetlist) == 1);
6599 1847 : tle_expr = castNode(TargetEntry, linitial(plan->targetlist))->expr;
6600 :
6601 1847 : if (IsA(plan, Result))
6602 : {
6603 1847 : Assert(plan->lefttree == NULL &&
6604 : plan->righttree == NULL &&
6605 : plan->initPlan == NULL &&
6606 : plan->qual == NULL &&
6607 : ((Result *) plan)->resconstantqual == NULL);
6608 1847 : break;
6609 : }
6610 0 : else if (IsA(plan, Gather))
6611 : {
6612 0 : Assert(plan->lefttree != NULL &&
6613 : plan->righttree == NULL &&
6614 : plan->initPlan == NULL &&
6615 : plan->qual == NULL);
6616 : /* If setrefs.c copied up a Const, no need to look further */
6617 0 : if (IsA(tle_expr, Const))
6618 0 : break;
6619 : /* Otherwise, it better be an outer Var */
6620 0 : Assert(IsA(tle_expr, Var));
6621 0 : Assert(((Var *) tle_expr)->varno == OUTER_VAR);
6622 : /* Descend to the child node */
6623 0 : plan = plan->lefttree;
6624 : }
6625 : else
6626 0 : elog(ERROR, "unexpected plan node type: %d",
6627 : (int) nodeTag(plan));
6628 0 : }
6629 :
6630 : /*
6631 : * Save the simple expression, and initialize state to "not valid in
6632 : * current transaction".
6633 : */
6634 1847 : expr->expr_simple_expr = tle_expr;
6635 1847 : expr->expr_simple_generation = cplan->generation;
6636 1847 : expr->expr_simple_state = NULL;
6637 1847 : expr->expr_simple_in_use = false;
6638 1847 : expr->expr_simple_lxid = InvalidLocalTransactionId;
6639 : /* Also stash away the expression result type */
6640 1847 : expr->expr_simple_type = exprType((Node *) tle_expr);
6641 1847 : expr->expr_simple_typmod = exprTypmod((Node *) tle_expr);
6642 1847 : }
6643 :
6644 : /*
6645 : * exec_check_rw_parameter --- can we pass expanded object as read/write param?
6646 : *
6647 : * If we have an assignment like "x := array_append(x, foo)" in which the
6648 : * top-level function is trusted not to corrupt its argument in case of an
6649 : * error, then when x has an expanded object as value, it is safe to pass the
6650 : * value as a read/write pointer and let the function modify the value
6651 : * in-place.
6652 : *
6653 : * This function checks for a safe expression, and sets expr->rwparam to the
6654 : * dno of the target variable (x) if safe, or -1 if not safe.
6655 : */
6656 : static void
6657 246 : exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno)
6658 : {
6659 : Oid funcid;
6660 : List *fargs;
6661 : ListCell *lc;
6662 :
6663 : /* Assume unsafe */
6664 246 : expr->rwparam = -1;
6665 :
6666 : /*
6667 : * If the expression isn't simple, there's no point in trying to optimize
6668 : * (because the exec_run_select code path will flatten any expanded result
6669 : * anyway). Even without that, this seems like a good safety restriction.
6670 : */
6671 246 : if (expr->expr_simple_expr == NULL)
6672 7 : return;
6673 :
6674 : /*
6675 : * If target variable isn't referenced by expression, no need to look
6676 : * further.
6677 : */
6678 239 : if (!bms_is_member(target_dno, expr->paramnos))
6679 177 : return;
6680 :
6681 : /*
6682 : * Top level of expression must be a simple FuncExpr or OpExpr.
6683 : */
6684 62 : if (IsA(expr->expr_simple_expr, FuncExpr))
6685 : {
6686 3 : FuncExpr *fexpr = (FuncExpr *) expr->expr_simple_expr;
6687 :
6688 3 : funcid = fexpr->funcid;
6689 3 : fargs = fexpr->args;
6690 : }
6691 59 : else if (IsA(expr->expr_simple_expr, OpExpr))
6692 : {
6693 59 : OpExpr *opexpr = (OpExpr *) expr->expr_simple_expr;
6694 :
6695 59 : funcid = opexpr->opfuncid;
6696 59 : fargs = opexpr->args;
6697 : }
6698 : else
6699 0 : return;
6700 :
6701 : /*
6702 : * The top-level function must be one that we trust to be "safe".
6703 : * Currently we hard-wire the list, but it would be very desirable to
6704 : * allow extensions to mark their functions as safe ...
6705 : */
6706 62 : if (!(funcid == F_ARRAY_APPEND ||
6707 : funcid == F_ARRAY_PREPEND))
6708 60 : return;
6709 :
6710 : /*
6711 : * The target variable (in the form of a Param) must only appear as a
6712 : * direct argument of the top-level function.
6713 : */
6714 3 : foreach(lc, fargs)
6715 : {
6716 3 : Node *arg = (Node *) lfirst(lc);
6717 :
6718 : /* A Param is OK, whether it's the target variable or not */
6719 3 : if (arg && IsA(arg, Param))
6720 0 : continue;
6721 : /* Otherwise, argument expression must not reference target */
6722 3 : if (contains_target_param(arg, &target_dno))
6723 2 : return;
6724 : }
6725 :
6726 : /* OK, we can pass target as a read-write parameter */
6727 0 : expr->rwparam = target_dno;
6728 : }
6729 :
6730 : /*
6731 : * Recursively check for a Param referencing the target variable
6732 : */
6733 : static bool
6734 5 : contains_target_param(Node *node, int *target_dno)
6735 : {
6736 5 : if (node == NULL)
6737 0 : return false;
6738 5 : if (IsA(node, Param))
6739 : {
6740 2 : Param *param = (Param *) node;
6741 :
6742 4 : if (param->paramkind == PARAM_EXTERN &&
6743 2 : param->paramid == *target_dno + 1)
6744 2 : return true;
6745 0 : return false;
6746 : }
6747 3 : return expression_tree_walker(node, contains_target_param,
6748 : (void *) target_dno);
6749 : }
6750 :
6751 : /* ----------
6752 : * exec_set_found Set the global found variable to true/false
6753 : * ----------
6754 : */
6755 : static void
6756 14046 : exec_set_found(PLpgSQL_execstate *estate, bool state)
6757 : {
6758 : PLpgSQL_var *var;
6759 :
6760 14046 : var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
6761 14046 : assign_simple_var(estate, var, BoolGetDatum(state), false, false);
6762 14046 : }
6763 :
6764 : /*
6765 : * plpgsql_create_econtext --- create an eval_econtext for the current function
6766 : *
6767 : * We may need to create a new shared_simple_eval_estate too, if there's not
6768 : * one already for the current transaction. The EState will be cleaned up at
6769 : * transaction end.
6770 : */
6771 : static void
6772 12578 : plpgsql_create_econtext(PLpgSQL_execstate *estate)
6773 : {
6774 : SimpleEcontextStackEntry *entry;
6775 :
6776 : /*
6777 : * Create an EState for evaluation of simple expressions, if there's not
6778 : * one already in the current transaction. The EState is made a child of
6779 : * TopTransactionContext so it will have the right lifespan.
6780 : *
6781 : * Note that this path is never taken when executing a DO block; the
6782 : * required EState was already made by plpgsql_inline_handler.
6783 : */
6784 12578 : if (estate->simple_eval_estate == NULL)
6785 : {
6786 : MemoryContext oldcontext;
6787 :
6788 767 : Assert(shared_simple_eval_estate == NULL);
6789 767 : oldcontext = MemoryContextSwitchTo(TopTransactionContext);
6790 767 : shared_simple_eval_estate = CreateExecutorState();
6791 767 : estate->simple_eval_estate = shared_simple_eval_estate;
6792 767 : MemoryContextSwitchTo(oldcontext);
6793 : }
6794 :
6795 : /*
6796 : * Create a child econtext for the current function.
6797 : */
6798 12578 : estate->eval_econtext = CreateExprContext(estate->simple_eval_estate);
6799 :
6800 : /*
6801 : * Make a stack entry so we can clean up the econtext at subxact end.
6802 : * Stack entries are kept in TopTransactionContext for simplicity.
6803 : */
6804 12578 : entry = (SimpleEcontextStackEntry *)
6805 12578 : MemoryContextAlloc(TopTransactionContext,
6806 : sizeof(SimpleEcontextStackEntry));
6807 :
6808 12578 : entry->stack_econtext = estate->eval_econtext;
6809 12578 : entry->xact_subxid = GetCurrentSubTransactionId();
6810 :
6811 12578 : entry->next = simple_econtext_stack;
6812 12578 : simple_econtext_stack = entry;
6813 12578 : }
6814 :
6815 : /*
6816 : * plpgsql_destroy_econtext --- destroy function's econtext
6817 : *
6818 : * We check that it matches the top stack entry, and destroy the stack
6819 : * entry along with the context.
6820 : */
6821 : static void
6822 12208 : plpgsql_destroy_econtext(PLpgSQL_execstate *estate)
6823 : {
6824 : SimpleEcontextStackEntry *next;
6825 :
6826 12208 : Assert(simple_econtext_stack != NULL);
6827 12208 : Assert(simple_econtext_stack->stack_econtext == estate->eval_econtext);
6828 :
6829 12208 : next = simple_econtext_stack->next;
6830 12208 : pfree(simple_econtext_stack);
6831 12208 : simple_econtext_stack = next;
6832 :
6833 12208 : FreeExprContext(estate->eval_econtext, true);
6834 12208 : estate->eval_econtext = NULL;
6835 12208 : }
6836 :
6837 : /*
6838 : * plpgsql_xact_cb --- post-transaction-commit-or-abort cleanup
6839 : *
6840 : * If a simple-expression EState was created in the current transaction,
6841 : * it has to be cleaned up.
6842 : */
6843 : void
6844 13913 : plpgsql_xact_cb(XactEvent event, void *arg)
6845 : {
6846 : /*
6847 : * If we are doing a clean transaction shutdown, free the EState (so that
6848 : * any remaining resources will be released correctly). In an abort, we
6849 : * expect the regular abort recovery procedures to release everything of
6850 : * interest.
6851 : */
6852 13913 : if (event == XACT_EVENT_COMMIT || event == XACT_EVENT_PREPARE)
6853 : {
6854 : /* Shouldn't be any econtext stack entries left at commit */
6855 6411 : Assert(simple_econtext_stack == NULL);
6856 :
6857 6411 : if (shared_simple_eval_estate)
6858 656 : FreeExecutorState(shared_simple_eval_estate);
6859 6411 : shared_simple_eval_estate = NULL;
6860 : }
6861 7502 : else if (event == XACT_EVENT_ABORT)
6862 : {
6863 862 : simple_econtext_stack = NULL;
6864 862 : shared_simple_eval_estate = NULL;
6865 : }
6866 13913 : }
6867 :
6868 : /*
6869 : * plpgsql_subxact_cb --- post-subtransaction-commit-or-abort cleanup
6870 : *
6871 : * Make sure any simple-expression econtexts created in the current
6872 : * subtransaction get cleaned up. We have to do this explicitly because
6873 : * no other code knows which econtexts belong to which level of subxact.
6874 : */
6875 : void
6876 636 : plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
6877 : SubTransactionId parentSubid, void *arg)
6878 : {
6879 636 : if (event == SUBXACT_EVENT_COMMIT_SUB || event == SUBXACT_EVENT_ABORT_SUB)
6880 : {
6881 1466 : while (simple_econtext_stack != NULL &&
6882 544 : simple_econtext_stack->xact_subxid == mySubid)
6883 : {
6884 : SimpleEcontextStackEntry *next;
6885 :
6886 282 : FreeExprContext(simple_econtext_stack->stack_econtext,
6887 : (event == SUBXACT_EVENT_COMMIT_SUB));
6888 282 : next = simple_econtext_stack->next;
6889 282 : pfree(simple_econtext_stack);
6890 282 : simple_econtext_stack = next;
6891 : }
6892 : }
6893 636 : }
6894 :
6895 : /*
6896 : * assign_simple_var --- assign a new value to any VAR datum.
6897 : *
6898 : * This should be the only mechanism for assignment to simple variables,
6899 : * lest we forget to update the paramLI image.
6900 : */
6901 : static void
6902 56280 : assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
6903 : Datum newvalue, bool isnull, bool freeable)
6904 : {
6905 : ParamExternData *prm;
6906 :
6907 56280 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6908 : /* Free the old value if needed */
6909 56280 : if (var->freeval)
6910 : {
6911 3824 : if (DatumIsReadWriteExpandedObject(var->value,
6912 : var->isnull,
6913 : var->datatype->typlen))
6914 785 : DeleteExpandedObject(var->value);
6915 : else
6916 3039 : pfree(DatumGetPointer(var->value));
6917 : }
6918 : /* Assign new value to datum */
6919 56280 : var->value = newvalue;
6920 56280 : var->isnull = isnull;
6921 56280 : var->freeval = freeable;
6922 : /* And update the image in the common parameter list */
6923 56280 : prm = &estate->paramLI->params[var->dno];
6924 56280 : prm->value = MakeExpandedObjectReadOnly(newvalue,
6925 : isnull,
6926 : var->datatype->typlen);
6927 56280 : prm->isnull = isnull;
6928 : /* these might be set already, but let's be sure */
6929 56280 : prm->pflags = PARAM_FLAG_CONST;
6930 56280 : prm->ptype = var->datatype->typoid;
6931 56280 : }
6932 :
6933 : /*
6934 : * free old value of a text variable and assign new value from C string
6935 : */
6936 : static void
6937 6068 : assign_text_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, const char *str)
6938 : {
6939 6068 : assign_simple_var(estate, var, CStringGetTextDatum(str), false, true);
6940 6068 : }
6941 :
6942 : /*
6943 : * exec_eval_using_params --- evaluate params of USING clause
6944 : *
6945 : * The result data structure is created in the stmt_mcontext, and should
6946 : * be freed by resetting that context.
6947 : */
6948 : static PreparedParamsData *
6949 6 : exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
6950 : {
6951 : PreparedParamsData *ppd;
6952 6 : MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
6953 : int nargs;
6954 : int i;
6955 : ListCell *lc;
6956 :
6957 6 : ppd = (PreparedParamsData *)
6958 : MemoryContextAlloc(stmt_mcontext, sizeof(PreparedParamsData));
6959 6 : nargs = list_length(params);
6960 :
6961 6 : ppd->nargs = nargs;
6962 6 : ppd->types = (Oid *)
6963 6 : MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Oid));
6964 6 : ppd->values = (Datum *)
6965 6 : MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Datum));
6966 6 : ppd->nulls = (char *)
6967 6 : MemoryContextAlloc(stmt_mcontext, nargs * sizeof(char));
6968 :
6969 6 : i = 0;
6970 15 : foreach(lc, params)
6971 : {
6972 9 : PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
6973 : bool isnull;
6974 : int32 ppdtypmod;
6975 : MemoryContext oldcontext;
6976 :
6977 27 : ppd->values[i] = exec_eval_expr(estate, param,
6978 : &isnull,
6979 18 : &ppd->types[i],
6980 : &ppdtypmod);
6981 9 : ppd->nulls[i] = isnull ? 'n' : ' ';
6982 :
6983 9 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
6984 :
6985 9 : if (ppd->types[i] == UNKNOWNOID)
6986 : {
6987 : /*
6988 : * Treat 'unknown' parameters as text, since that's what most
6989 : * people would expect. SPI_execute_with_args can coerce unknown
6990 : * constants in a more intelligent way, but not unknown Params.
6991 : * This code also takes care of copying into the right context.
6992 : * Note we assume 'unknown' has the representation of C-string.
6993 : */
6994 0 : ppd->types[i] = TEXTOID;
6995 0 : if (!isnull)
6996 0 : ppd->values[i] = CStringGetTextDatum(DatumGetCString(ppd->values[i]));
6997 : }
6998 : /* pass-by-ref non null values must be copied into stmt_mcontext */
6999 9 : else if (!isnull)
7000 : {
7001 : int16 typLen;
7002 : bool typByVal;
7003 :
7004 9 : get_typlenbyval(ppd->types[i], &typLen, &typByVal);
7005 9 : if (!typByVal)
7006 2 : ppd->values[i] = datumCopy(ppd->values[i], typByVal, typLen);
7007 : }
7008 :
7009 9 : MemoryContextSwitchTo(oldcontext);
7010 :
7011 9 : exec_eval_cleanup(estate);
7012 :
7013 9 : i++;
7014 : }
7015 :
7016 6 : return ppd;
7017 : }
7018 :
7019 : /*
7020 : * Open portal for dynamic query
7021 : *
7022 : * Caution: this resets the stmt_mcontext at exit. We might eventually need
7023 : * to move that responsibility to the callers, but currently no caller needs
7024 : * to have statement-lifetime temp data that survives past this, so it's
7025 : * simpler to do it here.
7026 : */
7027 : static Portal
7028 514 : exec_dynquery_with_params(PLpgSQL_execstate *estate,
7029 : PLpgSQL_expr *dynquery,
7030 : List *params,
7031 : const char *portalname,
7032 : int cursorOptions)
7033 : {
7034 : Portal portal;
7035 : Datum query;
7036 : bool isnull;
7037 : Oid restype;
7038 : int32 restypmod;
7039 : char *querystr;
7040 514 : MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
7041 :
7042 : /*
7043 : * Evaluate the string expression after the EXECUTE keyword. Its result is
7044 : * the querystring we have to execute.
7045 : */
7046 514 : query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod);
7047 514 : if (isnull)
7048 0 : ereport(ERROR,
7049 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
7050 : errmsg("query string argument of EXECUTE is null")));
7051 :
7052 : /* Get the C-String representation */
7053 514 : querystr = convert_value_to_string(estate, query, restype);
7054 :
7055 : /* copy it into the stmt_mcontext before we clean up */
7056 514 : querystr = MemoryContextStrdup(stmt_mcontext, querystr);
7057 :
7058 514 : exec_eval_cleanup(estate);
7059 :
7060 : /*
7061 : * Open an implicit cursor for the query. We use
7062 : * SPI_cursor_open_with_args even when there are no params, because this
7063 : * avoids making and freeing one copy of the plan.
7064 : */
7065 514 : if (params)
7066 : {
7067 : PreparedParamsData *ppd;
7068 :
7069 3 : ppd = exec_eval_using_params(estate, params);
7070 6 : portal = SPI_cursor_open_with_args(portalname,
7071 : querystr,
7072 : ppd->nargs, ppd->types,
7073 3 : ppd->values, ppd->nulls,
7074 3 : estate->readonly_func,
7075 : cursorOptions);
7076 : }
7077 : else
7078 : {
7079 511 : portal = SPI_cursor_open_with_args(portalname,
7080 : querystr,
7081 : 0, NULL,
7082 : NULL, NULL,
7083 511 : estate->readonly_func,
7084 : cursorOptions);
7085 : }
7086 :
7087 514 : if (portal == NULL)
7088 0 : elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
7089 : querystr, SPI_result_code_string(SPI_result));
7090 :
7091 : /* Release transient data */
7092 514 : MemoryContextReset(stmt_mcontext);
7093 :
7094 514 : return portal;
7095 : }
7096 :
7097 : /*
7098 : * Return a formatted string with information about an expression's parameters,
7099 : * or NULL if the expression does not take any parameters.
7100 : * The result is in the eval_mcontext.
7101 : */
7102 : static char *
7103 4 : format_expr_params(PLpgSQL_execstate *estate,
7104 : const PLpgSQL_expr *expr)
7105 : {
7106 : int paramno;
7107 : int dno;
7108 : StringInfoData paramstr;
7109 : MemoryContext oldcontext;
7110 :
7111 4 : if (!expr->paramnos)
7112 1 : return NULL;
7113 :
7114 3 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7115 :
7116 3 : initStringInfo(¶mstr);
7117 3 : paramno = 0;
7118 3 : dno = -1;
7119 12 : while ((dno = bms_next_member(expr->paramnos, dno)) >= 0)
7120 : {
7121 : Datum paramdatum;
7122 : Oid paramtypeid;
7123 : bool paramisnull;
7124 : int32 paramtypmod;
7125 : PLpgSQL_var *curvar;
7126 :
7127 6 : curvar = (PLpgSQL_var *) estate->datums[dno];
7128 :
7129 6 : exec_eval_datum(estate, (PLpgSQL_datum *) curvar,
7130 : ¶mtypeid, ¶mtypmod,
7131 : ¶mdatum, ¶misnull);
7132 :
7133 6 : appendStringInfo(¶mstr, "%s%s = ",
7134 : paramno > 0 ? ", " : "",
7135 : curvar->refname);
7136 :
7137 6 : if (paramisnull)
7138 0 : appendStringInfoString(¶mstr, "NULL");
7139 : else
7140 : {
7141 6 : char *value = convert_value_to_string(estate, paramdatum, paramtypeid);
7142 : char *p;
7143 :
7144 6 : appendStringInfoCharMacro(¶mstr, '\'');
7145 18 : for (p = value; *p; p++)
7146 : {
7147 12 : if (*p == '\'') /* double single quotes */
7148 0 : appendStringInfoCharMacro(¶mstr, *p);
7149 12 : appendStringInfoCharMacro(¶mstr, *p);
7150 : }
7151 6 : appendStringInfoCharMacro(¶mstr, '\'');
7152 : }
7153 :
7154 6 : paramno++;
7155 : }
7156 :
7157 3 : MemoryContextSwitchTo(oldcontext);
7158 :
7159 3 : return paramstr.data;
7160 : }
7161 :
7162 : /*
7163 : * Return a formatted string with information about PreparedParamsData, or NULL
7164 : * if there are no parameters.
7165 : * The result is in the eval_mcontext.
7166 : */
7167 : static char *
7168 3 : format_preparedparamsdata(PLpgSQL_execstate *estate,
7169 : const PreparedParamsData *ppd)
7170 : {
7171 : int paramno;
7172 : StringInfoData paramstr;
7173 : MemoryContext oldcontext;
7174 :
7175 3 : if (!ppd)
7176 1 : return NULL;
7177 :
7178 2 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7179 :
7180 2 : initStringInfo(¶mstr);
7181 5 : for (paramno = 0; paramno < ppd->nargs; paramno++)
7182 : {
7183 3 : appendStringInfo(¶mstr, "%s$%d = ",
7184 : paramno > 0 ? ", " : "",
7185 : paramno + 1);
7186 :
7187 3 : if (ppd->nulls[paramno] == 'n')
7188 0 : appendStringInfoString(¶mstr, "NULL");
7189 : else
7190 : {
7191 3 : char *value = convert_value_to_string(estate, ppd->values[paramno], ppd->types[paramno]);
7192 : char *p;
7193 :
7194 3 : appendStringInfoCharMacro(¶mstr, '\'');
7195 8 : for (p = value; *p; p++)
7196 : {
7197 5 : if (*p == '\'') /* double single quotes */
7198 0 : appendStringInfoCharMacro(¶mstr, *p);
7199 5 : appendStringInfoCharMacro(¶mstr, *p);
7200 : }
7201 3 : appendStringInfoCharMacro(¶mstr, '\'');
7202 : }
7203 : }
7204 :
7205 2 : MemoryContextSwitchTo(oldcontext);
7206 :
7207 2 : return paramstr.data;
7208 : }
|