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