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