Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pl_exec.c - Executor for the PL/pgSQL
4 : * procedural language
5 : *
6 : * Portions Copyright (c) 1996-2024, 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/detoast.h"
21 : #include "access/htup_details.h"
22 : #include "access/transam.h"
23 : #include "access/tupconvert.h"
24 : #include "catalog/pg_proc.h"
25 : #include "catalog/pg_type.h"
26 : #include "commands/defrem.h"
27 : #include "executor/execExpr.h"
28 : #include "executor/spi.h"
29 : #include "executor/tstoreReceiver.h"
30 : #include "funcapi.h"
31 : #include "mb/stringinfo_mb.h"
32 : #include "miscadmin.h"
33 : #include "nodes/nodeFuncs.h"
34 : #include "optimizer/optimizer.h"
35 : #include "parser/parse_coerce.h"
36 : #include "parser/parse_type.h"
37 : #include "parser/scansup.h"
38 : #include "plpgsql.h"
39 : #include "storage/proc.h"
40 : #include "tcop/cmdtag.h"
41 : #include "tcop/pquery.h"
42 : #include "tcop/tcopprot.h"
43 : #include "tcop/utility.h"
44 : #include "utils/array.h"
45 : #include "utils/builtins.h"
46 : #include "utils/datum.h"
47 : #include "utils/fmgroids.h"
48 : #include "utils/lsyscache.h"
49 : #include "utils/memutils.h"
50 : #include "utils/rel.h"
51 : #include "utils/snapmgr.h"
52 : #include "utils/syscache.h"
53 : #include "utils/typcache.h"
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 : * (However, if a DO block executes COMMIT or ROLLBACK, then exec_stmt_commit
82 : * or exec_stmt_rollback will unlink it from the DO's simple-expression EState
83 : * and create a new shared EState that will be used thenceforth. The original
84 : * EState will be cleaned up when we get back to plpgsql_inline_handler. This
85 : * is a bit ugly, but it isn't worth doing better, since scenarios like this
86 : * can't result in indefinite accumulation of state trees.)
87 : */
88 : typedef struct SimpleEcontextStackEntry
89 : {
90 : ExprContext *stack_econtext; /* a stacked econtext */
91 : SubTransactionId xact_subxid; /* ID for current subxact */
92 : struct SimpleEcontextStackEntry *next; /* next stack entry up */
93 : } SimpleEcontextStackEntry;
94 :
95 : static EState *shared_simple_eval_estate = NULL;
96 : static SimpleEcontextStackEntry *simple_econtext_stack = NULL;
97 :
98 : /*
99 : * In addition to the shared simple-eval EState, we have a shared resource
100 : * owner that holds refcounts on the CachedPlans for any "simple" expressions
101 : * we have evaluated in the current transaction. This allows us to avoid
102 : * continually grabbing and releasing a plan refcount when a simple expression
103 : * is used over and over. (DO blocks use their own resowner, in exactly the
104 : * same way described above for shared_simple_eval_estate.)
105 : */
106 : static ResourceOwner shared_simple_eval_resowner = NULL;
107 :
108 : /*
109 : * Memory management within a plpgsql function generally works with three
110 : * contexts:
111 : *
112 : * 1. Function-call-lifespan data, such as variable values, is kept in the
113 : * "main" context, a/k/a the "SPI Proc" context established by SPI_connect().
114 : * This is usually the CurrentMemoryContext while running code in this module
115 : * (which is not good, because careless coding can easily cause
116 : * function-lifespan memory leaks, but we live with it for now).
117 : *
118 : * 2. Some statement-execution routines need statement-lifespan workspace.
119 : * A suitable context is created on-demand by get_stmt_mcontext(), and must
120 : * be reset at the end of the requesting routine. Error recovery will clean
121 : * it up automatically. Nested statements requiring statement-lifespan
122 : * workspace will result in a stack of such contexts, see push_stmt_mcontext().
123 : *
124 : * 3. We use the eval_econtext's per-tuple memory context for expression
125 : * evaluation, and as a general-purpose workspace for short-lived allocations.
126 : * Such allocations usually aren't explicitly freed, but are left to be
127 : * cleaned up by a context reset, typically done by exec_eval_cleanup().
128 : *
129 : * These macros are for use in making short-lived allocations:
130 : */
131 : #define get_eval_mcontext(estate) \
132 : ((estate)->eval_econtext->ecxt_per_tuple_memory)
133 : #define eval_mcontext_alloc(estate, sz) \
134 : MemoryContextAlloc(get_eval_mcontext(estate), sz)
135 : #define eval_mcontext_alloc0(estate, sz) \
136 : MemoryContextAllocZero(get_eval_mcontext(estate), sz)
137 :
138 : /*
139 : * We use two session-wide hash tables for caching cast information.
140 : *
141 : * cast_expr_hash entries (of type plpgsql_CastExprHashEntry) hold compiled
142 : * expression trees for casts. These survive for the life of the session and
143 : * are shared across all PL/pgSQL functions and DO blocks. At some point it
144 : * might be worth invalidating them after pg_cast changes, but for the moment
145 : * we don't bother.
146 : *
147 : * There is a separate hash table shared_cast_hash (with entries of type
148 : * plpgsql_CastHashEntry) containing evaluation state trees for these
149 : * expressions, which are managed in the same way as simple expressions
150 : * (i.e., we assume cast expressions are always simple).
151 : *
152 : * As with simple expressions, DO blocks don't use the shared_cast_hash table
153 : * but must have their own evaluation state trees. This isn't ideal, but we
154 : * don't want to deal with multiple simple_eval_estates within a DO block.
155 : */
156 : typedef struct /* lookup key for cast info */
157 : {
158 : /* NB: we assume this struct contains no padding bytes */
159 : Oid srctype; /* source type for cast */
160 : Oid dsttype; /* destination type for cast */
161 : int32 srctypmod; /* source typmod for cast */
162 : int32 dsttypmod; /* destination typmod for cast */
163 : } plpgsql_CastHashKey;
164 :
165 : typedef struct /* cast_expr_hash table entry */
166 : {
167 : plpgsql_CastHashKey key; /* hash key --- MUST BE FIRST */
168 : Expr *cast_expr; /* cast expression, or NULL if no-op cast */
169 : CachedExpression *cast_cexpr; /* cached expression backing the above */
170 : } plpgsql_CastExprHashEntry;
171 :
172 : typedef struct /* cast_hash table entry */
173 : {
174 : plpgsql_CastHashKey key; /* hash key --- MUST BE FIRST */
175 : plpgsql_CastExprHashEntry *cast_centry; /* link to matching expr entry */
176 : /* ExprState is valid only when cast_lxid matches current LXID */
177 : ExprState *cast_exprstate; /* expression's eval tree */
178 : bool cast_in_use; /* true while we're executing eval tree */
179 : LocalTransactionId cast_lxid;
180 : } plpgsql_CastHashEntry;
181 :
182 : static HTAB *cast_expr_hash = NULL;
183 : static HTAB *shared_cast_hash = NULL;
184 :
185 : /*
186 : * LOOP_RC_PROCESSING encapsulates common logic for looping statements to
187 : * handle return/exit/continue result codes from the loop body statement(s).
188 : * It's meant to be used like this:
189 : *
190 : * int rc = PLPGSQL_RC_OK;
191 : * for (...)
192 : * {
193 : * ...
194 : * rc = exec_stmts(estate, stmt->body);
195 : * LOOP_RC_PROCESSING(stmt->label, break);
196 : * ...
197 : * }
198 : * return rc;
199 : *
200 : * If execution of the loop should terminate, LOOP_RC_PROCESSING will execute
201 : * "exit_action" (typically a "break" or "goto"), after updating "rc" to the
202 : * value the current statement should return. If execution should continue,
203 : * LOOP_RC_PROCESSING will do nothing except reset "rc" to PLPGSQL_RC_OK.
204 : *
205 : * estate and rc are implicit arguments to the macro.
206 : * estate->exitlabel is examined and possibly updated.
207 : */
208 : #define LOOP_RC_PROCESSING(looplabel, exit_action) \
209 : if (rc == PLPGSQL_RC_RETURN) \
210 : { \
211 : /* RETURN, so propagate RC_RETURN out */ \
212 : exit_action; \
213 : } \
214 : else if (rc == PLPGSQL_RC_EXIT) \
215 : { \
216 : if (estate->exitlabel == NULL) \
217 : { \
218 : /* unlabeled EXIT terminates this loop */ \
219 : rc = PLPGSQL_RC_OK; \
220 : exit_action; \
221 : } \
222 : else if ((looplabel) != NULL && \
223 : strcmp(looplabel, estate->exitlabel) == 0) \
224 : { \
225 : /* labeled EXIT matching this loop, so terminate loop */ \
226 : estate->exitlabel = NULL; \
227 : rc = PLPGSQL_RC_OK; \
228 : exit_action; \
229 : } \
230 : else \
231 : { \
232 : /* non-matching labeled EXIT, propagate RC_EXIT out */ \
233 : exit_action; \
234 : } \
235 : } \
236 : else if (rc == PLPGSQL_RC_CONTINUE) \
237 : { \
238 : if (estate->exitlabel == NULL) \
239 : { \
240 : /* unlabeled CONTINUE matches this loop, so continue in loop */ \
241 : rc = PLPGSQL_RC_OK; \
242 : } \
243 : else if ((looplabel) != NULL && \
244 : strcmp(looplabel, estate->exitlabel) == 0) \
245 : { \
246 : /* labeled CONTINUE matching this loop, so continue in loop */ \
247 : estate->exitlabel = NULL; \
248 : rc = PLPGSQL_RC_OK; \
249 : } \
250 : else \
251 : { \
252 : /* non-matching labeled CONTINUE, propagate RC_CONTINUE out */ \
253 : exit_action; \
254 : } \
255 : } \
256 : else \
257 : Assert(rc == PLPGSQL_RC_OK)
258 :
259 : /************************************************************
260 : * Local function forward declarations
261 : ************************************************************/
262 : static void coerce_function_result_tuple(PLpgSQL_execstate *estate,
263 : TupleDesc tupdesc);
264 : static void plpgsql_exec_error_callback(void *arg);
265 : static void copy_plpgsql_datums(PLpgSQL_execstate *estate,
266 : PLpgSQL_function *func);
267 : static void plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
268 : PLpgSQL_var *var);
269 : static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate);
270 : static void push_stmt_mcontext(PLpgSQL_execstate *estate);
271 : static void pop_stmt_mcontext(PLpgSQL_execstate *estate);
272 :
273 : static int exec_toplevel_block(PLpgSQL_execstate *estate,
274 : PLpgSQL_stmt_block *block);
275 : static int exec_stmt_block(PLpgSQL_execstate *estate,
276 : PLpgSQL_stmt_block *block);
277 : static int exec_stmts(PLpgSQL_execstate *estate,
278 : List *stmts);
279 : static int exec_stmt_assign(PLpgSQL_execstate *estate,
280 : PLpgSQL_stmt_assign *stmt);
281 : static int exec_stmt_perform(PLpgSQL_execstate *estate,
282 : PLpgSQL_stmt_perform *stmt);
283 : static int exec_stmt_call(PLpgSQL_execstate *estate,
284 : PLpgSQL_stmt_call *stmt);
285 : static int exec_stmt_getdiag(PLpgSQL_execstate *estate,
286 : PLpgSQL_stmt_getdiag *stmt);
287 : static int exec_stmt_if(PLpgSQL_execstate *estate,
288 : PLpgSQL_stmt_if *stmt);
289 : static int exec_stmt_case(PLpgSQL_execstate *estate,
290 : PLpgSQL_stmt_case *stmt);
291 : static int exec_stmt_loop(PLpgSQL_execstate *estate,
292 : PLpgSQL_stmt_loop *stmt);
293 : static int exec_stmt_while(PLpgSQL_execstate *estate,
294 : PLpgSQL_stmt_while *stmt);
295 : static int exec_stmt_fori(PLpgSQL_execstate *estate,
296 : PLpgSQL_stmt_fori *stmt);
297 : static int exec_stmt_fors(PLpgSQL_execstate *estate,
298 : PLpgSQL_stmt_fors *stmt);
299 : static int exec_stmt_forc(PLpgSQL_execstate *estate,
300 : PLpgSQL_stmt_forc *stmt);
301 : static int exec_stmt_foreach_a(PLpgSQL_execstate *estate,
302 : PLpgSQL_stmt_foreach_a *stmt);
303 : static int exec_stmt_open(PLpgSQL_execstate *estate,
304 : PLpgSQL_stmt_open *stmt);
305 : static int exec_stmt_fetch(PLpgSQL_execstate *estate,
306 : PLpgSQL_stmt_fetch *stmt);
307 : static int exec_stmt_close(PLpgSQL_execstate *estate,
308 : PLpgSQL_stmt_close *stmt);
309 : static int exec_stmt_exit(PLpgSQL_execstate *estate,
310 : PLpgSQL_stmt_exit *stmt);
311 : static int exec_stmt_return(PLpgSQL_execstate *estate,
312 : PLpgSQL_stmt_return *stmt);
313 : static int exec_stmt_return_next(PLpgSQL_execstate *estate,
314 : PLpgSQL_stmt_return_next *stmt);
315 : static int exec_stmt_return_query(PLpgSQL_execstate *estate,
316 : PLpgSQL_stmt_return_query *stmt);
317 : static int exec_stmt_raise(PLpgSQL_execstate *estate,
318 : PLpgSQL_stmt_raise *stmt);
319 : static int exec_stmt_assert(PLpgSQL_execstate *estate,
320 : PLpgSQL_stmt_assert *stmt);
321 : static int exec_stmt_execsql(PLpgSQL_execstate *estate,
322 : PLpgSQL_stmt_execsql *stmt);
323 : static int exec_stmt_dynexecute(PLpgSQL_execstate *estate,
324 : PLpgSQL_stmt_dynexecute *stmt);
325 : static int exec_stmt_dynfors(PLpgSQL_execstate *estate,
326 : PLpgSQL_stmt_dynfors *stmt);
327 : static int exec_stmt_commit(PLpgSQL_execstate *estate,
328 : PLpgSQL_stmt_commit *stmt);
329 : static int exec_stmt_rollback(PLpgSQL_execstate *estate,
330 : PLpgSQL_stmt_rollback *stmt);
331 :
332 : static void plpgsql_estate_setup(PLpgSQL_execstate *estate,
333 : PLpgSQL_function *func,
334 : ReturnSetInfo *rsi,
335 : EState *simple_eval_estate,
336 : ResourceOwner simple_eval_resowner);
337 : static void exec_eval_cleanup(PLpgSQL_execstate *estate);
338 :
339 : static void exec_prepare_plan(PLpgSQL_execstate *estate,
340 : PLpgSQL_expr *expr, int cursorOptions);
341 : static void exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr);
342 : static void exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan);
343 : static void exec_check_rw_parameter(PLpgSQL_expr *expr);
344 : static void exec_check_assignable(PLpgSQL_execstate *estate, int dno);
345 : static bool exec_eval_simple_expr(PLpgSQL_execstate *estate,
346 : PLpgSQL_expr *expr,
347 : Datum *result,
348 : bool *isNull,
349 : Oid *rettype,
350 : int32 *rettypmod);
351 :
352 : static void exec_assign_expr(PLpgSQL_execstate *estate,
353 : PLpgSQL_datum *target,
354 : PLpgSQL_expr *expr);
355 : static void exec_assign_c_string(PLpgSQL_execstate *estate,
356 : PLpgSQL_datum *target,
357 : const char *str);
358 : static void exec_assign_value(PLpgSQL_execstate *estate,
359 : PLpgSQL_datum *target,
360 : Datum value, bool isNull,
361 : Oid valtype, int32 valtypmod);
362 : static void exec_eval_datum(PLpgSQL_execstate *estate,
363 : PLpgSQL_datum *datum,
364 : Oid *typeid,
365 : int32 *typetypmod,
366 : Datum *value,
367 : bool *isnull);
368 : static int exec_eval_integer(PLpgSQL_execstate *estate,
369 : PLpgSQL_expr *expr,
370 : bool *isNull);
371 : static bool exec_eval_boolean(PLpgSQL_execstate *estate,
372 : PLpgSQL_expr *expr,
373 : bool *isNull);
374 : static Datum exec_eval_expr(PLpgSQL_execstate *estate,
375 : PLpgSQL_expr *expr,
376 : bool *isNull,
377 : Oid *rettype,
378 : int32 *rettypmod);
379 : static int exec_run_select(PLpgSQL_execstate *estate,
380 : PLpgSQL_expr *expr, long maxtuples, Portal *portalP);
381 : static int exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
382 : Portal portal, bool prefetch_ok);
383 : static ParamListInfo setup_param_list(PLpgSQL_execstate *estate,
384 : PLpgSQL_expr *expr);
385 : static ParamExternData *plpgsql_param_fetch(ParamListInfo params,
386 : int paramid, bool speculative,
387 : ParamExternData *prm);
388 : static void plpgsql_param_compile(ParamListInfo params, Param *param,
389 : ExprState *state,
390 : Datum *resv, bool *resnull);
391 : static void plpgsql_param_eval_var(ExprState *state, ExprEvalStep *op,
392 : ExprContext *econtext);
393 : static void plpgsql_param_eval_var_ro(ExprState *state, ExprEvalStep *op,
394 : ExprContext *econtext);
395 : static void plpgsql_param_eval_recfield(ExprState *state, ExprEvalStep *op,
396 : ExprContext *econtext);
397 : static void plpgsql_param_eval_generic(ExprState *state, ExprEvalStep *op,
398 : ExprContext *econtext);
399 : static void plpgsql_param_eval_generic_ro(ExprState *state, ExprEvalStep *op,
400 : ExprContext *econtext);
401 : static void exec_move_row(PLpgSQL_execstate *estate,
402 : PLpgSQL_variable *target,
403 : HeapTuple tup, TupleDesc tupdesc);
404 : static void revalidate_rectypeid(PLpgSQL_rec *rec);
405 : static ExpandedRecordHeader *make_expanded_record_for_rec(PLpgSQL_execstate *estate,
406 : PLpgSQL_rec *rec,
407 : TupleDesc srctupdesc,
408 : ExpandedRecordHeader *srcerh);
409 : static void exec_move_row_from_fields(PLpgSQL_execstate *estate,
410 : PLpgSQL_variable *target,
411 : ExpandedRecordHeader *newerh,
412 : Datum *values, bool *nulls,
413 : TupleDesc tupdesc);
414 : static bool compatible_tupdescs(TupleDesc src_tupdesc, TupleDesc dst_tupdesc);
415 : static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
416 : PLpgSQL_row *row,
417 : TupleDesc tupdesc);
418 : static TupleDesc deconstruct_composite_datum(Datum value,
419 : HeapTupleData *tmptup);
420 : static void exec_move_row_from_datum(PLpgSQL_execstate *estate,
421 : PLpgSQL_variable *target,
422 : Datum value);
423 : static void instantiate_empty_record_variable(PLpgSQL_execstate *estate,
424 : PLpgSQL_rec *rec);
425 : static char *convert_value_to_string(PLpgSQL_execstate *estate,
426 : Datum value, Oid valtype);
427 : static inline Datum exec_cast_value(PLpgSQL_execstate *estate,
428 : Datum value, bool *isnull,
429 : Oid valtype, int32 valtypmod,
430 : Oid reqtype, int32 reqtypmod);
431 : static Datum do_cast_value(PLpgSQL_execstate *estate,
432 : Datum value, bool *isnull,
433 : Oid valtype, int32 valtypmod,
434 : Oid reqtype, int32 reqtypmod);
435 : static plpgsql_CastHashEntry *get_cast_hashentry(PLpgSQL_execstate *estate,
436 : Oid srctype, int32 srctypmod,
437 : Oid dsttype, int32 dsttypmod);
438 : static void exec_init_tuple_store(PLpgSQL_execstate *estate);
439 : static void exec_set_found(PLpgSQL_execstate *estate, bool state);
440 : static void plpgsql_create_econtext(PLpgSQL_execstate *estate);
441 : static void plpgsql_destroy_econtext(PLpgSQL_execstate *estate);
442 : static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
443 : Datum newvalue, bool isnull, bool freeable);
444 : static void assign_text_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
445 : const char *str);
446 : static void assign_record_var(PLpgSQL_execstate *estate, PLpgSQL_rec *rec,
447 : ExpandedRecordHeader *erh);
448 : static ParamListInfo exec_eval_using_params(PLpgSQL_execstate *estate,
449 : List *params);
450 : static Portal exec_dynquery_with_params(PLpgSQL_execstate *estate,
451 : PLpgSQL_expr *dynquery, List *params,
452 : const char *portalname, int cursorOptions);
453 : static char *format_expr_params(PLpgSQL_execstate *estate,
454 : const PLpgSQL_expr *expr);
455 : static char *format_preparedparamsdata(PLpgSQL_execstate *estate,
456 : ParamListInfo paramLI);
457 : static PLpgSQL_variable *make_callstmt_target(PLpgSQL_execstate *estate,
458 : PLpgSQL_expr *expr);
459 :
460 :
461 : /* ----------
462 : * plpgsql_exec_function Called by the call handler for
463 : * function execution.
464 : *
465 : * This is also used to execute inline code blocks (DO blocks). The only
466 : * difference that this code is aware of is that for a DO block, we want
467 : * to use a private simple_eval_estate and a private simple_eval_resowner,
468 : * which are created and passed in by the caller. For regular functions,
469 : * pass NULL, which implies using shared_simple_eval_estate and
470 : * shared_simple_eval_resowner. (When using a private simple_eval_estate,
471 : * we must also use a private cast hashtable, but that's taken care of
472 : * within plpgsql_estate_setup.)
473 : * procedure_resowner is a resowner that will survive for the duration
474 : * of execution of this function/procedure. It is needed only if we
475 : * are doing non-atomic execution and there are CALL or DO statements
476 : * in the function; otherwise it can be NULL. We use it to hold refcounts
477 : * on the CALL/DO statements' plans.
478 : * ----------
479 : */
480 : Datum
481 65044 : plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
482 : EState *simple_eval_estate,
483 : ResourceOwner simple_eval_resowner,
484 : ResourceOwner procedure_resowner,
485 : bool atomic)
486 : {
487 : PLpgSQL_execstate estate;
488 : ErrorContextCallback plerrcontext;
489 : int i;
490 : int rc;
491 :
492 : /*
493 : * Setup the execution state
494 : */
495 65044 : plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo,
496 : simple_eval_estate, simple_eval_resowner);
497 65044 : estate.procedure_resowner = procedure_resowner;
498 65044 : estate.atomic = atomic;
499 :
500 : /*
501 : * Setup error traceback support for ereport()
502 : */
503 65044 : plerrcontext.callback = plpgsql_exec_error_callback;
504 65044 : plerrcontext.arg = &estate;
505 65044 : plerrcontext.previous = error_context_stack;
506 65044 : error_context_stack = &plerrcontext;
507 :
508 : /*
509 : * Make local execution copies of all the datums
510 : */
511 65044 : estate.err_text = gettext_noop("during initialization of execution state");
512 65044 : copy_plpgsql_datums(&estate, func);
513 :
514 : /*
515 : * Store the actual call argument values into the appropriate variables
516 : */
517 65044 : estate.err_text = gettext_noop("while storing call arguments into local variables");
518 144848 : for (i = 0; i < func->fn_nargs; i++)
519 : {
520 79804 : int n = func->fn_argvarnos[i];
521 :
522 79804 : switch (estate.datums[n]->dtype)
523 : {
524 79520 : case PLPGSQL_DTYPE_VAR:
525 : {
526 79520 : PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
527 :
528 79520 : assign_simple_var(&estate, var,
529 : fcinfo->args[i].value,
530 79520 : fcinfo->args[i].isnull,
531 : false);
532 :
533 : /*
534 : * Force any array-valued parameter to be stored in
535 : * expanded form in our local variable, in hopes of
536 : * improving efficiency of uses of the variable. (This is
537 : * a hack, really: why only arrays? Need more thought
538 : * about which cases are likely to win. See also
539 : * typisarray-specific heuristic in exec_assign_value.)
540 : *
541 : * Special cases: If passed a R/W expanded pointer, assume
542 : * we can commandeer the object rather than having to copy
543 : * it. If passed a R/O expanded pointer, just keep it as
544 : * the value of the variable for the moment. (We'll force
545 : * it to R/W if the variable gets modified, but that may
546 : * very well never happen.)
547 : */
548 79520 : if (!var->isnull && var->datatype->typisarray)
549 : {
550 3484 : if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(var->value)))
551 : {
552 : /* take ownership of R/W object */
553 6 : assign_simple_var(&estate, var,
554 : TransferExpandedObject(var->value,
555 : estate.datum_context),
556 : false,
557 : true);
558 : }
559 3478 : else if (VARATT_IS_EXTERNAL_EXPANDED_RO(DatumGetPointer(var->value)))
560 : {
561 : /* R/O pointer, keep it as-is until assigned to */
562 : }
563 : else
564 : {
565 : /* flat array, so force to expanded form */
566 3418 : assign_simple_var(&estate, var,
567 : expand_array(var->value,
568 : estate.datum_context,
569 : NULL),
570 : false,
571 : true);
572 : }
573 : }
574 : }
575 79520 : break;
576 :
577 284 : case PLPGSQL_DTYPE_REC:
578 : {
579 284 : PLpgSQL_rec *rec = (PLpgSQL_rec *) estate.datums[n];
580 :
581 284 : if (!fcinfo->args[i].isnull)
582 : {
583 : /* Assign row value from composite datum */
584 224 : exec_move_row_from_datum(&estate,
585 : (PLpgSQL_variable *) rec,
586 : fcinfo->args[i].value);
587 : }
588 : else
589 : {
590 : /* If arg is null, set variable to null */
591 60 : exec_move_row(&estate, (PLpgSQL_variable *) rec,
592 : NULL, NULL);
593 : }
594 : /* clean up after exec_move_row() */
595 284 : exec_eval_cleanup(&estate);
596 : }
597 284 : break;
598 :
599 0 : default:
600 : /* Anything else should not be an argument variable */
601 0 : elog(ERROR, "unrecognized dtype: %d", func->datums[i]->dtype);
602 : }
603 : }
604 :
605 65044 : estate.err_text = gettext_noop("during function entry");
606 :
607 : /*
608 : * Set the magic variable FOUND to false
609 : */
610 65044 : exec_set_found(&estate, false);
611 :
612 : /*
613 : * Let the instrumentation plugin peek at this function
614 : */
615 65044 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
616 0 : ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
617 :
618 : /*
619 : * Now call the toplevel block of statements
620 : */
621 65044 : estate.err_text = NULL;
622 65044 : rc = exec_toplevel_block(&estate, func->action);
623 64200 : if (rc != PLPGSQL_RC_RETURN)
624 : {
625 6 : estate.err_text = NULL;
626 6 : ereport(ERROR,
627 : (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
628 : errmsg("control reached end of function without RETURN")));
629 : }
630 :
631 : /*
632 : * We got a return value - process it
633 : */
634 64194 : estate.err_text = gettext_noop("while casting return value to function's return type");
635 :
636 64194 : fcinfo->isnull = estate.retisnull;
637 :
638 64194 : if (estate.retisset)
639 : {
640 3438 : ReturnSetInfo *rsi = estate.rsi;
641 :
642 : /* Check caller can handle a set result */
643 3438 : if (!rsi || !IsA(rsi, ReturnSetInfo))
644 0 : ereport(ERROR,
645 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
646 : errmsg("set-valued function called in context that cannot accept a set")));
647 :
648 3438 : if (!(rsi->allowedModes & SFRM_Materialize))
649 0 : ereport(ERROR,
650 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
651 : errmsg("materialize mode required, but it is not allowed in this context")));
652 :
653 3438 : rsi->returnMode = SFRM_Materialize;
654 :
655 : /* If we produced any tuples, send back the result */
656 3438 : if (estate.tuple_store)
657 : {
658 : MemoryContext oldcxt;
659 :
660 3420 : rsi->setResult = estate.tuple_store;
661 3420 : oldcxt = MemoryContextSwitchTo(estate.tuple_store_cxt);
662 3420 : rsi->setDesc = CreateTupleDescCopy(estate.tuple_store_desc);
663 3420 : MemoryContextSwitchTo(oldcxt);
664 : }
665 3438 : estate.retval = (Datum) 0;
666 3438 : fcinfo->isnull = true;
667 : }
668 60756 : else if (!estate.retisnull)
669 : {
670 : /*
671 : * Cast result value to function's declared result type, and copy it
672 : * out to the upper executor memory context. We must treat tuple
673 : * results specially in order to deal with cases like rowtypes
674 : * involving dropped columns.
675 : */
676 60320 : if (estate.retistuple)
677 : {
678 : /* Don't need coercion if rowtype is known to match */
679 6450 : if (func->fn_rettype == estate.rettype &&
680 6388 : func->fn_rettype != RECORDOID)
681 : {
682 : /*
683 : * Copy the tuple result into upper executor memory context.
684 : * However, if we have a R/W expanded datum, we can just
685 : * transfer its ownership out to the upper context.
686 : */
687 218 : estate.retval = SPI_datumTransfer(estate.retval,
688 : false,
689 : -1);
690 : }
691 : else
692 : {
693 : /*
694 : * Need to look up the expected result type. XXX would be
695 : * better to cache the tupdesc instead of repeating
696 : * get_call_result_type(), but the only easy place to save it
697 : * is in the PLpgSQL_function struct, and that's too
698 : * long-lived: composite types could change during the
699 : * existence of a PLpgSQL_function.
700 : */
701 : Oid resultTypeId;
702 : TupleDesc tupdesc;
703 :
704 6232 : switch (get_call_result_type(fcinfo, &resultTypeId, &tupdesc))
705 : {
706 6160 : case TYPEFUNC_COMPOSITE:
707 : /* got the expected result rowtype, now coerce it */
708 6160 : coerce_function_result_tuple(&estate, tupdesc);
709 6130 : break;
710 16 : case TYPEFUNC_COMPOSITE_DOMAIN:
711 : /* got the expected result rowtype, now coerce it */
712 16 : coerce_function_result_tuple(&estate, tupdesc);
713 : /* and check domain constraints */
714 : /* XXX allowing caching here would be good, too */
715 16 : domain_check(estate.retval, false, resultTypeId,
716 : NULL, NULL);
717 8 : break;
718 56 : case TYPEFUNC_RECORD:
719 :
720 : /*
721 : * Failed to determine actual type of RECORD. We
722 : * could raise an error here, but what this means in
723 : * practice is that the caller is expecting any old
724 : * generic rowtype, so we don't really need to be
725 : * restrictive. Pass back the generated result as-is.
726 : */
727 56 : estate.retval = SPI_datumTransfer(estate.retval,
728 : false,
729 : -1);
730 56 : break;
731 0 : default:
732 : /* shouldn't get here if retistuple is true ... */
733 0 : elog(ERROR, "return type must be a row type");
734 : break;
735 : }
736 : }
737 : }
738 : else
739 : {
740 : /* Scalar case: use exec_cast_value */
741 53870 : estate.retval = exec_cast_value(&estate,
742 : estate.retval,
743 : &fcinfo->isnull,
744 : estate.rettype,
745 : -1,
746 : func->fn_rettype,
747 : -1);
748 :
749 : /*
750 : * If the function's return type isn't by value, copy the value
751 : * into upper executor memory context. However, if we have a R/W
752 : * expanded datum, we can just transfer its ownership out to the
753 : * upper executor context.
754 : */
755 53834 : if (!fcinfo->isnull && !func->fn_retbyval)
756 5534 : estate.retval = SPI_datumTransfer(estate.retval,
757 : false,
758 : func->fn_rettyplen);
759 : }
760 : }
761 : else
762 : {
763 : /*
764 : * We're returning a NULL, which normally requires no conversion work
765 : * regardless of datatypes. But, if we are casting it to a domain
766 : * return type, we'd better check that the domain's constraints pass.
767 : */
768 436 : if (func->fn_retisdomain)
769 4 : estate.retval = exec_cast_value(&estate,
770 : estate.retval,
771 : &fcinfo->isnull,
772 : estate.rettype,
773 : -1,
774 : func->fn_rettype,
775 : -1);
776 : }
777 :
778 64118 : estate.err_text = gettext_noop("during function exit");
779 :
780 : /*
781 : * Let the instrumentation plugin peek at this function
782 : */
783 64118 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
784 0 : ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
785 :
786 : /* Clean up any leftover temporary memory */
787 64118 : plpgsql_destroy_econtext(&estate);
788 64118 : exec_eval_cleanup(&estate);
789 : /* stmt_mcontext will be destroyed when function's main context is */
790 :
791 : /*
792 : * Pop the error context stack
793 : */
794 64118 : error_context_stack = plerrcontext.previous;
795 :
796 : /*
797 : * Return the function's result
798 : */
799 64118 : return estate.retval;
800 : }
801 :
802 : /*
803 : * Helper for plpgsql_exec_function: coerce composite result to the specified
804 : * tuple descriptor, and copy it out to upper executor memory. This is split
805 : * out mostly for cosmetic reasons --- the logic would be very deeply nested
806 : * otherwise.
807 : *
808 : * estate->retval is updated in-place.
809 : */
810 : static void
811 6176 : coerce_function_result_tuple(PLpgSQL_execstate *estate, TupleDesc tupdesc)
812 : {
813 : HeapTuple rettup;
814 : TupleDesc retdesc;
815 : TupleConversionMap *tupmap;
816 :
817 : /* We assume exec_stmt_return verified that result is composite */
818 : Assert(type_is_rowtype(estate->rettype));
819 :
820 : /* We can special-case expanded records for speed */
821 6176 : if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(estate->retval)))
822 34 : {
823 46 : ExpandedRecordHeader *erh = (ExpandedRecordHeader *) DatumGetEOHP(estate->retval);
824 :
825 : Assert(erh->er_magic == ER_MAGIC);
826 :
827 : /* Extract record's TupleDesc */
828 46 : retdesc = expanded_record_get_tupdesc(erh);
829 :
830 : /* check rowtype compatibility */
831 46 : tupmap = convert_tuples_by_position(retdesc,
832 : tupdesc,
833 : gettext_noop("returned record type does not match expected record type"));
834 :
835 : /* it might need conversion */
836 34 : if (tupmap)
837 : {
838 2 : rettup = expanded_record_get_tuple(erh);
839 : Assert(rettup);
840 2 : rettup = execute_attr_map_tuple(rettup, tupmap);
841 :
842 : /*
843 : * Copy tuple to upper executor memory, as a tuple Datum. Make
844 : * sure it is labeled with the caller-supplied tuple type.
845 : */
846 2 : estate->retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
847 : /* no need to free map, we're about to return anyway */
848 : }
849 32 : else if (!(tupdesc->tdtypeid == erh->er_decltypeid ||
850 14 : (tupdesc->tdtypeid == RECORDOID &&
851 0 : !ExpandedRecordIsDomain(erh))))
852 14 : {
853 : /*
854 : * The expanded record has the right physical tupdesc, but the
855 : * wrong type ID. (Typically, the expanded record is RECORDOID
856 : * but the function is declared to return a named composite type.
857 : * As in exec_move_row_from_datum, we don't allow returning a
858 : * composite-domain record from a function declared to return
859 : * RECORD.) So we must flatten the record to a tuple datum and
860 : * overwrite its type fields with the right thing. spi.c doesn't
861 : * provide any easy way to deal with this case, so we end up
862 : * duplicating the guts of datumCopy() :-(
863 : */
864 : Size resultsize;
865 : HeapTupleHeader tuphdr;
866 :
867 14 : resultsize = EOH_get_flat_size(&erh->hdr);
868 14 : tuphdr = (HeapTupleHeader) SPI_palloc(resultsize);
869 14 : EOH_flatten_into(&erh->hdr, (void *) tuphdr, resultsize);
870 14 : HeapTupleHeaderSetTypeId(tuphdr, tupdesc->tdtypeid);
871 14 : HeapTupleHeaderSetTypMod(tuphdr, tupdesc->tdtypmod);
872 14 : estate->retval = PointerGetDatum(tuphdr);
873 : }
874 : else
875 : {
876 : /*
877 : * We need only copy result into upper executor memory context.
878 : * However, if we have a R/W expanded datum, we can just transfer
879 : * its ownership out to the upper executor context.
880 : */
881 18 : estate->retval = SPI_datumTransfer(estate->retval,
882 : false,
883 : -1);
884 : }
885 : }
886 : else
887 : {
888 : /* Convert composite datum to a HeapTuple and TupleDesc */
889 : HeapTupleData tmptup;
890 :
891 6130 : retdesc = deconstruct_composite_datum(estate->retval, &tmptup);
892 6130 : rettup = &tmptup;
893 :
894 : /* check rowtype compatibility */
895 6130 : tupmap = convert_tuples_by_position(retdesc,
896 : tupdesc,
897 : gettext_noop("returned record type does not match expected record type"));
898 :
899 : /* it might need conversion */
900 6112 : if (tupmap)
901 2 : rettup = execute_attr_map_tuple(rettup, tupmap);
902 :
903 : /*
904 : * Copy tuple to upper executor memory, as a tuple Datum. Make sure
905 : * it is labeled with the caller-supplied tuple type.
906 : */
907 6112 : estate->retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
908 :
909 : /* no need to free map, we're about to return anyway */
910 :
911 6112 : ReleaseTupleDesc(retdesc);
912 : }
913 6146 : }
914 :
915 :
916 : /* ----------
917 : * plpgsql_exec_trigger Called by the call handler for
918 : * trigger execution.
919 : * ----------
920 : */
921 : HeapTuple
922 15078 : plpgsql_exec_trigger(PLpgSQL_function *func,
923 : TriggerData *trigdata)
924 : {
925 : PLpgSQL_execstate estate;
926 : ErrorContextCallback plerrcontext;
927 : int rc;
928 : TupleDesc tupdesc;
929 : PLpgSQL_rec *rec_new,
930 : *rec_old;
931 : HeapTuple rettup;
932 :
933 : /*
934 : * Setup the execution state
935 : */
936 15078 : plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
937 15078 : estate.trigdata = trigdata;
938 :
939 : /*
940 : * Setup error traceback support for ereport()
941 : */
942 15078 : plerrcontext.callback = plpgsql_exec_error_callback;
943 15078 : plerrcontext.arg = &estate;
944 15078 : plerrcontext.previous = error_context_stack;
945 15078 : error_context_stack = &plerrcontext;
946 :
947 : /*
948 : * Make local execution copies of all the datums
949 : */
950 15078 : estate.err_text = gettext_noop("during initialization of execution state");
951 15078 : copy_plpgsql_datums(&estate, func);
952 :
953 : /*
954 : * Put the OLD and NEW tuples into record variables
955 : *
956 : * We set up expanded records for both variables even though only one may
957 : * have a value. This allows record references to succeed in functions
958 : * that are used for multiple trigger types. For example, we might have a
959 : * test like "if (TG_OP = 'INSERT' and NEW.foo = 'xyz')", which should
960 : * work regardless of the current trigger type. If a value is actually
961 : * fetched from an unsupplied tuple, it will read as NULL.
962 : */
963 15078 : tupdesc = RelationGetDescr(trigdata->tg_relation);
964 :
965 15078 : rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
966 15078 : rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
967 :
968 15078 : rec_new->erh = make_expanded_record_from_tupdesc(tupdesc,
969 : estate.datum_context);
970 15078 : rec_old->erh = make_expanded_record_from_exprecord(rec_new->erh,
971 : estate.datum_context);
972 :
973 15078 : if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
974 : {
975 : /*
976 : * Per-statement triggers don't use OLD/NEW variables
977 : */
978 : }
979 13634 : else if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
980 : {
981 6870 : expanded_record_set_tuple(rec_new->erh, trigdata->tg_trigtuple,
982 : false, false);
983 : }
984 6764 : else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
985 : {
986 6278 : expanded_record_set_tuple(rec_new->erh, trigdata->tg_newtuple,
987 : false, false);
988 6278 : expanded_record_set_tuple(rec_old->erh, trigdata->tg_trigtuple,
989 : false, false);
990 :
991 : /*
992 : * In BEFORE trigger, stored generated columns are not computed yet,
993 : * so make them null in the NEW row. (Only needed in UPDATE branch;
994 : * in the INSERT case, they are already null, but in UPDATE, the field
995 : * still contains the old value.) Alternatively, we could construct a
996 : * whole new row structure without the generated columns, but this way
997 : * seems more efficient and potentially less confusing.
998 : */
999 6278 : if (tupdesc->constr && tupdesc->constr->has_generated_stored &&
1000 44 : TRIGGER_FIRED_BEFORE(trigdata->tg_event))
1001 : {
1002 98 : for (int i = 0; i < tupdesc->natts; i++)
1003 66 : if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED)
1004 32 : expanded_record_set_field_internal(rec_new->erh,
1005 : i + 1,
1006 : (Datum) 0,
1007 : true, /* isnull */
1008 : false, false);
1009 : }
1010 : }
1011 486 : else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
1012 : {
1013 486 : expanded_record_set_tuple(rec_old->erh, trigdata->tg_trigtuple,
1014 : false, false);
1015 : }
1016 : else
1017 0 : elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
1018 :
1019 : /* Make transition tables visible to this SPI connection */
1020 15078 : rc = SPI_register_trigger_data(trigdata);
1021 : Assert(rc >= 0);
1022 :
1023 15078 : estate.err_text = gettext_noop("during function entry");
1024 :
1025 : /*
1026 : * Set the magic variable FOUND to false
1027 : */
1028 15078 : exec_set_found(&estate, false);
1029 :
1030 : /*
1031 : * Let the instrumentation plugin peek at this function
1032 : */
1033 15078 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1034 0 : ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1035 :
1036 : /*
1037 : * Now call the toplevel block of statements
1038 : */
1039 15078 : estate.err_text = NULL;
1040 15078 : rc = exec_toplevel_block(&estate, func->action);
1041 14888 : if (rc != PLPGSQL_RC_RETURN)
1042 : {
1043 0 : estate.err_text = NULL;
1044 0 : ereport(ERROR,
1045 : (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
1046 : errmsg("control reached end of trigger procedure without RETURN")));
1047 : }
1048 :
1049 14888 : estate.err_text = gettext_noop("during function exit");
1050 :
1051 14888 : if (estate.retisset)
1052 0 : ereport(ERROR,
1053 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1054 : errmsg("trigger procedure cannot return a set")));
1055 :
1056 : /*
1057 : * Check that the returned tuple structure has the same attributes, the
1058 : * relation that fired the trigger has. A per-statement trigger always
1059 : * needs to return NULL, so we ignore any return value the function itself
1060 : * produces (XXX: is this a good idea?)
1061 : *
1062 : * XXX This way it is possible, that the trigger returns a tuple where
1063 : * attributes don't have the correct atttypmod's length. It's up to the
1064 : * trigger's programmer to ensure that this doesn't happen. Jan
1065 : */
1066 14888 : if (estate.retisnull || !TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
1067 2728 : rettup = NULL;
1068 : else
1069 : {
1070 : TupleDesc retdesc;
1071 : TupleConversionMap *tupmap;
1072 :
1073 : /* We assume exec_stmt_return verified that result is composite */
1074 : Assert(type_is_rowtype(estate.rettype));
1075 :
1076 : /* We can special-case expanded records for speed */
1077 12160 : if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(estate.retval)))
1078 12156 : {
1079 12156 : ExpandedRecordHeader *erh = (ExpandedRecordHeader *) DatumGetEOHP(estate.retval);
1080 :
1081 : Assert(erh->er_magic == ER_MAGIC);
1082 :
1083 : /* Extract HeapTuple and TupleDesc */
1084 12156 : rettup = expanded_record_get_tuple(erh);
1085 : Assert(rettup);
1086 12156 : retdesc = expanded_record_get_tupdesc(erh);
1087 :
1088 12156 : if (retdesc != RelationGetDescr(trigdata->tg_relation))
1089 : {
1090 : /* check rowtype compatibility */
1091 4 : tupmap = convert_tuples_by_position(retdesc,
1092 4 : RelationGetDescr(trigdata->tg_relation),
1093 : gettext_noop("returned row structure does not match the structure of the triggering table"));
1094 : /* it might need conversion */
1095 4 : if (tupmap)
1096 4 : rettup = execute_attr_map_tuple(rettup, tupmap);
1097 : /* no need to free map, we're about to return anyway */
1098 : }
1099 :
1100 : /*
1101 : * Copy tuple to upper executor memory. But if user just did
1102 : * "return new" or "return old" without changing anything, there's
1103 : * no need to copy; we can return the original tuple (which will
1104 : * save a few cycles in trigger.c as well as here).
1105 : */
1106 12156 : if (rettup != trigdata->tg_newtuple &&
1107 7674 : rettup != trigdata->tg_trigtuple)
1108 2044 : rettup = SPI_copytuple(rettup);
1109 : }
1110 : else
1111 : {
1112 : /* Convert composite datum to a HeapTuple and TupleDesc */
1113 : HeapTupleData tmptup;
1114 :
1115 4 : retdesc = deconstruct_composite_datum(estate.retval, &tmptup);
1116 4 : rettup = &tmptup;
1117 :
1118 : /* check rowtype compatibility */
1119 4 : tupmap = convert_tuples_by_position(retdesc,
1120 4 : RelationGetDescr(trigdata->tg_relation),
1121 : gettext_noop("returned row structure does not match the structure of the triggering table"));
1122 : /* it might need conversion */
1123 4 : if (tupmap)
1124 4 : rettup = execute_attr_map_tuple(rettup, tupmap);
1125 :
1126 4 : ReleaseTupleDesc(retdesc);
1127 : /* no need to free map, we're about to return anyway */
1128 :
1129 : /* Copy tuple to upper executor memory */
1130 4 : rettup = SPI_copytuple(rettup);
1131 : }
1132 : }
1133 :
1134 : /*
1135 : * Let the instrumentation plugin peek at this function
1136 : */
1137 14888 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1138 0 : ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1139 :
1140 : /* Clean up any leftover temporary memory */
1141 14888 : plpgsql_destroy_econtext(&estate);
1142 14888 : exec_eval_cleanup(&estate);
1143 : /* stmt_mcontext will be destroyed when function's main context is */
1144 :
1145 : /*
1146 : * Pop the error context stack
1147 : */
1148 14888 : error_context_stack = plerrcontext.previous;
1149 :
1150 : /*
1151 : * Return the trigger's result
1152 : */
1153 14888 : return rettup;
1154 : }
1155 :
1156 : /* ----------
1157 : * plpgsql_exec_event_trigger Called by the call handler for
1158 : * event trigger execution.
1159 : * ----------
1160 : */
1161 : void
1162 1694 : plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
1163 : {
1164 : PLpgSQL_execstate estate;
1165 : ErrorContextCallback plerrcontext;
1166 : int rc;
1167 :
1168 : /*
1169 : * Setup the execution state
1170 : */
1171 1694 : plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
1172 1694 : estate.evtrigdata = trigdata;
1173 :
1174 : /*
1175 : * Setup error traceback support for ereport()
1176 : */
1177 1694 : plerrcontext.callback = plpgsql_exec_error_callback;
1178 1694 : plerrcontext.arg = &estate;
1179 1694 : plerrcontext.previous = error_context_stack;
1180 1694 : error_context_stack = &plerrcontext;
1181 :
1182 : /*
1183 : * Make local execution copies of all the datums
1184 : */
1185 1694 : estate.err_text = gettext_noop("during initialization of execution state");
1186 1694 : copy_plpgsql_datums(&estate, func);
1187 :
1188 : /*
1189 : * Let the instrumentation plugin peek at this function
1190 : */
1191 1694 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1192 0 : ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1193 :
1194 : /*
1195 : * Now call the toplevel block of statements
1196 : */
1197 1694 : estate.err_text = NULL;
1198 1694 : rc = exec_toplevel_block(&estate, func->action);
1199 1670 : if (rc != PLPGSQL_RC_RETURN)
1200 : {
1201 0 : estate.err_text = NULL;
1202 0 : ereport(ERROR,
1203 : (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
1204 : errmsg("control reached end of trigger procedure without RETURN")));
1205 : }
1206 :
1207 1670 : estate.err_text = gettext_noop("during function exit");
1208 :
1209 : /*
1210 : * Let the instrumentation plugin peek at this function
1211 : */
1212 1670 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1213 0 : ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1214 :
1215 : /* Clean up any leftover temporary memory */
1216 1670 : plpgsql_destroy_econtext(&estate);
1217 1670 : exec_eval_cleanup(&estate);
1218 : /* stmt_mcontext will be destroyed when function's main context is */
1219 :
1220 : /*
1221 : * Pop the error context stack
1222 : */
1223 1670 : error_context_stack = plerrcontext.previous;
1224 1670 : }
1225 :
1226 : /*
1227 : * error context callback to let us supply a call-stack traceback
1228 : */
1229 : static void
1230 21730 : plpgsql_exec_error_callback(void *arg)
1231 : {
1232 21730 : PLpgSQL_execstate *estate = (PLpgSQL_execstate *) arg;
1233 : int err_lineno;
1234 :
1235 : /*
1236 : * If err_var is set, report the variable's declaration line number.
1237 : * Otherwise, if err_stmt is set, report the err_stmt's line number. When
1238 : * err_stmt is not set, we're in function entry/exit, or some such place
1239 : * not attached to a specific line number.
1240 : */
1241 21730 : if (estate->err_var != NULL)
1242 60 : err_lineno = estate->err_var->lineno;
1243 21670 : else if (estate->err_stmt != NULL)
1244 21588 : err_lineno = estate->err_stmt->lineno;
1245 : else
1246 82 : err_lineno = 0;
1247 :
1248 21730 : if (estate->err_text != NULL)
1249 : {
1250 : /*
1251 : * We don't expend the cycles to run gettext() on err_text unless we
1252 : * actually need it. Therefore, places that set up err_text should
1253 : * use gettext_noop() to ensure the strings get recorded in the
1254 : * message dictionary.
1255 : */
1256 138 : if (err_lineno > 0)
1257 : {
1258 : /*
1259 : * translator: last %s is a phrase such as "during statement block
1260 : * local variable initialization"
1261 : */
1262 62 : errcontext("PL/pgSQL function %s line %d %s",
1263 62 : estate->func->fn_signature,
1264 : err_lineno,
1265 : _(estate->err_text));
1266 : }
1267 : else
1268 : {
1269 : /*
1270 : * translator: last %s is a phrase such as "while storing call
1271 : * arguments into local variables"
1272 : */
1273 76 : errcontext("PL/pgSQL function %s %s",
1274 76 : estate->func->fn_signature,
1275 : _(estate->err_text));
1276 : }
1277 : }
1278 21592 : else if (estate->err_stmt != NULL && err_lineno > 0)
1279 : {
1280 : /* translator: last %s is a plpgsql statement type name */
1281 21586 : errcontext("PL/pgSQL function %s line %d at %s",
1282 21586 : estate->func->fn_signature,
1283 : err_lineno,
1284 : plpgsql_stmt_typename(estate->err_stmt));
1285 : }
1286 : else
1287 6 : errcontext("PL/pgSQL function %s",
1288 6 : estate->func->fn_signature);
1289 21730 : }
1290 :
1291 :
1292 : /* ----------
1293 : * Support function for initializing local execution variables
1294 : * ----------
1295 : */
1296 : static void
1297 81816 : copy_plpgsql_datums(PLpgSQL_execstate *estate,
1298 : PLpgSQL_function *func)
1299 : {
1300 81816 : int ndatums = estate->ndatums;
1301 : PLpgSQL_datum **indatums;
1302 : PLpgSQL_datum **outdatums;
1303 : char *workspace;
1304 : char *ws_next;
1305 : int i;
1306 :
1307 : /* Allocate local datum-pointer array */
1308 81816 : estate->datums = (PLpgSQL_datum **)
1309 81816 : palloc(sizeof(PLpgSQL_datum *) * ndatums);
1310 :
1311 : /*
1312 : * To reduce palloc overhead, we make a single palloc request for all the
1313 : * space needed for locally-instantiated datums.
1314 : */
1315 81816 : workspace = palloc(func->copiable_size);
1316 81816 : ws_next = workspace;
1317 :
1318 : /* Fill datum-pointer array, copying datums into workspace as needed */
1319 81816 : indatums = func->datums;
1320 81816 : outdatums = estate->datums;
1321 560804 : for (i = 0; i < ndatums; i++)
1322 : {
1323 478988 : PLpgSQL_datum *indatum = indatums[i];
1324 : PLpgSQL_datum *outdatum;
1325 :
1326 : /* This must agree with plpgsql_finish_datums on what is copiable */
1327 478988 : switch (indatum->dtype)
1328 : {
1329 384092 : case PLPGSQL_DTYPE_VAR:
1330 : case PLPGSQL_DTYPE_PROMISE:
1331 384092 : outdatum = (PLpgSQL_datum *) ws_next;
1332 384092 : memcpy(outdatum, indatum, sizeof(PLpgSQL_var));
1333 384092 : ws_next += MAXALIGN(sizeof(PLpgSQL_var));
1334 384092 : break;
1335 :
1336 35712 : case PLPGSQL_DTYPE_REC:
1337 35712 : outdatum = (PLpgSQL_datum *) ws_next;
1338 35712 : memcpy(outdatum, indatum, sizeof(PLpgSQL_rec));
1339 35712 : ws_next += MAXALIGN(sizeof(PLpgSQL_rec));
1340 35712 : break;
1341 :
1342 59184 : case PLPGSQL_DTYPE_ROW:
1343 : case PLPGSQL_DTYPE_RECFIELD:
1344 :
1345 : /*
1346 : * These datum records are read-only at runtime, so no need to
1347 : * copy them (well, RECFIELD contains cached data, but we'd
1348 : * just as soon centralize the caching anyway).
1349 : */
1350 59184 : outdatum = indatum;
1351 59184 : break;
1352 :
1353 0 : default:
1354 0 : elog(ERROR, "unrecognized dtype: %d", indatum->dtype);
1355 : outdatum = NULL; /* keep compiler quiet */
1356 : break;
1357 : }
1358 :
1359 478988 : outdatums[i] = outdatum;
1360 : }
1361 :
1362 : Assert(ws_next == workspace + func->copiable_size);
1363 81816 : }
1364 :
1365 : /*
1366 : * If the variable has an armed "promise", compute the promised value
1367 : * and assign it to the variable.
1368 : * The assignment automatically disarms the promise.
1369 : */
1370 : static void
1371 22720 : plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
1372 : PLpgSQL_var *var)
1373 : {
1374 : MemoryContext oldcontext;
1375 :
1376 22720 : if (var->promise == PLPGSQL_PROMISE_NONE)
1377 6836 : return; /* nothing to do */
1378 :
1379 : /*
1380 : * This will typically be invoked in a short-lived context such as the
1381 : * mcontext. We must create variable values in the estate's datum
1382 : * context. This quick-and-dirty solution risks leaking some additional
1383 : * cruft there, but since any one promise is honored at most once per
1384 : * function call, it's probably not worth being more careful.
1385 : */
1386 15884 : oldcontext = MemoryContextSwitchTo(estate->datum_context);
1387 :
1388 15884 : switch (var->promise)
1389 : {
1390 1472 : case PLPGSQL_PROMISE_TG_NAME:
1391 1472 : if (estate->trigdata == NULL)
1392 0 : elog(ERROR, "trigger promise is not in a trigger function");
1393 1472 : assign_simple_var(estate, var,
1394 1472 : DirectFunctionCall1(namein,
1395 : CStringGetDatum(estate->trigdata->tg_trigger->tgname)),
1396 : false, true);
1397 1472 : break;
1398 :
1399 2442 : case PLPGSQL_PROMISE_TG_WHEN:
1400 2442 : if (estate->trigdata == NULL)
1401 0 : elog(ERROR, "trigger promise is not in a trigger function");
1402 2442 : if (TRIGGER_FIRED_BEFORE(estate->trigdata->tg_event))
1403 972 : assign_text_var(estate, var, "BEFORE");
1404 1470 : else if (TRIGGER_FIRED_AFTER(estate->trigdata->tg_event))
1405 1410 : assign_text_var(estate, var, "AFTER");
1406 60 : else if (TRIGGER_FIRED_INSTEAD(estate->trigdata->tg_event))
1407 60 : assign_text_var(estate, var, "INSTEAD OF");
1408 : else
1409 0 : elog(ERROR, "unrecognized trigger execution time: not BEFORE, AFTER, or INSTEAD OF");
1410 2442 : break;
1411 :
1412 2344 : case PLPGSQL_PROMISE_TG_LEVEL:
1413 2344 : if (estate->trigdata == NULL)
1414 0 : elog(ERROR, "trigger promise is not in a trigger function");
1415 2344 : if (TRIGGER_FIRED_FOR_ROW(estate->trigdata->tg_event))
1416 1504 : assign_text_var(estate, var, "ROW");
1417 840 : else if (TRIGGER_FIRED_FOR_STATEMENT(estate->trigdata->tg_event))
1418 840 : assign_text_var(estate, var, "STATEMENT");
1419 : else
1420 0 : elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
1421 2344 : break;
1422 :
1423 6064 : case PLPGSQL_PROMISE_TG_OP:
1424 6064 : if (estate->trigdata == NULL)
1425 0 : elog(ERROR, "trigger promise is not in a trigger function");
1426 6064 : if (TRIGGER_FIRED_BY_INSERT(estate->trigdata->tg_event))
1427 2910 : assign_text_var(estate, var, "INSERT");
1428 3154 : else if (TRIGGER_FIRED_BY_UPDATE(estate->trigdata->tg_event))
1429 2714 : assign_text_var(estate, var, "UPDATE");
1430 440 : else if (TRIGGER_FIRED_BY_DELETE(estate->trigdata->tg_event))
1431 424 : assign_text_var(estate, var, "DELETE");
1432 16 : else if (TRIGGER_FIRED_BY_TRUNCATE(estate->trigdata->tg_event))
1433 16 : assign_text_var(estate, var, "TRUNCATE");
1434 : else
1435 0 : elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, UPDATE, or TRUNCATE");
1436 6064 : break;
1437 :
1438 122 : case PLPGSQL_PROMISE_TG_RELID:
1439 122 : if (estate->trigdata == NULL)
1440 0 : elog(ERROR, "trigger promise is not in a trigger function");
1441 122 : assign_simple_var(estate, var,
1442 122 : ObjectIdGetDatum(estate->trigdata->tg_relation->rd_id),
1443 : false, false);
1444 122 : break;
1445 :
1446 884 : case PLPGSQL_PROMISE_TG_TABLE_NAME:
1447 884 : if (estate->trigdata == NULL)
1448 0 : elog(ERROR, "trigger promise is not in a trigger function");
1449 884 : assign_simple_var(estate, var,
1450 884 : DirectFunctionCall1(namein,
1451 : CStringGetDatum(RelationGetRelationName(estate->trigdata->tg_relation))),
1452 : false, true);
1453 884 : break;
1454 :
1455 18 : case PLPGSQL_PROMISE_TG_TABLE_SCHEMA:
1456 18 : if (estate->trigdata == NULL)
1457 0 : elog(ERROR, "trigger promise is not in a trigger function");
1458 18 : assign_simple_var(estate, var,
1459 18 : DirectFunctionCall1(namein,
1460 : CStringGetDatum(get_namespace_name(RelationGetNamespace(estate->trigdata->tg_relation)))),
1461 : false, true);
1462 18 : break;
1463 :
1464 290 : case PLPGSQL_PROMISE_TG_NARGS:
1465 290 : if (estate->trigdata == NULL)
1466 0 : elog(ERROR, "trigger promise is not in a trigger function");
1467 290 : assign_simple_var(estate, var,
1468 290 : Int16GetDatum(estate->trigdata->tg_trigger->tgnargs),
1469 : false, false);
1470 290 : break;
1471 :
1472 1796 : case PLPGSQL_PROMISE_TG_ARGV:
1473 1796 : if (estate->trigdata == NULL)
1474 0 : elog(ERROR, "trigger promise is not in a trigger function");
1475 1796 : if (estate->trigdata->tg_trigger->tgnargs > 0)
1476 : {
1477 : /*
1478 : * For historical reasons, tg_argv[] subscripts start at zero
1479 : * not one. So we can't use construct_array().
1480 : */
1481 1772 : int nelems = estate->trigdata->tg_trigger->tgnargs;
1482 : Datum *elems;
1483 : int dims[1];
1484 : int lbs[1];
1485 : int i;
1486 :
1487 1772 : elems = palloc(sizeof(Datum) * nelems);
1488 3684 : for (i = 0; i < nelems; i++)
1489 1912 : elems[i] = CStringGetTextDatum(estate->trigdata->tg_trigger->tgargs[i]);
1490 1772 : dims[0] = nelems;
1491 1772 : lbs[0] = 0;
1492 :
1493 1772 : assign_simple_var(estate, var,
1494 1772 : PointerGetDatum(construct_md_array(elems, NULL,
1495 : 1, dims, lbs,
1496 : TEXTOID,
1497 : -1, false, TYPALIGN_INT)),
1498 : false, true);
1499 : }
1500 : else
1501 : {
1502 24 : assign_simple_var(estate, var, (Datum) 0, true, false);
1503 : }
1504 1796 : break;
1505 :
1506 196 : case PLPGSQL_PROMISE_TG_EVENT:
1507 196 : if (estate->evtrigdata == NULL)
1508 0 : elog(ERROR, "event trigger promise is not in an event trigger function");
1509 196 : assign_text_var(estate, var, estate->evtrigdata->event);
1510 196 : break;
1511 :
1512 256 : case PLPGSQL_PROMISE_TG_TAG:
1513 256 : if (estate->evtrigdata == NULL)
1514 0 : elog(ERROR, "event trigger promise is not in an event trigger function");
1515 256 : assign_text_var(estate, var, GetCommandTagName(estate->evtrigdata->tag));
1516 256 : break;
1517 :
1518 0 : default:
1519 0 : elog(ERROR, "unrecognized promise type: %d", var->promise);
1520 : }
1521 :
1522 15884 : MemoryContextSwitchTo(oldcontext);
1523 : }
1524 :
1525 : /*
1526 : * Create a memory context for statement-lifespan variables, if we don't
1527 : * have one already. It will be a child of stmt_mcontext_parent, which is
1528 : * either the function's main context or a pushed-down outer stmt_mcontext.
1529 : */
1530 : static MemoryContext
1531 50376 : get_stmt_mcontext(PLpgSQL_execstate *estate)
1532 : {
1533 50376 : if (estate->stmt_mcontext == NULL)
1534 : {
1535 22382 : estate->stmt_mcontext =
1536 22382 : AllocSetContextCreate(estate->stmt_mcontext_parent,
1537 : "PLpgSQL per-statement data",
1538 : ALLOCSET_DEFAULT_SIZES);
1539 : }
1540 50376 : return estate->stmt_mcontext;
1541 : }
1542 :
1543 : /*
1544 : * Push down the current stmt_mcontext so that called statements won't use it.
1545 : * This is needed by statements that have statement-lifespan data and need to
1546 : * preserve it across some inner statements. The caller should eventually do
1547 : * pop_stmt_mcontext().
1548 : */
1549 : static void
1550 90 : push_stmt_mcontext(PLpgSQL_execstate *estate)
1551 : {
1552 : /* Should have done get_stmt_mcontext() first */
1553 : Assert(estate->stmt_mcontext != NULL);
1554 : /* Assert we've not messed up the stack linkage */
1555 : Assert(MemoryContextGetParent(estate->stmt_mcontext) == estate->stmt_mcontext_parent);
1556 : /* Push it down to become the parent of any nested stmt mcontext */
1557 90 : estate->stmt_mcontext_parent = estate->stmt_mcontext;
1558 : /* And make it not available for use directly */
1559 90 : estate->stmt_mcontext = NULL;
1560 90 : }
1561 :
1562 : /*
1563 : * Undo push_stmt_mcontext(). We assume this is done just before or after
1564 : * resetting the caller's stmt_mcontext; since that action will also delete
1565 : * any child contexts, there's no need to explicitly delete whatever context
1566 : * might currently be estate->stmt_mcontext.
1567 : */
1568 : static void
1569 6204 : pop_stmt_mcontext(PLpgSQL_execstate *estate)
1570 : {
1571 : /* We need only pop the stack */
1572 6204 : estate->stmt_mcontext = estate->stmt_mcontext_parent;
1573 6204 : estate->stmt_mcontext_parent = MemoryContextGetParent(estate->stmt_mcontext);
1574 6204 : }
1575 :
1576 :
1577 : /*
1578 : * Subroutine for exec_stmt_block: does any condition in the condition list
1579 : * match the current exception?
1580 : */
1581 : static bool
1582 6192 : exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond)
1583 : {
1584 6824 : for (; cond != NULL; cond = cond->next)
1585 : {
1586 6794 : int sqlerrstate = cond->sqlerrstate;
1587 :
1588 : /*
1589 : * OTHERS matches everything *except* query-canceled and
1590 : * assert-failure. If you're foolish enough, you can match those
1591 : * explicitly.
1592 : */
1593 6794 : if (sqlerrstate == 0)
1594 : {
1595 5348 : if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED &&
1596 5346 : edata->sqlerrcode != ERRCODE_ASSERT_FAILURE)
1597 5340 : return true;
1598 : }
1599 : /* Exact match? */
1600 1446 : else if (edata->sqlerrcode == sqlerrstate)
1601 818 : return true;
1602 : /* Category match? */
1603 628 : else if (ERRCODE_IS_CATEGORY(sqlerrstate) &&
1604 6 : ERRCODE_TO_CATEGORY(edata->sqlerrcode) == sqlerrstate)
1605 4 : return true;
1606 : }
1607 30 : return false;
1608 : }
1609 :
1610 :
1611 : /* ----------
1612 : * exec_toplevel_block Execute the toplevel block
1613 : *
1614 : * This is intentionally equivalent to executing exec_stmts() with a
1615 : * list consisting of the one statement. One tiny difference is that
1616 : * we do not bother to save the entry value of estate->err_stmt;
1617 : * that's assumed to be NULL.
1618 : * ----------
1619 : */
1620 : static int
1621 81816 : exec_toplevel_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
1622 : {
1623 : int rc;
1624 :
1625 81816 : estate->err_stmt = (PLpgSQL_stmt *) block;
1626 :
1627 : /* Let the plugin know that we are about to execute this statement */
1628 81816 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
1629 0 : ((*plpgsql_plugin_ptr)->stmt_beg) (estate, (PLpgSQL_stmt *) block);
1630 :
1631 81816 : CHECK_FOR_INTERRUPTS();
1632 :
1633 81816 : rc = exec_stmt_block(estate, block);
1634 :
1635 : /* Let the plugin know that we have finished executing this statement */
1636 80758 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
1637 0 : ((*plpgsql_plugin_ptr)->stmt_end) (estate, (PLpgSQL_stmt *) block);
1638 :
1639 80758 : estate->err_stmt = NULL;
1640 :
1641 80758 : return rc;
1642 : }
1643 :
1644 :
1645 : /* ----------
1646 : * exec_stmt_block Execute a block of statements
1647 : * ----------
1648 : */
1649 : static int
1650 94152 : exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
1651 : {
1652 94152 : volatile int rc = -1;
1653 : int i;
1654 :
1655 : /*
1656 : * First initialize all variables declared in this block
1657 : */
1658 94152 : estate->err_text = gettext_noop("during statement block local variable initialization");
1659 :
1660 126806 : for (i = 0; i < block->n_initvars; i++)
1661 : {
1662 32714 : int n = block->initvarnos[i];
1663 32714 : PLpgSQL_datum *datum = estate->datums[n];
1664 :
1665 : /*
1666 : * The set of dtypes handled here must match plpgsql_add_initdatums().
1667 : *
1668 : * Note that we currently don't support promise datums within blocks,
1669 : * only at a function's outermost scope, so we needn't handle those
1670 : * here.
1671 : *
1672 : * Since RECFIELD isn't a supported case either, it's okay to cast the
1673 : * PLpgSQL_datum to PLpgSQL_variable.
1674 : */
1675 32714 : estate->err_var = (PLpgSQL_variable *) datum;
1676 :
1677 32714 : switch (datum->dtype)
1678 : {
1679 27880 : case PLPGSQL_DTYPE_VAR:
1680 : {
1681 27880 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
1682 :
1683 : /*
1684 : * Free any old value, in case re-entering block, and
1685 : * initialize to NULL
1686 : */
1687 27880 : assign_simple_var(estate, var, (Datum) 0, true, false);
1688 :
1689 27880 : if (var->default_val == NULL)
1690 : {
1691 : /*
1692 : * If needed, give the datatype a chance to reject
1693 : * NULLs, by assigning a NULL to the variable. We
1694 : * claim the value is of type UNKNOWN, not the var's
1695 : * datatype, else coercion will be skipped.
1696 : */
1697 24316 : if (var->datatype->typtype == TYPTYPE_DOMAIN)
1698 110 : exec_assign_value(estate,
1699 : (PLpgSQL_datum *) var,
1700 : (Datum) 0,
1701 : true,
1702 : UNKNOWNOID,
1703 : -1);
1704 :
1705 : /* parser should have rejected NOT NULL */
1706 : Assert(!var->notnull);
1707 : }
1708 : else
1709 : {
1710 3564 : exec_assign_expr(estate, (PLpgSQL_datum *) var,
1711 : var->default_val);
1712 : }
1713 : }
1714 27838 : break;
1715 :
1716 4834 : case PLPGSQL_DTYPE_REC:
1717 : {
1718 4834 : PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
1719 :
1720 : /*
1721 : * Deletion of any existing object will be handled during
1722 : * the assignments below, and in some cases it's more
1723 : * efficient for us not to get rid of it beforehand.
1724 : */
1725 4834 : if (rec->default_val == NULL)
1726 : {
1727 : /*
1728 : * If needed, give the datatype a chance to reject
1729 : * NULLs, by assigning a NULL to the variable.
1730 : */
1731 4796 : exec_move_row(estate, (PLpgSQL_variable *) rec,
1732 : NULL, NULL);
1733 :
1734 : /* parser should have rejected NOT NULL */
1735 : Assert(!rec->notnull);
1736 : }
1737 : else
1738 : {
1739 38 : exec_assign_expr(estate, (PLpgSQL_datum *) rec,
1740 : rec->default_val);
1741 : }
1742 : }
1743 4816 : break;
1744 :
1745 0 : default:
1746 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
1747 : }
1748 : }
1749 :
1750 94092 : estate->err_var = NULL;
1751 :
1752 94092 : if (block->exceptions)
1753 : {
1754 : /*
1755 : * Execute the statements in the block's body inside a sub-transaction
1756 : */
1757 12524 : MemoryContext oldcontext = CurrentMemoryContext;
1758 12524 : ResourceOwner oldowner = CurrentResourceOwner;
1759 12524 : ExprContext *old_eval_econtext = estate->eval_econtext;
1760 12524 : ErrorData *save_cur_error = estate->cur_error;
1761 : MemoryContext stmt_mcontext;
1762 :
1763 12524 : estate->err_text = gettext_noop("during statement block entry");
1764 :
1765 : /*
1766 : * We will need a stmt_mcontext to hold the error data if an error
1767 : * occurs. It seems best to force it to exist before entering the
1768 : * subtransaction, so that we reduce the risk of out-of-memory during
1769 : * error recovery, and because this greatly simplifies restoring the
1770 : * stmt_mcontext stack to the correct state after an error. We can
1771 : * ameliorate the cost of this by allowing the called statements to
1772 : * use this mcontext too; so we don't push it down here.
1773 : */
1774 12524 : stmt_mcontext = get_stmt_mcontext(estate);
1775 :
1776 12524 : BeginInternalSubTransaction(NULL);
1777 : /* Want to run statements inside function's memory context */
1778 12524 : MemoryContextSwitchTo(oldcontext);
1779 :
1780 12524 : PG_TRY();
1781 : {
1782 : /*
1783 : * We need to run the block's statements with a new eval_econtext
1784 : * that belongs to the current subtransaction; if we try to use
1785 : * the outer econtext then ExprContext shutdown callbacks will be
1786 : * called at the wrong times.
1787 : */
1788 12524 : plpgsql_create_econtext(estate);
1789 :
1790 12524 : estate->err_text = NULL;
1791 :
1792 : /* Run the block's statements */
1793 12524 : rc = exec_stmts(estate, block->body);
1794 :
1795 6348 : estate->err_text = gettext_noop("during statement block exit");
1796 :
1797 : /*
1798 : * If the block ended with RETURN, we may need to copy the return
1799 : * value out of the subtransaction eval_context. We can avoid a
1800 : * physical copy if the value happens to be a R/W expanded object.
1801 : */
1802 6348 : if (rc == PLPGSQL_RC_RETURN &&
1803 1970 : !estate->retisset &&
1804 1970 : !estate->retisnull)
1805 : {
1806 : int16 resTypLen;
1807 : bool resTypByVal;
1808 :
1809 1970 : get_typlenbyval(estate->rettype, &resTypLen, &resTypByVal);
1810 1970 : estate->retval = datumTransfer(estate->retval,
1811 : resTypByVal, resTypLen);
1812 : }
1813 :
1814 : /* Commit the inner transaction, return to outer xact context */
1815 6348 : ReleaseCurrentSubTransaction();
1816 6348 : MemoryContextSwitchTo(oldcontext);
1817 6348 : CurrentResourceOwner = oldowner;
1818 :
1819 : /* Assert that the stmt_mcontext stack is unchanged */
1820 : Assert(stmt_mcontext == estate->stmt_mcontext);
1821 :
1822 : /*
1823 : * Revert to outer eval_econtext. (The inner one was
1824 : * automatically cleaned up during subxact exit.)
1825 : */
1826 6348 : estate->eval_econtext = old_eval_econtext;
1827 : }
1828 6176 : PG_CATCH();
1829 : {
1830 : ErrorData *edata;
1831 : ListCell *e;
1832 :
1833 6176 : estate->err_text = gettext_noop("during exception cleanup");
1834 :
1835 : /* Save error info in our stmt_mcontext */
1836 6176 : MemoryContextSwitchTo(stmt_mcontext);
1837 6176 : edata = CopyErrorData();
1838 6176 : FlushErrorState();
1839 :
1840 : /* Abort the inner transaction */
1841 6176 : RollbackAndReleaseCurrentSubTransaction();
1842 6176 : MemoryContextSwitchTo(oldcontext);
1843 6176 : CurrentResourceOwner = oldowner;
1844 :
1845 : /*
1846 : * Set up the stmt_mcontext stack as though we had restored our
1847 : * previous state and then done push_stmt_mcontext(). The push is
1848 : * needed so that statements in the exception handler won't
1849 : * clobber the error data that's in our stmt_mcontext.
1850 : */
1851 6176 : estate->stmt_mcontext_parent = stmt_mcontext;
1852 6176 : estate->stmt_mcontext = NULL;
1853 :
1854 : /*
1855 : * Now we can delete any nested stmt_mcontexts that might have
1856 : * been created as children of ours. (Note: we do not immediately
1857 : * release any statement-lifespan data that might have been left
1858 : * behind in stmt_mcontext itself. We could attempt that by doing
1859 : * a MemoryContextReset on it before collecting the error data
1860 : * above, but it seems too risky to do any significant amount of
1861 : * work before collecting the error.)
1862 : */
1863 6176 : MemoryContextDeleteChildren(stmt_mcontext);
1864 :
1865 : /* Revert to outer eval_econtext */
1866 6176 : estate->eval_econtext = old_eval_econtext;
1867 :
1868 : /*
1869 : * Must clean up the econtext too. However, any tuple table made
1870 : * in the subxact will have been thrown away by SPI during subxact
1871 : * abort, so we don't need to (and mustn't try to) free the
1872 : * eval_tuptable.
1873 : */
1874 6176 : estate->eval_tuptable = NULL;
1875 6176 : exec_eval_cleanup(estate);
1876 :
1877 : /* Look for a matching exception handler */
1878 6206 : foreach(e, block->exceptions->exc_list)
1879 : {
1880 6192 : PLpgSQL_exception *exception = (PLpgSQL_exception *) lfirst(e);
1881 :
1882 6192 : if (exception_matches_conditions(edata, exception->conditions))
1883 : {
1884 : /*
1885 : * Initialize the magic SQLSTATE and SQLERRM variables for
1886 : * the exception block; this also frees values from any
1887 : * prior use of the same exception. We needn't do this
1888 : * until we have found a matching exception.
1889 : */
1890 : PLpgSQL_var *state_var;
1891 : PLpgSQL_var *errm_var;
1892 :
1893 6162 : state_var = (PLpgSQL_var *)
1894 6162 : estate->datums[block->exceptions->sqlstate_varno];
1895 6162 : errm_var = (PLpgSQL_var *)
1896 6162 : estate->datums[block->exceptions->sqlerrm_varno];
1897 :
1898 6162 : assign_text_var(estate, state_var,
1899 6162 : unpack_sql_state(edata->sqlerrcode));
1900 6162 : assign_text_var(estate, errm_var, edata->message);
1901 :
1902 : /*
1903 : * Also set up cur_error so the error data is accessible
1904 : * inside the handler.
1905 : */
1906 6162 : estate->cur_error = edata;
1907 :
1908 6162 : estate->err_text = NULL;
1909 :
1910 6162 : rc = exec_stmts(estate, exception->action);
1911 :
1912 6132 : break;
1913 : }
1914 : }
1915 :
1916 : /*
1917 : * Restore previous state of cur_error, whether or not we executed
1918 : * a handler. This is needed in case an error got thrown from
1919 : * some inner block's exception handler.
1920 : */
1921 6146 : estate->cur_error = save_cur_error;
1922 :
1923 : /* If no match found, re-throw the error */
1924 6146 : if (e == NULL)
1925 14 : ReThrowError(edata);
1926 :
1927 : /* Restore stmt_mcontext stack and release the error data */
1928 6132 : pop_stmt_mcontext(estate);
1929 6132 : MemoryContextReset(stmt_mcontext);
1930 : }
1931 12480 : PG_END_TRY();
1932 :
1933 : Assert(save_cur_error == estate->cur_error);
1934 : }
1935 : else
1936 : {
1937 : /*
1938 : * Just execute the statements in the block's body
1939 : */
1940 81568 : estate->err_text = NULL;
1941 :
1942 81568 : rc = exec_stmts(estate, block->body);
1943 : }
1944 :
1945 93030 : estate->err_text = NULL;
1946 :
1947 : /*
1948 : * Handle the return code. This is intentionally different from
1949 : * LOOP_RC_PROCESSING(): CONTINUE never matches a block, and EXIT matches
1950 : * a block only if there is a label match.
1951 : */
1952 93030 : switch (rc)
1953 : {
1954 93014 : case PLPGSQL_RC_OK:
1955 : case PLPGSQL_RC_RETURN:
1956 : case PLPGSQL_RC_CONTINUE:
1957 93014 : return rc;
1958 :
1959 16 : case PLPGSQL_RC_EXIT:
1960 16 : if (estate->exitlabel == NULL)
1961 4 : return PLPGSQL_RC_EXIT;
1962 12 : if (block->label == NULL)
1963 2 : return PLPGSQL_RC_EXIT;
1964 10 : if (strcmp(block->label, estate->exitlabel) != 0)
1965 4 : return PLPGSQL_RC_EXIT;
1966 6 : estate->exitlabel = NULL;
1967 6 : return PLPGSQL_RC_OK;
1968 :
1969 0 : default:
1970 0 : elog(ERROR, "unrecognized rc: %d", rc);
1971 : }
1972 :
1973 : return PLPGSQL_RC_OK;
1974 : }
1975 :
1976 :
1977 : /* ----------
1978 : * exec_stmts Iterate over a list of statements
1979 : * as long as their return code is OK
1980 : * ----------
1981 : */
1982 : static int
1983 264668 : exec_stmts(PLpgSQL_execstate *estate, List *stmts)
1984 : {
1985 264668 : PLpgSQL_stmt *save_estmt = estate->err_stmt;
1986 : ListCell *s;
1987 :
1988 264668 : if (stmts == NIL)
1989 : {
1990 : /*
1991 : * Ensure we do a CHECK_FOR_INTERRUPTS() even though there is no
1992 : * statement. This prevents hangup in a tight loop if, for instance,
1993 : * there is a LOOP construct with an empty body.
1994 : */
1995 63566 : CHECK_FOR_INTERRUPTS();
1996 63566 : return PLPGSQL_RC_OK;
1997 : }
1998 :
1999 485034 : foreach(s, stmts)
2000 : {
2001 383824 : PLpgSQL_stmt *stmt = (PLpgSQL_stmt *) lfirst(s);
2002 : int rc;
2003 :
2004 383824 : estate->err_stmt = stmt;
2005 :
2006 : /* Let the plugin know that we are about to execute this statement */
2007 383824 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
2008 0 : ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
2009 :
2010 383824 : CHECK_FOR_INTERRUPTS();
2011 :
2012 383824 : switch (stmt->cmd_type)
2013 : {
2014 12336 : case PLPGSQL_STMT_BLOCK:
2015 12336 : rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
2016 12272 : break;
2017 :
2018 80564 : case PLPGSQL_STMT_ASSIGN:
2019 80564 : rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
2020 80316 : break;
2021 :
2022 3690 : case PLPGSQL_STMT_PERFORM:
2023 3690 : rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
2024 2282 : break;
2025 :
2026 114 : case PLPGSQL_STMT_CALL:
2027 114 : rc = exec_stmt_call(estate, (PLpgSQL_stmt_call *) stmt);
2028 102 : break;
2029 :
2030 152 : case PLPGSQL_STMT_GETDIAG:
2031 152 : rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
2032 146 : break;
2033 :
2034 89500 : case PLPGSQL_STMT_IF:
2035 89500 : rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
2036 89302 : break;
2037 :
2038 224 : case PLPGSQL_STMT_CASE:
2039 224 : rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
2040 218 : break;
2041 :
2042 76 : case PLPGSQL_STMT_LOOP:
2043 76 : rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
2044 76 : break;
2045 :
2046 426 : case PLPGSQL_STMT_WHILE:
2047 426 : rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
2048 426 : break;
2049 :
2050 3908 : case PLPGSQL_STMT_FORI:
2051 3908 : rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
2052 3894 : break;
2053 :
2054 2410 : case PLPGSQL_STMT_FORS:
2055 2410 : rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
2056 2364 : break;
2057 :
2058 104 : case PLPGSQL_STMT_FORC:
2059 104 : rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
2060 104 : break;
2061 :
2062 90 : case PLPGSQL_STMT_FOREACH_A:
2063 90 : rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
2064 72 : break;
2065 :
2066 2182 : case PLPGSQL_STMT_EXIT:
2067 2182 : rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
2068 2182 : break;
2069 :
2070 80852 : case PLPGSQL_STMT_RETURN:
2071 80852 : rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
2072 80752 : break;
2073 :
2074 4398 : case PLPGSQL_STMT_RETURN_NEXT:
2075 4398 : rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
2076 4394 : break;
2077 :
2078 2666 : case PLPGSQL_STMT_RETURN_QUERY:
2079 2666 : rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
2080 2654 : break;
2081 :
2082 14484 : case PLPGSQL_STMT_RAISE:
2083 14484 : rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
2084 13508 : break;
2085 :
2086 8720 : case PLPGSQL_STMT_ASSERT:
2087 8720 : rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
2088 8696 : break;
2089 :
2090 52126 : case PLPGSQL_STMT_EXECSQL:
2091 52126 : rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
2092 48086 : break;
2093 :
2094 10782 : case PLPGSQL_STMT_DYNEXECUTE:
2095 10782 : rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
2096 10550 : break;
2097 :
2098 9218 : case PLPGSQL_STMT_DYNFORS:
2099 9218 : rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
2100 9212 : break;
2101 :
2102 138 : case PLPGSQL_STMT_OPEN:
2103 138 : rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
2104 126 : break;
2105 :
2106 342 : case PLPGSQL_STMT_FETCH:
2107 342 : rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
2108 336 : break;
2109 :
2110 72 : case PLPGSQL_STMT_CLOSE:
2111 72 : rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
2112 72 : break;
2113 :
2114 4166 : case PLPGSQL_STMT_COMMIT:
2115 4166 : rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit *) stmt);
2116 4144 : break;
2117 :
2118 84 : case PLPGSQL_STMT_ROLLBACK:
2119 84 : rc = exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback *) stmt);
2120 78 : break;
2121 :
2122 0 : default:
2123 : /* point err_stmt to parent, since this one seems corrupt */
2124 0 : estate->err_stmt = save_estmt;
2125 0 : elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
2126 : rc = -1; /* keep compiler quiet */
2127 : }
2128 :
2129 : /* Let the plugin know that we have finished executing this statement */
2130 376364 : if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
2131 0 : ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
2132 :
2133 376364 : if (rc != PLPGSQL_RC_OK)
2134 : {
2135 92432 : estate->err_stmt = save_estmt;
2136 92432 : return rc;
2137 : }
2138 : } /* end of loop over statements */
2139 :
2140 101210 : estate->err_stmt = save_estmt;
2141 101210 : return PLPGSQL_RC_OK;
2142 : }
2143 :
2144 :
2145 : /* ----------
2146 : * exec_stmt_assign Evaluate an expression and
2147 : * put the result into a variable.
2148 : * ----------
2149 : */
2150 : static int
2151 80564 : exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
2152 : {
2153 : Assert(stmt->varno >= 0);
2154 :
2155 80564 : exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
2156 :
2157 80316 : return PLPGSQL_RC_OK;
2158 : }
2159 :
2160 : /* ----------
2161 : * exec_stmt_perform Evaluate query and discard result (but set
2162 : * FOUND depending on whether at least one row
2163 : * was returned).
2164 : * ----------
2165 : */
2166 : static int
2167 3690 : exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
2168 : {
2169 3690 : PLpgSQL_expr *expr = stmt->expr;
2170 :
2171 3690 : (void) exec_run_select(estate, expr, 0, NULL);
2172 2282 : exec_set_found(estate, (estate->eval_processed != 0));
2173 2282 : exec_eval_cleanup(estate);
2174 :
2175 2282 : return PLPGSQL_RC_OK;
2176 : }
2177 :
2178 : /*
2179 : * exec_stmt_call
2180 : *
2181 : * NOTE: this is used for both CALL and DO statements.
2182 : */
2183 : static int
2184 114 : exec_stmt_call(PLpgSQL_execstate *estate, PLpgSQL_stmt_call *stmt)
2185 : {
2186 114 : PLpgSQL_expr *expr = stmt->expr;
2187 : LocalTransactionId before_lxid;
2188 : LocalTransactionId after_lxid;
2189 : ParamListInfo paramLI;
2190 : SPIExecuteOptions options;
2191 : int rc;
2192 :
2193 : /*
2194 : * Make a plan if we don't have one already.
2195 : */
2196 114 : if (expr->plan == NULL)
2197 88 : exec_prepare_plan(estate, expr, 0);
2198 :
2199 : /*
2200 : * A CALL or DO can never be a simple expression.
2201 : */
2202 : Assert(!expr->expr_simple_expr);
2203 :
2204 : /*
2205 : * Also construct a DTYPE_ROW datum representing the plpgsql variables
2206 : * associated with the procedure's output arguments. Then we can use
2207 : * exec_move_row() to do the assignments.
2208 : */
2209 114 : if (stmt->is_call && stmt->target == NULL)
2210 86 : stmt->target = make_callstmt_target(estate, expr);
2211 :
2212 104 : paramLI = setup_param_list(estate, expr);
2213 :
2214 104 : before_lxid = MyProc->vxid.lxid;
2215 :
2216 : /*
2217 : * If we have a procedure-lifespan resowner, use that to hold the refcount
2218 : * for the plan. This avoids refcount leakage complaints if the called
2219 : * procedure ends the current transaction.
2220 : *
2221 : * Also, tell SPI to allow non-atomic execution.
2222 : */
2223 104 : memset(&options, 0, sizeof(options));
2224 104 : options.params = paramLI;
2225 104 : options.read_only = estate->readonly_func;
2226 104 : options.allow_nonatomic = true;
2227 104 : options.owner = estate->procedure_resowner;
2228 :
2229 104 : rc = SPI_execute_plan_extended(expr->plan, &options);
2230 :
2231 102 : if (rc < 0)
2232 0 : elog(ERROR, "SPI_execute_plan_extended failed executing query \"%s\": %s",
2233 : expr->query, SPI_result_code_string(rc));
2234 :
2235 102 : after_lxid = MyProc->vxid.lxid;
2236 :
2237 102 : if (before_lxid != after_lxid)
2238 : {
2239 : /*
2240 : * If we are in a new transaction after the call, we need to build new
2241 : * simple-expression infrastructure.
2242 : */
2243 8 : estate->simple_eval_estate = NULL;
2244 8 : estate->simple_eval_resowner = NULL;
2245 8 : plpgsql_create_econtext(estate);
2246 : }
2247 :
2248 : /*
2249 : * Check result rowcount; if there's one row, assign procedure's output
2250 : * values back to the appropriate variables.
2251 : */
2252 102 : if (SPI_processed == 1)
2253 : {
2254 74 : SPITupleTable *tuptab = SPI_tuptable;
2255 :
2256 74 : if (!stmt->is_call)
2257 0 : elog(ERROR, "DO statement returned a row");
2258 :
2259 74 : exec_move_row(estate, stmt->target, tuptab->vals[0], tuptab->tupdesc);
2260 : }
2261 28 : else if (SPI_processed > 1)
2262 0 : elog(ERROR, "procedure call returned more than one row");
2263 :
2264 102 : exec_eval_cleanup(estate);
2265 102 : SPI_freetuptable(SPI_tuptable);
2266 :
2267 102 : return PLPGSQL_RC_OK;
2268 : }
2269 :
2270 : /*
2271 : * We construct a DTYPE_ROW datum representing the plpgsql variables
2272 : * associated with the procedure's output arguments. Then we can use
2273 : * exec_move_row() to do the assignments.
2274 : */
2275 : static PLpgSQL_variable *
2276 86 : make_callstmt_target(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
2277 : {
2278 : List *plansources;
2279 : CachedPlanSource *plansource;
2280 : CallStmt *stmt;
2281 : FuncExpr *funcexpr;
2282 : HeapTuple func_tuple;
2283 : Oid *argtypes;
2284 : char **argnames;
2285 : char *argmodes;
2286 : int numargs;
2287 : MemoryContext oldcontext;
2288 : PLpgSQL_row *row;
2289 : int nfields;
2290 : int i;
2291 :
2292 : /* Use eval_mcontext for any cruft accumulated here */
2293 86 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2294 :
2295 : /*
2296 : * Get the parsed CallStmt, and look up the called procedure
2297 : */
2298 86 : plansources = SPI_plan_get_plan_sources(expr->plan);
2299 86 : if (list_length(plansources) != 1)
2300 0 : elog(ERROR, "query for CALL statement is not a CallStmt");
2301 86 : plansource = (CachedPlanSource *) linitial(plansources);
2302 86 : if (list_length(plansource->query_list) != 1)
2303 0 : elog(ERROR, "query for CALL statement is not a CallStmt");
2304 86 : stmt = (CallStmt *) linitial_node(Query,
2305 : plansource->query_list)->utilityStmt;
2306 86 : if (stmt == NULL || !IsA(stmt, CallStmt))
2307 0 : elog(ERROR, "query for CALL statement is not a CallStmt");
2308 :
2309 86 : funcexpr = stmt->funcexpr;
2310 :
2311 86 : func_tuple = SearchSysCache1(PROCOID,
2312 : ObjectIdGetDatum(funcexpr->funcid));
2313 86 : if (!HeapTupleIsValid(func_tuple))
2314 0 : elog(ERROR, "cache lookup failed for function %u",
2315 : funcexpr->funcid);
2316 :
2317 : /*
2318 : * Get the argument names and modes, so that we can deliver on-point error
2319 : * messages when something is wrong.
2320 : */
2321 86 : numargs = get_func_arg_info(func_tuple, &argtypes, &argnames, &argmodes);
2322 :
2323 86 : ReleaseSysCache(func_tuple);
2324 :
2325 : /*
2326 : * Begin constructing row Datum; keep it in fn_cxt so it's adequately
2327 : * long-lived.
2328 : */
2329 86 : MemoryContextSwitchTo(estate->func->fn_cxt);
2330 :
2331 86 : row = (PLpgSQL_row *) palloc0(sizeof(PLpgSQL_row));
2332 86 : row->dtype = PLPGSQL_DTYPE_ROW;
2333 86 : row->refname = "(unnamed row)";
2334 86 : row->lineno = -1;
2335 86 : row->varnos = (int *) palloc(numargs * sizeof(int));
2336 :
2337 86 : MemoryContextSwitchTo(get_eval_mcontext(estate));
2338 :
2339 : /*
2340 : * Examine procedure's argument list. Each output arg position should be
2341 : * an unadorned plpgsql variable (Datum), which we can insert into the row
2342 : * Datum.
2343 : */
2344 86 : nfields = 0;
2345 272 : for (i = 0; i < numargs; i++)
2346 : {
2347 196 : if (argmodes &&
2348 172 : (argmodes[i] == PROARGMODE_INOUT ||
2349 86 : argmodes[i] == PROARGMODE_OUT))
2350 : {
2351 110 : Node *n = list_nth(stmt->outargs, nfields);
2352 :
2353 110 : if (IsA(n, Param))
2354 : {
2355 102 : Param *param = (Param *) n;
2356 : int dno;
2357 :
2358 : /* paramid is offset by 1 (see make_datum_param()) */
2359 102 : dno = param->paramid - 1;
2360 : /* must check assignability now, because grammar can't */
2361 102 : exec_check_assignable(estate, dno);
2362 100 : row->varnos[nfields++] = dno;
2363 : }
2364 : else
2365 : {
2366 : /* report error using parameter name, if available */
2367 8 : if (argnames && argnames[i] && argnames[i][0])
2368 8 : ereport(ERROR,
2369 : (errcode(ERRCODE_SYNTAX_ERROR),
2370 : errmsg("procedure parameter \"%s\" is an output parameter but corresponding argument is not writable",
2371 : argnames[i])));
2372 : else
2373 0 : ereport(ERROR,
2374 : (errcode(ERRCODE_SYNTAX_ERROR),
2375 : errmsg("procedure parameter %d is an output parameter but corresponding argument is not writable",
2376 : i + 1)));
2377 : }
2378 : }
2379 : }
2380 :
2381 : Assert(nfields == list_length(stmt->outargs));
2382 :
2383 76 : row->nfields = nfields;
2384 :
2385 76 : MemoryContextSwitchTo(oldcontext);
2386 :
2387 76 : return (PLpgSQL_variable *) row;
2388 : }
2389 :
2390 : /* ----------
2391 : * exec_stmt_getdiag Put internal PG information into
2392 : * specified variables.
2393 : * ----------
2394 : */
2395 : static int
2396 152 : exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
2397 : {
2398 : ListCell *lc;
2399 :
2400 : /*
2401 : * GET STACKED DIAGNOSTICS is only valid inside an exception handler.
2402 : *
2403 : * Note: we trust the grammar to have disallowed the relevant item kinds
2404 : * if not is_stacked, otherwise we'd dump core below.
2405 : */
2406 152 : if (stmt->is_stacked && estate->cur_error == NULL)
2407 6 : ereport(ERROR,
2408 : (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
2409 : errmsg("GET STACKED DIAGNOSTICS cannot be used outside an exception handler")));
2410 :
2411 356 : foreach(lc, stmt->diag_items)
2412 : {
2413 210 : PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
2414 210 : PLpgSQL_datum *var = estate->datums[diag_item->target];
2415 :
2416 210 : switch (diag_item->kind)
2417 : {
2418 66 : case PLPGSQL_GETDIAG_ROW_COUNT:
2419 66 : exec_assign_value(estate, var,
2420 : UInt64GetDatum(estate->eval_processed),
2421 : false, INT8OID, -1);
2422 66 : break;
2423 :
2424 12 : case PLPGSQL_GETDIAG_ROUTINE_OID:
2425 12 : exec_assign_value(estate, var,
2426 12 : ObjectIdGetDatum(estate->func->fn_oid),
2427 : false, OIDOID, -1);
2428 12 : break;
2429 :
2430 6 : case PLPGSQL_GETDIAG_ERROR_CONTEXT:
2431 6 : exec_assign_c_string(estate, var,
2432 6 : estate->cur_error->context);
2433 6 : break;
2434 :
2435 8 : case PLPGSQL_GETDIAG_ERROR_DETAIL:
2436 8 : exec_assign_c_string(estate, var,
2437 8 : estate->cur_error->detail);
2438 8 : break;
2439 :
2440 8 : case PLPGSQL_GETDIAG_ERROR_HINT:
2441 8 : exec_assign_c_string(estate, var,
2442 8 : estate->cur_error->hint);
2443 8 : break;
2444 :
2445 8 : case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
2446 8 : exec_assign_c_string(estate, var,
2447 8 : unpack_sql_state(estate->cur_error->sqlerrcode));
2448 8 : break;
2449 :
2450 8 : case PLPGSQL_GETDIAG_COLUMN_NAME:
2451 8 : exec_assign_c_string(estate, var,
2452 8 : estate->cur_error->column_name);
2453 8 : break;
2454 :
2455 8 : case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
2456 8 : exec_assign_c_string(estate, var,
2457 8 : estate->cur_error->constraint_name);
2458 8 : break;
2459 :
2460 8 : case PLPGSQL_GETDIAG_DATATYPE_NAME:
2461 8 : exec_assign_c_string(estate, var,
2462 8 : estate->cur_error->datatype_name);
2463 8 : break;
2464 :
2465 14 : case PLPGSQL_GETDIAG_MESSAGE_TEXT:
2466 14 : exec_assign_c_string(estate, var,
2467 14 : estate->cur_error->message);
2468 14 : break;
2469 :
2470 8 : case PLPGSQL_GETDIAG_TABLE_NAME:
2471 8 : exec_assign_c_string(estate, var,
2472 8 : estate->cur_error->table_name);
2473 8 : break;
2474 :
2475 8 : case PLPGSQL_GETDIAG_SCHEMA_NAME:
2476 8 : exec_assign_c_string(estate, var,
2477 8 : estate->cur_error->schema_name);
2478 8 : break;
2479 :
2480 48 : case PLPGSQL_GETDIAG_CONTEXT:
2481 : {
2482 : char *contextstackstr;
2483 : MemoryContext oldcontext;
2484 :
2485 : /* Use eval_mcontext for short-lived string */
2486 48 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2487 48 : contextstackstr = GetErrorContextStack();
2488 48 : MemoryContextSwitchTo(oldcontext);
2489 :
2490 48 : exec_assign_c_string(estate, var, contextstackstr);
2491 : }
2492 48 : break;
2493 :
2494 0 : default:
2495 0 : elog(ERROR, "unrecognized diagnostic item kind: %d",
2496 : diag_item->kind);
2497 : }
2498 : }
2499 :
2500 146 : exec_eval_cleanup(estate);
2501 :
2502 146 : return PLPGSQL_RC_OK;
2503 : }
2504 :
2505 : /* ----------
2506 : * exec_stmt_if Evaluate a bool expression and
2507 : * execute the true or false body
2508 : * conditionally.
2509 : * ----------
2510 : */
2511 : static int
2512 89500 : exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
2513 : {
2514 : bool value;
2515 : bool isnull;
2516 : ListCell *lc;
2517 :
2518 89500 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
2519 89500 : exec_eval_cleanup(estate);
2520 89500 : if (!isnull && value)
2521 18858 : return exec_stmts(estate, stmt->then_body);
2522 :
2523 70868 : foreach(lc, stmt->elsif_list)
2524 : {
2525 844 : PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(lc);
2526 :
2527 844 : value = exec_eval_boolean(estate, elif->cond, &isnull);
2528 844 : exec_eval_cleanup(estate);
2529 844 : if (!isnull && value)
2530 618 : return exec_stmts(estate, elif->stmts);
2531 : }
2532 :
2533 70024 : return exec_stmts(estate, stmt->else_body);
2534 : }
2535 :
2536 :
2537 : /*-----------
2538 : * exec_stmt_case
2539 : *-----------
2540 : */
2541 : static int
2542 224 : exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
2543 : {
2544 224 : PLpgSQL_var *t_var = NULL;
2545 : bool isnull;
2546 : ListCell *l;
2547 :
2548 224 : if (stmt->t_expr != NULL)
2549 : {
2550 : /* simple case */
2551 : Datum t_val;
2552 : Oid t_typoid;
2553 : int32 t_typmod;
2554 :
2555 216 : t_val = exec_eval_expr(estate, stmt->t_expr,
2556 : &isnull, &t_typoid, &t_typmod);
2557 :
2558 216 : t_var = (PLpgSQL_var *) estate->datums[stmt->t_varno];
2559 :
2560 : /*
2561 : * When expected datatype is different from real, change it. Note that
2562 : * what we're modifying here is an execution copy of the datum, so
2563 : * this doesn't affect the originally stored function parse tree. (In
2564 : * theory, if the expression datatype keeps changing during execution,
2565 : * this could cause a function-lifespan memory leak. Doesn't seem
2566 : * worth worrying about though.)
2567 : */
2568 216 : if (t_var->datatype->typoid != t_typoid ||
2569 170 : t_var->datatype->atttypmod != t_typmod)
2570 46 : t_var->datatype = plpgsql_build_datatype(t_typoid,
2571 : t_typmod,
2572 46 : estate->func->fn_input_collation,
2573 : NULL);
2574 :
2575 : /* now we can assign to the variable */
2576 216 : exec_assign_value(estate,
2577 : (PLpgSQL_datum *) t_var,
2578 : t_val,
2579 : isnull,
2580 : t_typoid,
2581 : t_typmod);
2582 :
2583 216 : exec_eval_cleanup(estate);
2584 : }
2585 :
2586 : /* Now search for a successful WHEN clause */
2587 420 : foreach(l, stmt->case_when_list)
2588 : {
2589 410 : PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
2590 : bool value;
2591 :
2592 410 : value = exec_eval_boolean(estate, cwt->expr, &isnull);
2593 410 : exec_eval_cleanup(estate);
2594 410 : if (!isnull && value)
2595 : {
2596 : /* Found it */
2597 :
2598 : /* We can now discard any value we had for the temp variable */
2599 214 : if (t_var != NULL)
2600 210 : assign_simple_var(estate, t_var, (Datum) 0, true, false);
2601 :
2602 : /* Evaluate the statement(s), and we're done */
2603 214 : return exec_stmts(estate, cwt->stmts);
2604 : }
2605 : }
2606 :
2607 : /* We can now discard any value we had for the temp variable */
2608 10 : if (t_var != NULL)
2609 6 : assign_simple_var(estate, t_var, (Datum) 0, true, false);
2610 :
2611 : /* SQL2003 mandates this error if there was no ELSE clause */
2612 10 : if (!stmt->have_else)
2613 6 : ereport(ERROR,
2614 : (errcode(ERRCODE_CASE_NOT_FOUND),
2615 : errmsg("case not found"),
2616 : errhint("CASE statement is missing ELSE part.")));
2617 :
2618 : /* Evaluate the ELSE statements, and we're done */
2619 4 : return exec_stmts(estate, stmt->else_stmts);
2620 : }
2621 :
2622 :
2623 : /* ----------
2624 : * exec_stmt_loop Loop over statements until
2625 : * an exit occurs.
2626 : * ----------
2627 : */
2628 : static int
2629 76 : exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
2630 : {
2631 76 : int rc = PLPGSQL_RC_OK;
2632 :
2633 : for (;;)
2634 : {
2635 5040 : rc = exec_stmts(estate, stmt->body);
2636 :
2637 5040 : LOOP_RC_PROCESSING(stmt->label, break);
2638 : }
2639 :
2640 76 : return rc;
2641 : }
2642 :
2643 :
2644 : /* ----------
2645 : * exec_stmt_while Loop over statements as long
2646 : * as an expression evaluates to
2647 : * true or an exit occurs.
2648 : * ----------
2649 : */
2650 : static int
2651 426 : exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
2652 : {
2653 426 : int rc = PLPGSQL_RC_OK;
2654 :
2655 : for (;;)
2656 3132 : {
2657 : bool value;
2658 : bool isnull;
2659 :
2660 3558 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
2661 3558 : exec_eval_cleanup(estate);
2662 :
2663 3558 : if (isnull || !value)
2664 : break;
2665 :
2666 3152 : rc = exec_stmts(estate, stmt->body);
2667 :
2668 3152 : LOOP_RC_PROCESSING(stmt->label, break);
2669 : }
2670 :
2671 426 : return rc;
2672 : }
2673 :
2674 :
2675 : /* ----------
2676 : * exec_stmt_fori Iterate an integer variable
2677 : * from a lower to an upper value
2678 : * incrementing or decrementing by the BY value
2679 : * ----------
2680 : */
2681 : static int
2682 3908 : exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
2683 : {
2684 : PLpgSQL_var *var;
2685 : Datum value;
2686 : bool isnull;
2687 : Oid valtype;
2688 : int32 valtypmod;
2689 : int32 loop_value;
2690 : int32 end_value;
2691 : int32 step_value;
2692 3908 : bool found = false;
2693 3908 : int rc = PLPGSQL_RC_OK;
2694 :
2695 3908 : var = (PLpgSQL_var *) (estate->datums[stmt->var->dno]);
2696 :
2697 : /*
2698 : * Get the value of the lower bound
2699 : */
2700 3908 : value = exec_eval_expr(estate, stmt->lower,
2701 : &isnull, &valtype, &valtypmod);
2702 3908 : value = exec_cast_value(estate, value, &isnull,
2703 : valtype, valtypmod,
2704 3908 : var->datatype->typoid,
2705 3908 : var->datatype->atttypmod);
2706 3908 : if (isnull)
2707 0 : ereport(ERROR,
2708 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2709 : errmsg("lower bound of FOR loop cannot be null")));
2710 3908 : loop_value = DatumGetInt32(value);
2711 3908 : exec_eval_cleanup(estate);
2712 :
2713 : /*
2714 : * Get the value of the upper bound
2715 : */
2716 3908 : value = exec_eval_expr(estate, stmt->upper,
2717 : &isnull, &valtype, &valtypmod);
2718 3908 : value = exec_cast_value(estate, value, &isnull,
2719 : valtype, valtypmod,
2720 3908 : var->datatype->typoid,
2721 3908 : var->datatype->atttypmod);
2722 3908 : if (isnull)
2723 0 : ereport(ERROR,
2724 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2725 : errmsg("upper bound of FOR loop cannot be null")));
2726 3908 : end_value = DatumGetInt32(value);
2727 3908 : exec_eval_cleanup(estate);
2728 :
2729 : /*
2730 : * Get the step value
2731 : */
2732 3908 : if (stmt->step)
2733 : {
2734 18 : value = exec_eval_expr(estate, stmt->step,
2735 : &isnull, &valtype, &valtypmod);
2736 18 : value = exec_cast_value(estate, value, &isnull,
2737 : valtype, valtypmod,
2738 18 : var->datatype->typoid,
2739 18 : var->datatype->atttypmod);
2740 18 : if (isnull)
2741 0 : ereport(ERROR,
2742 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2743 : errmsg("BY value of FOR loop cannot be null")));
2744 18 : step_value = DatumGetInt32(value);
2745 18 : exec_eval_cleanup(estate);
2746 18 : if (step_value <= 0)
2747 6 : ereport(ERROR,
2748 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2749 : errmsg("BY value of FOR loop must be greater than zero")));
2750 : }
2751 : else
2752 3890 : step_value = 1;
2753 :
2754 : /*
2755 : * Now do the loop
2756 : */
2757 : for (;;)
2758 : {
2759 : /*
2760 : * Check against upper bound
2761 : */
2762 23738 : if (stmt->reverse)
2763 : {
2764 16 : if (loop_value < end_value)
2765 2 : break;
2766 : }
2767 : else
2768 : {
2769 23722 : if (loop_value > end_value)
2770 3872 : break;
2771 : }
2772 :
2773 19864 : found = true; /* looped at least once */
2774 :
2775 : /*
2776 : * Assign current value to loop var
2777 : */
2778 19864 : assign_simple_var(estate, var, Int32GetDatum(loop_value), false, false);
2779 :
2780 : /*
2781 : * Execute the statements
2782 : */
2783 19864 : rc = exec_stmts(estate, stmt->body);
2784 :
2785 19856 : LOOP_RC_PROCESSING(stmt->label, break);
2786 :
2787 : /*
2788 : * Increase/decrease loop value, unless it would overflow, in which
2789 : * case exit the loop.
2790 : */
2791 19840 : if (stmt->reverse)
2792 : {
2793 14 : if (loop_value < (PG_INT32_MIN + step_value))
2794 2 : break;
2795 12 : loop_value -= step_value;
2796 : }
2797 : else
2798 : {
2799 19826 : if (loop_value > (PG_INT32_MAX - step_value))
2800 2 : break;
2801 19824 : loop_value += step_value;
2802 : }
2803 : }
2804 :
2805 : /*
2806 : * Set the FOUND variable to indicate the result of executing the loop
2807 : * (namely, whether we looped one or more times). This must be set here so
2808 : * that it does not interfere with the value of the FOUND variable inside
2809 : * the loop processing itself.
2810 : */
2811 3894 : exec_set_found(estate, found);
2812 :
2813 3894 : return rc;
2814 : }
2815 :
2816 :
2817 : /* ----------
2818 : * exec_stmt_fors Execute a query, assign each
2819 : * tuple to a record or row and
2820 : * execute a group of statements
2821 : * for it.
2822 : * ----------
2823 : */
2824 : static int
2825 2410 : exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
2826 : {
2827 : Portal portal;
2828 : int rc;
2829 :
2830 : /*
2831 : * Open the implicit cursor for the statement using exec_run_select
2832 : */
2833 2410 : exec_run_select(estate, stmt->query, 0, &portal);
2834 :
2835 : /*
2836 : * Execute the loop
2837 : */
2838 2398 : rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
2839 :
2840 : /*
2841 : * Close the implicit cursor
2842 : */
2843 2364 : SPI_cursor_close(portal);
2844 :
2845 2364 : return rc;
2846 : }
2847 :
2848 :
2849 : /* ----------
2850 : * exec_stmt_forc Execute a loop for each row from a cursor.
2851 : * ----------
2852 : */
2853 : static int
2854 104 : exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
2855 : {
2856 : PLpgSQL_var *curvar;
2857 104 : MemoryContext stmt_mcontext = NULL;
2858 104 : char *curname = NULL;
2859 : PLpgSQL_expr *query;
2860 : ParamListInfo paramLI;
2861 : Portal portal;
2862 : int rc;
2863 :
2864 : /* ----------
2865 : * Get the cursor variable and if it has an assigned name, check
2866 : * that it's not in use currently.
2867 : * ----------
2868 : */
2869 104 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
2870 104 : if (!curvar->isnull)
2871 : {
2872 : MemoryContext oldcontext;
2873 :
2874 : /* We only need stmt_mcontext to hold the cursor name string */
2875 24 : stmt_mcontext = get_stmt_mcontext(estate);
2876 24 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
2877 24 : curname = TextDatumGetCString(curvar->value);
2878 24 : MemoryContextSwitchTo(oldcontext);
2879 :
2880 24 : if (SPI_cursor_find(curname) != NULL)
2881 0 : ereport(ERROR,
2882 : (errcode(ERRCODE_DUPLICATE_CURSOR),
2883 : errmsg("cursor \"%s\" already in use", curname)));
2884 : }
2885 :
2886 : /* ----------
2887 : * Open the cursor just like an OPEN command
2888 : *
2889 : * Note: parser should already have checked that statement supplies
2890 : * args iff cursor needs them, but we check again to be safe.
2891 : * ----------
2892 : */
2893 104 : if (stmt->argquery != NULL)
2894 : {
2895 : /* ----------
2896 : * OPEN CURSOR with args. We fake a SELECT ... INTO ...
2897 : * statement to evaluate the args and put 'em into the
2898 : * internal row.
2899 : * ----------
2900 : */
2901 : PLpgSQL_stmt_execsql set_args;
2902 :
2903 12 : if (curvar->cursor_explicit_argrow < 0)
2904 0 : ereport(ERROR,
2905 : (errcode(ERRCODE_SYNTAX_ERROR),
2906 : errmsg("arguments given for cursor without arguments")));
2907 :
2908 12 : memset(&set_args, 0, sizeof(set_args));
2909 12 : set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
2910 12 : set_args.lineno = stmt->lineno;
2911 12 : set_args.sqlstmt = stmt->argquery;
2912 12 : set_args.into = true;
2913 : /* XXX historically this has not been STRICT */
2914 12 : set_args.target = (PLpgSQL_variable *)
2915 12 : (estate->datums[curvar->cursor_explicit_argrow]);
2916 :
2917 12 : if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
2918 0 : elog(ERROR, "open cursor failed during argument processing");
2919 : }
2920 : else
2921 : {
2922 92 : if (curvar->cursor_explicit_argrow >= 0)
2923 0 : ereport(ERROR,
2924 : (errcode(ERRCODE_SYNTAX_ERROR),
2925 : errmsg("arguments required for cursor")));
2926 : }
2927 :
2928 104 : query = curvar->cursor_explicit_expr;
2929 : Assert(query);
2930 :
2931 104 : if (query->plan == NULL)
2932 32 : exec_prepare_plan(estate, query, curvar->cursor_options);
2933 :
2934 : /*
2935 : * Set up ParamListInfo for this query
2936 : */
2937 104 : paramLI = setup_param_list(estate, query);
2938 :
2939 : /*
2940 : * Open the cursor (the paramlist will get copied into the portal)
2941 : */
2942 104 : portal = SPI_cursor_open_with_paramlist(curname, query->plan,
2943 : paramLI,
2944 104 : estate->readonly_func);
2945 104 : if (portal == NULL)
2946 0 : elog(ERROR, "could not open cursor: %s",
2947 : SPI_result_code_string(SPI_result));
2948 :
2949 : /*
2950 : * If cursor variable was NULL, store the generated portal name in it,
2951 : * after verifying it's okay to assign to.
2952 : */
2953 104 : if (curname == NULL)
2954 : {
2955 80 : exec_check_assignable(estate, stmt->curvar);
2956 80 : assign_text_var(estate, curvar, portal->name);
2957 : }
2958 :
2959 : /*
2960 : * Clean up before entering exec_for_query
2961 : */
2962 104 : exec_eval_cleanup(estate);
2963 104 : if (stmt_mcontext)
2964 24 : MemoryContextReset(stmt_mcontext);
2965 :
2966 : /*
2967 : * Execute the loop. We can't prefetch because the cursor is accessible
2968 : * to the user, for instance via UPDATE WHERE CURRENT OF within the loop.
2969 : */
2970 104 : rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, false);
2971 :
2972 : /* ----------
2973 : * Close portal, and restore cursor variable if it was initially NULL.
2974 : * ----------
2975 : */
2976 104 : SPI_cursor_close(portal);
2977 :
2978 104 : if (curname == NULL)
2979 80 : assign_simple_var(estate, curvar, (Datum) 0, true, false);
2980 :
2981 104 : return rc;
2982 : }
2983 :
2984 :
2985 : /* ----------
2986 : * exec_stmt_foreach_a Loop over elements or slices of an array
2987 : *
2988 : * When looping over elements, the loop variable is the same type that the
2989 : * array stores (eg: integer), when looping through slices, the loop variable
2990 : * is an array of size and dimensions to match the size of the slice.
2991 : * ----------
2992 : */
2993 : static int
2994 90 : exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
2995 : {
2996 : ArrayType *arr;
2997 : Oid arrtype;
2998 : int32 arrtypmod;
2999 : PLpgSQL_datum *loop_var;
3000 : Oid loop_var_elem_type;
3001 90 : bool found = false;
3002 90 : int rc = PLPGSQL_RC_OK;
3003 : MemoryContext stmt_mcontext;
3004 : MemoryContext oldcontext;
3005 : ArrayIterator array_iterator;
3006 : Oid iterator_result_type;
3007 : int32 iterator_result_typmod;
3008 : Datum value;
3009 : bool isnull;
3010 :
3011 : /* get the value of the array expression */
3012 90 : value = exec_eval_expr(estate, stmt->expr, &isnull, &arrtype, &arrtypmod);
3013 90 : if (isnull)
3014 0 : ereport(ERROR,
3015 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3016 : errmsg("FOREACH expression must not be null")));
3017 :
3018 : /*
3019 : * Do as much as possible of the code below in stmt_mcontext, to avoid any
3020 : * leaks from called subroutines. We need a private stmt_mcontext since
3021 : * we'll be calling arbitrary statement code.
3022 : */
3023 90 : stmt_mcontext = get_stmt_mcontext(estate);
3024 90 : push_stmt_mcontext(estate);
3025 90 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3026 :
3027 : /* check the type of the expression - must be an array */
3028 90 : if (!OidIsValid(get_element_type(arrtype)))
3029 0 : ereport(ERROR,
3030 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3031 : errmsg("FOREACH expression must yield an array, not type %s",
3032 : format_type_be(arrtype))));
3033 :
3034 : /*
3035 : * We must copy the array into stmt_mcontext, else it will disappear in
3036 : * exec_eval_cleanup. This is annoying, but cleanup will certainly happen
3037 : * while running the loop body, so we have little choice.
3038 : */
3039 90 : arr = DatumGetArrayTypePCopy(value);
3040 :
3041 : /* Clean up any leftover temporary memory */
3042 90 : exec_eval_cleanup(estate);
3043 :
3044 : /* Slice dimension must be less than or equal to array dimension */
3045 90 : if (stmt->slice < 0 || stmt->slice > ARR_NDIM(arr))
3046 6 : ereport(ERROR,
3047 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3048 : errmsg("slice dimension (%d) is out of the valid range 0..%d",
3049 : stmt->slice, ARR_NDIM(arr))));
3050 :
3051 : /* Set up the loop variable and see if it is of an array type */
3052 84 : loop_var = estate->datums[stmt->varno];
3053 84 : if (loop_var->dtype == PLPGSQL_DTYPE_REC ||
3054 72 : loop_var->dtype == PLPGSQL_DTYPE_ROW)
3055 : {
3056 : /*
3057 : * Record/row variable is certainly not of array type, and might not
3058 : * be initialized at all yet, so don't try to get its type
3059 : */
3060 24 : loop_var_elem_type = InvalidOid;
3061 : }
3062 : else
3063 60 : loop_var_elem_type = get_element_type(plpgsql_exec_get_datum_type(estate,
3064 : loop_var));
3065 :
3066 : /*
3067 : * Sanity-check the loop variable type. We don't try very hard here, and
3068 : * should not be too picky since it's possible that exec_assign_value can
3069 : * coerce values of different types. But it seems worthwhile to complain
3070 : * if the array-ness of the loop variable is not right.
3071 : */
3072 84 : if (stmt->slice > 0 && loop_var_elem_type == InvalidOid)
3073 12 : ereport(ERROR,
3074 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3075 : errmsg("FOREACH ... SLICE loop variable must be of an array type")));
3076 72 : if (stmt->slice == 0 && loop_var_elem_type != InvalidOid)
3077 0 : ereport(ERROR,
3078 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3079 : errmsg("FOREACH loop variable must not be of an array type")));
3080 :
3081 : /* Create an iterator to step through the array */
3082 72 : array_iterator = array_create_iterator(arr, stmt->slice, NULL);
3083 :
3084 : /* Identify iterator result type */
3085 72 : if (stmt->slice > 0)
3086 : {
3087 : /* When slicing, nominal type of result is same as array type */
3088 36 : iterator_result_type = arrtype;
3089 36 : iterator_result_typmod = arrtypmod;
3090 : }
3091 : else
3092 : {
3093 : /* Without slicing, results are individual array elements */
3094 36 : iterator_result_type = ARR_ELEMTYPE(arr);
3095 36 : iterator_result_typmod = arrtypmod;
3096 : }
3097 :
3098 : /* Iterate over the array elements or slices */
3099 258 : while (array_iterate(array_iterator, &value, &isnull))
3100 : {
3101 186 : found = true; /* looped at least once */
3102 :
3103 : /* exec_assign_value and exec_stmts must run in the main context */
3104 186 : MemoryContextSwitchTo(oldcontext);
3105 :
3106 : /* Assign current element/slice to the loop variable */
3107 186 : exec_assign_value(estate, loop_var, value, isnull,
3108 : iterator_result_type, iterator_result_typmod);
3109 :
3110 : /* In slice case, value is temporary; must free it to avoid leakage */
3111 186 : if (stmt->slice > 0)
3112 54 : pfree(DatumGetPointer(value));
3113 :
3114 : /*
3115 : * Execute the statements
3116 : */
3117 186 : rc = exec_stmts(estate, stmt->body);
3118 :
3119 186 : LOOP_RC_PROCESSING(stmt->label, break);
3120 :
3121 186 : MemoryContextSwitchTo(stmt_mcontext);
3122 : }
3123 :
3124 : /* Restore memory context state */
3125 72 : MemoryContextSwitchTo(oldcontext);
3126 72 : pop_stmt_mcontext(estate);
3127 :
3128 : /* Release temporary memory, including the array value */
3129 72 : MemoryContextReset(stmt_mcontext);
3130 :
3131 : /*
3132 : * Set the FOUND variable to indicate the result of executing the loop
3133 : * (namely, whether we looped one or more times). This must be set here so
3134 : * that it does not interfere with the value of the FOUND variable inside
3135 : * the loop processing itself.
3136 : */
3137 72 : exec_set_found(estate, found);
3138 :
3139 72 : return rc;
3140 : }
3141 :
3142 :
3143 : /* ----------
3144 : * exec_stmt_exit Implements EXIT and CONTINUE
3145 : *
3146 : * This begins the process of exiting / restarting a loop.
3147 : * ----------
3148 : */
3149 : static int
3150 2182 : exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
3151 : {
3152 : /*
3153 : * If the exit / continue has a condition, evaluate it
3154 : */
3155 2182 : if (stmt->cond != NULL)
3156 : {
3157 : bool value;
3158 : bool isnull;
3159 :
3160 1890 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
3161 1890 : exec_eval_cleanup(estate);
3162 1890 : if (isnull || value == false)
3163 1744 : return PLPGSQL_RC_OK;
3164 : }
3165 :
3166 438 : estate->exitlabel = stmt->label;
3167 438 : if (stmt->is_exit)
3168 78 : return PLPGSQL_RC_EXIT;
3169 : else
3170 360 : return PLPGSQL_RC_CONTINUE;
3171 : }
3172 :
3173 :
3174 : /* ----------
3175 : * exec_stmt_return Evaluate an expression and start
3176 : * returning from the function.
3177 : *
3178 : * Note: The result may be in the eval_mcontext. Therefore, we must not
3179 : * do exec_eval_cleanup while unwinding the control stack.
3180 : * ----------
3181 : */
3182 : static int
3183 80852 : exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
3184 : {
3185 : /*
3186 : * If processing a set-returning PL/pgSQL function, the final RETURN
3187 : * indicates that the function is finished producing tuples. The rest of
3188 : * the work will be done at the top level.
3189 : */
3190 80852 : if (estate->retisset)
3191 3438 : return PLPGSQL_RC_RETURN;
3192 :
3193 : /* initialize for null result */
3194 77414 : estate->retval = (Datum) 0;
3195 77414 : estate->retisnull = true;
3196 77414 : estate->rettype = InvalidOid;
3197 :
3198 : /*
3199 : * Special case path when the RETURN expression is a simple variable
3200 : * reference; in particular, this path is always taken in functions with
3201 : * one or more OUT parameters.
3202 : *
3203 : * This special case is especially efficient for returning variables that
3204 : * have R/W expanded values: we can put the R/W pointer directly into
3205 : * estate->retval, leading to transferring the value to the caller's
3206 : * context cheaply. If we went through exec_eval_expr we'd end up with a
3207 : * R/O pointer. It's okay to skip MakeExpandedObjectReadOnly here since
3208 : * we know we won't need the variable's value within the function anymore.
3209 : */
3210 77414 : if (stmt->retvarno >= 0)
3211 : {
3212 57698 : PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
3213 :
3214 57698 : switch (retvar->dtype)
3215 : {
3216 0 : case PLPGSQL_DTYPE_PROMISE:
3217 : /* fulfill promise if needed, then handle like regular var */
3218 0 : plpgsql_fulfill_promise(estate, (PLpgSQL_var *) retvar);
3219 :
3220 : /* FALL THRU */
3221 :
3222 38926 : case PLPGSQL_DTYPE_VAR:
3223 : {
3224 38926 : PLpgSQL_var *var = (PLpgSQL_var *) retvar;
3225 :
3226 38926 : estate->retval = var->value;
3227 38926 : estate->retisnull = var->isnull;
3228 38926 : estate->rettype = var->datatype->typoid;
3229 :
3230 : /*
3231 : * A PLpgSQL_var could not be of composite type, so
3232 : * conversion must fail if retistuple. We throw a custom
3233 : * error mainly for consistency with historical behavior.
3234 : * For the same reason, we don't throw error if the result
3235 : * is NULL. (Note that plpgsql_exec_trigger assumes that
3236 : * any non-null result has been verified to be composite.)
3237 : */
3238 38926 : if (estate->retistuple && !estate->retisnull)
3239 6 : ereport(ERROR,
3240 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3241 : errmsg("cannot return non-composite value from function returning composite type")));
3242 : }
3243 38920 : break;
3244 :
3245 12680 : case PLPGSQL_DTYPE_REC:
3246 : {
3247 12680 : PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
3248 :
3249 : /* If record is empty, we return NULL not a row of nulls */
3250 12680 : if (rec->erh && !ExpandedRecordIsEmpty(rec->erh))
3251 : {
3252 12434 : estate->retval = ExpandedRecordGetDatum(rec->erh);
3253 12434 : estate->retisnull = false;
3254 12434 : estate->rettype = rec->rectypeid;
3255 : }
3256 : }
3257 12680 : break;
3258 :
3259 6092 : case PLPGSQL_DTYPE_ROW:
3260 : {
3261 6092 : PLpgSQL_row *row = (PLpgSQL_row *) retvar;
3262 : int32 rettypmod;
3263 :
3264 : /* We get here if there are multiple OUT parameters */
3265 6092 : exec_eval_datum(estate,
3266 : (PLpgSQL_datum *) row,
3267 : &estate->rettype,
3268 : &rettypmod,
3269 : &estate->retval,
3270 : &estate->retisnull);
3271 : }
3272 6092 : break;
3273 :
3274 0 : default:
3275 0 : elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
3276 : }
3277 :
3278 57692 : return PLPGSQL_RC_RETURN;
3279 : }
3280 :
3281 19716 : if (stmt->expr != NULL)
3282 : {
3283 : int32 rettypmod;
3284 :
3285 15058 : estate->retval = exec_eval_expr(estate, stmt->expr,
3286 : &(estate->retisnull),
3287 : &(estate->rettype),
3288 : &rettypmod);
3289 :
3290 : /*
3291 : * As in the DTYPE_VAR case above, throw a custom error if a non-null,
3292 : * non-composite value is returned in a function returning tuple.
3293 : */
3294 14970 : if (estate->retistuple && !estate->retisnull &&
3295 98 : !type_is_rowtype(estate->rettype))
3296 6 : ereport(ERROR,
3297 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3298 : errmsg("cannot return non-composite value from function returning composite type")));
3299 :
3300 14964 : return PLPGSQL_RC_RETURN;
3301 : }
3302 :
3303 : /*
3304 : * Special hack for function returning VOID: instead of NULL, return a
3305 : * non-null VOID value. This is of dubious importance but is kept for
3306 : * backwards compatibility. We don't do it for procedures, though.
3307 : */
3308 4658 : if (estate->fn_rettype == VOIDOID &&
3309 4658 : estate->func->fn_prokind != PROKIND_PROCEDURE)
3310 : {
3311 4588 : estate->retval = (Datum) 0;
3312 4588 : estate->retisnull = false;
3313 4588 : estate->rettype = VOIDOID;
3314 : }
3315 :
3316 4658 : return PLPGSQL_RC_RETURN;
3317 : }
3318 :
3319 : /* ----------
3320 : * exec_stmt_return_next Evaluate an expression and add it to the
3321 : * list of tuples returned by the current
3322 : * SRF.
3323 : * ----------
3324 : */
3325 : static int
3326 4398 : exec_stmt_return_next(PLpgSQL_execstate *estate,
3327 : PLpgSQL_stmt_return_next *stmt)
3328 : {
3329 : TupleDesc tupdesc;
3330 : int natts;
3331 : HeapTuple tuple;
3332 : MemoryContext oldcontext;
3333 :
3334 4398 : if (!estate->retisset)
3335 0 : ereport(ERROR,
3336 : (errcode(ERRCODE_SYNTAX_ERROR),
3337 : errmsg("cannot use RETURN NEXT in a non-SETOF function")));
3338 :
3339 4398 : if (estate->tuple_store == NULL)
3340 824 : exec_init_tuple_store(estate);
3341 :
3342 : /* tuple_store_desc will be filled by exec_init_tuple_store */
3343 4398 : tupdesc = estate->tuple_store_desc;
3344 4398 : natts = tupdesc->natts;
3345 :
3346 : /*
3347 : * Special case path when the RETURN NEXT expression is a simple variable
3348 : * reference; in particular, this path is always taken in functions with
3349 : * one or more OUT parameters.
3350 : *
3351 : * Unlike exec_stmt_return, there's no special win here for R/W expanded
3352 : * values, since they'll have to get flattened to go into the tuplestore.
3353 : * Indeed, we'd better make them R/O to avoid any risk of the casting step
3354 : * changing them in-place.
3355 : */
3356 4398 : if (stmt->retvarno >= 0)
3357 : {
3358 3852 : PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
3359 :
3360 3852 : switch (retvar->dtype)
3361 : {
3362 0 : case PLPGSQL_DTYPE_PROMISE:
3363 : /* fulfill promise if needed, then handle like regular var */
3364 0 : plpgsql_fulfill_promise(estate, (PLpgSQL_var *) retvar);
3365 :
3366 : /* FALL THRU */
3367 :
3368 3502 : case PLPGSQL_DTYPE_VAR:
3369 : {
3370 3502 : PLpgSQL_var *var = (PLpgSQL_var *) retvar;
3371 3502 : Datum retval = var->value;
3372 3502 : bool isNull = var->isnull;
3373 3502 : Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
3374 :
3375 3502 : if (natts != 1)
3376 0 : ereport(ERROR,
3377 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3378 : errmsg("wrong result type supplied in RETURN NEXT")));
3379 :
3380 : /* let's be very paranoid about the cast step */
3381 3502 : retval = MakeExpandedObjectReadOnly(retval,
3382 : isNull,
3383 : var->datatype->typlen);
3384 :
3385 : /* coerce type if needed */
3386 7004 : retval = exec_cast_value(estate,
3387 : retval,
3388 : &isNull,
3389 3502 : var->datatype->typoid,
3390 3502 : var->datatype->atttypmod,
3391 : attr->atttypid,
3392 : attr->atttypmod);
3393 :
3394 3502 : tuplestore_putvalues(estate->tuple_store, tupdesc,
3395 : &retval, &isNull);
3396 : }
3397 3502 : break;
3398 :
3399 206 : case PLPGSQL_DTYPE_REC:
3400 : {
3401 206 : PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
3402 : TupleDesc rec_tupdesc;
3403 : TupleConversionMap *tupmap;
3404 :
3405 : /* If rec is null, try to convert it to a row of nulls */
3406 206 : if (rec->erh == NULL)
3407 4 : instantiate_empty_record_variable(estate, rec);
3408 204 : if (ExpandedRecordIsEmpty(rec->erh))
3409 2 : deconstruct_expanded_record(rec->erh);
3410 :
3411 : /* Use eval_mcontext for tuple conversion work */
3412 204 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3413 204 : rec_tupdesc = expanded_record_get_tupdesc(rec->erh);
3414 204 : tupmap = convert_tuples_by_position(rec_tupdesc,
3415 : tupdesc,
3416 : gettext_noop("wrong record type supplied in RETURN NEXT"));
3417 204 : tuple = expanded_record_get_tuple(rec->erh);
3418 204 : if (tupmap)
3419 44 : tuple = execute_attr_map_tuple(tuple, tupmap);
3420 204 : tuplestore_puttuple(estate->tuple_store, tuple);
3421 204 : MemoryContextSwitchTo(oldcontext);
3422 : }
3423 204 : break;
3424 :
3425 144 : case PLPGSQL_DTYPE_ROW:
3426 : {
3427 144 : PLpgSQL_row *row = (PLpgSQL_row *) retvar;
3428 :
3429 : /* We get here if there are multiple OUT parameters */
3430 :
3431 : /* Use eval_mcontext for tuple conversion work */
3432 144 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3433 144 : tuple = make_tuple_from_row(estate, row, tupdesc);
3434 144 : if (tuple == NULL) /* should not happen */
3435 0 : ereport(ERROR,
3436 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3437 : errmsg("wrong record type supplied in RETURN NEXT")));
3438 144 : tuplestore_puttuple(estate->tuple_store, tuple);
3439 144 : MemoryContextSwitchTo(oldcontext);
3440 : }
3441 144 : break;
3442 :
3443 0 : default:
3444 0 : elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
3445 : break;
3446 : }
3447 : }
3448 546 : else if (stmt->expr)
3449 : {
3450 : Datum retval;
3451 : bool isNull;
3452 : Oid rettype;
3453 : int32 rettypmod;
3454 :
3455 546 : retval = exec_eval_expr(estate,
3456 : stmt->expr,
3457 : &isNull,
3458 : &rettype,
3459 : &rettypmod);
3460 :
3461 546 : if (estate->retistuple)
3462 : {
3463 : /* Expression should be of RECORD or composite type */
3464 486 : if (!isNull)
3465 : {
3466 : HeapTupleData tmptup;
3467 : TupleDesc retvaldesc;
3468 : TupleConversionMap *tupmap;
3469 :
3470 480 : if (!type_is_rowtype(rettype))
3471 0 : ereport(ERROR,
3472 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3473 : errmsg("cannot return non-composite value from function returning composite type")));
3474 :
3475 : /* Use eval_mcontext for tuple conversion work */
3476 480 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3477 480 : retvaldesc = deconstruct_composite_datum(retval, &tmptup);
3478 480 : tuple = &tmptup;
3479 480 : tupmap = convert_tuples_by_position(retvaldesc, tupdesc,
3480 : gettext_noop("returned record type does not match expected record type"));
3481 478 : if (tupmap)
3482 2 : tuple = execute_attr_map_tuple(tuple, tupmap);
3483 478 : tuplestore_puttuple(estate->tuple_store, tuple);
3484 478 : ReleaseTupleDesc(retvaldesc);
3485 478 : MemoryContextSwitchTo(oldcontext);
3486 : }
3487 : else
3488 : {
3489 : /* Composite NULL --- store a row of nulls */
3490 : Datum *nulldatums;
3491 : bool *nullflags;
3492 :
3493 : nulldatums = (Datum *)
3494 6 : eval_mcontext_alloc0(estate, natts * sizeof(Datum));
3495 : nullflags = (bool *)
3496 6 : eval_mcontext_alloc(estate, natts * sizeof(bool));
3497 6 : memset(nullflags, true, natts * sizeof(bool));
3498 6 : tuplestore_putvalues(estate->tuple_store, tupdesc,
3499 : nulldatums, nullflags);
3500 : }
3501 : }
3502 : else
3503 : {
3504 60 : Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
3505 :
3506 : /* Simple scalar result */
3507 60 : if (natts != 1)
3508 0 : ereport(ERROR,
3509 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3510 : errmsg("wrong result type supplied in RETURN NEXT")));
3511 :
3512 : /* coerce type if needed */
3513 60 : retval = exec_cast_value(estate,
3514 : retval,
3515 : &isNull,
3516 : rettype,
3517 : rettypmod,
3518 : attr->atttypid,
3519 : attr->atttypmod);
3520 :
3521 60 : tuplestore_putvalues(estate->tuple_store, tupdesc,
3522 : &retval, &isNull);
3523 : }
3524 : }
3525 : else
3526 : {
3527 0 : ereport(ERROR,
3528 : (errcode(ERRCODE_SYNTAX_ERROR),
3529 : errmsg("RETURN NEXT must have a parameter")));
3530 : }
3531 :
3532 4394 : exec_eval_cleanup(estate);
3533 :
3534 4394 : return PLPGSQL_RC_OK;
3535 : }
3536 :
3537 : /* ----------
3538 : * exec_stmt_return_query Evaluate a query and add it to the
3539 : * list of tuples returned by the current
3540 : * SRF.
3541 : * ----------
3542 : */
3543 : static int
3544 2666 : exec_stmt_return_query(PLpgSQL_execstate *estate,
3545 : PLpgSQL_stmt_return_query *stmt)
3546 : {
3547 : int64 tcount;
3548 : DestReceiver *treceiver;
3549 : int rc;
3550 : uint64 processed;
3551 2666 : MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
3552 : MemoryContext oldcontext;
3553 :
3554 2666 : if (!estate->retisset)
3555 0 : ereport(ERROR,
3556 : (errcode(ERRCODE_SYNTAX_ERROR),
3557 : errmsg("cannot use RETURN QUERY in a non-SETOF function")));
3558 :
3559 2666 : if (estate->tuple_store == NULL)
3560 2612 : exec_init_tuple_store(estate);
3561 : /* There might be some tuples in the tuplestore already */
3562 2666 : tcount = tuplestore_tuple_count(estate->tuple_store);
3563 :
3564 : /*
3565 : * Set up DestReceiver to transfer results directly to tuplestore,
3566 : * converting rowtype if necessary. DestReceiver lives in mcontext.
3567 : */
3568 2666 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3569 2666 : treceiver = CreateDestReceiver(DestTuplestore);
3570 2666 : SetTuplestoreDestReceiverParams(treceiver,
3571 : estate->tuple_store,
3572 : estate->tuple_store_cxt,
3573 : false,
3574 : estate->tuple_store_desc,
3575 : gettext_noop("structure of query does not match function result type"));
3576 2666 : MemoryContextSwitchTo(oldcontext);
3577 :
3578 2666 : if (stmt->query != NULL)
3579 : {
3580 : /* static query */
3581 2408 : PLpgSQL_expr *expr = stmt->query;
3582 : ParamListInfo paramLI;
3583 : SPIExecuteOptions options;
3584 :
3585 : /*
3586 : * On the first call for this expression generate the plan.
3587 : */
3588 2408 : if (expr->plan == NULL)
3589 62 : exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
3590 :
3591 : /*
3592 : * Set up ParamListInfo to pass to executor
3593 : */
3594 2408 : paramLI = setup_param_list(estate, expr);
3595 :
3596 : /*
3597 : * Execute the query
3598 : */
3599 2408 : memset(&options, 0, sizeof(options));
3600 2408 : options.params = paramLI;
3601 2408 : options.read_only = estate->readonly_func;
3602 2408 : options.must_return_tuples = true;
3603 2408 : options.dest = treceiver;
3604 :
3605 2408 : rc = SPI_execute_plan_extended(expr->plan, &options);
3606 2402 : if (rc < 0)
3607 0 : elog(ERROR, "SPI_execute_plan_extended failed executing query \"%s\": %s",
3608 : expr->query, SPI_result_code_string(rc));
3609 : }
3610 : else
3611 : {
3612 : /* RETURN QUERY EXECUTE */
3613 : Datum query;
3614 : bool isnull;
3615 : Oid restype;
3616 : int32 restypmod;
3617 : char *querystr;
3618 : SPIExecuteOptions options;
3619 :
3620 : /*
3621 : * Evaluate the string expression after the EXECUTE keyword. Its
3622 : * result is the querystring we have to execute.
3623 : */
3624 : Assert(stmt->dynquery != NULL);
3625 258 : query = exec_eval_expr(estate, stmt->dynquery,
3626 : &isnull, &restype, &restypmod);
3627 258 : if (isnull)
3628 0 : ereport(ERROR,
3629 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3630 : errmsg("query string argument of EXECUTE is null")));
3631 :
3632 : /* Get the C-String representation */
3633 258 : querystr = convert_value_to_string(estate, query, restype);
3634 :
3635 : /* copy it into the stmt_mcontext before we clean up */
3636 258 : querystr = MemoryContextStrdup(stmt_mcontext, querystr);
3637 :
3638 258 : exec_eval_cleanup(estate);
3639 :
3640 : /* Execute query, passing params if necessary */
3641 258 : memset(&options, 0, sizeof(options));
3642 258 : options.params = exec_eval_using_params(estate,
3643 : stmt->params);
3644 258 : options.read_only = estate->readonly_func;
3645 258 : options.must_return_tuples = true;
3646 258 : options.dest = treceiver;
3647 :
3648 258 : rc = SPI_execute_extended(querystr, &options);
3649 252 : if (rc < 0)
3650 0 : elog(ERROR, "SPI_execute_extended failed executing query \"%s\": %s",
3651 : querystr, SPI_result_code_string(rc));
3652 : }
3653 :
3654 : /* Clean up */
3655 2654 : treceiver->rDestroy(treceiver);
3656 2654 : exec_eval_cleanup(estate);
3657 2654 : MemoryContextReset(stmt_mcontext);
3658 :
3659 : /* Count how many tuples we got */
3660 2654 : processed = tuplestore_tuple_count(estate->tuple_store) - tcount;
3661 :
3662 2654 : estate->eval_processed = processed;
3663 2654 : exec_set_found(estate, processed != 0);
3664 :
3665 2654 : return PLPGSQL_RC_OK;
3666 : }
3667 :
3668 : static void
3669 3436 : exec_init_tuple_store(PLpgSQL_execstate *estate)
3670 : {
3671 3436 : ReturnSetInfo *rsi = estate->rsi;
3672 : MemoryContext oldcxt;
3673 : ResourceOwner oldowner;
3674 :
3675 : /*
3676 : * Check caller can handle a set result in the way we want
3677 : */
3678 3436 : if (!rsi || !IsA(rsi, ReturnSetInfo))
3679 0 : ereport(ERROR,
3680 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3681 : errmsg("set-valued function called in context that cannot accept a set")));
3682 :
3683 3436 : if (!(rsi->allowedModes & SFRM_Materialize) ||
3684 3436 : rsi->expectedDesc == NULL)
3685 0 : ereport(ERROR,
3686 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3687 : errmsg("materialize mode required, but it is not allowed in this context")));
3688 :
3689 : /*
3690 : * Switch to the right memory context and resource owner for storing the
3691 : * tuplestore for return set. If we're within a subtransaction opened for
3692 : * an exception-block, for example, we must still create the tuplestore in
3693 : * the resource owner that was active when this function was entered, and
3694 : * not in the subtransaction resource owner.
3695 : */
3696 3436 : oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
3697 3436 : oldowner = CurrentResourceOwner;
3698 3436 : CurrentResourceOwner = estate->tuple_store_owner;
3699 :
3700 3436 : estate->tuple_store =
3701 3436 : tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
3702 : false, work_mem);
3703 :
3704 3436 : CurrentResourceOwner = oldowner;
3705 3436 : MemoryContextSwitchTo(oldcxt);
3706 :
3707 3436 : estate->tuple_store_desc = rsi->expectedDesc;
3708 3436 : }
3709 :
3710 : #define SET_RAISE_OPTION_TEXT(opt, name) \
3711 : do { \
3712 : if (opt) \
3713 : ereport(ERROR, \
3714 : (errcode(ERRCODE_SYNTAX_ERROR), \
3715 : errmsg("RAISE option already specified: %s", \
3716 : name))); \
3717 : opt = MemoryContextStrdup(stmt_mcontext, extval); \
3718 : } while (0)
3719 :
3720 : /* ----------
3721 : * exec_stmt_raise Build a message and throw it with elog()
3722 : * ----------
3723 : */
3724 : static int
3725 14484 : exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
3726 : {
3727 14484 : int err_code = 0;
3728 14484 : char *condname = NULL;
3729 14484 : char *err_message = NULL;
3730 14484 : char *err_detail = NULL;
3731 14484 : char *err_hint = NULL;
3732 14484 : char *err_column = NULL;
3733 14484 : char *err_constraint = NULL;
3734 14484 : char *err_datatype = NULL;
3735 14484 : char *err_table = NULL;
3736 14484 : char *err_schema = NULL;
3737 : MemoryContext stmt_mcontext;
3738 : ListCell *lc;
3739 :
3740 : /* RAISE with no parameters: re-throw current exception */
3741 14484 : if (stmt->condname == NULL && stmt->message == NULL &&
3742 54 : stmt->options == NIL)
3743 : {
3744 36 : if (estate->cur_error != NULL)
3745 30 : ReThrowError(estate->cur_error);
3746 : /* oops, we're not inside a handler */
3747 6 : ereport(ERROR,
3748 : (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
3749 : errmsg("RAISE without parameters cannot be used outside an exception handler")));
3750 : }
3751 :
3752 : /* We'll need to accumulate the various strings in stmt_mcontext */
3753 14448 : stmt_mcontext = get_stmt_mcontext(estate);
3754 :
3755 14448 : if (stmt->condname)
3756 : {
3757 658 : err_code = plpgsql_recognize_err_condition(stmt->condname, true);
3758 658 : condname = MemoryContextStrdup(stmt_mcontext, stmt->condname);
3759 : }
3760 :
3761 14448 : if (stmt->message)
3762 : {
3763 : StringInfoData ds;
3764 : ListCell *current_param;
3765 : char *cp;
3766 : MemoryContext oldcontext;
3767 :
3768 : /* build string in stmt_mcontext */
3769 13772 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3770 13772 : initStringInfo(&ds);
3771 13772 : MemoryContextSwitchTo(oldcontext);
3772 :
3773 13772 : current_param = list_head(stmt->params);
3774 :
3775 275208 : for (cp = stmt->message; *cp; cp++)
3776 : {
3777 : /*
3778 : * Occurrences of a single % are replaced by the next parameter's
3779 : * external representation. Double %'s are converted to one %.
3780 : */
3781 261462 : if (cp[0] == '%')
3782 : {
3783 : Oid paramtypeid;
3784 : int32 paramtypmod;
3785 : Datum paramvalue;
3786 : bool paramisnull;
3787 : char *extval;
3788 :
3789 35202 : if (cp[1] == '%')
3790 : {
3791 6 : appendStringInfoChar(&ds, '%');
3792 6 : cp++;
3793 6 : continue;
3794 : }
3795 :
3796 : /* should have been checked at compile time */
3797 35196 : if (current_param == NULL)
3798 0 : elog(ERROR, "unexpected RAISE parameter list length");
3799 :
3800 35196 : paramvalue = exec_eval_expr(estate,
3801 35196 : (PLpgSQL_expr *) lfirst(current_param),
3802 : ¶misnull,
3803 : ¶mtypeid,
3804 : ¶mtypmod);
3805 :
3806 35170 : if (paramisnull)
3807 344 : extval = "<NULL>";
3808 : else
3809 34826 : extval = convert_value_to_string(estate,
3810 : paramvalue,
3811 : paramtypeid);
3812 35170 : appendStringInfoString(&ds, extval);
3813 35170 : current_param = lnext(stmt->params, current_param);
3814 35170 : exec_eval_cleanup(estate);
3815 : }
3816 : else
3817 226260 : appendStringInfoChar(&ds, cp[0]);
3818 : }
3819 :
3820 : /* should have been checked at compile time */
3821 13746 : if (current_param != NULL)
3822 0 : elog(ERROR, "unexpected RAISE parameter list length");
3823 :
3824 13746 : err_message = ds.data;
3825 : }
3826 :
3827 15192 : foreach(lc, stmt->options)
3828 : {
3829 782 : PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
3830 : Datum optionvalue;
3831 : bool optionisnull;
3832 : Oid optiontypeid;
3833 : int32 optiontypmod;
3834 : char *extval;
3835 :
3836 782 : optionvalue = exec_eval_expr(estate, opt->expr,
3837 : &optionisnull,
3838 : &optiontypeid,
3839 : &optiontypmod);
3840 782 : if (optionisnull)
3841 0 : ereport(ERROR,
3842 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3843 : errmsg("RAISE statement option cannot be null")));
3844 :
3845 782 : extval = convert_value_to_string(estate, optionvalue, optiontypeid);
3846 :
3847 782 : switch (opt->opt_type)
3848 : {
3849 42 : case PLPGSQL_RAISEOPTION_ERRCODE:
3850 42 : if (err_code)
3851 6 : ereport(ERROR,
3852 : (errcode(ERRCODE_SYNTAX_ERROR),
3853 : errmsg("RAISE option already specified: %s",
3854 : "ERRCODE")));
3855 36 : err_code = plpgsql_recognize_err_condition(extval, true);
3856 36 : condname = MemoryContextStrdup(stmt_mcontext, extval);
3857 36 : break;
3858 640 : case PLPGSQL_RAISEOPTION_MESSAGE:
3859 640 : SET_RAISE_OPTION_TEXT(err_message, "MESSAGE");
3860 634 : break;
3861 46 : case PLPGSQL_RAISEOPTION_DETAIL:
3862 46 : SET_RAISE_OPTION_TEXT(err_detail, "DETAIL");
3863 46 : break;
3864 14 : case PLPGSQL_RAISEOPTION_HINT:
3865 14 : SET_RAISE_OPTION_TEXT(err_hint, "HINT");
3866 14 : break;
3867 8 : case PLPGSQL_RAISEOPTION_COLUMN:
3868 8 : SET_RAISE_OPTION_TEXT(err_column, "COLUMN");
3869 8 : break;
3870 8 : case PLPGSQL_RAISEOPTION_CONSTRAINT:
3871 8 : SET_RAISE_OPTION_TEXT(err_constraint, "CONSTRAINT");
3872 8 : break;
3873 8 : case PLPGSQL_RAISEOPTION_DATATYPE:
3874 8 : SET_RAISE_OPTION_TEXT(err_datatype, "DATATYPE");
3875 8 : break;
3876 8 : case PLPGSQL_RAISEOPTION_TABLE:
3877 8 : SET_RAISE_OPTION_TEXT(err_table, "TABLE");
3878 8 : break;
3879 8 : case PLPGSQL_RAISEOPTION_SCHEMA:
3880 8 : SET_RAISE_OPTION_TEXT(err_schema, "SCHEMA");
3881 8 : break;
3882 0 : default:
3883 0 : elog(ERROR, "unrecognized raise option: %d", opt->opt_type);
3884 : }
3885 :
3886 770 : exec_eval_cleanup(estate);
3887 : }
3888 :
3889 : /* Default code if nothing specified */
3890 14410 : if (err_code == 0 && stmt->elog_level >= ERROR)
3891 220 : err_code = ERRCODE_RAISE_EXCEPTION;
3892 :
3893 : /* Default error message if nothing specified */
3894 14410 : if (err_message == NULL)
3895 : {
3896 42 : if (condname)
3897 : {
3898 36 : err_message = condname;
3899 36 : condname = NULL;
3900 : }
3901 : else
3902 6 : err_message = MemoryContextStrdup(stmt_mcontext,
3903 6 : unpack_sql_state(err_code));
3904 : }
3905 :
3906 : /*
3907 : * Throw the error (may or may not come back)
3908 : */
3909 14410 : ereport(stmt->elog_level,
3910 : (err_code ? errcode(err_code) : 0,
3911 : errmsg_internal("%s", err_message),
3912 : (err_detail != NULL) ? errdetail_internal("%s", err_detail) : 0,
3913 : (err_hint != NULL) ? errhint("%s", err_hint) : 0,
3914 : (err_column != NULL) ?
3915 : err_generic_string(PG_DIAG_COLUMN_NAME, err_column) : 0,
3916 : (err_constraint != NULL) ?
3917 : err_generic_string(PG_DIAG_CONSTRAINT_NAME, err_constraint) : 0,
3918 : (err_datatype != NULL) ?
3919 : err_generic_string(PG_DIAG_DATATYPE_NAME, err_datatype) : 0,
3920 : (err_table != NULL) ?
3921 : err_generic_string(PG_DIAG_TABLE_NAME, err_table) : 0,
3922 : (err_schema != NULL) ?
3923 : err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema) : 0));
3924 :
3925 : /* Clean up transient strings */
3926 13508 : MemoryContextReset(stmt_mcontext);
3927 :
3928 13508 : return PLPGSQL_RC_OK;
3929 : }
3930 :
3931 : /* ----------
3932 : * exec_stmt_assert Assert statement
3933 : * ----------
3934 : */
3935 : static int
3936 8720 : exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
3937 : {
3938 : bool value;
3939 : bool isnull;
3940 :
3941 : /* do nothing when asserts are not enabled */
3942 8720 : if (!plpgsql_check_asserts)
3943 6 : return PLPGSQL_RC_OK;
3944 :
3945 8714 : value = exec_eval_boolean(estate, stmt->cond, &isnull);
3946 8714 : exec_eval_cleanup(estate);
3947 :
3948 8714 : if (isnull || !value)
3949 : {
3950 24 : char *message = NULL;
3951 :
3952 24 : if (stmt->message != NULL)
3953 : {
3954 : Datum val;
3955 : Oid typeid;
3956 : int32 typmod;
3957 :
3958 12 : val = exec_eval_expr(estate, stmt->message,
3959 : &isnull, &typeid, &typmod);
3960 12 : if (!isnull)
3961 12 : message = convert_value_to_string(estate, val, typeid);
3962 : /* we mustn't do exec_eval_cleanup here */
3963 : }
3964 :
3965 24 : ereport(ERROR,
3966 : (errcode(ERRCODE_ASSERT_FAILURE),
3967 : message ? errmsg_internal("%s", message) :
3968 : errmsg("assertion failed")));
3969 : }
3970 :
3971 8690 : return PLPGSQL_RC_OK;
3972 : }
3973 :
3974 : /* ----------
3975 : * Initialize a mostly empty execution state
3976 : * ----------
3977 : */
3978 : static void
3979 81816 : plpgsql_estate_setup(PLpgSQL_execstate *estate,
3980 : PLpgSQL_function *func,
3981 : ReturnSetInfo *rsi,
3982 : EState *simple_eval_estate,
3983 : ResourceOwner simple_eval_resowner)
3984 : {
3985 : HASHCTL ctl;
3986 :
3987 : /* this link will be restored at exit from plpgsql_call_handler */
3988 81816 : func->cur_estate = estate;
3989 :
3990 81816 : estate->func = func;
3991 81816 : estate->trigdata = NULL;
3992 81816 : estate->evtrigdata = NULL;
3993 :
3994 81816 : estate->retval = (Datum) 0;
3995 81816 : estate->retisnull = true;
3996 81816 : estate->rettype = InvalidOid;
3997 :
3998 81816 : estate->fn_rettype = func->fn_rettype;
3999 81816 : estate->retistuple = func->fn_retistuple;
4000 81816 : estate->retisset = func->fn_retset;
4001 :
4002 81816 : estate->readonly_func = func->fn_readonly;
4003 81816 : estate->atomic = true;
4004 :
4005 81816 : estate->exitlabel = NULL;
4006 81816 : estate->cur_error = NULL;
4007 :
4008 81816 : estate->tuple_store = NULL;
4009 81816 : estate->tuple_store_desc = NULL;
4010 81816 : if (rsi)
4011 : {
4012 3768 : estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
4013 3768 : estate->tuple_store_owner = CurrentResourceOwner;
4014 : }
4015 : else
4016 : {
4017 78048 : estate->tuple_store_cxt = NULL;
4018 78048 : estate->tuple_store_owner = NULL;
4019 : }
4020 81816 : estate->rsi = rsi;
4021 :
4022 81816 : estate->found_varno = func->found_varno;
4023 81816 : estate->ndatums = func->ndatums;
4024 81816 : estate->datums = NULL;
4025 : /* the datums array will be filled by copy_plpgsql_datums() */
4026 81816 : estate->datum_context = CurrentMemoryContext;
4027 :
4028 : /* initialize our ParamListInfo with appropriate hook functions */
4029 81816 : estate->paramLI = makeParamList(0);
4030 81816 : estate->paramLI->paramFetch = plpgsql_param_fetch;
4031 81816 : estate->paramLI->paramFetchArg = (void *) estate;
4032 81816 : estate->paramLI->paramCompile = plpgsql_param_compile;
4033 81816 : estate->paramLI->paramCompileArg = NULL; /* not needed */
4034 81816 : estate->paramLI->parserSetup = (ParserSetupHook) plpgsql_parser_setup;
4035 81816 : estate->paramLI->parserSetupArg = NULL; /* filled during use */
4036 81816 : estate->paramLI->numParams = estate->ndatums;
4037 :
4038 : /* Create the session-wide cast-expression hash if we didn't already */
4039 81816 : if (cast_expr_hash == NULL)
4040 : {
4041 964 : ctl.keysize = sizeof(plpgsql_CastHashKey);
4042 964 : ctl.entrysize = sizeof(plpgsql_CastExprHashEntry);
4043 964 : cast_expr_hash = hash_create("PLpgSQL cast expressions",
4044 : 16, /* start small and extend */
4045 : &ctl,
4046 : HASH_ELEM | HASH_BLOBS);
4047 : }
4048 :
4049 : /* set up for use of appropriate simple-expression EState and cast hash */
4050 81816 : if (simple_eval_estate)
4051 : {
4052 944 : estate->simple_eval_estate = simple_eval_estate;
4053 : /* Private cast hash just lives in function's main context */
4054 944 : ctl.keysize = sizeof(plpgsql_CastHashKey);
4055 944 : ctl.entrysize = sizeof(plpgsql_CastHashEntry);
4056 944 : ctl.hcxt = CurrentMemoryContext;
4057 944 : estate->cast_hash = hash_create("PLpgSQL private cast cache",
4058 : 16, /* start small and extend */
4059 : &ctl,
4060 : HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
4061 : }
4062 : else
4063 : {
4064 80872 : estate->simple_eval_estate = shared_simple_eval_estate;
4065 : /* Create the session-wide cast-info hash table if we didn't already */
4066 80872 : if (shared_cast_hash == NULL)
4067 : {
4068 824 : ctl.keysize = sizeof(plpgsql_CastHashKey);
4069 824 : ctl.entrysize = sizeof(plpgsql_CastHashEntry);
4070 824 : shared_cast_hash = hash_create("PLpgSQL cast cache",
4071 : 16, /* start small and extend */
4072 : &ctl,
4073 : HASH_ELEM | HASH_BLOBS);
4074 : }
4075 80872 : estate->cast_hash = shared_cast_hash;
4076 : }
4077 : /* likewise for the simple-expression resource owner */
4078 81816 : if (simple_eval_resowner)
4079 944 : estate->simple_eval_resowner = simple_eval_resowner;
4080 : else
4081 80872 : estate->simple_eval_resowner = shared_simple_eval_resowner;
4082 :
4083 : /* if there's a procedure resowner, it'll be filled in later */
4084 81816 : estate->procedure_resowner = NULL;
4085 :
4086 : /*
4087 : * We start with no stmt_mcontext; one will be created only if needed.
4088 : * That context will be a direct child of the function's main execution
4089 : * context. Additional stmt_mcontexts might be created as children of it.
4090 : */
4091 81816 : estate->stmt_mcontext = NULL;
4092 81816 : estate->stmt_mcontext_parent = CurrentMemoryContext;
4093 :
4094 81816 : estate->eval_tuptable = NULL;
4095 81816 : estate->eval_processed = 0;
4096 81816 : estate->eval_econtext = NULL;
4097 :
4098 81816 : estate->err_stmt = NULL;
4099 81816 : estate->err_var = NULL;
4100 81816 : estate->err_text = NULL;
4101 :
4102 81816 : estate->plugin_info = NULL;
4103 :
4104 : /*
4105 : * Create an EState and ExprContext for evaluation of simple expressions.
4106 : */
4107 81816 : plpgsql_create_econtext(estate);
4108 :
4109 : /*
4110 : * Let the plugin, if any, see this function before we initialize local
4111 : * PL/pgSQL variables. Note that we also give the plugin a few function
4112 : * pointers, so it can call back into PL/pgSQL for doing things like
4113 : * variable assignments and stack traces.
4114 : */
4115 81816 : if (*plpgsql_plugin_ptr)
4116 : {
4117 0 : (*plpgsql_plugin_ptr)->error_callback = plpgsql_exec_error_callback;
4118 0 : (*plpgsql_plugin_ptr)->assign_expr = exec_assign_expr;
4119 0 : (*plpgsql_plugin_ptr)->assign_value = exec_assign_value;
4120 0 : (*plpgsql_plugin_ptr)->eval_datum = exec_eval_datum;
4121 0 : (*plpgsql_plugin_ptr)->cast_value = exec_cast_value;
4122 :
4123 0 : if ((*plpgsql_plugin_ptr)->func_setup)
4124 0 : ((*plpgsql_plugin_ptr)->func_setup) (estate, func);
4125 : }
4126 81816 : }
4127 :
4128 : /* ----------
4129 : * Release temporary memory used by expression/subselect evaluation
4130 : *
4131 : * NB: the result of the evaluation is no longer valid after this is done,
4132 : * unless it is a pass-by-value datatype.
4133 : * ----------
4134 : */
4135 : static void
4136 418956 : exec_eval_cleanup(PLpgSQL_execstate *estate)
4137 : {
4138 : /* Clear result of a full SPI_execute */
4139 418956 : if (estate->eval_tuptable != NULL)
4140 8628 : SPI_freetuptable(estate->eval_tuptable);
4141 418956 : estate->eval_tuptable = NULL;
4142 :
4143 : /*
4144 : * Clear result of exec_eval_simple_expr (but keep the econtext). This
4145 : * also clears any short-lived allocations done via get_eval_mcontext.
4146 : */
4147 418956 : if (estate->eval_econtext != NULL)
4148 338280 : ResetExprContext(estate->eval_econtext);
4149 418956 : }
4150 :
4151 :
4152 : /* ----------
4153 : * Generate a prepared plan
4154 : *
4155 : * CAUTION: it is possible for this function to throw an error after it has
4156 : * built a SPIPlan and saved it in expr->plan. Therefore, be wary of doing
4157 : * additional things contingent on expr->plan being NULL. That is, given
4158 : * code like
4159 : *
4160 : * if (query->plan == NULL)
4161 : * {
4162 : * // okay to put setup code here
4163 : * exec_prepare_plan(estate, query, ...);
4164 : * // NOT okay to put more logic here
4165 : * }
4166 : *
4167 : * extra steps at the end are unsafe because they will not be executed when
4168 : * re-executing the calling statement, if exec_prepare_plan failed the first
4169 : * time. This is annoyingly error-prone, but the alternatives are worse.
4170 : * ----------
4171 : */
4172 : static void
4173 24582 : exec_prepare_plan(PLpgSQL_execstate *estate,
4174 : PLpgSQL_expr *expr, int cursorOptions)
4175 : {
4176 : SPIPlanPtr plan;
4177 : SPIPrepareOptions options;
4178 :
4179 : /*
4180 : * The grammar can't conveniently set expr->func while building the parse
4181 : * tree, so make sure it's set before parser hooks need it.
4182 : */
4183 24582 : expr->func = estate->func;
4184 :
4185 : /*
4186 : * Generate and save the plan
4187 : */
4188 24582 : memset(&options, 0, sizeof(options));
4189 24582 : options.parserSetup = (ParserSetupHook) plpgsql_parser_setup;
4190 24582 : options.parserSetupArg = (void *) expr;
4191 24582 : options.parseMode = expr->parseMode;
4192 24582 : options.cursorOptions = cursorOptions;
4193 24582 : plan = SPI_prepare_extended(expr->query, &options);
4194 24496 : if (plan == NULL)
4195 0 : elog(ERROR, "SPI_prepare_extended failed for \"%s\": %s",
4196 : expr->query, SPI_result_code_string(SPI_result));
4197 :
4198 24496 : SPI_keepplan(plan);
4199 24496 : expr->plan = plan;
4200 :
4201 : /* Check to see if it's a simple expression */
4202 24496 : exec_simple_check_plan(estate, expr);
4203 24464 : }
4204 :
4205 :
4206 : /* ----------
4207 : * exec_stmt_execsql Execute an SQL statement (possibly with INTO).
4208 : *
4209 : * Note: some callers rely on this not touching stmt_mcontext. If it ever
4210 : * needs to use that, fix those callers to push/pop stmt_mcontext.
4211 : * ----------
4212 : */
4213 : static int
4214 52186 : exec_stmt_execsql(PLpgSQL_execstate *estate,
4215 : PLpgSQL_stmt_execsql *stmt)
4216 : {
4217 : ParamListInfo paramLI;
4218 : long tcount;
4219 : int rc;
4220 52186 : PLpgSQL_expr *expr = stmt->sqlstmt;
4221 52186 : int too_many_rows_level = 0;
4222 :
4223 52186 : if (plpgsql_extra_errors & PLPGSQL_XCHECK_TOOMANYROWS)
4224 6 : too_many_rows_level = ERROR;
4225 52180 : else if (plpgsql_extra_warnings & PLPGSQL_XCHECK_TOOMANYROWS)
4226 6 : too_many_rows_level = WARNING;
4227 :
4228 : /*
4229 : * On the first call for this statement generate the plan, and detect
4230 : * whether the statement is INSERT/UPDATE/DELETE/MERGE
4231 : */
4232 52186 : if (expr->plan == NULL)
4233 1896 : exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
4234 :
4235 52176 : if (!stmt->mod_stmt_set)
4236 : {
4237 : ListCell *l;
4238 :
4239 1902 : stmt->mod_stmt = false;
4240 2992 : foreach(l, SPI_plan_get_plan_sources(expr->plan))
4241 : {
4242 1902 : CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l);
4243 :
4244 : /*
4245 : * We could look at the raw_parse_tree, but it seems simpler to
4246 : * check the command tag. Note we should *not* look at the Query
4247 : * tree(s), since those are the result of rewriting and could have
4248 : * been transmogrified into something else entirely.
4249 : */
4250 1902 : if (plansource->commandTag == CMDTAG_INSERT ||
4251 1400 : plansource->commandTag == CMDTAG_UPDATE ||
4252 1218 : plansource->commandTag == CMDTAG_DELETE ||
4253 1144 : plansource->commandTag == CMDTAG_MERGE)
4254 : {
4255 812 : stmt->mod_stmt = true;
4256 812 : break;
4257 : }
4258 : }
4259 1902 : stmt->mod_stmt_set = true;
4260 : }
4261 :
4262 : /*
4263 : * Set up ParamListInfo to pass to executor
4264 : */
4265 52176 : paramLI = setup_param_list(estate, expr);
4266 :
4267 : /*
4268 : * If we have INTO, then we only need one row back ... but if we have INTO
4269 : * STRICT or extra check too_many_rows, ask for two rows, so that we can
4270 : * verify the statement returns only one. INSERT/UPDATE/DELETE/MERGE are
4271 : * always treated strictly. Without INTO, just run the statement to
4272 : * completion (tcount = 0).
4273 : *
4274 : * We could just ask for two rows always when using INTO, but there are
4275 : * some cases where demanding the extra row costs significant time, eg by
4276 : * forcing completion of a sequential scan. So don't do it unless we need
4277 : * to enforce strictness.
4278 : */
4279 52176 : if (stmt->into)
4280 : {
4281 14878 : if (stmt->strict || stmt->mod_stmt || too_many_rows_level)
4282 1186 : tcount = 2;
4283 : else
4284 13692 : tcount = 1;
4285 : }
4286 : else
4287 37298 : tcount = 0;
4288 :
4289 : /*
4290 : * Execute the plan
4291 : */
4292 52176 : rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
4293 52176 : estate->readonly_func, tcount);
4294 :
4295 : /*
4296 : * Check for error, and set FOUND if appropriate (for historical reasons
4297 : * we set FOUND only for certain query types). Also Assert that we
4298 : * identified the statement type the same as SPI did.
4299 : */
4300 48230 : switch (rc)
4301 : {
4302 10044 : case SPI_OK_SELECT:
4303 : Assert(!stmt->mod_stmt);
4304 10044 : exec_set_found(estate, (SPI_processed != 0));
4305 10044 : break;
4306 :
4307 27378 : case SPI_OK_INSERT:
4308 : case SPI_OK_UPDATE:
4309 : case SPI_OK_DELETE:
4310 : case SPI_OK_MERGE:
4311 : case SPI_OK_INSERT_RETURNING:
4312 : case SPI_OK_UPDATE_RETURNING:
4313 : case SPI_OK_DELETE_RETURNING:
4314 : case SPI_OK_MERGE_RETURNING:
4315 : Assert(stmt->mod_stmt);
4316 27378 : exec_set_found(estate, (SPI_processed != 0));
4317 27378 : break;
4318 :
4319 10802 : case SPI_OK_SELINTO:
4320 : case SPI_OK_UTILITY:
4321 : Assert(!stmt->mod_stmt);
4322 10802 : break;
4323 :
4324 0 : case SPI_OK_REWRITTEN:
4325 :
4326 : /*
4327 : * The command was rewritten into another kind of command. It's
4328 : * not clear what FOUND would mean in that case (and SPI doesn't
4329 : * return the row count either), so just set it to false. Note
4330 : * that we can't assert anything about mod_stmt here.
4331 : */
4332 0 : exec_set_found(estate, false);
4333 0 : break;
4334 :
4335 : /* Some SPI errors deserve specific error messages */
4336 4 : case SPI_ERROR_COPY:
4337 4 : ereport(ERROR,
4338 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4339 : errmsg("cannot COPY to/from client in PL/pgSQL")));
4340 : break;
4341 :
4342 2 : case SPI_ERROR_TRANSACTION:
4343 2 : ereport(ERROR,
4344 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4345 : errmsg("unsupported transaction command in PL/pgSQL")));
4346 : break;
4347 :
4348 0 : default:
4349 0 : elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s",
4350 : expr->query, SPI_result_code_string(rc));
4351 : break;
4352 : }
4353 :
4354 : /* All variants should save result info for GET DIAGNOSTICS */
4355 48224 : estate->eval_processed = SPI_processed;
4356 :
4357 : /* Process INTO if present */
4358 48224 : if (stmt->into)
4359 : {
4360 10996 : SPITupleTable *tuptab = SPI_tuptable;
4361 10996 : uint64 n = SPI_processed;
4362 : PLpgSQL_variable *target;
4363 :
4364 : /* If the statement did not return a tuple table, complain */
4365 10996 : if (tuptab == NULL)
4366 0 : ereport(ERROR,
4367 : (errcode(ERRCODE_SYNTAX_ERROR),
4368 : errmsg("INTO used with a command that cannot return data")));
4369 :
4370 : /* Fetch target's datum entry */
4371 10996 : target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4372 :
4373 : /*
4374 : * If SELECT ... INTO specified STRICT, and the query didn't find
4375 : * exactly one row, throw an error. If STRICT was not specified, then
4376 : * allow the query to find any number of rows.
4377 : */
4378 10996 : if (n == 0)
4379 : {
4380 62 : if (stmt->strict)
4381 : {
4382 : char *errdetail;
4383 :
4384 18 : if (estate->func->print_strict_params)
4385 12 : errdetail = format_expr_params(estate, expr);
4386 : else
4387 6 : errdetail = NULL;
4388 :
4389 18 : ereport(ERROR,
4390 : (errcode(ERRCODE_NO_DATA_FOUND),
4391 : errmsg("query returned no rows"),
4392 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4393 : }
4394 : /* set the target to NULL(s) */
4395 44 : exec_move_row(estate, target, NULL, tuptab->tupdesc);
4396 : }
4397 : else
4398 : {
4399 10934 : if (n > 1 && (stmt->strict || stmt->mod_stmt || too_many_rows_level))
4400 : {
4401 : char *errdetail;
4402 : int errlevel;
4403 :
4404 48 : if (estate->func->print_strict_params)
4405 18 : errdetail = format_expr_params(estate, expr);
4406 : else
4407 30 : errdetail = NULL;
4408 :
4409 48 : errlevel = (stmt->strict || stmt->mod_stmt) ? ERROR : too_many_rows_level;
4410 :
4411 48 : ereport(errlevel,
4412 : (errcode(ERRCODE_TOO_MANY_ROWS),
4413 : errmsg("query returned more than one row"),
4414 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0,
4415 : errhint("Make sure the query returns a single row, or use LIMIT 1.")));
4416 : }
4417 : /* Put the first result row into the target */
4418 10892 : exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4419 : }
4420 :
4421 : /* Clean up */
4422 10912 : exec_eval_cleanup(estate);
4423 10912 : SPI_freetuptable(SPI_tuptable);
4424 : }
4425 : else
4426 : {
4427 : /* If the statement returned a tuple table, complain */
4428 37228 : if (SPI_tuptable != NULL)
4429 0 : ereport(ERROR,
4430 : (errcode(ERRCODE_SYNTAX_ERROR),
4431 : errmsg("query has no destination for result data"),
4432 : (rc == SPI_OK_SELECT) ? errhint("If you want to discard the results of a SELECT, use PERFORM instead.") : 0));
4433 : }
4434 :
4435 48140 : return PLPGSQL_RC_OK;
4436 : }
4437 :
4438 :
4439 : /* ----------
4440 : * exec_stmt_dynexecute Execute a dynamic SQL query
4441 : * (possibly with INTO).
4442 : * ----------
4443 : */
4444 : static int
4445 10782 : exec_stmt_dynexecute(PLpgSQL_execstate *estate,
4446 : PLpgSQL_stmt_dynexecute *stmt)
4447 : {
4448 : Datum query;
4449 : bool isnull;
4450 : Oid restype;
4451 : int32 restypmod;
4452 : char *querystr;
4453 : int exec_res;
4454 : ParamListInfo paramLI;
4455 : SPIExecuteOptions options;
4456 10782 : MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
4457 :
4458 : /*
4459 : * First we evaluate the string expression after the EXECUTE keyword. Its
4460 : * result is the querystring we have to execute.
4461 : */
4462 10782 : query = exec_eval_expr(estate, stmt->query, &isnull, &restype, &restypmod);
4463 10782 : if (isnull)
4464 0 : ereport(ERROR,
4465 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4466 : errmsg("query string argument of EXECUTE is null")));
4467 :
4468 : /* Get the C-String representation */
4469 10782 : querystr = convert_value_to_string(estate, query, restype);
4470 :
4471 : /* copy it into the stmt_mcontext before we clean up */
4472 10782 : querystr = MemoryContextStrdup(stmt_mcontext, querystr);
4473 :
4474 10782 : exec_eval_cleanup(estate);
4475 :
4476 : /*
4477 : * Execute the query without preparing a saved plan.
4478 : */
4479 10782 : paramLI = exec_eval_using_params(estate, stmt->params);
4480 :
4481 10782 : memset(&options, 0, sizeof(options));
4482 10782 : options.params = paramLI;
4483 10782 : options.read_only = estate->readonly_func;
4484 :
4485 10782 : exec_res = SPI_execute_extended(querystr, &options);
4486 :
4487 10586 : switch (exec_res)
4488 : {
4489 10580 : case SPI_OK_SELECT:
4490 : case SPI_OK_INSERT:
4491 : case SPI_OK_UPDATE:
4492 : case SPI_OK_DELETE:
4493 : case SPI_OK_MERGE:
4494 : case SPI_OK_INSERT_RETURNING:
4495 : case SPI_OK_UPDATE_RETURNING:
4496 : case SPI_OK_DELETE_RETURNING:
4497 : case SPI_OK_MERGE_RETURNING:
4498 : case SPI_OK_UTILITY:
4499 : case SPI_OK_REWRITTEN:
4500 10580 : break;
4501 :
4502 0 : case 0:
4503 :
4504 : /*
4505 : * Also allow a zero return, which implies the querystring
4506 : * contained no commands.
4507 : */
4508 0 : break;
4509 :
4510 0 : case SPI_OK_SELINTO:
4511 :
4512 : /*
4513 : * We want to disallow SELECT INTO for now, because its behavior
4514 : * is not consistent with SELECT INTO in a normal plpgsql context.
4515 : * (We need to reimplement EXECUTE to parse the string as a
4516 : * plpgsql command, not just feed it to SPI_execute.) This is not
4517 : * a functional limitation because CREATE TABLE AS is allowed.
4518 : */
4519 0 : ereport(ERROR,
4520 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4521 : errmsg("EXECUTE of SELECT ... INTO is not implemented"),
4522 : errhint("You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.")));
4523 : break;
4524 :
4525 : /* Some SPI errors deserve specific error messages */
4526 4 : case SPI_ERROR_COPY:
4527 4 : ereport(ERROR,
4528 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4529 : errmsg("cannot COPY to/from client in PL/pgSQL")));
4530 : break;
4531 :
4532 2 : case SPI_ERROR_TRANSACTION:
4533 2 : ereport(ERROR,
4534 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4535 : errmsg("EXECUTE of transaction commands is not implemented")));
4536 : break;
4537 :
4538 0 : default:
4539 0 : elog(ERROR, "SPI_execute_extended failed executing query \"%s\": %s",
4540 : querystr, SPI_result_code_string(exec_res));
4541 : break;
4542 : }
4543 :
4544 : /* Save result info for GET DIAGNOSTICS */
4545 10580 : estate->eval_processed = SPI_processed;
4546 :
4547 : /* Process INTO if present */
4548 10580 : if (stmt->into)
4549 : {
4550 6064 : SPITupleTable *tuptab = SPI_tuptable;
4551 6064 : uint64 n = SPI_processed;
4552 : PLpgSQL_variable *target;
4553 :
4554 : /* If the statement did not return a tuple table, complain */
4555 6064 : if (tuptab == NULL)
4556 0 : ereport(ERROR,
4557 : (errcode(ERRCODE_SYNTAX_ERROR),
4558 : errmsg("INTO used with a command that cannot return data")));
4559 :
4560 : /* Fetch target's datum entry */
4561 6064 : target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4562 :
4563 : /*
4564 : * If SELECT ... INTO specified STRICT, and the query didn't find
4565 : * exactly one row, throw an error. If STRICT was not specified, then
4566 : * allow the query to find any number of rows.
4567 : */
4568 6064 : if (n == 0)
4569 : {
4570 12 : if (stmt->strict)
4571 : {
4572 : char *errdetail;
4573 :
4574 12 : if (estate->func->print_strict_params)
4575 6 : errdetail = format_preparedparamsdata(estate, paramLI);
4576 : else
4577 6 : errdetail = NULL;
4578 :
4579 12 : ereport(ERROR,
4580 : (errcode(ERRCODE_NO_DATA_FOUND),
4581 : errmsg("query returned no rows"),
4582 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4583 : }
4584 : /* set the target to NULL(s) */
4585 0 : exec_move_row(estate, target, NULL, tuptab->tupdesc);
4586 : }
4587 : else
4588 : {
4589 6052 : if (n > 1 && stmt->strict)
4590 : {
4591 : char *errdetail;
4592 :
4593 18 : if (estate->func->print_strict_params)
4594 12 : errdetail = format_preparedparamsdata(estate, paramLI);
4595 : else
4596 6 : errdetail = NULL;
4597 :
4598 18 : ereport(ERROR,
4599 : (errcode(ERRCODE_TOO_MANY_ROWS),
4600 : errmsg("query returned more than one row"),
4601 : errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4602 : }
4603 :
4604 : /* Put the first result row into the target */
4605 6034 : exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4606 : }
4607 : /* clean up after exec_move_row() */
4608 6034 : exec_eval_cleanup(estate);
4609 : }
4610 : else
4611 : {
4612 : /*
4613 : * It might be a good idea to raise an error if the query returned
4614 : * tuples that are being ignored, but historically we have not done
4615 : * that.
4616 : */
4617 : }
4618 :
4619 : /* Release any result from SPI_execute, as well as transient data */
4620 10550 : SPI_freetuptable(SPI_tuptable);
4621 10550 : MemoryContextReset(stmt_mcontext);
4622 :
4623 10550 : return PLPGSQL_RC_OK;
4624 : }
4625 :
4626 :
4627 : /* ----------
4628 : * exec_stmt_dynfors Execute a dynamic query, assign each
4629 : * tuple to a record or row and
4630 : * execute a group of statements
4631 : * for it.
4632 : * ----------
4633 : */
4634 : static int
4635 9218 : exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
4636 : {
4637 : Portal portal;
4638 : int rc;
4639 :
4640 9218 : portal = exec_dynquery_with_params(estate, stmt->query, stmt->params,
4641 : NULL, CURSOR_OPT_NO_SCROLL);
4642 :
4643 : /*
4644 : * Execute the loop
4645 : */
4646 9218 : rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
4647 :
4648 : /*
4649 : * Close the implicit cursor
4650 : */
4651 9212 : SPI_cursor_close(portal);
4652 :
4653 9212 : return rc;
4654 : }
4655 :
4656 :
4657 : /* ----------
4658 : * exec_stmt_open Execute an OPEN cursor statement
4659 : * ----------
4660 : */
4661 : static int
4662 138 : exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
4663 : {
4664 : PLpgSQL_var *curvar;
4665 138 : MemoryContext stmt_mcontext = NULL;
4666 138 : char *curname = NULL;
4667 : PLpgSQL_expr *query;
4668 : Portal portal;
4669 : ParamListInfo paramLI;
4670 :
4671 : /* ----------
4672 : * Get the cursor variable and if it has an assigned name, check
4673 : * that it's not in use currently.
4674 : * ----------
4675 : */
4676 138 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4677 138 : if (!curvar->isnull)
4678 : {
4679 : MemoryContext oldcontext;
4680 :
4681 : /* We only need stmt_mcontext to hold the cursor name string */
4682 24 : stmt_mcontext = get_stmt_mcontext(estate);
4683 24 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
4684 24 : curname = TextDatumGetCString(curvar->value);
4685 24 : MemoryContextSwitchTo(oldcontext);
4686 :
4687 24 : if (SPI_cursor_find(curname) != NULL)
4688 0 : ereport(ERROR,
4689 : (errcode(ERRCODE_DUPLICATE_CURSOR),
4690 : errmsg("cursor \"%s\" already in use", curname)));
4691 : }
4692 :
4693 : /* ----------
4694 : * Process the OPEN according to it's type.
4695 : * ----------
4696 : */
4697 138 : if (stmt->query != NULL)
4698 : {
4699 : /* ----------
4700 : * This is an OPEN refcursor FOR SELECT ...
4701 : *
4702 : * We just make sure the query is planned. The real work is
4703 : * done downstairs.
4704 : * ----------
4705 : */
4706 48 : query = stmt->query;
4707 48 : if (query->plan == NULL)
4708 36 : exec_prepare_plan(estate, query, stmt->cursor_options);
4709 : }
4710 90 : else if (stmt->dynquery != NULL)
4711 : {
4712 : /* ----------
4713 : * This is an OPEN refcursor FOR EXECUTE ...
4714 : * ----------
4715 : */
4716 18 : portal = exec_dynquery_with_params(estate,
4717 : stmt->dynquery,
4718 : stmt->params,
4719 : curname,
4720 : stmt->cursor_options);
4721 :
4722 : /*
4723 : * If cursor variable was NULL, store the generated portal name in it,
4724 : * after verifying it's okay to assign to.
4725 : *
4726 : * Note: exec_dynquery_with_params already reset the stmt_mcontext, so
4727 : * curname is a dangling pointer here; but testing it for nullness is
4728 : * OK.
4729 : */
4730 18 : if (curname == NULL)
4731 : {
4732 18 : exec_check_assignable(estate, stmt->curvar);
4733 18 : assign_text_var(estate, curvar, portal->name);
4734 : }
4735 :
4736 18 : return PLPGSQL_RC_OK;
4737 : }
4738 : else
4739 : {
4740 : /* ----------
4741 : * This is an OPEN cursor
4742 : *
4743 : * Note: parser should already have checked that statement supplies
4744 : * args iff cursor needs them, but we check again to be safe.
4745 : * ----------
4746 : */
4747 72 : if (stmt->argquery != NULL)
4748 : {
4749 : /* ----------
4750 : * OPEN CURSOR with args. We fake a SELECT ... INTO ...
4751 : * statement to evaluate the args and put 'em into the
4752 : * internal row.
4753 : * ----------
4754 : */
4755 : PLpgSQL_stmt_execsql set_args;
4756 :
4757 48 : if (curvar->cursor_explicit_argrow < 0)
4758 0 : ereport(ERROR,
4759 : (errcode(ERRCODE_SYNTAX_ERROR),
4760 : errmsg("arguments given for cursor without arguments")));
4761 :
4762 48 : memset(&set_args, 0, sizeof(set_args));
4763 48 : set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
4764 48 : set_args.lineno = stmt->lineno;
4765 48 : set_args.sqlstmt = stmt->argquery;
4766 48 : set_args.into = true;
4767 : /* XXX historically this has not been STRICT */
4768 48 : set_args.target = (PLpgSQL_variable *)
4769 48 : (estate->datums[curvar->cursor_explicit_argrow]);
4770 :
4771 48 : if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
4772 0 : elog(ERROR, "open cursor failed during argument processing");
4773 : }
4774 : else
4775 : {
4776 24 : if (curvar->cursor_explicit_argrow >= 0)
4777 0 : ereport(ERROR,
4778 : (errcode(ERRCODE_SYNTAX_ERROR),
4779 : errmsg("arguments required for cursor")));
4780 : }
4781 :
4782 66 : query = curvar->cursor_explicit_expr;
4783 66 : if (query->plan == NULL)
4784 54 : exec_prepare_plan(estate, query, curvar->cursor_options);
4785 : }
4786 :
4787 : /*
4788 : * Set up ParamListInfo for this query
4789 : */
4790 114 : paramLI = setup_param_list(estate, query);
4791 :
4792 : /*
4793 : * Open the cursor (the paramlist will get copied into the portal)
4794 : */
4795 114 : portal = SPI_cursor_open_with_paramlist(curname, query->plan,
4796 : paramLI,
4797 114 : estate->readonly_func);
4798 114 : if (portal == NULL)
4799 0 : elog(ERROR, "could not open cursor: %s",
4800 : SPI_result_code_string(SPI_result));
4801 :
4802 : /*
4803 : * If cursor variable was NULL, store the generated portal name in it,
4804 : * after verifying it's okay to assign to.
4805 : */
4806 114 : if (curname == NULL)
4807 : {
4808 90 : exec_check_assignable(estate, stmt->curvar);
4809 84 : assign_text_var(estate, curvar, portal->name);
4810 : }
4811 :
4812 : /* If we had any transient data, clean it up */
4813 108 : exec_eval_cleanup(estate);
4814 108 : if (stmt_mcontext)
4815 24 : MemoryContextReset(stmt_mcontext);
4816 :
4817 108 : return PLPGSQL_RC_OK;
4818 : }
4819 :
4820 :
4821 : /* ----------
4822 : * exec_stmt_fetch Fetch from a cursor into a target, or just
4823 : * move the current position of the cursor
4824 : * ----------
4825 : */
4826 : static int
4827 342 : exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
4828 : {
4829 : PLpgSQL_var *curvar;
4830 342 : long how_many = stmt->how_many;
4831 : SPITupleTable *tuptab;
4832 : Portal portal;
4833 : char *curname;
4834 : uint64 n;
4835 : MemoryContext oldcontext;
4836 :
4837 : /* ----------
4838 : * Get the portal of the cursor by name
4839 : * ----------
4840 : */
4841 342 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4842 342 : if (curvar->isnull)
4843 0 : ereport(ERROR,
4844 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4845 : errmsg("cursor variable \"%s\" is null", curvar->refname)));
4846 :
4847 : /* Use eval_mcontext for short-lived string */
4848 342 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4849 342 : curname = TextDatumGetCString(curvar->value);
4850 342 : MemoryContextSwitchTo(oldcontext);
4851 :
4852 342 : portal = SPI_cursor_find(curname);
4853 342 : if (portal == NULL)
4854 0 : ereport(ERROR,
4855 : (errcode(ERRCODE_UNDEFINED_CURSOR),
4856 : errmsg("cursor \"%s\" does not exist", curname)));
4857 :
4858 : /* Calculate position for FETCH_RELATIVE or FETCH_ABSOLUTE */
4859 342 : if (stmt->expr)
4860 : {
4861 : bool isnull;
4862 :
4863 : /* XXX should be doing this in LONG not INT width */
4864 66 : how_many = exec_eval_integer(estate, stmt->expr, &isnull);
4865 :
4866 66 : if (isnull)
4867 0 : ereport(ERROR,
4868 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4869 : errmsg("relative or absolute cursor position is null")));
4870 :
4871 66 : exec_eval_cleanup(estate);
4872 : }
4873 :
4874 342 : if (!stmt->is_move)
4875 : {
4876 : PLpgSQL_variable *target;
4877 :
4878 : /* ----------
4879 : * Fetch 1 tuple from the cursor
4880 : * ----------
4881 : */
4882 300 : SPI_scroll_cursor_fetch(portal, stmt->direction, how_many);
4883 294 : tuptab = SPI_tuptable;
4884 294 : n = SPI_processed;
4885 :
4886 : /* ----------
4887 : * Set the target appropriately.
4888 : * ----------
4889 : */
4890 294 : target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4891 294 : if (n == 0)
4892 48 : exec_move_row(estate, target, NULL, tuptab->tupdesc);
4893 : else
4894 246 : exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4895 :
4896 294 : exec_eval_cleanup(estate);
4897 294 : SPI_freetuptable(tuptab);
4898 : }
4899 : else
4900 : {
4901 : /* Move the cursor */
4902 42 : SPI_scroll_cursor_move(portal, stmt->direction, how_many);
4903 42 : n = SPI_processed;
4904 : }
4905 :
4906 : /* Set the ROW_COUNT and the global FOUND variable appropriately. */
4907 336 : estate->eval_processed = n;
4908 336 : exec_set_found(estate, n != 0);
4909 :
4910 336 : return PLPGSQL_RC_OK;
4911 : }
4912 :
4913 : /* ----------
4914 : * exec_stmt_close Close a cursor
4915 : * ----------
4916 : */
4917 : static int
4918 72 : exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
4919 : {
4920 : PLpgSQL_var *curvar;
4921 : Portal portal;
4922 : char *curname;
4923 : MemoryContext oldcontext;
4924 :
4925 : /* ----------
4926 : * Get the portal of the cursor by name
4927 : * ----------
4928 : */
4929 72 : curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4930 72 : if (curvar->isnull)
4931 0 : ereport(ERROR,
4932 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4933 : errmsg("cursor variable \"%s\" is null", curvar->refname)));
4934 :
4935 : /* Use eval_mcontext for short-lived string */
4936 72 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4937 72 : curname = TextDatumGetCString(curvar->value);
4938 72 : MemoryContextSwitchTo(oldcontext);
4939 :
4940 72 : portal = SPI_cursor_find(curname);
4941 72 : if (portal == NULL)
4942 0 : ereport(ERROR,
4943 : (errcode(ERRCODE_UNDEFINED_CURSOR),
4944 : errmsg("cursor \"%s\" does not exist", curname)));
4945 :
4946 : /* ----------
4947 : * And close it.
4948 : * ----------
4949 : */
4950 72 : SPI_cursor_close(portal);
4951 :
4952 72 : return PLPGSQL_RC_OK;
4953 : }
4954 :
4955 : /*
4956 : * exec_stmt_commit
4957 : *
4958 : * Commit the transaction.
4959 : */
4960 : static int
4961 4166 : exec_stmt_commit(PLpgSQL_execstate *estate, PLpgSQL_stmt_commit *stmt)
4962 : {
4963 4166 : if (stmt->chain)
4964 4 : SPI_commit_and_chain();
4965 : else
4966 4162 : SPI_commit();
4967 :
4968 : /*
4969 : * We need to build new simple-expression infrastructure, since the old
4970 : * data structures are gone.
4971 : */
4972 4144 : estate->simple_eval_estate = NULL;
4973 4144 : estate->simple_eval_resowner = NULL;
4974 4144 : plpgsql_create_econtext(estate);
4975 :
4976 4144 : return PLPGSQL_RC_OK;
4977 : }
4978 :
4979 : /*
4980 : * exec_stmt_rollback
4981 : *
4982 : * Abort the transaction.
4983 : */
4984 : static int
4985 84 : exec_stmt_rollback(PLpgSQL_execstate *estate, PLpgSQL_stmt_rollback *stmt)
4986 : {
4987 84 : if (stmt->chain)
4988 4 : SPI_rollback_and_chain();
4989 : else
4990 80 : SPI_rollback();
4991 :
4992 : /*
4993 : * We need to build new simple-expression infrastructure, since the old
4994 : * data structures are gone.
4995 : */
4996 78 : estate->simple_eval_estate = NULL;
4997 78 : estate->simple_eval_resowner = NULL;
4998 78 : plpgsql_create_econtext(estate);
4999 :
5000 78 : return PLPGSQL_RC_OK;
5001 : }
5002 :
5003 : /* ----------
5004 : * exec_assign_expr Put an expression's result into a variable.
5005 : * ----------
5006 : */
5007 : static void
5008 84166 : exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
5009 : PLpgSQL_expr *expr)
5010 : {
5011 : Datum value;
5012 : bool isnull;
5013 : Oid valtype;
5014 : int32 valtypmod;
5015 :
5016 : /*
5017 : * If first time through, create a plan for this expression.
5018 : */
5019 84166 : if (expr->plan == NULL)
5020 : {
5021 : /*
5022 : * Mark the expression as being an assignment source, if target is a
5023 : * simple variable. (This is a bit messy, but it seems cleaner than
5024 : * modifying the API of exec_prepare_plan for the purpose. We need to
5025 : * stash the target dno into the expr anyway, so that it will be
5026 : * available if we have to replan.)
5027 : */
5028 4316 : if (target->dtype == PLPGSQL_DTYPE_VAR)
5029 3392 : expr->target_param = target->dno;
5030 : else
5031 924 : expr->target_param = -1; /* should be that already */
5032 :
5033 4316 : exec_prepare_plan(estate, expr, 0);
5034 : }
5035 :
5036 84126 : value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
5037 83934 : exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
5038 83870 : exec_eval_cleanup(estate);
5039 83870 : }
5040 :
5041 :
5042 : /* ----------
5043 : * exec_assign_c_string Put a C string into a text variable.
5044 : *
5045 : * We take a NULL pointer as signifying empty string, not SQL null.
5046 : *
5047 : * As with the underlying exec_assign_value, caller is expected to do
5048 : * exec_eval_cleanup later.
5049 : * ----------
5050 : */
5051 : static void
5052 132 : exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
5053 : const char *str)
5054 : {
5055 : text *value;
5056 : MemoryContext oldcontext;
5057 :
5058 : /* Use eval_mcontext for short-lived text value */
5059 132 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5060 132 : if (str != NULL)
5061 132 : value = cstring_to_text(str);
5062 : else
5063 0 : value = cstring_to_text("");
5064 132 : MemoryContextSwitchTo(oldcontext);
5065 :
5066 132 : exec_assign_value(estate, target, PointerGetDatum(value), false,
5067 : TEXTOID, -1);
5068 132 : }
5069 :
5070 :
5071 : /* ----------
5072 : * exec_assign_value Put a value into a target datum
5073 : *
5074 : * Note: in some code paths, this will leak memory in the eval_mcontext;
5075 : * we assume that will be cleaned up later by exec_eval_cleanup. We cannot
5076 : * call exec_eval_cleanup here for fear of destroying the input Datum value.
5077 : * ----------
5078 : */
5079 : static void
5080 145068 : exec_assign_value(PLpgSQL_execstate *estate,
5081 : PLpgSQL_datum *target,
5082 : Datum value, bool isNull,
5083 : Oid valtype, int32 valtypmod)
5084 : {
5085 145068 : switch (target->dtype)
5086 : {
5087 141974 : case PLPGSQL_DTYPE_VAR:
5088 : case PLPGSQL_DTYPE_PROMISE:
5089 : {
5090 : /*
5091 : * Target is a variable
5092 : */
5093 141974 : PLpgSQL_var *var = (PLpgSQL_var *) target;
5094 : Datum newvalue;
5095 :
5096 141974 : newvalue = exec_cast_value(estate,
5097 : value,
5098 : &isNull,
5099 : valtype,
5100 : valtypmod,
5101 141974 : var->datatype->typoid,
5102 141974 : var->datatype->atttypmod);
5103 :
5104 141948 : if (isNull && var->notnull)
5105 10 : ereport(ERROR,
5106 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5107 : errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
5108 : var->refname)));
5109 :
5110 : /*
5111 : * If type is by-reference, copy the new value (which is
5112 : * probably in the eval_mcontext) into the procedure's main
5113 : * memory context. But if it's a read/write reference to an
5114 : * expanded object, no physical copy needs to happen; at most
5115 : * we need to reparent the object's memory context.
5116 : *
5117 : * If it's an array, we force the value to be stored in R/W
5118 : * expanded form. This wins if the function later does, say,
5119 : * a lot of array subscripting operations on the variable, and
5120 : * otherwise might lose. We might need to use a different
5121 : * heuristic, but it's too soon to tell. Also, are there
5122 : * cases where it'd be useful to force non-array values into
5123 : * expanded form?
5124 : */
5125 141938 : if (!var->datatype->typbyval && !isNull)
5126 : {
5127 96964 : if (var->datatype->typisarray &&
5128 9874 : !VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(newvalue)))
5129 : {
5130 : /* array and not already R/W, so apply expand_array */
5131 9654 : newvalue = expand_array(newvalue,
5132 : estate->datum_context,
5133 : NULL);
5134 : }
5135 : else
5136 : {
5137 : /* else transfer value if R/W, else just datumCopy */
5138 87310 : newvalue = datumTransfer(newvalue,
5139 : false,
5140 87310 : var->datatype->typlen);
5141 : }
5142 : }
5143 :
5144 : /*
5145 : * Now free the old value, if any, and assign the new one. But
5146 : * skip the assignment if old and new values are the same.
5147 : * Note that for expanded objects, this test is necessary and
5148 : * cannot reliably be made any earlier; we have to be looking
5149 : * at the object's standard R/W pointer to be sure pointer
5150 : * equality is meaningful.
5151 : *
5152 : * Also, if it's a promise variable, we should disarm the
5153 : * promise in any case --- otherwise, assigning null to an
5154 : * armed promise variable would fail to disarm the promise.
5155 : */
5156 141938 : if (var->value != newvalue || var->isnull || isNull)
5157 139198 : assign_simple_var(estate, var, newvalue, isNull,
5158 139198 : (!var->datatype->typbyval && !isNull));
5159 : else
5160 2740 : var->promise = PLPGSQL_PROMISE_NONE;
5161 141938 : break;
5162 : }
5163 :
5164 42 : case PLPGSQL_DTYPE_ROW:
5165 : {
5166 : /*
5167 : * Target is a row variable
5168 : */
5169 42 : PLpgSQL_row *row = (PLpgSQL_row *) target;
5170 :
5171 42 : if (isNull)
5172 : {
5173 : /* If source is null, just assign nulls to the row */
5174 0 : exec_move_row(estate, (PLpgSQL_variable *) row,
5175 : NULL, NULL);
5176 : }
5177 : else
5178 : {
5179 : /* Source must be of RECORD or composite type */
5180 42 : if (!type_is_rowtype(valtype))
5181 0 : ereport(ERROR,
5182 : (errcode(ERRCODE_DATATYPE_MISMATCH),
5183 : errmsg("cannot assign non-composite value to a row variable")));
5184 42 : exec_move_row_from_datum(estate, (PLpgSQL_variable *) row,
5185 : value);
5186 : }
5187 42 : break;
5188 : }
5189 :
5190 816 : case PLPGSQL_DTYPE_REC:
5191 : {
5192 : /*
5193 : * Target is a record variable
5194 : */
5195 816 : PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
5196 :
5197 816 : if (isNull)
5198 : {
5199 178 : if (rec->notnull)
5200 8 : ereport(ERROR,
5201 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5202 : errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
5203 : rec->refname)));
5204 :
5205 : /* Set variable to a simple NULL */
5206 170 : exec_move_row(estate, (PLpgSQL_variable *) rec,
5207 : NULL, NULL);
5208 : }
5209 : else
5210 : {
5211 : /* Source must be of RECORD or composite type */
5212 638 : if (!type_is_rowtype(valtype))
5213 0 : ereport(ERROR,
5214 : (errcode(ERRCODE_DATATYPE_MISMATCH),
5215 : errmsg("cannot assign non-composite value to a record variable")));
5216 638 : exec_move_row_from_datum(estate, (PLpgSQL_variable *) rec,
5217 : value);
5218 : }
5219 790 : break;
5220 : }
5221 :
5222 2236 : case PLPGSQL_DTYPE_RECFIELD:
5223 : {
5224 : /*
5225 : * Target is a field of a record
5226 : */
5227 2236 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) target;
5228 : PLpgSQL_rec *rec;
5229 : ExpandedRecordHeader *erh;
5230 :
5231 2236 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5232 2236 : erh = rec->erh;
5233 :
5234 : /*
5235 : * If record variable is NULL, instantiate it if it has a
5236 : * named composite type, else complain. (This won't change
5237 : * the logical state of the record, but if we successfully
5238 : * assign below, the unassigned fields will all become NULLs.)
5239 : */
5240 2236 : if (erh == NULL)
5241 : {
5242 58 : instantiate_empty_record_variable(estate, rec);
5243 56 : erh = rec->erh;
5244 : }
5245 :
5246 : /*
5247 : * Look up the field's properties if we have not already, or
5248 : * if the tuple descriptor ID changed since last time.
5249 : */
5250 2234 : if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
5251 : {
5252 12 : if (!expanded_record_lookup_field(erh,
5253 12 : recfield->fieldname,
5254 : &recfield->finfo))
5255 2 : ereport(ERROR,
5256 : (errcode(ERRCODE_UNDEFINED_COLUMN),
5257 : errmsg("record \"%s\" has no field \"%s\"",
5258 : rec->refname, recfield->fieldname)));
5259 10 : recfield->rectupledescid = erh->er_tupdesc_id;
5260 : }
5261 :
5262 : /* We don't support assignments to system columns. */
5263 2232 : if (recfield->finfo.fnumber <= 0)
5264 0 : ereport(ERROR,
5265 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5266 : errmsg("cannot assign to system column \"%s\"",
5267 : recfield->fieldname)));
5268 :
5269 : /* Cast the new value to the right type, if needed. */
5270 2232 : value = exec_cast_value(estate,
5271 : value,
5272 : &isNull,
5273 : valtype,
5274 : valtypmod,
5275 : recfield->finfo.ftypeid,
5276 : recfield->finfo.ftypmod);
5277 :
5278 : /* And assign it. */
5279 2232 : expanded_record_set_field(erh, recfield->finfo.fnumber,
5280 : value, isNull, !estate->atomic);
5281 2226 : break;
5282 : }
5283 :
5284 0 : default:
5285 0 : elog(ERROR, "unrecognized dtype: %d", target->dtype);
5286 : }
5287 144996 : }
5288 :
5289 : /*
5290 : * exec_eval_datum Get current value of a PLpgSQL_datum
5291 : *
5292 : * The type oid, typmod, value in Datum format, and null flag are returned.
5293 : *
5294 : * At present this doesn't handle PLpgSQL_expr datums; that's not needed
5295 : * because we never pass references to such datums to SPI.
5296 : *
5297 : * NOTE: the returned Datum points right at the stored value in the case of
5298 : * pass-by-reference datatypes. Generally callers should take care not to
5299 : * modify the stored value. Some callers intentionally manipulate variables
5300 : * referenced by R/W expanded pointers, though; it is those callers'
5301 : * responsibility that the results are semantically OK.
5302 : *
5303 : * In some cases we have to palloc a return value, and in such cases we put
5304 : * it into the estate's eval_mcontext.
5305 : */
5306 : static void
5307 55976 : exec_eval_datum(PLpgSQL_execstate *estate,
5308 : PLpgSQL_datum *datum,
5309 : Oid *typeid,
5310 : int32 *typetypmod,
5311 : Datum *value,
5312 : bool *isnull)
5313 : {
5314 : MemoryContext oldcontext;
5315 :
5316 55976 : switch (datum->dtype)
5317 : {
5318 22720 : case PLPGSQL_DTYPE_PROMISE:
5319 : /* fulfill promise if needed, then handle like regular var */
5320 22720 : plpgsql_fulfill_promise(estate, (PLpgSQL_var *) datum);
5321 :
5322 : /* FALL THRU */
5323 :
5324 44686 : case PLPGSQL_DTYPE_VAR:
5325 : {
5326 44686 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
5327 :
5328 44686 : *typeid = var->datatype->typoid;
5329 44686 : *typetypmod = var->datatype->atttypmod;
5330 44686 : *value = var->value;
5331 44686 : *isnull = var->isnull;
5332 44686 : break;
5333 : }
5334 :
5335 6092 : case PLPGSQL_DTYPE_ROW:
5336 : {
5337 6092 : PLpgSQL_row *row = (PLpgSQL_row *) datum;
5338 : HeapTuple tup;
5339 :
5340 : /* We get here if there are multiple OUT parameters */
5341 6092 : if (!row->rowtupdesc) /* should not happen */
5342 0 : elog(ERROR, "row variable has no tupdesc");
5343 : /* Make sure we have a valid type/typmod setting */
5344 6092 : BlessTupleDesc(row->rowtupdesc);
5345 6092 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5346 6092 : tup = make_tuple_from_row(estate, row, row->rowtupdesc);
5347 6092 : if (tup == NULL) /* should not happen */
5348 0 : elog(ERROR, "row not compatible with its own tupdesc");
5349 6092 : *typeid = row->rowtupdesc->tdtypeid;
5350 6092 : *typetypmod = row->rowtupdesc->tdtypmod;
5351 6092 : *value = HeapTupleGetDatum(tup);
5352 6092 : *isnull = false;
5353 6092 : MemoryContextSwitchTo(oldcontext);
5354 6092 : break;
5355 : }
5356 :
5357 3482 : case PLPGSQL_DTYPE_REC:
5358 : {
5359 3482 : PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5360 :
5361 3482 : if (rec->erh == NULL)
5362 : {
5363 : /* Treat uninstantiated record as a simple NULL */
5364 74 : *value = (Datum) 0;
5365 74 : *isnull = true;
5366 : /* Report variable's declared type */
5367 74 : *typeid = rec->rectypeid;
5368 74 : *typetypmod = -1;
5369 : }
5370 : else
5371 : {
5372 3408 : if (ExpandedRecordIsEmpty(rec->erh))
5373 : {
5374 : /* Empty record is also a NULL */
5375 56 : *value = (Datum) 0;
5376 56 : *isnull = true;
5377 : }
5378 : else
5379 : {
5380 3352 : *value = ExpandedRecordGetDatum(rec->erh);
5381 3352 : *isnull = false;
5382 : }
5383 3408 : if (rec->rectypeid != RECORDOID)
5384 : {
5385 : /* Report variable's declared type, if not RECORD */
5386 342 : *typeid = rec->rectypeid;
5387 342 : *typetypmod = -1;
5388 : }
5389 : else
5390 : {
5391 : /* Report record's actual type if declared RECORD */
5392 3066 : *typeid = rec->erh->er_typeid;
5393 3066 : *typetypmod = rec->erh->er_typmod;
5394 : }
5395 : }
5396 3482 : break;
5397 : }
5398 :
5399 1716 : case PLPGSQL_DTYPE_RECFIELD:
5400 : {
5401 1716 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
5402 : PLpgSQL_rec *rec;
5403 : ExpandedRecordHeader *erh;
5404 :
5405 1716 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5406 1716 : erh = rec->erh;
5407 :
5408 : /*
5409 : * If record variable is NULL, instantiate it if it has a
5410 : * named composite type, else complain. (This won't change
5411 : * the logical state of the record: it's still NULL.)
5412 : */
5413 1716 : if (erh == NULL)
5414 : {
5415 0 : instantiate_empty_record_variable(estate, rec);
5416 0 : erh = rec->erh;
5417 : }
5418 :
5419 : /*
5420 : * Look up the field's properties if we have not already, or
5421 : * if the tuple descriptor ID changed since last time.
5422 : */
5423 1716 : if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
5424 : {
5425 0 : if (!expanded_record_lookup_field(erh,
5426 0 : recfield->fieldname,
5427 : &recfield->finfo))
5428 0 : ereport(ERROR,
5429 : (errcode(ERRCODE_UNDEFINED_COLUMN),
5430 : errmsg("record \"%s\" has no field \"%s\"",
5431 : rec->refname, recfield->fieldname)));
5432 0 : recfield->rectupledescid = erh->er_tupdesc_id;
5433 : }
5434 :
5435 : /* Report type data. */
5436 1716 : *typeid = recfield->finfo.ftypeid;
5437 1716 : *typetypmod = recfield->finfo.ftypmod;
5438 :
5439 : /* And fetch the field value. */
5440 1716 : *value = expanded_record_get_field(erh,
5441 : recfield->finfo.fnumber,
5442 : isnull);
5443 1716 : break;
5444 : }
5445 :
5446 0 : default:
5447 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5448 : }
5449 55976 : }
5450 :
5451 : /*
5452 : * plpgsql_exec_get_datum_type Get datatype of a PLpgSQL_datum
5453 : *
5454 : * This is the same logic as in exec_eval_datum, but we skip acquiring
5455 : * the actual value of the variable. Also, needn't support DTYPE_ROW.
5456 : */
5457 : Oid
5458 60 : plpgsql_exec_get_datum_type(PLpgSQL_execstate *estate,
5459 : PLpgSQL_datum *datum)
5460 : {
5461 : Oid typeid;
5462 :
5463 60 : switch (datum->dtype)
5464 : {
5465 60 : case PLPGSQL_DTYPE_VAR:
5466 : case PLPGSQL_DTYPE_PROMISE:
5467 : {
5468 60 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
5469 :
5470 60 : typeid = var->datatype->typoid;
5471 60 : break;
5472 : }
5473 :
5474 0 : case PLPGSQL_DTYPE_REC:
5475 : {
5476 0 : PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5477 :
5478 0 : if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5479 : {
5480 : /* Report variable's declared type */
5481 0 : typeid = rec->rectypeid;
5482 : }
5483 : else
5484 : {
5485 : /* Report record's actual type if declared RECORD */
5486 0 : typeid = rec->erh->er_typeid;
5487 : }
5488 0 : break;
5489 : }
5490 :
5491 0 : case PLPGSQL_DTYPE_RECFIELD:
5492 : {
5493 0 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
5494 : PLpgSQL_rec *rec;
5495 :
5496 0 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5497 :
5498 : /*
5499 : * If record variable is NULL, instantiate it if it has a
5500 : * named composite type, else complain. (This won't change
5501 : * the logical state of the record: it's still NULL.)
5502 : */
5503 0 : if (rec->erh == NULL)
5504 0 : instantiate_empty_record_variable(estate, rec);
5505 :
5506 : /*
5507 : * Look up the field's properties if we have not already, or
5508 : * if the tuple descriptor ID changed since last time.
5509 : */
5510 0 : if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5511 : {
5512 0 : if (!expanded_record_lookup_field(rec->erh,
5513 0 : recfield->fieldname,
5514 : &recfield->finfo))
5515 0 : ereport(ERROR,
5516 : (errcode(ERRCODE_UNDEFINED_COLUMN),
5517 : errmsg("record \"%s\" has no field \"%s\"",
5518 : rec->refname, recfield->fieldname)));
5519 0 : recfield->rectupledescid = rec->erh->er_tupdesc_id;
5520 : }
5521 :
5522 0 : typeid = recfield->finfo.ftypeid;
5523 0 : break;
5524 : }
5525 :
5526 0 : default:
5527 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5528 : typeid = InvalidOid; /* keep compiler quiet */
5529 : break;
5530 : }
5531 :
5532 60 : return typeid;
5533 : }
5534 :
5535 : /*
5536 : * plpgsql_exec_get_datum_type_info Get datatype etc of a PLpgSQL_datum
5537 : *
5538 : * An extended version of plpgsql_exec_get_datum_type, which also retrieves the
5539 : * typmod and collation of the datum. Note however that we don't report the
5540 : * possibly-mutable typmod of RECORD values, but say -1 always.
5541 : */
5542 : void
5543 33248 : plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate,
5544 : PLpgSQL_datum *datum,
5545 : Oid *typeId, int32 *typMod, Oid *collation)
5546 : {
5547 33248 : switch (datum->dtype)
5548 : {
5549 25358 : case PLPGSQL_DTYPE_VAR:
5550 : case PLPGSQL_DTYPE_PROMISE:
5551 : {
5552 25358 : PLpgSQL_var *var = (PLpgSQL_var *) datum;
5553 :
5554 25358 : *typeId = var->datatype->typoid;
5555 25358 : *typMod = var->datatype->atttypmod;
5556 25358 : *collation = var->datatype->collation;
5557 25358 : break;
5558 : }
5559 :
5560 2342 : case PLPGSQL_DTYPE_REC:
5561 : {
5562 2342 : PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5563 :
5564 2342 : if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5565 : {
5566 : /* Report variable's declared type */
5567 552 : *typeId = rec->rectypeid;
5568 552 : *typMod = -1;
5569 : }
5570 : else
5571 : {
5572 : /* Report record's actual type if declared RECORD */
5573 1790 : *typeId = rec->erh->er_typeid;
5574 : /* do NOT return the mutable typmod of a RECORD variable */
5575 1790 : *typMod = -1;
5576 : }
5577 : /* composite types are never collatable */
5578 2342 : *collation = InvalidOid;
5579 2342 : break;
5580 : }
5581 :
5582 5548 : case PLPGSQL_DTYPE_RECFIELD:
5583 : {
5584 5548 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
5585 : PLpgSQL_rec *rec;
5586 :
5587 5548 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5588 :
5589 : /*
5590 : * If record variable is NULL, instantiate it if it has a
5591 : * named composite type, else complain. (This won't change
5592 : * the logical state of the record: it's still NULL.)
5593 : */
5594 5548 : if (rec->erh == NULL)
5595 46 : instantiate_empty_record_variable(estate, rec);
5596 :
5597 : /*
5598 : * Look up the field's properties if we have not already, or
5599 : * if the tuple descriptor ID changed since last time.
5600 : */
5601 5546 : if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5602 : {
5603 2670 : if (!expanded_record_lookup_field(rec->erh,
5604 2670 : recfield->fieldname,
5605 : &recfield->finfo))
5606 20 : ereport(ERROR,
5607 : (errcode(ERRCODE_UNDEFINED_COLUMN),
5608 : errmsg("record \"%s\" has no field \"%s\"",
5609 : rec->refname, recfield->fieldname)));
5610 2650 : recfield->rectupledescid = rec->erh->er_tupdesc_id;
5611 : }
5612 :
5613 5526 : *typeId = recfield->finfo.ftypeid;
5614 5526 : *typMod = recfield->finfo.ftypmod;
5615 5526 : *collation = recfield->finfo.fcollation;
5616 5526 : break;
5617 : }
5618 :
5619 0 : default:
5620 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5621 : *typeId = InvalidOid; /* keep compiler quiet */
5622 : *typMod = -1;
5623 : *collation = InvalidOid;
5624 : break;
5625 : }
5626 33226 : }
5627 :
5628 : /* ----------
5629 : * exec_eval_integer Evaluate an expression, coerce result to int4
5630 : *
5631 : * Note we do not do exec_eval_cleanup here; the caller must do it at
5632 : * some later point. (We do this because the caller may be holding the
5633 : * results of other, pass-by-reference, expression evaluations, such as
5634 : * an array value to be subscripted.)
5635 : * ----------
5636 : */
5637 : static int
5638 66 : exec_eval_integer(PLpgSQL_execstate *estate,
5639 : PLpgSQL_expr *expr,
5640 : bool *isNull)
5641 : {
5642 : Datum exprdatum;
5643 : Oid exprtypeid;
5644 : int32 exprtypmod;
5645 :
5646 66 : exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5647 66 : exprdatum = exec_cast_value(estate, exprdatum, isNull,
5648 : exprtypeid, exprtypmod,
5649 : INT4OID, -1);
5650 66 : return DatumGetInt32(exprdatum);
5651 : }
5652 :
5653 : /* ----------
5654 : * exec_eval_boolean Evaluate an expression, coerce result to bool
5655 : *
5656 : * Note we do not do exec_eval_cleanup here; the caller must do it at
5657 : * some later point.
5658 : * ----------
5659 : */
5660 : static bool
5661 104916 : exec_eval_boolean(PLpgSQL_execstate *estate,
5662 : PLpgSQL_expr *expr,
5663 : bool *isNull)
5664 : {
5665 : Datum exprdatum;
5666 : Oid exprtypeid;
5667 : int32 exprtypmod;
5668 :
5669 104916 : exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5670 104916 : exprdatum = exec_cast_value(estate, exprdatum, isNull,
5671 : exprtypeid, exprtypmod,
5672 : BOOLOID, -1);
5673 104916 : return DatumGetBool(exprdatum);
5674 : }
5675 :
5676 : /* ----------
5677 : * exec_eval_expr Evaluate an expression and return
5678 : * the result Datum, along with data type/typmod.
5679 : *
5680 : * NOTE: caller must do exec_eval_cleanup when done with the Datum.
5681 : * ----------
5682 : */
5683 : static Datum
5684 270264 : exec_eval_expr(PLpgSQL_execstate *estate,
5685 : PLpgSQL_expr *expr,
5686 : bool *isNull,
5687 : Oid *rettype,
5688 : int32 *rettypmod)
5689 : {
5690 270264 : Datum result = 0;
5691 : int rc;
5692 : Form_pg_attribute attr;
5693 :
5694 : /*
5695 : * If first time through, create a plan for this expression.
5696 : */
5697 270264 : if (expr->plan == NULL)
5698 17434 : exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
5699 :
5700 : /*
5701 : * If this is a simple expression, bypass SPI and use the executor
5702 : * directly
5703 : */
5704 270226 : if (exec_eval_simple_expr(estate, expr,
5705 : &result, isNull, rettype, rettypmod))
5706 263606 : return result;
5707 :
5708 : /*
5709 : * Else do it the hard way via exec_run_select
5710 : */
5711 6380 : rc = exec_run_select(estate, expr, 2, NULL);
5712 6354 : if (rc != SPI_OK_SELECT)
5713 0 : ereport(ERROR,
5714 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5715 : errmsg("query did not return data"),
5716 : errcontext("query: %s", expr->query)));
5717 :
5718 : /*
5719 : * Check that the expression returns exactly one column...
5720 : */
5721 6354 : if (estate->eval_tuptable->tupdesc->natts != 1)
5722 0 : ereport(ERROR,
5723 : (errcode(ERRCODE_SYNTAX_ERROR),
5724 : errmsg_plural("query returned %d column",
5725 : "query returned %d columns",
5726 : estate->eval_tuptable->tupdesc->natts,
5727 : estate->eval_tuptable->tupdesc->natts),
5728 : errcontext("query: %s", expr->query)));
5729 :
5730 : /*
5731 : * ... and get the column's datatype.
5732 : */
5733 6354 : attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0);
5734 6354 : *rettype = attr->atttypid;
5735 6354 : *rettypmod = attr->atttypmod;
5736 :
5737 : /*
5738 : * If there are no rows selected, the result is a NULL of that type.
5739 : */
5740 6354 : if (estate->eval_processed == 0)
5741 : {
5742 0 : *isNull = true;
5743 0 : return (Datum) 0;
5744 : }
5745 :
5746 : /*
5747 : * Check that the expression returned no more than one row.
5748 : */
5749 6354 : if (estate->eval_processed != 1)
5750 2 : ereport(ERROR,
5751 : (errcode(ERRCODE_CARDINALITY_VIOLATION),
5752 : errmsg("query returned more than one row"),
5753 : errcontext("query: %s", expr->query)));
5754 :
5755 : /*
5756 : * Return the single result Datum.
5757 : */
5758 6352 : return SPI_getbinval(estate->eval_tuptable->vals[0],
5759 6352 : estate->eval_tuptable->tupdesc, 1, isNull);
5760 : }
5761 :
5762 :
5763 : /* ----------
5764 : * exec_run_select Execute a select query
5765 : * ----------
5766 : */
5767 : static int
5768 12480 : exec_run_select(PLpgSQL_execstate *estate,
5769 : PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
5770 : {
5771 : ParamListInfo paramLI;
5772 : int rc;
5773 :
5774 : /*
5775 : * On the first call for this expression generate the plan.
5776 : *
5777 : * If we don't need to return a portal, then we're just going to execute
5778 : * the query immediately, which means it's OK to use a parallel plan, even
5779 : * if the number of rows being fetched is limited. If we do need to
5780 : * return a portal (i.e., this is for a FOR loop), the user's code might
5781 : * invoke additional operations inside the FOR loop, making parallel query
5782 : * unsafe. In any case, we don't expect any cursor operations to be done,
5783 : * so specify NO_SCROLL for efficiency and semantic safety.
5784 : */
5785 12480 : if (expr->plan == NULL)
5786 : {
5787 664 : int cursorOptions = CURSOR_OPT_NO_SCROLL;
5788 :
5789 664 : if (portalP == NULL)
5790 364 : cursorOptions |= CURSOR_OPT_PARALLEL_OK;
5791 664 : exec_prepare_plan(estate, expr, cursorOptions);
5792 : }
5793 :
5794 : /*
5795 : * Set up ParamListInfo to pass to executor
5796 : */
5797 12450 : paramLI = setup_param_list(estate, expr);
5798 :
5799 : /*
5800 : * If a portal was requested, put the query and paramlist into the portal
5801 : */
5802 12450 : if (portalP != NULL)
5803 : {
5804 4796 : *portalP = SPI_cursor_open_with_paramlist(NULL, expr->plan,
5805 : paramLI,
5806 2398 : estate->readonly_func);
5807 2398 : if (*portalP == NULL)
5808 0 : elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
5809 : expr->query, SPI_result_code_string(SPI_result));
5810 2398 : exec_eval_cleanup(estate);
5811 2398 : return SPI_OK_CURSOR;
5812 : }
5813 :
5814 : /*
5815 : * Execute the query
5816 : */
5817 10052 : rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
5818 10052 : estate->readonly_func, maxtuples);
5819 8636 : if (rc != SPI_OK_SELECT)
5820 : {
5821 : /*
5822 : * SELECT INTO deserves a special error message, because "query is not
5823 : * a SELECT" is not very helpful in that case.
5824 : */
5825 0 : if (rc == SPI_OK_SELINTO)
5826 0 : ereport(ERROR,
5827 : (errcode(ERRCODE_SYNTAX_ERROR),
5828 : errmsg("query is SELECT INTO, but it should be plain SELECT"),
5829 : errcontext("query: %s", expr->query)));
5830 : else
5831 0 : ereport(ERROR,
5832 : (errcode(ERRCODE_SYNTAX_ERROR),
5833 : errmsg("query is not a SELECT"),
5834 : errcontext("query: %s", expr->query)));
5835 : }
5836 :
5837 : /* Save query results for eventual cleanup */
5838 : Assert(estate->eval_tuptable == NULL);
5839 8636 : estate->eval_tuptable = SPI_tuptable;
5840 8636 : estate->eval_processed = SPI_processed;
5841 :
5842 8636 : return rc;
5843 : }
5844 :
5845 :
5846 : /*
5847 : * exec_for_query --- execute body of FOR loop for each row from a portal
5848 : *
5849 : * Used by exec_stmt_fors, exec_stmt_forc and exec_stmt_dynfors
5850 : */
5851 : static int
5852 11720 : exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
5853 : Portal portal, bool prefetch_ok)
5854 : {
5855 : PLpgSQL_variable *var;
5856 : SPITupleTable *tuptab;
5857 11720 : bool found = false;
5858 11720 : int rc = PLPGSQL_RC_OK;
5859 11720 : uint64 previous_id = INVALID_TUPLEDESC_IDENTIFIER;
5860 11720 : bool tupdescs_match = true;
5861 : uint64 n;
5862 :
5863 : /* Fetch loop variable's datum entry */
5864 11720 : var = (PLpgSQL_variable *) estate->datums[stmt->var->dno];
5865 :
5866 : /*
5867 : * Make sure the portal doesn't get closed by the user statements we
5868 : * execute.
5869 : */
5870 11720 : PinPortal(portal);
5871 :
5872 : /*
5873 : * In a non-atomic context, we dare not prefetch, even if it would
5874 : * otherwise be safe. Aside from any semantic hazards that that might
5875 : * create, if we prefetch toasted data and then the user commits the
5876 : * transaction, the toast references could turn into dangling pointers.
5877 : * (Rows we haven't yet fetched from the cursor are safe, because the
5878 : * PersistHoldablePortal mechanism handles this scenario.)
5879 : */
5880 11720 : if (!estate->atomic)
5881 7398 : prefetch_ok = false;
5882 :
5883 : /*
5884 : * Fetch the initial tuple(s). If prefetching is allowed then we grab a
5885 : * few more rows to avoid multiple trips through executor startup
5886 : * overhead.
5887 : */
5888 11720 : SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1);
5889 11714 : tuptab = SPI_tuptable;
5890 11714 : n = SPI_processed;
5891 :
5892 : /*
5893 : * If the query didn't return any rows, set the target to NULL and fall
5894 : * through with found = false.
5895 : */
5896 11714 : if (n == 0)
5897 : {
5898 1584 : exec_move_row(estate, var, NULL, tuptab->tupdesc);
5899 1584 : exec_eval_cleanup(estate);
5900 : }
5901 : else
5902 10130 : found = true; /* processed at least one tuple */
5903 :
5904 : /*
5905 : * Now do the loop
5906 : */
5907 42936 : while (n > 0)
5908 : {
5909 : uint64 i;
5910 :
5911 77680 : for (i = 0; i < n; i++)
5912 : {
5913 : /*
5914 : * Assign the tuple to the target. Here, because we know that all
5915 : * loop iterations should be assigning the same tupdesc, we can
5916 : * optimize away repeated creations of expanded records with
5917 : * identical tupdescs. Testing for changes of er_tupdesc_id is
5918 : * reliable even if the loop body contains assignments that
5919 : * replace the target's value entirely, because it's assigned from
5920 : * a process-global counter. The case where the tupdescs don't
5921 : * match could possibly be handled more efficiently than this
5922 : * coding does, but it's not clear extra effort is worthwhile.
5923 : */
5924 46458 : if (var->dtype == PLPGSQL_DTYPE_REC)
5925 : {
5926 6628 : PLpgSQL_rec *rec = (PLpgSQL_rec *) var;
5927 :
5928 6628 : if (rec->erh &&
5929 5792 : rec->erh->er_tupdesc_id == previous_id &&
5930 : tupdescs_match)
5931 : {
5932 : /* Only need to assign a new tuple value */
5933 5716 : expanded_record_set_tuple(rec->erh, tuptab->vals[i],
5934 5716 : true, !estate->atomic);
5935 : }
5936 : else
5937 : {
5938 : /*
5939 : * First time through, or var's tupdesc changed in loop,
5940 : * or we have to do it the hard way because type coercion
5941 : * is needed.
5942 : */
5943 912 : exec_move_row(estate, var,
5944 912 : tuptab->vals[i], tuptab->tupdesc);
5945 :
5946 : /*
5947 : * Check to see if physical assignment is OK next time.
5948 : * Once the tupdesc comparison has failed once, we don't
5949 : * bother rechecking in subsequent loop iterations.
5950 : */
5951 910 : if (tupdescs_match)
5952 : {
5953 902 : tupdescs_match =
5954 922 : (rec->rectypeid == RECORDOID ||
5955 922 : rec->rectypeid == tuptab->tupdesc->tdtypeid ||
5956 20 : compatible_tupdescs(tuptab->tupdesc,
5957 : expanded_record_get_tupdesc(rec->erh)));
5958 : }
5959 910 : previous_id = rec->erh->er_tupdesc_id;
5960 : }
5961 : }
5962 : else
5963 39830 : exec_move_row(estate, var, tuptab->vals[i], tuptab->tupdesc);
5964 :
5965 46454 : exec_eval_cleanup(estate);
5966 :
5967 : /*
5968 : * Execute the statements
5969 : */
5970 46454 : rc = exec_stmts(estate, stmt->body);
5971 :
5972 46424 : LOOP_RC_PROCESSING(stmt->label, goto loop_exit);
5973 : }
5974 :
5975 31222 : SPI_freetuptable(tuptab);
5976 :
5977 : /*
5978 : * Fetch more tuples. If prefetching is allowed, grab 50 at a time.
5979 : */
5980 31222 : SPI_cursor_fetch(portal, true, prefetch_ok ? 50 : 1);
5981 31222 : tuptab = SPI_tuptable;
5982 31222 : n = SPI_processed;
5983 : }
5984 :
5985 11302 : loop_exit:
5986 :
5987 : /*
5988 : * Release last group of tuples (if any)
5989 : */
5990 11680 : SPI_freetuptable(tuptab);
5991 :
5992 11680 : UnpinPortal(portal);
5993 :
5994 : /*
5995 : * Set the FOUND variable to indicate the result of executing the loop
5996 : * (namely, whether we looped one or more times). This must be set last so
5997 : * that it does not interfere with the value of the FOUND variable inside
5998 : * the loop processing itself.
5999 : */
6000 11680 : exec_set_found(estate, found);
6001 :
6002 11680 : return rc;
6003 : }
6004 :
6005 :
6006 : /* ----------
6007 : * exec_eval_simple_expr - Evaluate a simple expression returning
6008 : * a Datum by directly calling ExecEvalExpr().
6009 : *
6010 : * If successful, store results into *result, *isNull, *rettype, *rettypmod
6011 : * and return true. If the expression cannot be handled by simple evaluation,
6012 : * return false.
6013 : *
6014 : * Because we only store one execution tree for a simple expression, we
6015 : * can't handle recursion cases. So, if we see the tree is already busy
6016 : * with an evaluation in the current xact, we just return false and let the
6017 : * caller run the expression the hard way. (Other alternatives such as
6018 : * creating a new tree for a recursive call either introduce memory leaks,
6019 : * or add enough bookkeeping to be doubtful wins anyway.) Another case that
6020 : * is covered by the expr_simple_in_use test is where a previous execution
6021 : * of the tree was aborted by an error: the tree may contain bogus state
6022 : * so we dare not re-use it.
6023 : *
6024 : * It is possible that we'd need to replan a simple expression; for example,
6025 : * someone might redefine a SQL function that had been inlined into the simple
6026 : * expression. That cannot cause a simple expression to become non-simple (or
6027 : * vice versa), but we do have to handle replacing the expression tree.
6028 : *
6029 : * Note: if pass-by-reference, the result is in the eval_mcontext.
6030 : * It will be freed when exec_eval_cleanup is done.
6031 : * ----------
6032 : */
6033 : static bool
6034 270226 : exec_eval_simple_expr(PLpgSQL_execstate *estate,
6035 : PLpgSQL_expr *expr,
6036 : Datum *result,
6037 : bool *isNull,
6038 : Oid *rettype,
6039 : int32 *rettypmod)
6040 : {
6041 270226 : ExprContext *econtext = estate->eval_econtext;
6042 270226 : LocalTransactionId curlxid = MyProc->vxid.lxid;
6043 : ParamListInfo paramLI;
6044 : void *save_setup_arg;
6045 : bool need_snapshot;
6046 : MemoryContext oldcontext;
6047 :
6048 : /*
6049 : * Forget it if expression wasn't simple before.
6050 : */
6051 270226 : if (expr->expr_simple_expr == NULL)
6052 5832 : return false;
6053 :
6054 : /*
6055 : * If expression is in use in current xact, don't touch it.
6056 : */
6057 264394 : if (unlikely(expr->expr_simple_in_use) &&
6058 614 : expr->expr_simple_lxid == curlxid)
6059 548 : return false;
6060 :
6061 : /*
6062 : * Ensure that there's a portal-level snapshot, in case this simple
6063 : * expression is the first thing evaluated after a COMMIT or ROLLBACK.
6064 : * We'd have to do this anyway before executing the expression, so we
6065 : * might as well do it now to ensure that any possible replanning doesn't
6066 : * need to take a new snapshot.
6067 : */
6068 263846 : EnsurePortalSnapshotExists();
6069 :
6070 : /*
6071 : * Check to see if the cached plan has been invalidated. If not, and this
6072 : * is the first use in the current transaction, save a plan refcount in
6073 : * the simple-expression resowner.
6074 : */
6075 263846 : if (likely(CachedPlanIsSimplyValid(expr->expr_simple_plansource,
6076 : expr->expr_simple_plan,
6077 : (expr->expr_simple_plan_lxid != curlxid ?
6078 : estate->simple_eval_resowner : NULL))))
6079 : {
6080 : /*
6081 : * It's still good, so just remember that we have a refcount on the
6082 : * plan in the current transaction. (If we already had one, this
6083 : * assignment is a no-op.)
6084 : */
6085 258372 : expr->expr_simple_plan_lxid = curlxid;
6086 : }
6087 : else
6088 : {
6089 : /* Need to replan */
6090 : CachedPlan *cplan;
6091 :
6092 : /*
6093 : * If we have a valid refcount on some previous version of the plan,
6094 : * release it, so we don't leak plans intra-transaction.
6095 : */
6096 5474 : if (expr->expr_simple_plan_lxid == curlxid)
6097 : {
6098 3194 : ReleaseCachedPlan(expr->expr_simple_plan,
6099 : estate->simple_eval_resowner);
6100 3194 : expr->expr_simple_plan = NULL;
6101 3194 : expr->expr_simple_plan_lxid = InvalidLocalTransactionId;
6102 : }
6103 :
6104 : /* Do the replanning work in the eval_mcontext */
6105 5474 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6106 5474 : cplan = SPI_plan_get_cached_plan(expr->plan);
6107 5474 : MemoryContextSwitchTo(oldcontext);
6108 :
6109 : /*
6110 : * We can't get a failure here, because the number of
6111 : * CachedPlanSources in the SPI plan can't change from what
6112 : * exec_simple_check_plan saw; it's a property of the raw parsetree
6113 : * generated from the query text.
6114 : */
6115 : Assert(cplan != NULL);
6116 :
6117 : /*
6118 : * This test probably can't fail either, but if it does, cope by
6119 : * declaring the plan to be non-simple. On success, we'll acquire a
6120 : * refcount on the new plan, stored in simple_eval_resowner.
6121 : */
6122 5474 : if (CachedPlanAllowsSimpleValidityCheck(expr->expr_simple_plansource,
6123 : cplan,
6124 : estate->simple_eval_resowner))
6125 : {
6126 : /* Remember that we have the refcount */
6127 5474 : expr->expr_simple_plan = cplan;
6128 5474 : expr->expr_simple_plan_lxid = curlxid;
6129 : }
6130 : else
6131 : {
6132 : /* Release SPI_plan_get_cached_plan's refcount */
6133 0 : ReleaseCachedPlan(cplan, CurrentResourceOwner);
6134 : /* Mark expression as non-simple, and fail */
6135 0 : expr->expr_simple_expr = NULL;
6136 0 : expr->expr_rw_param = NULL;
6137 0 : return false;
6138 : }
6139 :
6140 : /*
6141 : * SPI_plan_get_cached_plan acquired a plan refcount stored in the
6142 : * active resowner. We don't need that anymore, so release it.
6143 : */
6144 5474 : ReleaseCachedPlan(cplan, CurrentResourceOwner);
6145 :
6146 : /* Extract desired scalar expression from cached plan */
6147 5474 : exec_save_simple_expr(expr, cplan);
6148 : }
6149 :
6150 : /*
6151 : * Pass back previously-determined result type.
6152 : */
6153 263846 : *rettype = expr->expr_simple_type;
6154 263846 : *rettypmod = expr->expr_simple_typmod;
6155 :
6156 : /*
6157 : * Set up ParamListInfo to pass to executor. For safety, save and restore
6158 : * estate->paramLI->parserSetupArg around our use of the param list.
6159 : */
6160 263846 : paramLI = estate->paramLI;
6161 263846 : save_setup_arg = paramLI->parserSetupArg;
6162 :
6163 : /*
6164 : * We can skip using setup_param_list() in favor of just doing this
6165 : * unconditionally, because there's no need for the optimization of
6166 : * possibly setting ecxt_param_list_info to NULL; we've already forced use
6167 : * of a generic plan.
6168 : */
6169 263846 : paramLI->parserSetupArg = (void *) expr;
6170 263846 : econtext->ecxt_param_list_info = paramLI;
6171 :
6172 : /*
6173 : * Prepare the expression for execution, if it's not been done already in
6174 : * the current transaction. (This will be forced to happen if we called
6175 : * exec_save_simple_expr above.)
6176 : */
6177 263846 : if (unlikely(expr->expr_simple_lxid != curlxid))
6178 : {
6179 75980 : oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
6180 75980 : expr->expr_simple_state =
6181 75980 : ExecInitExprWithParams(expr->expr_simple_expr,
6182 : econtext->ecxt_param_list_info);
6183 75980 : expr->expr_simple_in_use = false;
6184 75980 : expr->expr_simple_lxid = curlxid;
6185 75980 : MemoryContextSwitchTo(oldcontext);
6186 : }
6187 :
6188 : /*
6189 : * We have to do some of the things SPI_execute_plan would do, in
6190 : * particular push a new snapshot so that stable functions within the
6191 : * expression can see updates made so far by our own function. However,
6192 : * we can skip doing that (and just invoke the expression with the same
6193 : * snapshot passed to our function) in some cases, which is useful because
6194 : * it's quite expensive relative to the cost of a simple expression. We
6195 : * can skip it if the expression contains no stable or volatile functions;
6196 : * immutable functions shouldn't need to see our updates. Also, if this
6197 : * is a read-only function, we haven't made any updates so again it's okay
6198 : * to skip.
6199 : */
6200 263846 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6201 263846 : need_snapshot = (expr->expr_simple_mutable && !estate->readonly_func);
6202 263846 : if (need_snapshot)
6203 : {
6204 27514 : CommandCounterIncrement();
6205 27514 : PushActiveSnapshot(GetTransactionSnapshot());
6206 : }
6207 :
6208 : /*
6209 : * Mark expression as busy for the duration of the ExecEvalExpr call.
6210 : */
6211 263846 : expr->expr_simple_in_use = true;
6212 :
6213 : /*
6214 : * Finally we can call the executor to evaluate the expression
6215 : */
6216 263846 : *result = ExecEvalExpr(expr->expr_simple_state,
6217 : econtext,
6218 : isNull);
6219 :
6220 : /* Assorted cleanup */
6221 263606 : expr->expr_simple_in_use = false;
6222 :
6223 263606 : econtext->ecxt_param_list_info = NULL;
6224 :
6225 263606 : paramLI->parserSetupArg = save_setup_arg;
6226 :
6227 263606 : if (need_snapshot)
6228 27470 : PopActiveSnapshot();
6229 :
6230 263606 : MemoryContextSwitchTo(oldcontext);
6231 :
6232 : /*
6233 : * That's it.
6234 : */
6235 263606 : return true;
6236 : }
6237 :
6238 :
6239 : /*
6240 : * Create a ParamListInfo to pass to SPI
6241 : *
6242 : * We use a single ParamListInfo struct for all SPI calls made to evaluate
6243 : * PLpgSQL_exprs in this estate. It contains no per-param data, just hook
6244 : * functions, so it's effectively read-only for SPI.
6245 : *
6246 : * An exception from pure read-only-ness is that the parserSetupArg points
6247 : * to the specific PLpgSQL_expr being evaluated. This is not an issue for
6248 : * statement-level callers, but lower-level callers must save and restore
6249 : * estate->paramLI->parserSetupArg just in case there's an active evaluation
6250 : * at an outer call level. (A plausible alternative design would be to
6251 : * create a ParamListInfo struct for each PLpgSQL_expr, but for the moment
6252 : * that seems like a waste of memory.)
6253 : */
6254 : static ParamListInfo
6255 67356 : setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
6256 : {
6257 : ParamListInfo paramLI;
6258 :
6259 : /*
6260 : * We must have created the SPIPlan already (hence, query text has been
6261 : * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
6262 : */
6263 : Assert(expr->plan != NULL);
6264 :
6265 : /*
6266 : * We only need a ParamListInfo if the expression has parameters.
6267 : */
6268 67356 : if (!bms_is_empty(expr->paramnos))
6269 : {
6270 : /* Use the common ParamListInfo */
6271 29628 : paramLI = estate->paramLI;
6272 :
6273 : /*
6274 : * Set up link to active expr where the hook functions can find it.
6275 : * Callers must save and restore parserSetupArg if there is any chance
6276 : * that they are interrupting an active use of parameters.
6277 : */
6278 29628 : paramLI->parserSetupArg = (void *) expr;
6279 :
6280 : /*
6281 : * Also make sure this is set before parser hooks need it. There is
6282 : * no need to save and restore, since the value is always correct once
6283 : * set. (Should be set already, but let's be sure.)
6284 : */
6285 29628 : expr->func = estate->func;
6286 : }
6287 : else
6288 : {
6289 : /*
6290 : * Expression requires no parameters. Be sure we represent this case
6291 : * as a NULL ParamListInfo, so that plancache.c knows there is no
6292 : * point in a custom plan.
6293 : */
6294 37728 : paramLI = NULL;
6295 : }
6296 67356 : return paramLI;
6297 : }
6298 :
6299 : /*
6300 : * plpgsql_param_fetch paramFetch callback for dynamic parameter fetch
6301 : *
6302 : * We always use the caller's workspace to construct the returned struct.
6303 : *
6304 : * Note: this is no longer used during query execution. It is used during
6305 : * planning (with speculative == true) and when the ParamListInfo we supply
6306 : * to the executor is copied into a cursor portal or transferred to a
6307 : * parallel child process.
6308 : */
6309 : static ParamExternData *
6310 11616 : plpgsql_param_fetch(ParamListInfo params,
6311 : int paramid, bool speculative,
6312 : ParamExternData *prm)
6313 : {
6314 : int dno;
6315 : PLpgSQL_execstate *estate;
6316 : PLpgSQL_expr *expr;
6317 : PLpgSQL_datum *datum;
6318 11616 : bool ok = true;
6319 : int32 prmtypmod;
6320 :
6321 : /* paramid's are 1-based, but dnos are 0-based */
6322 11616 : dno = paramid - 1;
6323 : Assert(dno >= 0 && dno < params->numParams);
6324 :
6325 : /* fetch back the hook data */
6326 11616 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
6327 11616 : expr = (PLpgSQL_expr *) params->parserSetupArg;
6328 : Assert(params->numParams == estate->ndatums);
6329 :
6330 : /* now we can access the target datum */
6331 11616 : datum = estate->datums[dno];
6332 :
6333 : /*
6334 : * Since copyParamList() or SerializeParamList() will try to materialize
6335 : * every single parameter slot, it's important to return a dummy param
6336 : * when asked for a datum that's not supposed to be used by this SQL
6337 : * expression. Otherwise we risk failures in exec_eval_datum(), or
6338 : * copying a lot more data than necessary.
6339 : */
6340 11616 : if (!bms_is_member(dno, expr->paramnos))
6341 3624 : ok = false;
6342 :
6343 : /*
6344 : * If the access is speculative, we prefer to return no data rather than
6345 : * to fail in exec_eval_datum(). Check the likely failure cases.
6346 : */
6347 7992 : else if (speculative)
6348 : {
6349 6954 : switch (datum->dtype)
6350 : {
6351 4744 : case PLPGSQL_DTYPE_VAR:
6352 : case PLPGSQL_DTYPE_PROMISE:
6353 : /* always safe */
6354 4744 : break;
6355 :
6356 0 : case PLPGSQL_DTYPE_ROW:
6357 : /* should be safe in all interesting cases */
6358 0 : break;
6359 :
6360 578 : case PLPGSQL_DTYPE_REC:
6361 : /* always safe (might return NULL, that's fine) */
6362 578 : break;
6363 :
6364 1632 : case PLPGSQL_DTYPE_RECFIELD:
6365 : {
6366 1632 : PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
6367 : PLpgSQL_rec *rec;
6368 :
6369 1632 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
6370 :
6371 : /*
6372 : * If record variable is NULL, don't risk anything.
6373 : */
6374 1632 : if (rec->erh == NULL)
6375 0 : ok = false;
6376 :
6377 : /*
6378 : * Look up the field's properties if we have not already,
6379 : * or if the tuple descriptor ID changed since last time.
6380 : */
6381 1632 : else if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
6382 : {
6383 20 : if (expanded_record_lookup_field(rec->erh,
6384 20 : recfield->fieldname,
6385 : &recfield->finfo))
6386 20 : recfield->rectupledescid = rec->erh->er_tupdesc_id;
6387 : else
6388 0 : ok = false;
6389 : }
6390 1632 : break;
6391 : }
6392 :
6393 0 : default:
6394 0 : ok = false;
6395 0 : break;
6396 : }
6397 1038 : }
6398 :
6399 : /* Return "no such parameter" if not ok */
6400 11616 : if (!ok)
6401 : {
6402 3624 : prm->value = (Datum) 0;
6403 3624 : prm->isnull = true;
6404 3624 : prm->pflags = 0;
6405 3624 : prm->ptype = InvalidOid;
6406 3624 : return prm;
6407 : }
6408 :
6409 : /* OK, evaluate the value and store into the return struct */
6410 7992 : exec_eval_datum(estate, datum,
6411 : &prm->ptype, &prmtypmod,
6412 : &prm->value, &prm->isnull);
6413 : /* We can always mark params as "const" for executor's purposes */
6414 7992 : prm->pflags = PARAM_FLAG_CONST;
6415 :
6416 : /*
6417 : * If it's a read/write expanded datum, convert reference to read-only.
6418 : * (There's little point in trying to optimize read/write parameters,
6419 : * given the cases in which this function is used.)
6420 : */
6421 7992 : if (datum->dtype == PLPGSQL_DTYPE_VAR)
6422 3520 : prm->value = MakeExpandedObjectReadOnly(prm->value,
6423 : prm->isnull,
6424 : ((PLpgSQL_var *) datum)->datatype->typlen);
6425 4472 : else if (datum->dtype == PLPGSQL_DTYPE_REC)
6426 578 : prm->value = MakeExpandedObjectReadOnly(prm->value,
6427 : prm->isnull,
6428 : -1);
6429 :
6430 7992 : return prm;
6431 : }
6432 :
6433 : /*
6434 : * plpgsql_param_compile paramCompile callback for plpgsql parameters
6435 : */
6436 : static void
6437 126300 : plpgsql_param_compile(ParamListInfo params, Param *param,
6438 : ExprState *state,
6439 : Datum *resv, bool *resnull)
6440 : {
6441 : PLpgSQL_execstate *estate;
6442 : PLpgSQL_expr *expr;
6443 : int dno;
6444 : PLpgSQL_datum *datum;
6445 : ExprEvalStep scratch;
6446 :
6447 : /* fetch back the hook data */
6448 126300 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
6449 126300 : expr = (PLpgSQL_expr *) params->parserSetupArg;
6450 :
6451 : /* paramid's are 1-based, but dnos are 0-based */
6452 126300 : dno = param->paramid - 1;
6453 : Assert(dno >= 0 && dno < estate->ndatums);
6454 :
6455 : /* now we can access the target datum */
6456 126300 : datum = estate->datums[dno];
6457 :
6458 126300 : scratch.opcode = EEOP_PARAM_CALLBACK;
6459 126300 : scratch.resvalue = resv;
6460 126300 : scratch.resnull = resnull;
6461 :
6462 : /*
6463 : * Select appropriate eval function. It seems worth special-casing
6464 : * DTYPE_VAR and DTYPE_RECFIELD for performance. Also, we can determine
6465 : * in advance whether MakeExpandedObjectReadOnly() will be required.
6466 : * Currently, only VAR/PROMISE and REC datums could contain read/write
6467 : * expanded objects.
6468 : */
6469 126300 : if (datum->dtype == PLPGSQL_DTYPE_VAR)
6470 : {
6471 81064 : if (param != expr->expr_rw_param &&
6472 80898 : ((PLpgSQL_var *) datum)->datatype->typlen == -1)
6473 62746 : scratch.d.cparam.paramfunc = plpgsql_param_eval_var_ro;
6474 : else
6475 18318 : scratch.d.cparam.paramfunc = plpgsql_param_eval_var;
6476 : }
6477 45236 : else if (datum->dtype == PLPGSQL_DTYPE_RECFIELD)
6478 23864 : scratch.d.cparam.paramfunc = plpgsql_param_eval_recfield;
6479 21372 : else if (datum->dtype == PLPGSQL_DTYPE_PROMISE)
6480 : {
6481 18512 : if (param != expr->expr_rw_param &&
6482 18512 : ((PLpgSQL_var *) datum)->datatype->typlen == -1)
6483 15962 : scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro;
6484 : else
6485 2550 : scratch.d.cparam.paramfunc = plpgsql_param_eval_generic;
6486 : }
6487 2860 : else if (datum->dtype == PLPGSQL_DTYPE_REC &&
6488 2860 : param != expr->expr_rw_param)
6489 2860 : scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro;
6490 : else
6491 0 : scratch.d.cparam.paramfunc = plpgsql_param_eval_generic;
6492 :
6493 : /*
6494 : * Note: it's tempting to use paramarg to store the estate pointer and
6495 : * thereby save an indirection or two in the eval functions. But that
6496 : * doesn't work because the compiled expression might be used with
6497 : * different estates for the same PL/pgSQL function.
6498 : */
6499 126300 : scratch.d.cparam.paramarg = NULL;
6500 126300 : scratch.d.cparam.paramid = param->paramid;
6501 126300 : scratch.d.cparam.paramtype = param->paramtype;
6502 126300 : ExprEvalPushStep(state, &scratch);
6503 126300 : }
6504 :
6505 : /*
6506 : * plpgsql_param_eval_var evaluation of EEOP_PARAM_CALLBACK step
6507 : *
6508 : * This is specialized to the case of DTYPE_VAR variables for which
6509 : * we do not need to invoke MakeExpandedObjectReadOnly.
6510 : */
6511 : static void
6512 90650 : plpgsql_param_eval_var(ExprState *state, ExprEvalStep *op,
6513 : ExprContext *econtext)
6514 : {
6515 : ParamListInfo params;
6516 : PLpgSQL_execstate *estate;
6517 90650 : int dno = op->d.cparam.paramid - 1;
6518 : PLpgSQL_var *var;
6519 :
6520 : /* fetch back the hook data */
6521 90650 : params = econtext->ecxt_param_list_info;
6522 90650 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
6523 : Assert(dno >= 0 && dno < estate->ndatums);
6524 :
6525 : /* now we can access the target datum */
6526 90650 : var = (PLpgSQL_var *) estate->datums[dno];
6527 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6528 :
6529 : /* inlined version of exec_eval_datum() */
6530 90650 : *op->resvalue = var->value;
6531 90650 : *op->resnull = var->isnull;
6532 :
6533 : /* safety check -- an assertion should be sufficient */
6534 : Assert(var->datatype->typoid == op->d.cparam.paramtype);
6535 90650 : }
6536 :
6537 : /*
6538 : * plpgsql_param_eval_var_ro evaluation of EEOP_PARAM_CALLBACK step
6539 : *
6540 : * This is specialized to the case of DTYPE_VAR variables for which
6541 : * we need to invoke MakeExpandedObjectReadOnly.
6542 : */
6543 : static void
6544 155444 : plpgsql_param_eval_var_ro(ExprState *state, ExprEvalStep *op,
6545 : ExprContext *econtext)
6546 : {
6547 : ParamListInfo params;
6548 : PLpgSQL_execstate *estate;
6549 155444 : int dno = op->d.cparam.paramid - 1;
6550 : PLpgSQL_var *var;
6551 :
6552 : /* fetch back the hook data */
6553 155444 : params = econtext->ecxt_param_list_info;
6554 155444 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
6555 : Assert(dno >= 0 && dno < estate->ndatums);
6556 :
6557 : /* now we can access the target datum */
6558 155444 : var = (PLpgSQL_var *) estate->datums[dno];
6559 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6560 :
6561 : /*
6562 : * Inlined version of exec_eval_datum() ... and while we're at it, force
6563 : * expanded datums to read-only.
6564 : */
6565 155444 : *op->resvalue = MakeExpandedObjectReadOnly(var->value,
6566 : var->isnull,
6567 : -1);
6568 155444 : *op->resnull = var->isnull;
6569 :
6570 : /* safety check -- an assertion should be sufficient */
6571 : Assert(var->datatype->typoid == op->d.cparam.paramtype);
6572 155444 : }
6573 :
6574 : /*
6575 : * plpgsql_param_eval_recfield evaluation of EEOP_PARAM_CALLBACK step
6576 : *
6577 : * This is specialized to the case of DTYPE_RECFIELD variables, for which
6578 : * we never need to invoke MakeExpandedObjectReadOnly.
6579 : */
6580 : static void
6581 60416 : plpgsql_param_eval_recfield(ExprState *state, ExprEvalStep *op,
6582 : ExprContext *econtext)
6583 : {
6584 : ParamListInfo params;
6585 : PLpgSQL_execstate *estate;
6586 60416 : int dno = op->d.cparam.paramid - 1;
6587 : PLpgSQL_recfield *recfield;
6588 : PLpgSQL_rec *rec;
6589 : ExpandedRecordHeader *erh;
6590 :
6591 : /* fetch back the hook data */
6592 60416 : params = econtext->ecxt_param_list_info;
6593 60416 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
6594 : Assert(dno >= 0 && dno < estate->ndatums);
6595 :
6596 : /* now we can access the target datum */
6597 60416 : recfield = (PLpgSQL_recfield *) estate->datums[dno];
6598 : Assert(recfield->dtype == PLPGSQL_DTYPE_RECFIELD);
6599 :
6600 : /* inline the relevant part of exec_eval_datum */
6601 60416 : rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
6602 60416 : erh = rec->erh;
6603 :
6604 : /*
6605 : * If record variable is NULL, instantiate it if it has a named composite
6606 : * type, else complain. (This won't change the logical state of the
6607 : * record: it's still NULL.)
6608 : */
6609 60416 : if (erh == NULL)
6610 : {
6611 2 : instantiate_empty_record_variable(estate, rec);
6612 2 : erh = rec->erh;
6613 : }
6614 :
6615 : /*
6616 : * Look up the field's properties if we have not already, or if the tuple
6617 : * descriptor ID changed since last time.
6618 : */
6619 60416 : if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
6620 : {
6621 3484 : if (!expanded_record_lookup_field(erh,
6622 3484 : recfield->fieldname,
6623 : &recfield->finfo))
6624 2 : ereport(ERROR,
6625 : (errcode(ERRCODE_UNDEFINED_COLUMN),
6626 : errmsg("record \"%s\" has no field \"%s\"",
6627 : rec->refname, recfield->fieldname)));
6628 3482 : recfield->rectupledescid = erh->er_tupdesc_id;
6629 : }
6630 :
6631 : /* OK to fetch the field value. */
6632 60414 : *op->resvalue = expanded_record_get_field(erh,
6633 : recfield->finfo.fnumber,
6634 : op->resnull);
6635 :
6636 : /* safety check -- needed for, eg, record fields */
6637 60414 : if (unlikely(recfield->finfo.ftypeid != op->d.cparam.paramtype))
6638 4 : ereport(ERROR,
6639 : (errcode(ERRCODE_DATATYPE_MISMATCH),
6640 : errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6641 : op->d.cparam.paramid,
6642 : format_type_be(recfield->finfo.ftypeid),
6643 : format_type_be(op->d.cparam.paramtype))));
6644 60410 : }
6645 :
6646 : /*
6647 : * plpgsql_param_eval_generic evaluation of EEOP_PARAM_CALLBACK step
6648 : *
6649 : * This handles all variable types, but assumes we do not need to invoke
6650 : * MakeExpandedObjectReadOnly.
6651 : */
6652 : static void
6653 2812 : plpgsql_param_eval_generic(ExprState *state, ExprEvalStep *op,
6654 : ExprContext *econtext)
6655 : {
6656 : ParamListInfo params;
6657 : PLpgSQL_execstate *estate;
6658 2812 : int dno = op->d.cparam.paramid - 1;
6659 : PLpgSQL_datum *datum;
6660 : Oid datumtype;
6661 : int32 datumtypmod;
6662 :
6663 : /* fetch back the hook data */
6664 2812 : params = econtext->ecxt_param_list_info;
6665 2812 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
6666 : Assert(dno >= 0 && dno < estate->ndatums);
6667 :
6668 : /* now we can access the target datum */
6669 2812 : datum = estate->datums[dno];
6670 :
6671 : /* fetch datum's value */
6672 2812 : exec_eval_datum(estate, datum,
6673 : &datumtype, &datumtypmod,
6674 : op->resvalue, op->resnull);
6675 :
6676 : /* safety check -- needed for, eg, record fields */
6677 2812 : if (unlikely(datumtype != op->d.cparam.paramtype))
6678 0 : ereport(ERROR,
6679 : (errcode(ERRCODE_DATATYPE_MISMATCH),
6680 : errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6681 : op->d.cparam.paramid,
6682 : format_type_be(datumtype),
6683 : format_type_be(op->d.cparam.paramtype))));
6684 2812 : }
6685 :
6686 : /*
6687 : * plpgsql_param_eval_generic_ro evaluation of EEOP_PARAM_CALLBACK step
6688 : *
6689 : * This handles all variable types, but assumes we need to invoke
6690 : * MakeExpandedObjectReadOnly (hence, variable must be of a varlena type).
6691 : */
6692 : static void
6693 20634 : plpgsql_param_eval_generic_ro(ExprState *state, ExprEvalStep *op,
6694 : ExprContext *econtext)
6695 : {
6696 : ParamListInfo params;
6697 : PLpgSQL_execstate *estate;
6698 20634 : int dno = op->d.cparam.paramid - 1;
6699 : PLpgSQL_datum *datum;
6700 : Oid datumtype;
6701 : int32 datumtypmod;
6702 :
6703 : /* fetch back the hook data */
6704 20634 : params = econtext->ecxt_param_list_info;
6705 20634 : estate = (PLpgSQL_execstate *) params->paramFetchArg;
6706 : Assert(dno >= 0 && dno < estate->ndatums);
6707 :
6708 : /* now we can access the target datum */
6709 20634 : datum = estate->datums[dno];
6710 :
6711 : /* fetch datum's value */
6712 20634 : exec_eval_datum(estate, datum,
6713 : &datumtype, &datumtypmod,
6714 : op->resvalue, op->resnull);
6715 :
6716 : /* safety check -- needed for, eg, record fields */
6717 20634 : if (unlikely(datumtype != op->d.cparam.paramtype))
6718 0 : ereport(ERROR,
6719 : (errcode(ERRCODE_DATATYPE_MISMATCH),
6720 : errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6721 : op->d.cparam.paramid,
6722 : format_type_be(datumtype),
6723 : format_type_be(op->d.cparam.paramtype))));
6724 :
6725 : /* force the value to read-only */
6726 20634 : *op->resvalue = MakeExpandedObjectReadOnly(*op->resvalue,
6727 : *op->resnull,
6728 : -1);
6729 20634 : }
6730 :
6731 :
6732 : /*
6733 : * exec_move_row Move one tuple's values into a record or row
6734 : *
6735 : * tup and tupdesc may both be NULL if we're just assigning an indeterminate
6736 : * composite NULL to the target. Alternatively, can have tup be NULL and
6737 : * tupdesc not NULL, in which case we assign a row of NULLs to the target.
6738 : *
6739 : * Since this uses the mcontext for workspace, caller should eventually call
6740 : * exec_eval_cleanup to prevent long-term memory leaks.
6741 : */
6742 : static void
6743 64828 : exec_move_row(PLpgSQL_execstate *estate,
6744 : PLpgSQL_variable *target,
6745 : HeapTuple tup, TupleDesc tupdesc)
6746 : {
6747 64828 : ExpandedRecordHeader *newerh = NULL;
6748 :
6749 : /*
6750 : * If target is RECORD, we may be able to avoid field-by-field processing.
6751 : */
6752 64828 : if (target->dtype == PLPGSQL_DTYPE_REC)
6753 : {
6754 10664 : PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
6755 :
6756 : /*
6757 : * If we have no source tupdesc, just set the record variable to NULL.
6758 : * (If we have a source tupdesc but not a tuple, we'll set the
6759 : * variable to a row of nulls, instead. This is odd perhaps, but
6760 : * backwards compatible.)
6761 : */
6762 10664 : if (tupdesc == NULL)
6763 : {
6764 5026 : if (rec->datatype &&
6765 5026 : rec->datatype->typtype == TYPTYPE_DOMAIN)
6766 : {
6767 : /*
6768 : * If it's a composite domain, NULL might not be a legal
6769 : * value, so we instead need to make an empty expanded record
6770 : * and ensure that domain type checking gets done. If there
6771 : * is already an expanded record, piggyback on its lookups.
6772 : */
6773 32 : newerh = make_expanded_record_for_rec(estate, rec,
6774 : NULL, rec->erh);
6775 32 : expanded_record_set_tuple(newerh, NULL, false, false);
6776 24 : assign_record_var(estate, rec, newerh);
6777 : }
6778 : else
6779 : {
6780 : /* Just clear it to NULL */
6781 4994 : if (rec->erh)
6782 162 : DeleteExpandedObject(ExpandedRecordGetDatum(rec->erh));
6783 4994 : rec->erh = NULL;
6784 : }
6785 5018 : return;
6786 : }
6787 :
6788 : /*
6789 : * Build a new expanded record with appropriate tupdesc.
6790 : */
6791 5638 : newerh = make_expanded_record_for_rec(estate, rec, tupdesc, NULL);
6792 :
6793 : /*
6794 : * If the rowtypes match, or if we have no tuple anyway, we can
6795 : * complete the assignment without field-by-field processing.
6796 : *
6797 : * The tests here are ordered more or less in order of cheapness. We
6798 : * can easily detect it will work if the target is declared RECORD or
6799 : * has the same typeid as the source. But when assigning from a query
6800 : * result, it's common to have a source tupdesc that's labeled RECORD
6801 : * but is actually physically compatible with a named-composite-type
6802 : * target, so it's worth spending extra cycles to check for that.
6803 : */
6804 5638 : if (rec->rectypeid == RECORDOID ||
6805 218 : rec->rectypeid == tupdesc->tdtypeid ||
6806 218 : !HeapTupleIsValid(tup) ||
6807 218 : compatible_tupdescs(tupdesc, expanded_record_get_tupdesc(newerh)))
6808 : {
6809 5542 : if (!HeapTupleIsValid(tup))
6810 : {
6811 : /* No data, so force the record into all-nulls state */
6812 1488 : deconstruct_expanded_record(newerh);
6813 : }
6814 : else
6815 : {
6816 : /* No coercion is needed, so just assign the row value */
6817 4054 : expanded_record_set_tuple(newerh, tup, true, !estate->atomic);
6818 : }
6819 :
6820 : /* Complete the assignment */
6821 5536 : assign_record_var(estate, rec, newerh);
6822 :
6823 5536 : return;
6824 : }
6825 : }
6826 :
6827 : /*
6828 : * Otherwise, deconstruct the tuple and do field-by-field assignment,
6829 : * using exec_move_row_from_fields.
6830 : */
6831 54260 : if (tupdesc && HeapTupleIsValid(tup))
6832 54038 : {
6833 54072 : int td_natts = tupdesc->natts;
6834 : Datum *values;
6835 : bool *nulls;
6836 : Datum values_local[64];
6837 : bool nulls_local[64];
6838 :
6839 : /*
6840 : * Need workspace arrays. If td_natts is small enough, use local
6841 : * arrays to save doing a palloc. Even if it's not small, we can
6842 : * allocate both the Datum and isnull arrays in one palloc chunk.
6843 : */
6844 54072 : if (td_natts <= lengthof(values_local))
6845 : {
6846 54072 : values = values_local;
6847 54072 : nulls = nulls_local;
6848 : }
6849 : else
6850 : {
6851 : char *chunk;
6852 :
6853 0 : chunk = eval_mcontext_alloc(estate,
6854 : td_natts * (sizeof(Datum) + sizeof(bool)));
6855 0 : values = (Datum *) chunk;
6856 0 : nulls = (bool *) (chunk + td_natts * sizeof(Datum));
6857 : }
6858 :
6859 54072 : heap_deform_tuple(tup, tupdesc, values, nulls);
6860 :
6861 54072 : exec_move_row_from_fields(estate, target, newerh,
6862 : values, nulls, tupdesc);
6863 : }
6864 : else
6865 : {
6866 : /*
6867 : * Assign all-nulls.
6868 : */
6869 188 : exec_move_row_from_fields(estate, target, newerh,
6870 : NULL, NULL, NULL);
6871 : }
6872 : }
6873 :
6874 : /*
6875 : * Verify that a PLpgSQL_rec's rectypeid is up-to-date.
6876 : */
6877 : static void
6878 710 : revalidate_rectypeid(PLpgSQL_rec *rec)
6879 : {
6880 710 : PLpgSQL_type *typ = rec->datatype;
6881 : TypeCacheEntry *typentry;
6882 :
6883 710 : if (rec->rectypeid == RECORDOID)
6884 300 : return; /* it's RECORD, so nothing to do */
6885 : Assert(typ != NULL);
6886 410 : if (typ->tcache &&
6887 410 : typ->tcache->tupDesc_identifier == typ->tupdesc_id)
6888 : {
6889 : /*
6890 : * Although *typ is known up-to-date, it's possible that rectypeid
6891 : * isn't, because *rec is cloned during each function startup from a
6892 : * copy that we don't have a good way to update. Hence, forcibly fix
6893 : * rectypeid before returning.
6894 : */
6895 398 : rec->rectypeid = typ->typoid;
6896 398 : return;
6897 : }
6898 :
6899 : /*
6900 : * typcache entry has suffered invalidation, so re-look-up the type name
6901 : * if possible, and then recheck the type OID. If we don't have a
6902 : * TypeName, then we just have to soldier on with the OID we've got.
6903 : */
6904 12 : if (typ->origtypname != NULL)
6905 : {
6906 : /* this bit should match parse_datatype() in pl_gram.y */
6907 8 : typenameTypeIdAndMod(NULL, typ->origtypname,
6908 : &typ->typoid,
6909 : &typ->atttypmod);
6910 : }
6911 :
6912 : /* this bit should match build_datatype() in pl_comp.c */
6913 10 : typentry = lookup_type_cache(typ->typoid,
6914 : TYPECACHE_TUPDESC |
6915 : TYPECACHE_DOMAIN_BASE_INFO);
6916 10 : if (typentry->typtype == TYPTYPE_DOMAIN)
6917 0 : typentry = lookup_type_cache(typentry->domainBaseType,
6918 : TYPECACHE_TUPDESC);
6919 10 : if (typentry->tupDesc == NULL)
6920 : {
6921 : /*
6922 : * If we get here, user tried to replace a composite type with a
6923 : * non-composite one. We're not gonna support that.
6924 : */
6925 0 : ereport(ERROR,
6926 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
6927 : errmsg("type %s is not composite",
6928 : format_type_be(typ->typoid))));
6929 : }
6930 :
6931 : /*
6932 : * Update tcache and tupdesc_id. Since we don't support changing to a
6933 : * non-composite type, none of the rest of *typ needs to change.
6934 : */
6935 10 : typ->tcache = typentry;
6936 10 : typ->tupdesc_id = typentry->tupDesc_identifier;
6937 :
6938 : /*
6939 : * Update *rec, too. (We'll deal with subsidiary RECFIELDs as needed.)
6940 : */
6941 10 : rec->rectypeid = typ->typoid;
6942 : }
6943 :
6944 : /*
6945 : * Build an expanded record object suitable for assignment to "rec".
6946 : *
6947 : * Caller must supply either a source tuple descriptor or a source expanded
6948 : * record (not both). If the record variable has declared type RECORD,
6949 : * it'll adopt the source's rowtype. Even if it doesn't, we may be able to
6950 : * piggyback on a source expanded record to save a typcache lookup.
6951 : *
6952 : * Caller must fill the object with data, then do assign_record_var().
6953 : *
6954 : * The new record is initially put into the mcontext, so it will be cleaned up
6955 : * if we fail before reaching assign_record_var().
6956 : */
6957 : static ExpandedRecordHeader *
6958 5992 : make_expanded_record_for_rec(PLpgSQL_execstate *estate,
6959 : PLpgSQL_rec *rec,
6960 : TupleDesc srctupdesc,
6961 : ExpandedRecordHeader *srcerh)
6962 : {
6963 : ExpandedRecordHeader *newerh;
6964 5992 : MemoryContext mcontext = get_eval_mcontext(estate);
6965 :
6966 5992 : if (rec->rectypeid != RECORDOID)
6967 : {
6968 : /*
6969 : * Make sure rec->rectypeid is up-to-date before using it.
6970 : */
6971 274 : revalidate_rectypeid(rec);
6972 :
6973 : /*
6974 : * New record must be of desired type, but maybe srcerh has already
6975 : * done all the same lookups.
6976 : */
6977 274 : if (srcerh && rec->rectypeid == srcerh->er_decltypeid)
6978 26 : newerh = make_expanded_record_from_exprecord(srcerh,
6979 : mcontext);
6980 : else
6981 248 : newerh = make_expanded_record_from_typeid(rec->rectypeid, -1,
6982 : mcontext);
6983 : }
6984 : else
6985 : {
6986 : /*
6987 : * We'll adopt the input tupdesc. We can still use
6988 : * make_expanded_record_from_exprecord, if srcerh isn't a composite
6989 : * domain. (If it is, we effectively adopt its base type.)
6990 : */
6991 5718 : if (srcerh && !ExpandedRecordIsDomain(srcerh))
6992 298 : newerh = make_expanded_record_from_exprecord(srcerh,
6993 : mcontext);
6994 : else
6995 : {
6996 5420 : if (!srctupdesc)
6997 0 : srctupdesc = expanded_record_get_tupdesc(srcerh);
6998 5420 : newerh = make_expanded_record_from_tupdesc(srctupdesc,
6999 : mcontext);
7000 : }
7001 : }
7002 :
7003 5992 : return newerh;
7004 : }
7005 :
7006 : /*
7007 : * exec_move_row_from_fields Move arrays of field values into a record or row
7008 : *
7009 : * When assigning to a record, the caller must have already created a suitable
7010 : * new expanded record object, newerh. Pass NULL when assigning to a row.
7011 : *
7012 : * tupdesc describes the input row, which might have different column
7013 : * types and/or different dropped-column positions than the target.
7014 : * values/nulls/tupdesc can all be NULL if we just want to assign nulls to
7015 : * all fields of the record or row.
7016 : *
7017 : * Since this uses the mcontext for workspace, caller should eventually call
7018 : * exec_eval_cleanup to prevent long-term memory leaks.
7019 : */
7020 : static void
7021 54280 : exec_move_row_from_fields(PLpgSQL_execstate *estate,
7022 : PLpgSQL_variable *target,
7023 : ExpandedRecordHeader *newerh,
7024 : Datum *values, bool *nulls,
7025 : TupleDesc tupdesc)
7026 : {
7027 54280 : int td_natts = tupdesc ? tupdesc->natts : 0;
7028 : int fnum;
7029 : int anum;
7030 54280 : int strict_multiassignment_level = 0;
7031 :
7032 : /*
7033 : * The extra check strict strict_multi_assignment can be active, only when
7034 : * input tupdesc is specified.
7035 : */
7036 54280 : if (tupdesc != NULL)
7037 : {
7038 54092 : if (plpgsql_extra_errors & PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT)
7039 36 : strict_multiassignment_level = ERROR;
7040 54056 : else if (plpgsql_extra_warnings & PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT)
7041 18 : strict_multiassignment_level = WARNING;
7042 : }
7043 :
7044 : /* Handle RECORD-target case */
7045 54280 : if (target->dtype == PLPGSQL_DTYPE_REC)
7046 : {
7047 116 : PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7048 : TupleDesc var_tupdesc;
7049 : Datum newvalues_local[64];
7050 : bool newnulls_local[64];
7051 :
7052 : Assert(newerh != NULL); /* caller must have built new object */
7053 :
7054 116 : var_tupdesc = expanded_record_get_tupdesc(newerh);
7055 :
7056 : /*
7057 : * Coerce field values if needed. This might involve dealing with
7058 : * different sets of dropped columns and/or coercing individual column
7059 : * types. That's sort of a pain, but historically plpgsql has allowed
7060 : * it, so we preserve the behavior. However, it's worth a quick check
7061 : * to see if the tupdescs are identical. (Since expandedrecord.c
7062 : * prefers to use refcounted tupdescs from the typcache, expanded
7063 : * records with the same rowtype will have pointer-equal tupdescs.)
7064 : */
7065 116 : if (var_tupdesc != tupdesc)
7066 : {
7067 102 : int vtd_natts = var_tupdesc->natts;
7068 : Datum *newvalues;
7069 : bool *newnulls;
7070 :
7071 : /*
7072 : * Need workspace arrays. If vtd_natts is small enough, use local
7073 : * arrays to save doing a palloc. Even if it's not small, we can
7074 : * allocate both the Datum and isnull arrays in one palloc chunk.
7075 : */
7076 102 : if (vtd_natts <= lengthof(newvalues_local))
7077 : {
7078 102 : newvalues = newvalues_local;
7079 102 : newnulls = newnulls_local;
7080 : }
7081 : else
7082 : {
7083 : char *chunk;
7084 :
7085 0 : chunk = eval_mcontext_alloc(estate,
7086 : vtd_natts * (sizeof(Datum) + sizeof(bool)));
7087 0 : newvalues = (Datum *) chunk;
7088 0 : newnulls = (bool *) (chunk + vtd_natts * sizeof(Datum));
7089 : }
7090 :
7091 : /* Walk over destination columns */
7092 102 : anum = 0;
7093 318 : for (fnum = 0; fnum < vtd_natts; fnum++)
7094 : {
7095 224 : Form_pg_attribute attr = TupleDescAttr(var_tupdesc, fnum);
7096 : Datum value;
7097 : bool isnull;
7098 : Oid valtype;
7099 : int32 valtypmod;
7100 :
7101 224 : if (attr->attisdropped)
7102 : {
7103 : /* expanded_record_set_fields should ignore this column */
7104 20 : continue; /* skip dropped column in record */
7105 : }
7106 :
7107 204 : while (anum < td_natts &&
7108 198 : TupleDescAttr(tupdesc, anum)->attisdropped)
7109 0 : anum++; /* skip dropped column in tuple */
7110 :
7111 204 : if (anum < td_natts)
7112 : {
7113 198 : value = values[anum];
7114 198 : isnull = nulls[anum];
7115 198 : valtype = TupleDescAttr(tupdesc, anum)->atttypid;
7116 198 : valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
7117 198 : anum++;
7118 : }
7119 : else
7120 : {
7121 : /* no source for destination column */
7122 6 : value = (Datum) 0;
7123 6 : isnull = true;
7124 6 : valtype = UNKNOWNOID;
7125 6 : valtypmod = -1;
7126 :
7127 : /* When source value is missing */
7128 6 : if (strict_multiassignment_level)
7129 6 : ereport(strict_multiassignment_level,
7130 : (errcode(ERRCODE_DATATYPE_MISMATCH),
7131 : errmsg("number of source and target fields in assignment does not match"),
7132 : /* translator: %s represents a name of an extra check */
7133 : errdetail("%s check of %s is active.",
7134 : "strict_multi_assignment",
7135 : strict_multiassignment_level == ERROR ? "extra_errors" :
7136 : "extra_warnings"),
7137 : errhint("Make sure the query returns the exact list of columns.")));
7138 : }
7139 :
7140 : /* Cast the new value to the right type, if needed. */
7141 198 : newvalues[fnum] = exec_cast_value(estate,
7142 : value,
7143 : &isnull,
7144 : valtype,
7145 : valtypmod,
7146 : attr->atttypid,
7147 : attr->atttypmod);
7148 196 : newnulls[fnum] = isnull;
7149 : }
7150 :
7151 : /*
7152 : * When strict_multiassignment extra check is active, then ensure
7153 : * there are no unassigned source attributes.
7154 : */
7155 94 : if (strict_multiassignment_level && anum < td_natts)
7156 : {
7157 : /* skip dropped columns in the source descriptor */
7158 6 : while (anum < td_natts &&
7159 6 : TupleDescAttr(tupdesc, anum)->attisdropped)
7160 0 : anum++;
7161 :
7162 6 : if (anum < td_natts)
7163 6 : ereport(strict_multiassignment_level,
7164 : (errcode(ERRCODE_DATATYPE_MISMATCH),
7165 : errmsg("number of source and target fields in assignment does not match"),
7166 : /* translator: %s represents a name of an extra check */
7167 : errdetail("%s check of %s is active.",
7168 : "strict_multi_assignment",
7169 : strict_multiassignment_level == ERROR ? "extra_errors" :
7170 : "extra_warnings"),
7171 : errhint("Make sure the query returns the exact list of columns.")));
7172 : }
7173 :
7174 88 : values = newvalues;
7175 88 : nulls = newnulls;
7176 : }
7177 :
7178 : /* Insert the coerced field values into the new expanded record */
7179 102 : expanded_record_set_fields(newerh, values, nulls, !estate->atomic);
7180 :
7181 : /* Complete the assignment */
7182 94 : assign_record_var(estate, rec, newerh);
7183 :
7184 94 : return;
7185 : }
7186 :
7187 : /* newerh should not have been passed in non-RECORD cases */
7188 : Assert(newerh == NULL);
7189 :
7190 : /*
7191 : * For a row, we assign the individual field values to the variables the
7192 : * row points to.
7193 : *
7194 : * NOTE: both this code and the record code above silently ignore extra
7195 : * columns in the source and assume NULL for missing columns. This is
7196 : * pretty dubious but it's the historical behavior.
7197 : *
7198 : * If we have no input data at all, we'll assign NULL to all columns of
7199 : * the row variable.
7200 : */
7201 54164 : if (target->dtype == PLPGSQL_DTYPE_ROW)
7202 : {
7203 54164 : PLpgSQL_row *row = (PLpgSQL_row *) target;
7204 :
7205 54164 : anum = 0;
7206 114576 : for (fnum = 0; fnum < row->nfields; fnum++)
7207 : {
7208 : PLpgSQL_var *var;
7209 : Datum value;
7210 : bool isnull;
7211 : Oid valtype;
7212 : int32 valtypmod;
7213 :
7214 60418 : var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
7215 :
7216 60418 : while (anum < td_natts &&
7217 60212 : TupleDescAttr(tupdesc, anum)->attisdropped)
7218 0 : anum++; /* skip dropped column in tuple */
7219 :
7220 60418 : if (anum < td_natts)
7221 : {
7222 60212 : value = values[anum];
7223 60212 : isnull = nulls[anum];
7224 60212 : valtype = TupleDescAttr(tupdesc, anum)->atttypid;
7225 60212 : valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
7226 60212 : anum++;
7227 : }
7228 : else
7229 : {
7230 : /* no source for destination column */
7231 206 : value = (Datum) 0;
7232 206 : isnull = true;
7233 206 : valtype = UNKNOWNOID;
7234 206 : valtypmod = -1;
7235 :
7236 206 : if (strict_multiassignment_level)
7237 12 : ereport(strict_multiassignment_level,
7238 : (errcode(ERRCODE_DATATYPE_MISMATCH),
7239 : errmsg("number of source and target fields in assignment does not match"),
7240 : /* translator: %s represents a name of an extra check */
7241 : errdetail("%s check of %s is active.",
7242 : "strict_multi_assignment",
7243 : strict_multiassignment_level == ERROR ? "extra_errors" :
7244 : "extra_warnings"),
7245 : errhint("Make sure the query returns the exact list of columns.")));
7246 : }
7247 :
7248 60412 : exec_assign_value(estate, (PLpgSQL_datum *) var,
7249 : value, isnull, valtype, valtypmod);
7250 : }
7251 :
7252 : /*
7253 : * When strict_multiassignment extra check is active, ensure there are
7254 : * no unassigned source attributes.
7255 : */
7256 54158 : if (strict_multiassignment_level && anum < td_natts)
7257 : {
7258 12 : while (anum < td_natts &&
7259 12 : TupleDescAttr(tupdesc, anum)->attisdropped)
7260 0 : anum++; /* skip dropped column in tuple */
7261 :
7262 12 : if (anum < td_natts)
7263 12 : ereport(strict_multiassignment_level,
7264 : (errcode(ERRCODE_DATATYPE_MISMATCH),
7265 : errmsg("number of source and target fields in assignment does not match"),
7266 : /* translator: %s represents a name of an extra check */
7267 : errdetail("%s check of %s is active.",
7268 : "strict_multi_assignment",
7269 : strict_multiassignment_level == ERROR ? "extra_errors" :
7270 : "extra_warnings"),
7271 : errhint("Make sure the query returns the exact list of columns.")));
7272 : }
7273 :
7274 54152 : return;
7275 : }
7276 :
7277 0 : elog(ERROR, "unsupported target type: %d", target->dtype);
7278 : }
7279 :
7280 : /*
7281 : * compatible_tupdescs: detect whether two tupdescs are physically compatible
7282 : *
7283 : * TRUE indicates that a tuple satisfying src_tupdesc can be used directly as
7284 : * a value for a composite variable using dst_tupdesc.
7285 : */
7286 : static bool
7287 238 : compatible_tupdescs(TupleDesc src_tupdesc, TupleDesc dst_tupdesc)
7288 : {
7289 : int i;
7290 :
7291 : /* Possibly we could allow src_tupdesc to have extra columns? */
7292 238 : if (dst_tupdesc->natts != src_tupdesc->natts)
7293 22 : return false;
7294 :
7295 558 : for (i = 0; i < dst_tupdesc->natts; i++)
7296 : {
7297 422 : Form_pg_attribute dattr = TupleDescAttr(dst_tupdesc, i);
7298 422 : Form_pg_attribute sattr = TupleDescAttr(src_tupdesc, i);
7299 :
7300 422 : if (dattr->attisdropped != sattr->attisdropped)
7301 6 : return false;
7302 416 : if (!dattr->attisdropped)
7303 : {
7304 : /* Normal columns must match by type and typmod */
7305 416 : if (dattr->atttypid != sattr->atttypid ||
7306 342 : (dattr->atttypmod >= 0 &&
7307 12 : dattr->atttypmod != sattr->atttypmod))
7308 74 : return false;
7309 : }
7310 : else
7311 : {
7312 : /* Dropped columns are OK as long as length/alignment match */
7313 0 : if (dattr->attlen != sattr->attlen ||
7314 0 : dattr->attalign != sattr->attalign)
7315 0 : return false;
7316 : }
7317 : }
7318 136 : return true;
7319 : }
7320 :
7321 : /* ----------
7322 : * make_tuple_from_row Make a tuple from the values of a row object
7323 : *
7324 : * A NULL return indicates rowtype mismatch; caller must raise suitable error
7325 : *
7326 : * The result tuple is freshly palloc'd in caller's context. Some junk
7327 : * may be left behind in eval_mcontext, too.
7328 : * ----------
7329 : */
7330 : static HeapTuple
7331 6236 : make_tuple_from_row(PLpgSQL_execstate *estate,
7332 : PLpgSQL_row *row,
7333 : TupleDesc tupdesc)
7334 : {
7335 6236 : int natts = tupdesc->natts;
7336 : HeapTuple tuple;
7337 : Datum *dvalues;
7338 : bool *nulls;
7339 : int i;
7340 :
7341 6236 : if (natts != row->nfields)
7342 0 : return NULL;
7343 :
7344 6236 : dvalues = (Datum *) eval_mcontext_alloc0(estate, natts * sizeof(Datum));
7345 6236 : nulls = (bool *) eval_mcontext_alloc(estate, natts * sizeof(bool));
7346 :
7347 24634 : for (i = 0; i < natts; i++)
7348 : {
7349 : Oid fieldtypeid;
7350 : int32 fieldtypmod;
7351 :
7352 18398 : if (TupleDescAttr(tupdesc, i)->attisdropped)
7353 : {
7354 0 : nulls[i] = true; /* leave the column as null */
7355 0 : continue;
7356 : }
7357 :
7358 18398 : exec_eval_datum(estate, estate->datums[row->varnos[i]],
7359 : &fieldtypeid, &fieldtypmod,
7360 18398 : &dvalues[i], &nulls[i]);
7361 18398 : if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid)
7362 0 : return NULL;
7363 : /* XXX should we insist on typmod match, too? */
7364 : }
7365 :
7366 6236 : tuple = heap_form_tuple(tupdesc, dvalues, nulls);
7367 :
7368 6236 : return tuple;
7369 : }
7370 :
7371 : /*
7372 : * deconstruct_composite_datum extract tuple+tupdesc from composite Datum
7373 : *
7374 : * The caller must supply a HeapTupleData variable, in which we set up a
7375 : * tuple header pointing to the composite datum's body. To make the tuple
7376 : * value outlive that variable, caller would need to apply heap_copytuple...
7377 : * but current callers only need a short-lived tuple value anyway.
7378 : *
7379 : * Returns a pointer to the TupleDesc of the datum's rowtype.
7380 : * Caller is responsible for calling ReleaseTupleDesc when done with it.
7381 : *
7382 : * Note: it's caller's responsibility to be sure value is of composite type.
7383 : * Also, best to call this in a short-lived context, as it might leak memory.
7384 : */
7385 : static TupleDesc
7386 6614 : deconstruct_composite_datum(Datum value, HeapTupleData *tmptup)
7387 : {
7388 : HeapTupleHeader td;
7389 : Oid tupType;
7390 : int32 tupTypmod;
7391 :
7392 : /* Get tuple body (note this could involve detoasting) */
7393 6614 : td = DatumGetHeapTupleHeader(value);
7394 :
7395 : /* Build a temporary HeapTuple control structure */
7396 6614 : tmptup->t_len = HeapTupleHeaderGetDatumLength(td);
7397 6614 : ItemPointerSetInvalid(&(tmptup->t_self));
7398 6614 : tmptup->t_tableOid = InvalidOid;
7399 6614 : tmptup->t_data = td;
7400 :
7401 : /* Extract rowtype info and find a tupdesc */
7402 6614 : tupType = HeapTupleHeaderGetTypeId(td);
7403 6614 : tupTypmod = HeapTupleHeaderGetTypMod(td);
7404 6614 : return lookup_rowtype_tupdesc(tupType, tupTypmod);
7405 : }
7406 :
7407 : /*
7408 : * exec_move_row_from_datum Move a composite Datum into a record or row
7409 : *
7410 : * This is equivalent to deconstruct_composite_datum() followed by
7411 : * exec_move_row(), but we can optimize things if the Datum is an
7412 : * expanded-record reference.
7413 : *
7414 : * Note: it's caller's responsibility to be sure value is of composite type.
7415 : */
7416 : static void
7417 904 : exec_move_row_from_datum(PLpgSQL_execstate *estate,
7418 : PLpgSQL_variable *target,
7419 : Datum value)
7420 : {
7421 : /* Check to see if source is an expanded record */
7422 904 : if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
7423 20 : {
7424 332 : ExpandedRecordHeader *erh = (ExpandedRecordHeader *) DatumGetEOHP(value);
7425 332 : ExpandedRecordHeader *newerh = NULL;
7426 :
7427 : Assert(erh->er_magic == ER_MAGIC);
7428 :
7429 : /* These cases apply if the target is record not row... */
7430 332 : if (target->dtype == PLPGSQL_DTYPE_REC)
7431 : {
7432 332 : PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7433 :
7434 : /*
7435 : * If it's the same record already stored in the variable, do
7436 : * nothing. This would happen only in silly cases like "r := r",
7437 : * but we need some check to avoid possibly freeing the variable's
7438 : * live value below. Note that this applies even if what we have
7439 : * is a R/O pointer.
7440 : */
7441 332 : if (erh == rec->erh)
7442 2 : return;
7443 :
7444 : /*
7445 : * Make sure rec->rectypeid is up-to-date before using it.
7446 : */
7447 330 : revalidate_rectypeid(rec);
7448 :
7449 : /*
7450 : * If we have a R/W pointer, we're allowed to just commandeer
7451 : * ownership of the expanded record. If it's of the right type to
7452 : * put into the record variable, do that. (Note we don't accept
7453 : * an expanded record of a composite-domain type as a RECORD
7454 : * value. We'll treat it as the base composite type instead;
7455 : * compare logic in make_expanded_record_for_rec.)
7456 : */
7457 330 : if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(value)) &&
7458 6 : (rec->rectypeid == erh->er_decltypeid ||
7459 2 : (rec->rectypeid == RECORDOID &&
7460 2 : !ExpandedRecordIsDomain(erh))))
7461 : {
7462 6 : assign_record_var(estate, rec, erh);
7463 6 : return;
7464 : }
7465 :
7466 : /*
7467 : * If we already have an expanded record object in the target
7468 : * variable, and the source record contains a valid tuple
7469 : * representation with the right rowtype, then we can skip making
7470 : * a new expanded record and just assign the tuple with
7471 : * expanded_record_set_tuple. (We can't do the equivalent if we
7472 : * have to do field-by-field assignment, since that wouldn't be
7473 : * atomic if there's an error.) We consider that there's a
7474 : * rowtype match only if it's the same named composite type or
7475 : * same registered rowtype; checking for matches of anonymous
7476 : * rowtypes would be more expensive than this is worth.
7477 : */
7478 324 : if (rec->erh &&
7479 8 : (erh->flags & ER_FLAG_FVALUE_VALID) &&
7480 4 : erh->er_typeid == rec->erh->er_typeid &&
7481 2 : (erh->er_typeid != RECORDOID ||
7482 0 : (erh->er_typmod == rec->erh->er_typmod &&
7483 0 : erh->er_typmod >= 0)))
7484 : {
7485 2 : expanded_record_set_tuple(rec->erh, erh->fvalue,
7486 2 : true, !estate->atomic);
7487 2 : return;
7488 : }
7489 :
7490 : /*
7491 : * Otherwise we're gonna need a new expanded record object. Make
7492 : * it here in hopes of piggybacking on the source object's
7493 : * previous typcache lookup.
7494 : */
7495 322 : newerh = make_expanded_record_for_rec(estate, rec, NULL, erh);
7496 :
7497 : /*
7498 : * If the expanded record contains a valid tuple representation,
7499 : * and we don't need rowtype conversion, then just copying the
7500 : * tuple is probably faster than field-by-field processing. (This
7501 : * isn't duplicative of the previous check, since here we will
7502 : * catch the case where the record variable was previously empty.)
7503 : */
7504 322 : if ((erh->flags & ER_FLAG_FVALUE_VALID) &&
7505 304 : (rec->rectypeid == RECORDOID ||
7506 8 : rec->rectypeid == erh->er_typeid))
7507 : {
7508 302 : expanded_record_set_tuple(newerh, erh->fvalue,
7509 302 : true, !estate->atomic);
7510 302 : assign_record_var(estate, rec, newerh);
7511 302 : return;
7512 : }
7513 :
7514 : /*
7515 : * Need to special-case empty source record, else code below would
7516 : * leak newerh.
7517 : */
7518 20 : if (ExpandedRecordIsEmpty(erh))
7519 : {
7520 : /* Set newerh to a row of NULLs */
7521 0 : deconstruct_expanded_record(newerh);
7522 0 : assign_record_var(estate, rec, newerh);
7523 0 : return;
7524 : }
7525 : } /* end of record-target-only cases */
7526 :
7527 : /*
7528 : * If the source expanded record is empty, we should treat that like a
7529 : * NULL tuple value. (We're unlikely to see such a case, but we must
7530 : * check this; deconstruct_expanded_record would cause a change of
7531 : * logical state, which is not OK.)
7532 : */
7533 20 : if (ExpandedRecordIsEmpty(erh))
7534 : {
7535 0 : exec_move_row(estate, target, NULL,
7536 : expanded_record_get_tupdesc(erh));
7537 0 : return;
7538 : }
7539 :
7540 : /*
7541 : * Otherwise, ensure that the source record is deconstructed, and
7542 : * assign from its field values.
7543 : */
7544 20 : deconstruct_expanded_record(erh);
7545 20 : exec_move_row_from_fields(estate, target, newerh,
7546 : erh->dvalues, erh->dnulls,
7547 : expanded_record_get_tupdesc(erh));
7548 : }
7549 : else
7550 : {
7551 : /*
7552 : * Nope, we've got a plain composite Datum. Deconstruct it; but we
7553 : * don't use deconstruct_composite_datum(), because we may be able to
7554 : * skip calling lookup_rowtype_tupdesc().
7555 : */
7556 : HeapTupleHeader td;
7557 : HeapTupleData tmptup;
7558 : Oid tupType;
7559 : int32 tupTypmod;
7560 : TupleDesc tupdesc;
7561 : MemoryContext oldcontext;
7562 :
7563 : /* Ensure that any detoasted data winds up in the eval_mcontext */
7564 572 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7565 : /* Get tuple body (note this could involve detoasting) */
7566 572 : td = DatumGetHeapTupleHeader(value);
7567 572 : MemoryContextSwitchTo(oldcontext);
7568 :
7569 : /* Build a temporary HeapTuple control structure */
7570 572 : tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
7571 572 : ItemPointerSetInvalid(&(tmptup.t_self));
7572 572 : tmptup.t_tableOid = InvalidOid;
7573 572 : tmptup.t_data = td;
7574 :
7575 : /* Extract rowtype info */
7576 572 : tupType = HeapTupleHeaderGetTypeId(td);
7577 572 : tupTypmod = HeapTupleHeaderGetTypMod(td);
7578 :
7579 : /* Now, if the target is record not row, maybe we can optimize ... */
7580 572 : if (target->dtype == PLPGSQL_DTYPE_REC)
7581 : {
7582 530 : PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7583 :
7584 : /*
7585 : * If we already have an expanded record object in the target
7586 : * variable, and the source datum has a matching rowtype, then we
7587 : * can skip making a new expanded record and just assign the tuple
7588 : * with expanded_record_set_tuple. We consider that there's a
7589 : * rowtype match only if it's the same named composite type or
7590 : * same registered rowtype. (Checking to reject an anonymous
7591 : * rowtype here should be redundant, but let's be safe.)
7592 : */
7593 530 : if (rec->erh &&
7594 160 : tupType == rec->erh->er_typeid &&
7595 4 : (tupType != RECORDOID ||
7596 4 : (tupTypmod == rec->erh->er_typmod &&
7597 : tupTypmod >= 0)))
7598 : {
7599 132 : expanded_record_set_tuple(rec->erh, &tmptup,
7600 132 : true, !estate->atomic);
7601 434 : return;
7602 : }
7603 :
7604 : /*
7605 : * If the source datum has a rowtype compatible with the target
7606 : * variable, just build a new expanded record and assign the tuple
7607 : * into it. Using make_expanded_record_from_typeid() here saves
7608 : * one typcache lookup compared to the code below.
7609 : */
7610 398 : if (rec->rectypeid == RECORDOID || rec->rectypeid == tupType)
7611 : {
7612 : ExpandedRecordHeader *newerh;
7613 302 : MemoryContext mcontext = get_eval_mcontext(estate);
7614 :
7615 302 : newerh = make_expanded_record_from_typeid(tupType, tupTypmod,
7616 : mcontext);
7617 302 : expanded_record_set_tuple(newerh, &tmptup,
7618 302 : true, !estate->atomic);
7619 302 : assign_record_var(estate, rec, newerh);
7620 302 : return;
7621 : }
7622 :
7623 : /*
7624 : * Otherwise, we're going to need conversion, so fall through to
7625 : * do it the hard way.
7626 : */
7627 : }
7628 :
7629 : /*
7630 : * ROW target, or unoptimizable RECORD target, so we have to expend a
7631 : * lookup to obtain the source datum's tupdesc.
7632 : */
7633 138 : tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
7634 :
7635 : /* Do the move */
7636 138 : exec_move_row(estate, target, &tmptup, tupdesc);
7637 :
7638 : /* Release tupdesc usage count */
7639 124 : ReleaseTupleDesc(tupdesc);
7640 : }
7641 : }
7642 :
7643 : /*
7644 : * If we have not created an expanded record to hold the record variable's
7645 : * value, do so. The expanded record will be "empty", so this does not
7646 : * change the logical state of the record variable: it's still NULL.
7647 : * However, now we'll have a tupdesc with which we can e.g. look up fields.
7648 : */
7649 : static void
7650 110 : instantiate_empty_record_variable(PLpgSQL_execstate *estate, PLpgSQL_rec *rec)
7651 : {
7652 : Assert(rec->erh == NULL); /* else caller error */
7653 :
7654 : /* If declared type is RECORD, we can't instantiate */
7655 110 : if (rec->rectypeid == RECORDOID)
7656 4 : ereport(ERROR,
7657 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7658 : errmsg("record \"%s\" is not assigned yet", rec->refname),
7659 : errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
7660 :
7661 : /* Make sure rec->rectypeid is up-to-date before using it */
7662 106 : revalidate_rectypeid(rec);
7663 :
7664 : /* OK, do it */
7665 104 : rec->erh = make_expanded_record_from_typeid(rec->rectypeid, -1,
7666 : estate->datum_context);
7667 104 : }
7668 :
7669 : /* ----------
7670 : * convert_value_to_string Convert a non-null Datum to C string
7671 : *
7672 : * Note: the result is in the estate's eval_mcontext, and will be cleared
7673 : * by the next exec_eval_cleanup() call. The invoked output function might
7674 : * leave additional cruft there as well, so just pfree'ing the result string
7675 : * would not be enough to avoid memory leaks if we did not do it like this.
7676 : * In most usages the Datum being passed in is also in that context (if
7677 : * pass-by-reference) and so an exec_eval_cleanup() call is needed anyway.
7678 : *
7679 : * Note: not caching the conversion function lookup is bad for performance.
7680 : * However, this function isn't currently used in any places where an extra
7681 : * catalog lookup or two seems like a big deal.
7682 : * ----------
7683 : */
7684 : static char *
7685 55962 : convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
7686 : {
7687 : char *result;
7688 : MemoryContext oldcontext;
7689 : Oid typoutput;
7690 : bool typIsVarlena;
7691 :
7692 55962 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7693 55962 : getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
7694 55962 : result = OidOutputFunctionCall(typoutput, value);
7695 55962 : MemoryContextSwitchTo(oldcontext);
7696 :
7697 55962 : return result;
7698 : }
7699 :
7700 : /* ----------
7701 : * exec_cast_value Cast a value if required
7702 : *
7703 : * Note that *isnull is an input and also an output parameter. While it's
7704 : * unlikely that a cast operation would produce null from non-null or vice
7705 : * versa, that could happen in principle.
7706 : *
7707 : * Note: the estate's eval_mcontext is used for temporary storage, and may
7708 : * also contain the result Datum if we have to do a conversion to a pass-
7709 : * by-reference data type. Be sure to do an exec_eval_cleanup() call when
7710 : * done with the result.
7711 : * ----------
7712 : */
7713 : static inline Datum
7714 314656 : exec_cast_value(PLpgSQL_execstate *estate,
7715 : Datum value, bool *isnull,
7716 : Oid valtype, int32 valtypmod,
7717 : Oid reqtype, int32 reqtypmod)
7718 : {
7719 : /*
7720 : * If the type of the given value isn't what's requested, convert it.
7721 : */
7722 314656 : if (valtype != reqtype ||
7723 0 : (valtypmod != reqtypmod && reqtypmod != -1))
7724 : {
7725 : /* We keep the slow path out-of-line. */
7726 3254 : value = do_cast_value(estate, value, isnull, valtype, valtypmod,
7727 : reqtype, reqtypmod);
7728 : }
7729 :
7730 314590 : return value;
7731 : }
7732 :
7733 : /* ----------
7734 : * do_cast_value Slow path for exec_cast_value.
7735 : * ----------
7736 : */
7737 : static Datum
7738 3254 : do_cast_value(PLpgSQL_execstate *estate,
7739 : Datum value, bool *isnull,
7740 : Oid valtype, int32 valtypmod,
7741 : Oid reqtype, int32 reqtypmod)
7742 : {
7743 : plpgsql_CastHashEntry *cast_entry;
7744 :
7745 3254 : cast_entry = get_cast_hashentry(estate,
7746 : valtype, valtypmod,
7747 : reqtype, reqtypmod);
7748 3254 : if (cast_entry)
7749 : {
7750 3254 : ExprContext *econtext = estate->eval_econtext;
7751 : MemoryContext oldcontext;
7752 :
7753 3254 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7754 :
7755 3254 : econtext->caseValue_datum = value;
7756 3254 : econtext->caseValue_isNull = *isnull;
7757 :
7758 3254 : cast_entry->cast_in_use = true;
7759 :
7760 3254 : value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
7761 : isnull);
7762 :
7763 3188 : cast_entry->cast_in_use = false;
7764 :
7765 3188 : MemoryContextSwitchTo(oldcontext);
7766 : }
7767 :
7768 3188 : return value;
7769 : }
7770 :
7771 : /* ----------
7772 : * get_cast_hashentry Look up how to perform a type cast
7773 : *
7774 : * Returns a plpgsql_CastHashEntry if an expression has to be evaluated,
7775 : * or NULL if the cast is a mere no-op relabeling. If there's work to be
7776 : * done, the cast_exprstate field contains an expression evaluation tree
7777 : * based on a CaseTestExpr input, and the cast_in_use field should be set
7778 : * true while executing it.
7779 : * ----------
7780 : */
7781 : static plpgsql_CastHashEntry *
7782 3254 : get_cast_hashentry(PLpgSQL_execstate *estate,
7783 : Oid srctype, int32 srctypmod,
7784 : Oid dsttype, int32 dsttypmod)
7785 : {
7786 : plpgsql_CastHashKey cast_key;
7787 : plpgsql_CastHashEntry *cast_entry;
7788 : plpgsql_CastExprHashEntry *expr_entry;
7789 : bool found;
7790 : LocalTransactionId curlxid;
7791 : MemoryContext oldcontext;
7792 :
7793 : /* Look for existing entry */
7794 3254 : cast_key.srctype = srctype;
7795 3254 : cast_key.dsttype = dsttype;
7796 3254 : cast_key.srctypmod = srctypmod;
7797 3254 : cast_key.dsttypmod = dsttypmod;
7798 3254 : cast_entry = (plpgsql_CastHashEntry *) hash_search(estate->cast_hash,
7799 : &cast_key,
7800 : HASH_ENTER, &found);
7801 3254 : if (!found) /* initialize if new entry */
7802 : {
7803 : /* We need a second lookup to see if a cast_expr_hash entry exists */
7804 368 : expr_entry = (plpgsql_CastExprHashEntry *) hash_search(cast_expr_hash,
7805 : &cast_key,
7806 : HASH_ENTER,
7807 : &found);
7808 368 : if (!found) /* initialize if new expr entry */
7809 308 : expr_entry->cast_cexpr = NULL;
7810 :
7811 368 : cast_entry->cast_centry = expr_entry;
7812 368 : cast_entry->cast_exprstate = NULL;
7813 368 : cast_entry->cast_in_use = false;
7814 368 : cast_entry->cast_lxid = InvalidLocalTransactionId;
7815 : }
7816 : else
7817 : {
7818 : /* Use always-valid link to avoid a second hash lookup */
7819 2886 : expr_entry = cast_entry->cast_centry;
7820 : }
7821 :
7822 3254 : if (expr_entry->cast_cexpr == NULL ||
7823 2946 : !expr_entry->cast_cexpr->is_valid)
7824 : {
7825 : /*
7826 : * We've not looked up this coercion before, or we have but the cached
7827 : * expression has been invalidated.
7828 : */
7829 : Node *cast_expr;
7830 : CachedExpression *cast_cexpr;
7831 : CaseTestExpr *placeholder;
7832 :
7833 : /*
7834 : * Drop old cached expression if there is one.
7835 : */
7836 354 : if (expr_entry->cast_cexpr)
7837 : {
7838 46 : FreeCachedExpression(expr_entry->cast_cexpr);
7839 46 : expr_entry->cast_cexpr = NULL;
7840 : }
7841 :
7842 : /*
7843 : * Since we could easily fail (no such coercion), construct a
7844 : * temporary coercion expression tree in the short-lived
7845 : * eval_mcontext, then if successful save it as a CachedExpression.
7846 : */
7847 354 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7848 :
7849 : /*
7850 : * We use a CaseTestExpr as the base of the coercion tree, since it's
7851 : * very cheap to insert the source value for that.
7852 : */
7853 354 : placeholder = makeNode(CaseTestExpr);
7854 354 : placeholder->typeId = srctype;
7855 354 : placeholder->typeMod = srctypmod;
7856 354 : placeholder->collation = get_typcollation(srctype);
7857 :
7858 : /*
7859 : * Apply coercion. We use the special coercion context
7860 : * COERCION_PLPGSQL to match plpgsql's historical behavior, namely
7861 : * that any cast not available at ASSIGNMENT level will be implemented
7862 : * as an I/O coercion. (It's somewhat dubious that we prefer I/O
7863 : * coercion over cast pathways that exist at EXPLICIT level. Changing
7864 : * that would cause assorted minor behavioral differences though, and
7865 : * a user who wants the explicit-cast behavior can always write an
7866 : * explicit cast.)
7867 : *
7868 : * If source type is UNKNOWN, coerce_to_target_type will fail (it only
7869 : * expects to see that for Const input nodes), so don't call it; we'll
7870 : * apply CoerceViaIO instead. Likewise, it doesn't currently work for
7871 : * coercing RECORD to some other type, so skip for that too.
7872 : */
7873 354 : if (srctype == UNKNOWNOID || srctype == RECORDOID)
7874 106 : cast_expr = NULL;
7875 : else
7876 248 : cast_expr = coerce_to_target_type(NULL,
7877 : (Node *) placeholder, srctype,
7878 : dsttype, dsttypmod,
7879 : COERCION_PLPGSQL,
7880 : COERCE_IMPLICIT_CAST,
7881 : -1);
7882 :
7883 : /*
7884 : * If there's no cast path according to the parser, fall back to using
7885 : * an I/O coercion; this is semantically dubious but matches plpgsql's
7886 : * historical behavior. We would need something of the sort for
7887 : * UNKNOWN literals in any case. (This is probably now only reachable
7888 : * in the case where srctype is UNKNOWN/RECORD.)
7889 : */
7890 354 : if (cast_expr == NULL)
7891 : {
7892 106 : CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
7893 :
7894 106 : iocoerce->arg = (Expr *) placeholder;
7895 106 : iocoerce->resulttype = dsttype;
7896 106 : iocoerce->resultcollid = InvalidOid;
7897 106 : iocoerce->coerceformat = COERCE_IMPLICIT_CAST;
7898 106 : iocoerce->location = -1;
7899 106 : cast_expr = (Node *) iocoerce;
7900 106 : if (dsttypmod != -1)
7901 0 : cast_expr = coerce_to_target_type(NULL,
7902 : cast_expr, dsttype,
7903 : dsttype, dsttypmod,
7904 : COERCION_ASSIGNMENT,
7905 : COERCE_IMPLICIT_CAST,
7906 : -1);
7907 : }
7908 :
7909 : /* Note: we don't bother labeling the expression tree with collation */
7910 :
7911 : /* Plan the expression and build a CachedExpression */
7912 354 : cast_cexpr = GetCachedExpression(cast_expr);
7913 354 : cast_expr = cast_cexpr->expr;
7914 :
7915 : /* Detect whether we have a no-op (RelabelType) coercion */
7916 354 : if (IsA(cast_expr, RelabelType) &&
7917 20 : ((RelabelType *) cast_expr)->arg == (Expr *) placeholder)
7918 0 : cast_expr = NULL;
7919 :
7920 : /* Now we can fill in the expression hashtable entry. */
7921 354 : expr_entry->cast_cexpr = cast_cexpr;
7922 354 : expr_entry->cast_expr = (Expr *) cast_expr;
7923 :
7924 : /* Be sure to reset the exprstate hashtable entry, too. */
7925 354 : cast_entry->cast_exprstate = NULL;
7926 354 : cast_entry->cast_in_use = false;
7927 354 : cast_entry->cast_lxid = InvalidLocalTransactionId;
7928 :
7929 354 : MemoryContextSwitchTo(oldcontext);
7930 : }
7931 :
7932 : /* Done if we have determined that this is a no-op cast. */
7933 3254 : if (expr_entry->cast_expr == NULL)
7934 0 : return NULL;
7935 :
7936 : /*
7937 : * Prepare the expression for execution, if it's not been done already in
7938 : * the current transaction; also, if it's marked busy in the current
7939 : * transaction, abandon that expression tree and build a new one, so as to
7940 : * avoid potential problems with recursive cast expressions and failed
7941 : * executions. (We will leak some memory intra-transaction if that
7942 : * happens a lot, but we don't expect it to.) It's okay to update the
7943 : * hash table with the new tree because all plpgsql functions within a
7944 : * given transaction share the same simple_eval_estate. (Well, regular
7945 : * functions do; DO blocks have private simple_eval_estates, and private
7946 : * cast hash tables to go with them.)
7947 : */
7948 3254 : curlxid = MyProc->vxid.lxid;
7949 3254 : if (cast_entry->cast_lxid != curlxid || cast_entry->cast_in_use)
7950 : {
7951 708 : oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
7952 708 : cast_entry->cast_exprstate = ExecInitExpr(expr_entry->cast_expr, NULL);
7953 708 : cast_entry->cast_in_use = false;
7954 708 : cast_entry->cast_lxid = curlxid;
7955 708 : MemoryContextSwitchTo(oldcontext);
7956 : }
7957 :
7958 3254 : return cast_entry;
7959 : }
7960 :
7961 :
7962 : /* ----------
7963 : * exec_simple_check_plan - Check if a plan is simple enough to
7964 : * be evaluated by ExecEvalExpr() instead
7965 : * of SPI.
7966 : *
7967 : * Note: the refcount manipulations in this function assume that expr->plan
7968 : * is a "saved" SPI plan. That's a bit annoying from the caller's standpoint,
7969 : * but it's otherwise difficult to avoid leaking the plan on failure.
7970 : * ----------
7971 : */
7972 : static void
7973 24496 : exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
7974 : {
7975 : List *plansources;
7976 : CachedPlanSource *plansource;
7977 : Query *query;
7978 : CachedPlan *cplan;
7979 : MemoryContext oldcontext;
7980 :
7981 : /*
7982 : * Initialize to "not simple".
7983 : */
7984 24496 : expr->expr_simple_expr = NULL;
7985 24496 : expr->expr_rw_param = NULL;
7986 :
7987 : /*
7988 : * Check the analyzed-and-rewritten form of the query to see if we will be
7989 : * able to treat it as a simple expression. Since this function is only
7990 : * called immediately after creating the CachedPlanSource, we need not
7991 : * worry about the query being stale.
7992 : */
7993 :
7994 : /*
7995 : * We can only test queries that resulted in exactly one CachedPlanSource
7996 : */
7997 24496 : plansources = SPI_plan_get_plan_sources(expr->plan);
7998 24496 : if (list_length(plansources) != 1)
7999 0 : return;
8000 24496 : plansource = (CachedPlanSource *) linitial(plansources);
8001 :
8002 : /*
8003 : * 1. There must be one single querytree.
8004 : */
8005 24496 : if (list_length(plansource->query_list) != 1)
8006 0 : return;
8007 24496 : query = (Query *) linitial(plansource->query_list);
8008 :
8009 : /*
8010 : * 2. It must be a plain SELECT query without any input tables
8011 : */
8012 24496 : if (!IsA(query, Query))
8013 0 : return;
8014 24496 : if (query->commandType != CMD_SELECT)
8015 1192 : return;
8016 23304 : if (query->rtable != NIL)
8017 1122 : return;
8018 :
8019 : /*
8020 : * 3. Can't have any subplans, aggregates, qual clauses either. (These
8021 : * tests should generally match what inline_function() checks before
8022 : * inlining a SQL function; otherwise, inlining could change our
8023 : * conclusion about whether an expression is simple, which we don't want.)
8024 : */
8025 22182 : if (query->hasAggs ||
8026 22182 : query->hasWindowFuncs ||
8027 22182 : query->hasTargetSRFs ||
8028 22152 : query->hasSubLinks ||
8029 21740 : query->cteList ||
8030 21740 : query->jointree->fromlist ||
8031 21740 : query->jointree->quals ||
8032 21740 : query->groupClause ||
8033 21740 : query->groupingSets ||
8034 21740 : query->havingQual ||
8035 21740 : query->windowClause ||
8036 21740 : query->distinctClause ||
8037 21740 : query->sortClause ||
8038 21740 : query->limitOffset ||
8039 21740 : query->limitCount ||
8040 21740 : query->setOperations)
8041 442 : return;
8042 :
8043 : /*
8044 : * 4. The query must have a single attribute as result
8045 : */
8046 21740 : if (list_length(query->targetList) != 1)
8047 104 : return;
8048 :
8049 : /*
8050 : * OK, we can treat it as a simple plan.
8051 : *
8052 : * Get the generic plan for the query. If replanning is needed, do that
8053 : * work in the eval_mcontext. (Note that replanning could throw an error,
8054 : * in which case the expr is left marked "not simple", which is fine.)
8055 : */
8056 21636 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8057 21636 : cplan = SPI_plan_get_cached_plan(expr->plan);
8058 21604 : MemoryContextSwitchTo(oldcontext);
8059 :
8060 : /* Can't fail, because we checked for a single CachedPlanSource above */
8061 : Assert(cplan != NULL);
8062 :
8063 : /*
8064 : * Verify that plancache.c thinks the plan is simple enough to use
8065 : * CachedPlanIsSimplyValid. Given the restrictions above, it's unlikely
8066 : * that this could fail, but if it does, just treat plan as not simple. On
8067 : * success, save a refcount on the plan in the simple-expression resowner.
8068 : */
8069 21604 : if (CachedPlanAllowsSimpleValidityCheck(plansource, cplan,
8070 : estate->simple_eval_resowner))
8071 : {
8072 : /* Remember that we have the refcount */
8073 21604 : expr->expr_simple_plansource = plansource;
8074 21604 : expr->expr_simple_plan = cplan;
8075 21604 : expr->expr_simple_plan_lxid = MyProc->vxid.lxid;
8076 :
8077 : /* Share the remaining work with the replan code path */
8078 21604 : exec_save_simple_expr(expr, cplan);
8079 : }
8080 :
8081 : /*
8082 : * Release the plan refcount obtained by SPI_plan_get_cached_plan. (This
8083 : * refcount is held by the wrong resowner, so we can't just repurpose it.)
8084 : */
8085 21604 : ReleaseCachedPlan(cplan, CurrentResourceOwner);
8086 : }
8087 :
8088 : /*
8089 : * exec_save_simple_expr --- extract simple expression from CachedPlan
8090 : */
8091 : static void
8092 27078 : exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
8093 : {
8094 : PlannedStmt *stmt;
8095 : Plan *plan;
8096 : Expr *tle_expr;
8097 :
8098 : /*
8099 : * Given the checks that exec_simple_check_plan did, none of the Asserts
8100 : * here should ever fail.
8101 : */
8102 :
8103 : /* Extract the single PlannedStmt */
8104 : Assert(list_length(cplan->stmt_list) == 1);
8105 27078 : stmt = linitial_node(PlannedStmt, cplan->stmt_list);
8106 : Assert(stmt->commandType == CMD_SELECT);
8107 :
8108 : /*
8109 : * Ordinarily, the plan node should be a simple Result. However, if
8110 : * debug_parallel_query is on, the planner might've stuck a Gather node
8111 : * atop that. The simplest way to deal with this is to look through the
8112 : * Gather node. The Gather node's tlist would normally contain a Var
8113 : * referencing the child node's output, but it could also be a Param, or
8114 : * it could be a Const that setrefs.c copied as-is.
8115 : */
8116 27078 : plan = stmt->planTree;
8117 : for (;;)
8118 : {
8119 : /* Extract the single tlist expression */
8120 0 : Assert(list_length(plan->targetlist) == 1);
8121 27078 : tle_expr = linitial_node(TargetEntry, plan->targetlist)->expr;
8122 :
8123 27078 : if (IsA(plan, Result))
8124 : {
8125 : Assert(plan->lefttree == NULL &&
8126 : plan->righttree == NULL &&
8127 : plan->initPlan == NULL &&
8128 : plan->qual == NULL &&
8129 : ((Result *) plan)->resconstantqual == NULL);
8130 27078 : break;
8131 : }
8132 0 : else if (IsA(plan, Gather))
8133 : {
8134 : Assert(plan->lefttree != NULL &&
8135 : plan->righttree == NULL &&
8136 : plan->initPlan == NULL &&
8137 : plan->qual == NULL);
8138 : /* If setrefs.c copied up a Const, no need to look further */
8139 0 : if (IsA(tle_expr, Const))
8140 0 : break;
8141 : /* Otherwise, it had better be a Param or an outer Var */
8142 : Assert(IsA(tle_expr, Param) || (IsA(tle_expr, Var) &&
8143 : ((Var *) tle_expr)->varno == OUTER_VAR));
8144 : /* Descend to the child node */
8145 0 : plan = plan->lefttree;
8146 : }
8147 : else
8148 0 : elog(ERROR, "unexpected plan node type: %d",
8149 : (int) nodeTag(plan));
8150 : }
8151 :
8152 : /*
8153 : * Save the simple expression, and initialize state to "not valid in
8154 : * current transaction".
8155 : */
8156 27078 : expr->expr_simple_expr = tle_expr;
8157 27078 : expr->expr_simple_state = NULL;
8158 27078 : expr->expr_simple_in_use = false;
8159 27078 : expr->expr_simple_lxid = InvalidLocalTransactionId;
8160 : /* Also stash away the expression result type */
8161 27078 : expr->expr_simple_type = exprType((Node *) tle_expr);
8162 27078 : expr->expr_simple_typmod = exprTypmod((Node *) tle_expr);
8163 : /* We also want to remember if it is immutable or not */
8164 27078 : expr->expr_simple_mutable = contain_mutable_functions((Node *) tle_expr);
8165 :
8166 : /*
8167 : * Lastly, check to see if there's a possibility of optimizing a
8168 : * read/write parameter.
8169 : */
8170 27078 : exec_check_rw_parameter(expr);
8171 27078 : }
8172 :
8173 : /*
8174 : * exec_check_rw_parameter --- can we pass expanded object as read/write param?
8175 : *
8176 : * If we have an assignment like "x := array_append(x, foo)" in which the
8177 : * top-level function is trusted not to corrupt its argument in case of an
8178 : * error, then when x has an expanded object as value, it is safe to pass the
8179 : * value as a read/write pointer and let the function modify the value
8180 : * in-place.
8181 : *
8182 : * This function checks for a safe expression, and sets expr->expr_rw_param
8183 : * to the address of any Param within the expression that can be passed as
8184 : * read/write (there can be only one); or to NULL when there is no safe Param.
8185 : *
8186 : * Note that this mechanism intentionally applies the safety labeling to just
8187 : * one Param; the expression could contain other Params referencing the target
8188 : * variable, but those must still be treated as read-only.
8189 : *
8190 : * Also note that we only apply this optimization within simple expressions.
8191 : * There's no point in it for non-simple expressions, because the
8192 : * exec_run_select code path will flatten any expanded result anyway.
8193 : * Also, it's safe to assume that an expr_simple_expr tree won't get copied
8194 : * somewhere before it gets compiled, so that looking for pointer equality
8195 : * to expr_rw_param will work for matching the target Param. That'd be much
8196 : * shakier in the general case.
8197 : */
8198 : static void
8199 27078 : exec_check_rw_parameter(PLpgSQL_expr *expr)
8200 : {
8201 : int target_dno;
8202 : Oid funcid;
8203 : List *fargs;
8204 : ListCell *lc;
8205 :
8206 : /* Assume unsafe */
8207 27078 : expr->expr_rw_param = NULL;
8208 :
8209 : /* Done if expression isn't an assignment source */
8210 27078 : target_dno = expr->target_param;
8211 27078 : if (target_dno < 0)
8212 22152 : return;
8213 :
8214 : /*
8215 : * If target variable isn't referenced by expression, no need to look
8216 : * further.
8217 : */
8218 4926 : if (!bms_is_member(target_dno, expr->paramnos))
8219 718 : return;
8220 :
8221 : /* Shouldn't be here for non-simple expression */
8222 : Assert(expr->expr_simple_expr != NULL);
8223 :
8224 : /*
8225 : * Top level of expression must be a simple FuncExpr, OpExpr, or
8226 : * SubscriptingRef, else we can't optimize.
8227 : */
8228 4208 : if (IsA(expr->expr_simple_expr, FuncExpr))
8229 : {
8230 1230 : FuncExpr *fexpr = (FuncExpr *) expr->expr_simple_expr;
8231 :
8232 1230 : funcid = fexpr->funcid;
8233 1230 : fargs = fexpr->args;
8234 : }
8235 2978 : else if (IsA(expr->expr_simple_expr, OpExpr))
8236 : {
8237 1032 : OpExpr *opexpr = (OpExpr *) expr->expr_simple_expr;
8238 :
8239 1032 : funcid = opexpr->opfuncid;
8240 1032 : fargs = opexpr->args;
8241 : }
8242 1946 : else if (IsA(expr->expr_simple_expr, SubscriptingRef))
8243 : {
8244 60 : SubscriptingRef *sbsref = (SubscriptingRef *) expr->expr_simple_expr;
8245 :
8246 : /* We only trust standard varlena arrays to be safe */
8247 60 : if (get_typsubscript(sbsref->refcontainertype, NULL) !=
8248 : F_ARRAY_SUBSCRIPT_HANDLER)
8249 2 : return;
8250 :
8251 : /* We can optimize the refexpr if it's the target, otherwise not */
8252 58 : if (sbsref->refexpr && IsA(sbsref->refexpr, Param))
8253 : {
8254 58 : Param *param = (Param *) sbsref->refexpr;
8255 :
8256 58 : if (param->paramkind == PARAM_EXTERN &&
8257 58 : param->paramid == target_dno + 1)
8258 : {
8259 : /* Found the Param we want to pass as read/write */
8260 52 : expr->expr_rw_param = param;
8261 52 : return;
8262 : }
8263 : }
8264 :
8265 6 : return;
8266 : }
8267 : else
8268 1886 : return;
8269 :
8270 : /*
8271 : * The top-level function must be one that we trust to be "safe".
8272 : * Currently we hard-wire the list, but it would be very desirable to
8273 : * allow extensions to mark their functions as safe ...
8274 : */
8275 2262 : if (!(funcid == F_ARRAY_APPEND ||
8276 : funcid == F_ARRAY_PREPEND))
8277 2190 : return;
8278 :
8279 : /*
8280 : * The target variable (in the form of a Param) must appear as a direct
8281 : * argument of the top-level function. References further down in the
8282 : * tree can't be optimized; but on the other hand, they don't invalidate
8283 : * optimizing the top-level call, since that will be executed last.
8284 : */
8285 96 : foreach(lc, fargs)
8286 : {
8287 84 : Node *arg = (Node *) lfirst(lc);
8288 :
8289 84 : if (arg && IsA(arg, Param))
8290 : {
8291 84 : Param *param = (Param *) arg;
8292 :
8293 84 : if (param->paramkind == PARAM_EXTERN &&
8294 84 : param->paramid == target_dno + 1)
8295 : {
8296 : /* Found the Param we want to pass as read/write */
8297 60 : expr->expr_rw_param = param;
8298 60 : return;
8299 : }
8300 : }
8301 : }
8302 : }
8303 :
8304 : /*
8305 : * exec_check_assignable --- is it OK to assign to the indicated datum?
8306 : *
8307 : * This should match pl_gram.y's check_assignable().
8308 : */
8309 : static void
8310 294 : exec_check_assignable(PLpgSQL_execstate *estate, int dno)
8311 : {
8312 : PLpgSQL_datum *datum;
8313 :
8314 : Assert(dno >= 0 && dno < estate->ndatums);
8315 294 : datum = estate->datums[dno];
8316 294 : switch (datum->dtype)
8317 : {
8318 290 : case PLPGSQL_DTYPE_VAR:
8319 : case PLPGSQL_DTYPE_PROMISE:
8320 : case PLPGSQL_DTYPE_REC:
8321 290 : if (((PLpgSQL_variable *) datum)->isconst)
8322 8 : ereport(ERROR,
8323 : (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
8324 : errmsg("variable \"%s\" is declared CONSTANT",
8325 : ((PLpgSQL_variable *) datum)->refname)));
8326 282 : break;
8327 0 : case PLPGSQL_DTYPE_ROW:
8328 : /* always assignable; member vars were checked at compile time */
8329 0 : break;
8330 4 : case PLPGSQL_DTYPE_RECFIELD:
8331 : /* assignable if parent record is */
8332 4 : exec_check_assignable(estate,
8333 : ((PLpgSQL_recfield *) datum)->recparentno);
8334 4 : break;
8335 0 : default:
8336 0 : elog(ERROR, "unrecognized dtype: %d", datum->dtype);
8337 : break;
8338 : }
8339 286 : }
8340 :
8341 : /* ----------
8342 : * exec_set_found Set the global found variable to true/false
8343 : * ----------
8344 : */
8345 : static void
8346 138462 : exec_set_found(PLpgSQL_execstate *estate, bool state)
8347 : {
8348 : PLpgSQL_var *var;
8349 :
8350 138462 : var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
8351 138462 : assign_simple_var(estate, var, BoolGetDatum(state), false, false);
8352 138462 : }
8353 :
8354 : /*
8355 : * plpgsql_create_econtext --- create an eval_econtext for the current function
8356 : *
8357 : * We may need to create a new shared_simple_eval_estate too, if there's not
8358 : * one already for the current transaction. The EState will be cleaned up at
8359 : * transaction end. Ditto for shared_simple_eval_resowner.
8360 : */
8361 : static void
8362 98570 : plpgsql_create_econtext(PLpgSQL_execstate *estate)
8363 : {
8364 : SimpleEcontextStackEntry *entry;
8365 :
8366 : /*
8367 : * Create an EState for evaluation of simple expressions, if there's not
8368 : * one already in the current transaction. The EState is made a child of
8369 : * TopTransactionContext so it will have the right lifespan.
8370 : *
8371 : * Note that this path is never taken when beginning a DO block; the
8372 : * required EState was already made by plpgsql_inline_handler. However,
8373 : * if the DO block executes COMMIT or ROLLBACK, then we'll come here and
8374 : * make a shared EState to use for the rest of the DO block. That's OK;
8375 : * see the comments for shared_simple_eval_estate. (Note also that a DO
8376 : * block will continue to use its private cast hash table for the rest of
8377 : * the block. That's okay for now, but it might cause problems someday.)
8378 : */
8379 98570 : if (estate->simple_eval_estate == NULL)
8380 : {
8381 : MemoryContext oldcontext;
8382 :
8383 15762 : if (shared_simple_eval_estate == NULL)
8384 : {
8385 15754 : oldcontext = MemoryContextSwitchTo(TopTransactionContext);
8386 15754 : shared_simple_eval_estate = CreateExecutorState();
8387 15754 : MemoryContextSwitchTo(oldcontext);
8388 : }
8389 15762 : estate->simple_eval_estate = shared_simple_eval_estate;
8390 : }
8391 :
8392 : /*
8393 : * Likewise for the simple-expression resource owner.
8394 : */
8395 98570 : if (estate->simple_eval_resowner == NULL)
8396 : {
8397 15762 : if (shared_simple_eval_resowner == NULL)
8398 15754 : shared_simple_eval_resowner =
8399 15754 : ResourceOwnerCreate(TopTransactionResourceOwner,
8400 : "PL/pgSQL simple expressions");
8401 15762 : estate->simple_eval_resowner = shared_simple_eval_resowner;
8402 : }
8403 :
8404 : /*
8405 : * Create a child econtext for the current function.
8406 : */
8407 98570 : estate->eval_econtext = CreateExprContext(estate->simple_eval_estate);
8408 :
8409 : /*
8410 : * Make a stack entry so we can clean up the econtext at subxact end.
8411 : * Stack entries are kept in TopTransactionContext for simplicity.
8412 : */
8413 : entry = (SimpleEcontextStackEntry *)
8414 98570 : MemoryContextAlloc(TopTransactionContext,
8415 : sizeof(SimpleEcontextStackEntry));
8416 :
8417 98570 : entry->stack_econtext = estate->eval_econtext;
8418 98570 : entry->xact_subxid = GetCurrentSubTransactionId();
8419 :
8420 98570 : entry->next = simple_econtext_stack;
8421 98570 : simple_econtext_stack = entry;
8422 98570 : }
8423 :
8424 : /*
8425 : * plpgsql_destroy_econtext --- destroy function's econtext
8426 : *
8427 : * We check that it matches the top stack entry, and destroy the stack
8428 : * entry along with the context.
8429 : */
8430 : static void
8431 80676 : plpgsql_destroy_econtext(PLpgSQL_execstate *estate)
8432 : {
8433 : SimpleEcontextStackEntry *next;
8434 :
8435 : Assert(simple_econtext_stack != NULL);
8436 : Assert(simple_econtext_stack->stack_econtext == estate->eval_econtext);
8437 :
8438 80676 : next = simple_econtext_stack->next;
8439 80676 : pfree(simple_econtext_stack);
8440 80676 : simple_econtext_stack = next;
8441 :
8442 80676 : FreeExprContext(estate->eval_econtext, true);
8443 80676 : estate->eval_econtext = NULL;
8444 80676 : }
8445 :
8446 : /*
8447 : * plpgsql_xact_cb --- post-transaction-commit-or-abort cleanup
8448 : *
8449 : * If a simple-expression EState was created in the current transaction,
8450 : * it has to be cleaned up. The same for the simple-expression resowner.
8451 : */
8452 : void
8453 263226 : plpgsql_xact_cb(XactEvent event, void *arg)
8454 : {
8455 : /*
8456 : * If we are doing a clean transaction shutdown, free the EState and tell
8457 : * the resowner to release whatever plancache references it has, so that
8458 : * all remaining resources will be released correctly. (We don't need to
8459 : * actually delete the resowner here; deletion of the
8460 : * TopTransactionResourceOwner will take care of that.)
8461 : *
8462 : * In an abort, we expect the regular abort recovery procedures to release
8463 : * everything of interest, so just clear our pointers.
8464 : */
8465 263226 : if (event == XACT_EVENT_COMMIT ||
8466 137782 : event == XACT_EVENT_PARALLEL_COMMIT ||
8467 : event == XACT_EVENT_PREPARE)
8468 : {
8469 125480 : simple_econtext_stack = NULL;
8470 :
8471 125480 : if (shared_simple_eval_estate)
8472 14458 : FreeExecutorState(shared_simple_eval_estate);
8473 125480 : shared_simple_eval_estate = NULL;
8474 125480 : if (shared_simple_eval_resowner)
8475 14458 : ReleaseAllPlanCacheRefsInOwner(shared_simple_eval_resowner);
8476 125480 : shared_simple_eval_resowner = NULL;
8477 : }
8478 137746 : else if (event == XACT_EVENT_ABORT ||
8479 : event == XACT_EVENT_PARALLEL_ABORT)
8480 : {
8481 12184 : simple_econtext_stack = NULL;
8482 12184 : shared_simple_eval_estate = NULL;
8483 12184 : shared_simple_eval_resowner = NULL;
8484 : }
8485 263226 : }
8486 :
8487 : /*
8488 : * plpgsql_subxact_cb --- post-subtransaction-commit-or-abort cleanup
8489 : *
8490 : * Make sure any simple-expression econtexts created in the current
8491 : * subtransaction get cleaned up. We have to do this explicitly because
8492 : * no other code knows which econtexts belong to which level of subxact.
8493 : */
8494 : void
8495 34246 : plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
8496 : SubTransactionId parentSubid, void *arg)
8497 : {
8498 34246 : if (event == SUBXACT_EVENT_COMMIT_SUB || event == SUBXACT_EVENT_ABORT_SUB)
8499 : {
8500 26860 : while (simple_econtext_stack != NULL &&
8501 25524 : simple_econtext_stack->xact_subxid == mySubid)
8502 : {
8503 : SimpleEcontextStackEntry *next;
8504 :
8505 12922 : FreeExprContext(simple_econtext_stack->stack_econtext,
8506 : (event == SUBXACT_EVENT_COMMIT_SUB));
8507 12922 : next = simple_econtext_stack->next;
8508 12922 : pfree(simple_econtext_stack);
8509 12922 : simple_econtext_stack = next;
8510 : }
8511 : }
8512 34246 : }
8513 :
8514 : /*
8515 : * assign_simple_var --- assign a new value to any VAR datum.
8516 : *
8517 : * This should be the only mechanism for assignment to simple variables,
8518 : * lest we do the release of the old value incorrectly (not to mention
8519 : * the detoasting business).
8520 : */
8521 : static void
8522 437034 : assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
8523 : Datum newvalue, bool isnull, bool freeable)
8524 : {
8525 : Assert(var->dtype == PLPGSQL_DTYPE_VAR ||
8526 : var->dtype == PLPGSQL_DTYPE_PROMISE);
8527 :
8528 : /*
8529 : * In non-atomic contexts, we do not want to store TOAST pointers in
8530 : * variables, because such pointers might become stale after a commit.
8531 : * Forcibly detoast in such cases. We don't want to detoast (flatten)
8532 : * expanded objects, however; those should be OK across a transaction
8533 : * boundary since they're just memory-resident objects. (Elsewhere in
8534 : * this module, operations on expanded records likewise need to request
8535 : * detoasting of record fields when !estate->atomic. Expanded arrays are
8536 : * not a problem since all array entries are always detoasted.)
8537 : */
8538 437034 : if (!estate->atomic && !isnull && var->datatype->typlen == -1 &&
8539 43538 : VARATT_IS_EXTERNAL_NON_EXPANDED(DatumGetPointer(newvalue)))
8540 : {
8541 : MemoryContext oldcxt;
8542 : Datum detoasted;
8543 :
8544 : /*
8545 : * Do the detoasting in the eval_mcontext to avoid long-term leakage
8546 : * of whatever memory toast fetching might leak. Then we have to copy
8547 : * the detoasted datum to the function's main context, which is a
8548 : * pain, but there's little choice.
8549 : */
8550 16 : oldcxt = MemoryContextSwitchTo(get_eval_mcontext(estate));
8551 16 : detoasted = PointerGetDatum(detoast_external_attr((struct varlena *) DatumGetPointer(newvalue)));
8552 16 : MemoryContextSwitchTo(oldcxt);
8553 : /* Now's a good time to not leak the input value if it's freeable */
8554 16 : if (freeable)
8555 16 : pfree(DatumGetPointer(newvalue));
8556 : /* Once we copy the value, it's definitely freeable */
8557 16 : newvalue = datumCopy(detoasted, false, -1);
8558 16 : freeable = true;
8559 : /* Can't clean up eval_mcontext here, but it'll happen before long */
8560 : }
8561 :
8562 : /* Free the old value if needed */
8563 437034 : if (var->freeval)
8564 : {
8565 74630 : if (DatumIsReadWriteExpandedObject(var->value,
8566 : var->isnull,
8567 : var->datatype->typlen))
8568 6960 : DeleteExpandedObject(var->value);
8569 : else
8570 67670 : pfree(DatumGetPointer(var->value));
8571 : }
8572 : /* Assign new value to datum */
8573 437034 : var->value = newvalue;
8574 437034 : var->isnull = isnull;
8575 437034 : var->freeval = freeable;
8576 :
8577 : /*
8578 : * If it's a promise variable, then either we just assigned the promised
8579 : * value, or the user explicitly assigned an overriding value. Either
8580 : * way, cancel the promise.
8581 : */
8582 437034 : var->promise = PLPGSQL_PROMISE_NONE;
8583 437034 : }
8584 :
8585 : /*
8586 : * free old value of a text variable and assign new value from C string
8587 : */
8588 : static void
8589 23808 : assign_text_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, const char *str)
8590 : {
8591 23808 : assign_simple_var(estate, var, CStringGetTextDatum(str), false, true);
8592 23808 : }
8593 :
8594 : /*
8595 : * assign_record_var --- assign a new value to any REC datum.
8596 : */
8597 : static void
8598 6264 : assign_record_var(PLpgSQL_execstate *estate, PLpgSQL_rec *rec,
8599 : ExpandedRecordHeader *erh)
8600 : {
8601 : Assert(rec->dtype == PLPGSQL_DTYPE_REC);
8602 :
8603 : /* Transfer new record object into datum_context */
8604 6264 : TransferExpandedRecord(erh, estate->datum_context);
8605 :
8606 : /* Free the old value ... */
8607 6264 : if (rec->erh)
8608 1776 : DeleteExpandedObject(ExpandedRecordGetDatum(rec->erh));
8609 :
8610 : /* ... and install the new */
8611 6264 : rec->erh = erh;
8612 6264 : }
8613 :
8614 : /*
8615 : * exec_eval_using_params --- evaluate params of USING clause
8616 : *
8617 : * The result data structure is created in the stmt_mcontext, and should
8618 : * be freed by resetting that context.
8619 : */
8620 : static ParamListInfo
8621 20276 : exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
8622 : {
8623 : ParamListInfo paramLI;
8624 : int nargs;
8625 : MemoryContext stmt_mcontext;
8626 : MemoryContext oldcontext;
8627 : int i;
8628 : ListCell *lc;
8629 :
8630 : /* Fast path for no parameters: we can just return NULL */
8631 20276 : if (params == NIL)
8632 19694 : return NULL;
8633 :
8634 582 : nargs = list_length(params);
8635 582 : stmt_mcontext = get_stmt_mcontext(estate);
8636 582 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
8637 582 : paramLI = makeParamList(nargs);
8638 582 : MemoryContextSwitchTo(oldcontext);
8639 :
8640 582 : i = 0;
8641 1728 : foreach(lc, params)
8642 : {
8643 1146 : PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
8644 1146 : ParamExternData *prm = ¶mLI->params[i];
8645 : int32 ppdtypmod;
8646 :
8647 : /*
8648 : * Always mark params as const, since we only use the result with
8649 : * one-shot plans.
8650 : */
8651 1146 : prm->pflags = PARAM_FLAG_CONST;
8652 :
8653 1146 : prm->value = exec_eval_expr(estate, param,
8654 : &prm->isnull,
8655 : &prm->ptype,
8656 : &ppdtypmod);
8657 :
8658 1146 : oldcontext = MemoryContextSwitchTo(stmt_mcontext);
8659 :
8660 1146 : if (prm->ptype == UNKNOWNOID)
8661 : {
8662 : /*
8663 : * Treat 'unknown' parameters as text, since that's what most
8664 : * people would expect. The SPI functions can coerce unknown
8665 : * constants in a more intelligent way, but not unknown Params.
8666 : * This code also takes care of copying into the right context.
8667 : * Note we assume 'unknown' has the representation of C-string.
8668 : */
8669 0 : prm->ptype = TEXTOID;
8670 0 : if (!prm->isnull)
8671 0 : prm->value = CStringGetTextDatum(DatumGetCString(prm->value));
8672 : }
8673 : /* pass-by-ref non null values must be copied into stmt_mcontext */
8674 1146 : else if (!prm->isnull)
8675 : {
8676 : int16 typLen;
8677 : bool typByVal;
8678 :
8679 1146 : get_typlenbyval(prm->ptype, &typLen, &typByVal);
8680 1146 : if (!typByVal)
8681 1104 : prm->value = datumCopy(prm->value, typByVal, typLen);
8682 : }
8683 :
8684 1146 : MemoryContextSwitchTo(oldcontext);
8685 :
8686 1146 : exec_eval_cleanup(estate);
8687 :
8688 1146 : i++;
8689 : }
8690 :
8691 582 : return paramLI;
8692 : }
8693 :
8694 : /*
8695 : * Open portal for dynamic query
8696 : *
8697 : * Caution: this resets the stmt_mcontext at exit. We might eventually need
8698 : * to move that responsibility to the callers, but currently no caller needs
8699 : * to have statement-lifetime temp data that survives past this, so it's
8700 : * simpler to do it here.
8701 : */
8702 : static Portal
8703 9236 : exec_dynquery_with_params(PLpgSQL_execstate *estate,
8704 : PLpgSQL_expr *dynquery,
8705 : List *params,
8706 : const char *portalname,
8707 : int cursorOptions)
8708 : {
8709 : Portal portal;
8710 : Datum query;
8711 : bool isnull;
8712 : Oid restype;
8713 : int32 restypmod;
8714 : char *querystr;
8715 : SPIParseOpenOptions options;
8716 9236 : MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
8717 :
8718 : /*
8719 : * Evaluate the string expression after the EXECUTE keyword. Its result is
8720 : * the querystring we have to execute.
8721 : */
8722 9236 : query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod);
8723 9236 : if (isnull)
8724 0 : ereport(ERROR,
8725 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
8726 : errmsg("query string argument of EXECUTE is null")));
8727 :
8728 : /* Get the C-String representation */
8729 9236 : querystr = convert_value_to_string(estate, query, restype);
8730 :
8731 : /* copy it into the stmt_mcontext before we clean up */
8732 9236 : querystr = MemoryContextStrdup(stmt_mcontext, querystr);
8733 :
8734 9236 : exec_eval_cleanup(estate);
8735 :
8736 : /*
8737 : * Open an implicit cursor for the query. We use SPI_cursor_parse_open
8738 : * even when there are no params, because this avoids making and freeing
8739 : * one copy of the plan.
8740 : */
8741 9236 : memset(&options, 0, sizeof(options));
8742 9236 : options.params = exec_eval_using_params(estate, params);
8743 9236 : options.cursorOptions = cursorOptions;
8744 9236 : options.read_only = estate->readonly_func;
8745 :
8746 9236 : portal = SPI_cursor_parse_open(portalname, querystr, &options);
8747 :
8748 9236 : if (portal == NULL)
8749 0 : elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
8750 : querystr, SPI_result_code_string(SPI_result));
8751 :
8752 : /* Release transient data */
8753 9236 : MemoryContextReset(stmt_mcontext);
8754 :
8755 9236 : return portal;
8756 : }
8757 :
8758 : /*
8759 : * Return a formatted string with information about an expression's parameters,
8760 : * or NULL if the expression does not take any parameters.
8761 : * The result is in the eval_mcontext.
8762 : */
8763 : static char *
8764 30 : format_expr_params(PLpgSQL_execstate *estate,
8765 : const PLpgSQL_expr *expr)
8766 : {
8767 : int paramno;
8768 : int dno;
8769 : StringInfoData paramstr;
8770 : MemoryContext oldcontext;
8771 :
8772 30 : if (!expr->paramnos)
8773 6 : return NULL;
8774 :
8775 24 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8776 :
8777 24 : initStringInfo(¶mstr);
8778 24 : paramno = 0;
8779 24 : dno = -1;
8780 72 : while ((dno = bms_next_member(expr->paramnos, dno)) >= 0)
8781 : {
8782 : Datum paramdatum;
8783 : Oid paramtypeid;
8784 : bool paramisnull;
8785 : int32 paramtypmod;
8786 : PLpgSQL_var *curvar;
8787 :
8788 48 : curvar = (PLpgSQL_var *) estate->datums[dno];
8789 :
8790 48 : exec_eval_datum(estate, (PLpgSQL_datum *) curvar,
8791 : ¶mtypeid, ¶mtypmod,
8792 : ¶mdatum, ¶misnull);
8793 :
8794 48 : appendStringInfo(¶mstr, "%s%s = ",
8795 : paramno > 0 ? ", " : "",
8796 : curvar->refname);
8797 :
8798 48 : if (paramisnull)
8799 0 : appendStringInfoString(¶mstr, "NULL");
8800 : else
8801 48 : appendStringInfoStringQuoted(¶mstr,
8802 48 : convert_value_to_string(estate,
8803 : paramdatum,
8804 : paramtypeid),
8805 : -1);
8806 :
8807 48 : paramno++;
8808 : }
8809 :
8810 24 : MemoryContextSwitchTo(oldcontext);
8811 :
8812 24 : return paramstr.data;
8813 : }
8814 :
8815 : /*
8816 : * Return a formatted string with information about the parameter values,
8817 : * or NULL if there are no parameters.
8818 : * The result is in the eval_mcontext.
8819 : */
8820 : static char *
8821 18 : format_preparedparamsdata(PLpgSQL_execstate *estate,
8822 : ParamListInfo paramLI)
8823 : {
8824 : int paramno;
8825 : StringInfoData paramstr;
8826 : MemoryContext oldcontext;
8827 :
8828 18 : if (!paramLI)
8829 6 : return NULL;
8830 :
8831 12 : oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8832 :
8833 12 : initStringInfo(¶mstr);
8834 30 : for (paramno = 0; paramno < paramLI->numParams; paramno++)
8835 : {
8836 18 : ParamExternData *prm = ¶mLI->params[paramno];
8837 :
8838 : /*
8839 : * Note: for now, this is only used on ParamListInfos produced by
8840 : * exec_eval_using_params(), so we don't worry about invoking the
8841 : * paramFetch hook or skipping unused parameters.
8842 : */
8843 18 : appendStringInfo(¶mstr, "%s$%d = ",
8844 : paramno > 0 ? ", " : "",
8845 : paramno + 1);
8846 :
8847 18 : if (prm->isnull)
8848 0 : appendStringInfoString(¶mstr, "NULL");
8849 : else
8850 18 : appendStringInfoStringQuoted(¶mstr,
8851 18 : convert_value_to_string(estate,
8852 : prm->value,
8853 : prm->ptype),
8854 : -1);
8855 : }
8856 :
8857 12 : MemoryContextSwitchTo(oldcontext);
8858 :
8859 12 : return paramstr.data;
8860 : }
|