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