PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pl_exec.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/detoast.h"
#include "access/htup_details.h"
#include "access/tupconvert.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/execExpr.h"
#include "executor/spi.h"
#include "executor/tstoreReceiver.h"
#include "funcapi.h"
#include "mb/stringinfo_mb.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "optimizer/optimizer.h"
#include "parser/parse_coerce.h"
#include "parser/parse_type.h"
#include "plpgsql.h"
#include "storage/proc.h"
#include "tcop/cmdtag.h"
#include "tcop/pquery.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for pl_exec.c:

Go to the source code of this file.

Data Structures

struct  SimpleEcontextStackEntry
 
struct  plpgsql_CastHashKey
 
struct  plpgsql_CastExprHashEntry
 
struct  plpgsql_CastHashEntry
 
struct  count_param_references_context
 

Macros

#define get_eval_mcontext(estate)    ((estate)->eval_econtext->ecxt_per_tuple_memory)
 
#define eval_mcontext_alloc(estate, sz)    MemoryContextAlloc(get_eval_mcontext(estate), sz)
 
#define eval_mcontext_alloc0(estate, sz)    MemoryContextAllocZero(get_eval_mcontext(estate), sz)
 
#define LOOP_RC_PROCESSING(looplabel, exit_action)
 
#define SET_RAISE_OPTION_TEXT(opt, name)
 

Typedefs

typedef struct SimpleEcontextStackEntry SimpleEcontextStackEntry
 
typedef struct count_param_references_context count_param_references_context
 

Functions

static void coerce_function_result_tuple (PLpgSQL_execstate *estate, TupleDesc tupdesc)
 
static void plpgsql_exec_error_callback (void *arg)
 
static void copy_plpgsql_datums (PLpgSQL_execstate *estate, PLpgSQL_function *func)
 
static void plpgsql_fulfill_promise (PLpgSQL_execstate *estate, PLpgSQL_var *var)
 
static MemoryContext get_stmt_mcontext (PLpgSQL_execstate *estate)
 
static void push_stmt_mcontext (PLpgSQL_execstate *estate)
 
static void pop_stmt_mcontext (PLpgSQL_execstate *estate)
 
static int exec_toplevel_block (PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 
static int exec_stmt_block (PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 
static int exec_stmts (PLpgSQL_execstate *estate, List *stmts)
 
static int exec_stmt_assign (PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
 
static int exec_stmt_perform (PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
 
static int exec_stmt_call (PLpgSQL_execstate *estate, PLpgSQL_stmt_call *stmt)
 
static int exec_stmt_getdiag (PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
 
static int exec_stmt_if (PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
 
static int exec_stmt_case (PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
 
static int exec_stmt_loop (PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
 
static int exec_stmt_while (PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
 
static int exec_stmt_fori (PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
 
static int exec_stmt_fors (PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
 
static int exec_stmt_forc (PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
 
static int exec_stmt_foreach_a (PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
 
static int exec_stmt_open (PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
 
static int exec_stmt_fetch (PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
 
static int exec_stmt_close (PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
 
static int exec_stmt_exit (PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
 
static int exec_stmt_return (PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
 
static int exec_stmt_return_next (PLpgSQL_execstate *estate, PLpgSQL_stmt_return_next *stmt)
 
static int exec_stmt_return_query (PLpgSQL_execstate *estate, PLpgSQL_stmt_return_query *stmt)
 
static int exec_stmt_raise (PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 
static int exec_stmt_assert (PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
 
static int exec_stmt_execsql (PLpgSQL_execstate *estate, PLpgSQL_stmt_execsql *stmt)
 
static int exec_stmt_dynexecute (PLpgSQL_execstate *estate, PLpgSQL_stmt_dynexecute *stmt)
 
static int exec_stmt_dynfors (PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
 
static int exec_stmt_commit (PLpgSQL_execstate *estate, PLpgSQL_stmt_commit *stmt)
 
static int exec_stmt_rollback (PLpgSQL_execstate *estate, PLpgSQL_stmt_rollback *stmt)
 
static void plpgsql_estate_setup (PLpgSQL_execstate *estate, PLpgSQL_function *func, ReturnSetInfo *rsi, EState *simple_eval_estate, ResourceOwner simple_eval_resowner)
 
static void exec_eval_cleanup (PLpgSQL_execstate *estate)
 
static void exec_prepare_plan (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
 
static void exec_simple_check_plan (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
static bool exec_is_simple_query (PLpgSQL_expr *expr)
 
static void exec_save_simple_expr (PLpgSQL_expr *expr, CachedPlan *cplan)
 
static void exec_check_rw_parameter (PLpgSQL_expr *expr, int paramid)
 
static bool count_param_references (Node *node, count_param_references_context *context)
 
static void exec_check_assignable (PLpgSQL_execstate *estate, int dno)
 
static bool exec_eval_simple_expr (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, Datum *result, bool *isNull, Oid *rettype, int32 *rettypmod)
 
static void exec_assign_expr (PLpgSQL_execstate *estate, PLpgSQL_datum *target, PLpgSQL_expr *expr)
 
static void exec_assign_c_string (PLpgSQL_execstate *estate, PLpgSQL_datum *target, const char *str)
 
static void exec_assign_value (PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
 
static void exec_eval_datum (PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeid, int32 *typetypmod, Datum *value, bool *isnull)
 
static int exec_eval_integer (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
 
static bool exec_eval_boolean (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
 
static Datum exec_eval_expr (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
 
static int exec_run_select (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
 
static int exec_for_query (PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, Portal portal, bool prefetch_ok)
 
static ParamListInfo setup_param_list (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
static ParamExternDataplpgsql_param_fetch (ParamListInfo params, int paramid, bool speculative, ParamExternData *prm)
 
static void plpgsql_param_compile (ParamListInfo params, Param *param, ExprState *state, Datum *resv, bool *resnull)
 
static void plpgsql_param_eval_var_check (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void plpgsql_param_eval_var_transfer (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void plpgsql_param_eval_var (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void plpgsql_param_eval_var_ro (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void plpgsql_param_eval_recfield (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void plpgsql_param_eval_generic (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void plpgsql_param_eval_generic_ro (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void exec_move_row (PLpgSQL_execstate *estate, PLpgSQL_variable *target, HeapTuple tup, TupleDesc tupdesc)
 
static void revalidate_rectypeid (PLpgSQL_rec *rec)
 
static ExpandedRecordHeadermake_expanded_record_for_rec (PLpgSQL_execstate *estate, PLpgSQL_rec *rec, TupleDesc srctupdesc, ExpandedRecordHeader *srcerh)
 
static void exec_move_row_from_fields (PLpgSQL_execstate *estate, PLpgSQL_variable *target, ExpandedRecordHeader *newerh, Datum *values, bool *nulls, TupleDesc tupdesc)
 
static bool compatible_tupdescs (TupleDesc src_tupdesc, TupleDesc dst_tupdesc)
 
static HeapTuple make_tuple_from_row (PLpgSQL_execstate *estate, PLpgSQL_row *row, TupleDesc tupdesc)
 
static TupleDesc deconstruct_composite_datum (Datum value, HeapTupleData *tmptup)
 
static void exec_move_row_from_datum (PLpgSQL_execstate *estate, PLpgSQL_variable *target, Datum value)
 
static void instantiate_empty_record_variable (PLpgSQL_execstate *estate, PLpgSQL_rec *rec)
 
static charconvert_value_to_string (PLpgSQL_execstate *estate, Datum value, Oid valtype)
 
static Datum exec_cast_value (PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
 
static Datum do_cast_value (PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
 
static plpgsql_CastHashEntryget_cast_hashentry (PLpgSQL_execstate *estate, Oid srctype, int32 srctypmod, Oid dsttype, int32 dsttypmod)
 
static void exec_init_tuple_store (PLpgSQL_execstate *estate)
 
static void exec_set_found (PLpgSQL_execstate *estate, bool state)
 
static void plpgsql_create_econtext (PLpgSQL_execstate *estate)
 
static void plpgsql_destroy_econtext (PLpgSQL_execstate *estate)
 
static void assign_simple_var (PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
 
static void assign_text_var (PLpgSQL_execstate *estate, PLpgSQL_var *var, const char *str)
 
static void assign_record_var (PLpgSQL_execstate *estate, PLpgSQL_rec *rec, ExpandedRecordHeader *erh)
 
static ParamListInfo exec_eval_using_params (PLpgSQL_execstate *estate, List *params)
 
static Portal exec_dynquery_with_params (PLpgSQL_execstate *estate, PLpgSQL_expr *dynquery, List *params, const char *portalname, int cursorOptions)
 
static charformat_expr_params (PLpgSQL_execstate *estate, const PLpgSQL_expr *expr)
 
static charformat_preparedparamsdata (PLpgSQL_execstate *estate, ParamListInfo paramLI)
 
static PLpgSQL_variablemake_callstmt_target (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
Datum plpgsql_exec_function (PLpgSQL_function *func, FunctionCallInfo fcinfo, EState *simple_eval_estate, ResourceOwner simple_eval_resowner, ResourceOwner procedure_resowner, bool atomic)
 
HeapTuple plpgsql_exec_trigger (PLpgSQL_function *func, TriggerData *trigdata)
 
void plpgsql_exec_event_trigger (PLpgSQL_function *func, EventTriggerData *trigdata)
 
static bool exception_matches_conditions (ErrorData *edata, PLpgSQL_condition *cond)
 
Oid plpgsql_exec_get_datum_type (PLpgSQL_execstate *estate, PLpgSQL_datum *datum)
 
void plpgsql_exec_get_datum_type_info (PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
 
void plpgsql_xact_cb (XactEvent event, void *arg)
 
void plpgsql_subxact_cb (SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
 

Variables

static EStateshared_simple_eval_estate = NULL
 
static SimpleEcontextStackEntrysimple_econtext_stack = NULL
 
static ResourceOwner shared_simple_eval_resowner = NULL
 
static HTABcast_expr_hash = NULL
 
static HTABshared_cast_hash = NULL
 

Macro Definition Documentation

◆ eval_mcontext_alloc

#define eval_mcontext_alloc (   estate,
  sz 
)     MemoryContextAlloc(get_eval_mcontext(estate), sz)

Definition at line 129 of file pl_exec.c.

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

◆ eval_mcontext_alloc0

#define eval_mcontext_alloc0 (   estate,
  sz 
)     MemoryContextAllocZero(get_eval_mcontext(estate), sz)

Definition at line 131 of file pl_exec.c.

◆ get_eval_mcontext

#define get_eval_mcontext (   estate)     ((estate)->eval_econtext->ecxt_per_tuple_memory)

Definition at line 127 of file pl_exec.c.

◆ LOOP_RC_PROCESSING

#define LOOP_RC_PROCESSING (   looplabel,
  exit_action 
)

Definition at line 204 of file pl_exec.c.

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 } \

◆ SET_RAISE_OPTION_TEXT

#define SET_RAISE_OPTION_TEXT (   opt,
  name 
)
Value:
do { \
if (opt) \
errmsg("RAISE option already specified: %s", \
name))); \
opt = MemoryContextStrdup(stmt_mcontext, extval); \
} while (0)
const char * name

Definition at line 3709 of file pl_exec.c.

3710 { \
3711 if (opt) \
3712 ereport(ERROR, \
3714 errmsg("RAISE option already specified: %s", \
3715 name))); \
3716 opt = MemoryContextStrdup(stmt_mcontext, extval); \
3717} while (0)

Typedef Documentation

◆ count_param_references_context

◆ SimpleEcontextStackEntry

Function Documentation

◆ assign_record_var()

static void assign_record_var ( PLpgSQL_execstate estate,
PLpgSQL_rec rec,
ExpandedRecordHeader erh 
)
static

Definition at line 8854 of file pl_exec.c.

8856{
8858
8859 /* Transfer new record object into datum_context */
8861
8862 /* Free the old value ... */
8863 if (rec->erh)
8865
8866 /* ... and install the new */
8867 rec->erh = erh;
8868}

References Assert, PLpgSQL_execstate::datum_context, DeleteExpandedObject(), PLpgSQL_rec::dtype, PLpgSQL_rec::erh, ExpandedRecordGetDatum(), PLPGSQL_DTYPE_REC, and TransferExpandedRecord.

Referenced by exec_move_row(), exec_move_row_from_datum(), and exec_move_row_from_fields().

◆ assign_simple_var()

static void assign_simple_var ( PLpgSQL_execstate estate,
PLpgSQL_var var,
Datum  newvalue,
bool  isnull,
bool  freeable 
)
static

Definition at line 8778 of file pl_exec.c.

8780{
8781 Assert(var->dtype == PLPGSQL_DTYPE_VAR ||
8783
8784 /*
8785 * In non-atomic contexts, we do not want to store TOAST pointers in
8786 * variables, because such pointers might become stale after a commit.
8787 * Forcibly detoast in such cases. We don't want to detoast (flatten)
8788 * expanded objects, however; those should be OK across a transaction
8789 * boundary since they're just memory-resident objects. (Elsewhere in
8790 * this module, operations on expanded records likewise need to request
8791 * detoasting of record fields when !estate->atomic. Expanded arrays are
8792 * not a problem since all array entries are always detoasted.)
8793 */
8794 if (!estate->atomic && !isnull && var->datatype->typlen == -1 &&
8796 {
8799
8800 /*
8801 * Do the detoasting in the eval_mcontext to avoid long-term leakage
8802 * of whatever memory toast fetching might leak. Then we have to copy
8803 * the detoasted datum to the function's main context, which is a
8804 * pain, but there's little choice.
8805 */
8809 /* Now's a good time to not leak the input value if it's freeable */
8810 if (freeable)
8812 /* Once we copy the value, it's definitely freeable */
8813 newvalue = datumCopy(detoasted, false, -1);
8814 freeable = true;
8815 /* Can't clean up eval_mcontext here, but it'll happen before long */
8816 }
8817
8818 /* Free the old value if needed */
8819 if (var->freeval)
8820 {
8822 var->isnull,
8823 var->datatype->typlen))
8825 else
8827 }
8828 /* Assign new value to datum */
8829 var->value = newvalue;
8830 var->isnull = isnull;
8831 var->freeval = freeable;
8832
8833 /*
8834 * If it's a promise variable, then either we just assigned the promised
8835 * value, or the user explicitly assigned an overriding value. Either
8836 * way, cancel the promise.
8837 */
8839}

References Assert, PLpgSQL_execstate::atomic, PLpgSQL_var::datatype, datumCopy(), DatumGetPointer(), DatumIsReadWriteExpandedObject, DeleteExpandedObject(), detoast_external_attr(), PLpgSQL_var::dtype, fb(), PLpgSQL_var::freeval, get_eval_mcontext, PLpgSQL_var::isnull, MemoryContextSwitchTo(), pfree(), PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_VAR, PLPGSQL_PROMISE_NONE, PointerGetDatum(), PLpgSQL_var::promise, PLpgSQL_type::typlen, PLpgSQL_var::value, and VARATT_IS_EXTERNAL_NON_EXPANDED().

Referenced by assign_text_var(), exec_assign_value(), exec_set_found(), exec_stmt_block(), exec_stmt_case(), exec_stmt_forc(), exec_stmt_fori(), plpgsql_exec_function(), and plpgsql_fulfill_promise().

◆ assign_text_var()

static void assign_text_var ( PLpgSQL_execstate estate,
PLpgSQL_var var,
const char str 
)
static

Definition at line 8845 of file pl_exec.c.

8846{
8847 assign_simple_var(estate, var, CStringGetTextDatum(str), false, true);
8848}

References assign_simple_var(), CStringGetTextDatum, and str.

Referenced by exec_stmt_block(), exec_stmt_forc(), exec_stmt_open(), and plpgsql_fulfill_promise().

◆ coerce_function_result_tuple()

static void coerce_function_result_tuple ( PLpgSQL_execstate estate,
TupleDesc  tupdesc 
)
static

Definition at line 824 of file pl_exec.c.

825{
828 TupleConversionMap *tupmap;
829
830 /* We assume exec_stmt_return verified that result is composite */
832
833 /* We can special-case expanded records for speed */
835 {
837
838 Assert(erh->er_magic == ER_MAGIC);
839
840 /* Extract record's TupleDesc */
842
843 /* check rowtype compatibility */
845 tupdesc,
846 gettext_noop("returned record type does not match expected record type"));
847
848 /* it might need conversion */
849 if (tupmap)
850 {
852 Assert(rettup);
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 estate->retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
860 /* no need to free map, we're about to return anyway */
861 }
862 else if (!(tupdesc->tdtypeid == erh->er_decltypeid ||
863 (tupdesc->tdtypeid == RECORDOID &&
865 {
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 */
878 HeapTupleHeader tuphdr;
879
882 EOH_flatten_into(&erh->hdr, tuphdr, resultsize);
883 HeapTupleHeaderSetTypeId(tuphdr, tupdesc->tdtypeid);
884 HeapTupleHeaderSetTypMod(tuphdr, tupdesc->tdtypmod);
885 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 estate->retval = SPI_datumTransfer(estate->retval,
895 false,
896 -1);
897 }
898 }
899 else
900 {
901 /* Convert composite datum to a HeapTuple and TupleDesc */
903
905 rettup = &tmptup;
906
907 /* check rowtype compatibility */
909 tupdesc,
910 gettext_noop("returned record type does not match expected record type"));
911
912 /* it might need conversion */
913 if (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 estate->retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
921
922 /* no need to free map, we're about to return anyway */
923
925 }
926}

References Assert, convert_tuples_by_position(), DatumGetEOHP(), DatumGetPointer(), deconstruct_composite_datum(), EOH_flatten_into(), EOH_get_flat_size(), ExpandedRecordHeader::er_decltypeid, ER_MAGIC, ExpandedRecordHeader::er_magic, execute_attr_map_tuple(), expanded_record_get_tupdesc(), expanded_record_get_tuple(), ExpandedRecordIsDomain, fb(), gettext_noop, ExpandedRecordHeader::hdr, HeapTupleHeaderSetTypeId(), HeapTupleHeaderSetTypMod(), PointerGetDatum(), ReleaseTupleDesc, PLpgSQL_execstate::rettype, PLpgSQL_execstate::retval, SPI_datumTransfer(), SPI_palloc(), SPI_returntuple(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, type_is_rowtype(), and VARATT_IS_EXTERNAL_EXPANDED().

Referenced by plpgsql_exec_function().

◆ compatible_tupdescs()

static bool compatible_tupdescs ( TupleDesc  src_tupdesc,
TupleDesc  dst_tupdesc 
)
static

Definition at line 7446 of file pl_exec.c.

7447{
7448 int i;
7449
7450 /* Possibly we could allow src_tupdesc to have extra columns? */
7451 if (dst_tupdesc->natts != src_tupdesc->natts)
7452 return false;
7453
7454 for (i = 0; i < dst_tupdesc->natts; i++)
7455 {
7458
7459 if (dattr->attisdropped != sattr->attisdropped)
7460 return false;
7461 if (!dattr->attisdropped)
7462 {
7463 /* Normal columns must match by type and typmod */
7464 if (dattr->atttypid != sattr->atttypid ||
7465 (dattr->atttypmod >= 0 &&
7466 dattr->atttypmod != sattr->atttypmod))
7467 return false;
7468 }
7469 else
7470 {
7471 /* Dropped columns are OK as long as length/alignment match */
7472 if (dattr->attlen != sattr->attlen ||
7473 dattr->attalign != sattr->attalign)
7474 return false;
7475 }
7476 }
7477 return true;
7478}

References fb(), i, and TupleDescAttr().

Referenced by exec_for_query(), and exec_move_row().

◆ convert_value_to_string()

static char * convert_value_to_string ( PLpgSQL_execstate estate,
Datum  value,
Oid  valtype 
)
static

Definition at line 7844 of file pl_exec.c.

7845{
7846 char *result;
7847 MemoryContext oldcontext;
7848 Oid typoutput;
7849 bool typIsVarlena;
7850
7851 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7852 getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
7853 result = OidOutputFunctionCall(typoutput, value);
7854 MemoryContextSwitchTo(oldcontext);
7855
7856 return result;
7857}

References fb(), get_eval_mcontext, getTypeOutputInfo(), MemoryContextSwitchTo(), OidOutputFunctionCall(), and value.

Referenced by exec_dynquery_with_params(), exec_stmt_assert(), exec_stmt_dynexecute(), exec_stmt_raise(), exec_stmt_return_query(), format_expr_params(), and format_preparedparamsdata().

◆ copy_plpgsql_datums()

static void copy_plpgsql_datums ( PLpgSQL_execstate estate,
PLpgSQL_function func 
)
static

Definition at line 1310 of file pl_exec.c.

1312{
1313 int ndatums = estate->ndatums;
1316 char *workspace;
1317 char *ws_next;
1318 int i;
1319
1320 /* Allocate local datum-pointer array */
1321 estate->datums = palloc_array(PLpgSQL_datum *, ndatums);
1322
1323 /*
1324 * To reduce palloc overhead, we make a single palloc request for all the
1325 * space needed for locally-instantiated datums.
1326 */
1327 workspace = palloc(func->copiable_size);
1328 ws_next = workspace;
1329
1330 /* Fill datum-pointer array, copying datums into workspace as needed */
1331 indatums = func->datums;
1332 outdatums = estate->datums;
1333 for (i = 0; i < ndatums; i++)
1334 {
1337
1338 /* This must agree with plpgsql_finish_datums on what is copiable */
1339 switch (indatum->dtype)
1340 {
1341 case PLPGSQL_DTYPE_VAR:
1345 ws_next += MAXALIGN(sizeof(PLpgSQL_var));
1346 break;
1347
1348 case PLPGSQL_DTYPE_REC:
1351 ws_next += MAXALIGN(sizeof(PLpgSQL_rec));
1352 break;
1353
1354 case PLPGSQL_DTYPE_ROW:
1356
1357 /*
1358 * These datum records are read-only at runtime, so no need to
1359 * copy them (well, RECFIELD contains cached data, but we'd
1360 * just as soon centralize the caching anyway).
1361 */
1362 outdatum = indatum;
1363 break;
1364
1365 default:
1366 elog(ERROR, "unrecognized dtype: %d", indatum->dtype);
1367 outdatum = NULL; /* keep compiler quiet */
1368 break;
1369 }
1370
1371 outdatums[i] = outdatum;
1372 }
1373
1374 Assert(ws_next == workspace + func->copiable_size);
1375}

References Assert, PLpgSQL_function::copiable_size, PLpgSQL_function::datums, PLpgSQL_execstate::datums, elog, ERROR, fb(), i, MAXALIGN, PLpgSQL_execstate::ndatums, palloc(), palloc_array, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, and PLPGSQL_DTYPE_VAR.

Referenced by plpgsql_exec_event_trigger(), plpgsql_exec_function(), and plpgsql_exec_trigger().

◆ count_param_references()

static bool count_param_references ( Node node,
count_param_references_context context 
)
static

Definition at line 8530 of file pl_exec.c.

8531{
8532 if (node == NULL)
8533 return false;
8534 else if (IsA(node, Param))
8535 {
8536 Param *param = (Param *) node;
8537
8538 if (param->paramkind == PARAM_EXTERN &&
8539 param->paramid == context->paramid)
8540 {
8541 context->last_param = param;
8542 if (++(context->count) > 1)
8543 return true; /* abort tree traversal */
8544 }
8545 return false;
8546 }
8547 else
8548 return expression_tree_walker(node, count_param_references, context);
8549}

References count_param_references_context::count, count_param_references(), expression_tree_walker, fb(), IsA, count_param_references_context::last_param, PARAM_EXTERN, Param::paramid, count_param_references_context::paramid, and Param::paramkind.

Referenced by count_param_references(), and exec_check_rw_parameter().

◆ deconstruct_composite_datum()

static TupleDesc deconstruct_composite_datum ( Datum  value,
HeapTupleData tmptup 
)
static

Definition at line 7545 of file pl_exec.c.

7546{
7547 HeapTupleHeader td;
7548 Oid tupType;
7550
7551 /* Get tuple body (note this could involve detoasting) */
7553
7554 /* Build a temporary HeapTuple control structure */
7556 ItemPointerSetInvalid(&(tmptup->t_self));
7557 tmptup->t_tableOid = InvalidOid;
7558 tmptup->t_data = td;
7559
7560 /* Extract rowtype info and find a tupdesc */
7564}

References DatumGetHeapTupleHeader, fb(), HeapTupleHeaderGetDatumLength(), HeapTupleHeaderGetTypeId(), HeapTupleHeaderGetTypMod(), InvalidOid, ItemPointerSetInvalid(), lookup_rowtype_tupdesc(), and value.

Referenced by coerce_function_result_tuple(), exec_stmt_return_next(), and plpgsql_exec_trigger().

◆ do_cast_value()

static Datum do_cast_value ( PLpgSQL_execstate estate,
Datum  value,
bool isnull,
Oid  valtype,
int32  valtypmod,
Oid  reqtype,
int32  reqtypmod 
)
static

Definition at line 7897 of file pl_exec.c.

7901{
7903
7907 if (cast_entry)
7908 {
7909 ExprContext *econtext = estate->eval_econtext;
7910 MemoryContext oldcontext;
7911
7912 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7913
7914 econtext->caseValue_datum = value;
7915 econtext->caseValue_isNull = *isnull;
7916
7917 cast_entry->cast_in_use = true;
7918
7919 value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
7920 isnull);
7921
7922 cast_entry->cast_in_use = false;
7923
7924 MemoryContextSwitchTo(oldcontext);
7925 }
7926
7927 return value;
7928}

References ExprContext::caseValue_datum, ExprContext::caseValue_isNull, PLpgSQL_execstate::eval_econtext, ExecEvalExpr(), fb(), get_cast_hashentry(), get_eval_mcontext, MemoryContextSwitchTo(), and value.

Referenced by exec_cast_value().

◆ exception_matches_conditions()

static bool exception_matches_conditions ( ErrorData edata,
PLpgSQL_condition cond 
)
static

Definition at line 1594 of file pl_exec.c.

1595{
1596 for (; cond != NULL; cond = cond->next)
1597 {
1598 int sqlerrstate = cond->sqlerrstate;
1599
1600 /*
1601 * OTHERS matches everything *except* query-canceled and
1602 * assert-failure. If you're foolish enough, you can match those
1603 * explicitly.
1604 */
1605 if (sqlerrstate == PLPGSQL_OTHERS)
1606 {
1607 if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED &&
1608 edata->sqlerrcode != ERRCODE_ASSERT_FAILURE)
1609 return true;
1610 }
1611 /* Exact match? */
1612 else if (edata->sqlerrcode == sqlerrstate)
1613 return true;
1614 /* Category match? */
1615 else if (ERRCODE_IS_CATEGORY(sqlerrstate) &&
1616 ERRCODE_TO_CATEGORY(edata->sqlerrcode) == sqlerrstate)
1617 return true;
1618 }
1619 return false;
1620}

References ERRCODE_IS_CATEGORY, ERRCODE_TO_CATEGORY, fb(), PLpgSQL_condition::next, PLPGSQL_OTHERS, and PLpgSQL_condition::sqlerrstate.

Referenced by exec_stmt_block().

◆ exec_assign_c_string()

static void exec_assign_c_string ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
const char str 
)
static

Definition at line 5032 of file pl_exec.c.

5034{
5035 text *value;
5036 MemoryContext oldcontext;
5037
5038 /* Use eval_mcontext for short-lived text value */
5039 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5040 if (str != NULL)
5042 else
5043 value = cstring_to_text("");
5044 MemoryContextSwitchTo(oldcontext);
5045
5046 exec_assign_value(estate, target, PointerGetDatum(value), false,
5047 TEXTOID, -1);
5048}

References cstring_to_text(), exec_assign_value(), fb(), get_eval_mcontext, MemoryContextSwitchTo(), PointerGetDatum(), str, and value.

Referenced by exec_stmt_getdiag().

◆ exec_assign_expr()

static void exec_assign_expr ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
PLpgSQL_expr expr 
)
static

Definition at line 5002 of file pl_exec.c.

5004{
5005 Datum value;
5006 bool isnull;
5007 Oid valtype;
5009
5010 /*
5011 * If first time through, create a plan for this expression.
5012 */
5013 if (expr->plan == NULL)
5014 exec_prepare_plan(estate, expr, 0);
5015
5016 value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
5017 exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
5018 exec_eval_cleanup(estate);
5019}

References exec_assign_value(), exec_eval_cleanup(), exec_eval_expr(), exec_prepare_plan(), fb(), PLpgSQL_expr::plan, and value.

Referenced by exec_stmt_assign(), exec_stmt_block(), and plpgsql_estate_setup().

◆ exec_assign_value()

static void exec_assign_value ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
Datum  value,
bool  isNull,
Oid  valtype,
int32  valtypmod 
)
static

Definition at line 5060 of file pl_exec.c.

5064{
5065 switch (target->dtype)
5066 {
5067 case PLPGSQL_DTYPE_VAR:
5069 {
5070 /*
5071 * Target is a variable
5072 */
5073 PLpgSQL_var *var = (PLpgSQL_var *) target;
5075
5076 newvalue = exec_cast_value(estate,
5077 value,
5078 &isNull,
5079 valtype,
5080 valtypmod,
5081 var->datatype->typoid,
5082 var->datatype->atttypmod);
5083
5084 if (isNull && var->notnull)
5085 ereport(ERROR,
5087 errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
5088 var->refname)));
5089
5090 /*
5091 * If type is by-reference, copy the new value (which is
5092 * probably in the eval_mcontext) into the procedure's main
5093 * memory context. But if it's a read/write reference to an
5094 * expanded object, no physical copy needs to happen; at most
5095 * we need to reparent the object's memory context.
5096 *
5097 * If it's an array, we force the value to be stored in R/W
5098 * expanded form. This wins if the function later does, say,
5099 * a lot of array subscripting operations on the variable, and
5100 * otherwise might lose. We might need to use a different
5101 * heuristic, but it's too soon to tell. Also, are there
5102 * cases where it'd be useful to force non-array values into
5103 * expanded form?
5104 */
5105 if (!var->datatype->typbyval && !isNull)
5106 {
5107 if (var->datatype->typisarray &&
5109 {
5110 /* array and not already R/W, so apply expand_array */
5112 estate->datum_context,
5113 NULL);
5114 }
5115 else
5116 {
5117 /* else transfer value if R/W, else just datumCopy */
5119 false,
5120 var->datatype->typlen);
5121 }
5122 }
5123
5124 /*
5125 * Now free the old value, if any, and assign the new one. But
5126 * skip the assignment if old and new values are the same.
5127 * Note that for expanded objects, this test is necessary and
5128 * cannot reliably be made any earlier; we have to be looking
5129 * at the object's standard R/W pointer to be sure pointer
5130 * equality is meaningful.
5131 *
5132 * Also, if it's a promise variable, we should disarm the
5133 * promise in any case --- otherwise, assigning null to an
5134 * armed promise variable would fail to disarm the promise.
5135 */
5136 if (var->value != newvalue || var->isnull || isNull)
5137 assign_simple_var(estate, var, newvalue, isNull,
5138 (!var->datatype->typbyval && !isNull));
5139 else
5141 break;
5142 }
5143
5144 case PLPGSQL_DTYPE_ROW:
5145 {
5146 /*
5147 * Target is a row variable
5148 */
5149 PLpgSQL_row *row = (PLpgSQL_row *) target;
5150
5151 if (isNull)
5152 {
5153 /* If source is null, just assign nulls to the row */
5154 exec_move_row(estate, (PLpgSQL_variable *) row,
5155 NULL, NULL);
5156 }
5157 else
5158 {
5159 /* Source must be of RECORD or composite type */
5161 ereport(ERROR,
5163 errmsg("cannot assign non-composite value to a row variable")));
5165 value);
5166 }
5167 break;
5168 }
5169
5170 case PLPGSQL_DTYPE_REC:
5171 {
5172 /*
5173 * Target is a record variable
5174 */
5175 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
5176
5177 if (isNull)
5178 {
5179 if (rec->notnull)
5180 ereport(ERROR,
5182 errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
5183 rec->refname)));
5184
5185 /* Set variable to a simple NULL */
5186 exec_move_row(estate, (PLpgSQL_variable *) rec,
5187 NULL, NULL);
5188 }
5189 else
5190 {
5191 /* Source must be of RECORD or composite type */
5193 ereport(ERROR,
5195 errmsg("cannot assign non-composite value to a record variable")));
5197 value);
5198 }
5199 break;
5200 }
5201
5203 {
5204 /*
5205 * Target is a field of a record
5206 */
5208 PLpgSQL_rec *rec;
5210
5211 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5212 erh = rec->erh;
5213
5214 /*
5215 * If record variable is NULL, instantiate it if it has a
5216 * named composite type, else complain. (This won't change
5217 * the logical state of the record, but if we successfully
5218 * assign below, the unassigned fields will all become NULLs.)
5219 */
5220 if (erh == NULL)
5221 {
5223 erh = rec->erh;
5224 }
5225
5226 /*
5227 * Look up the field's properties if we have not already, or
5228 * if the tuple descriptor ID changed since last time.
5229 */
5230 if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
5231 {
5233 recfield->fieldname,
5234 &recfield->finfo))
5235 ereport(ERROR,
5237 errmsg("record \"%s\" has no field \"%s\"",
5238 rec->refname, recfield->fieldname)));
5239 recfield->rectupledescid = erh->er_tupdesc_id;
5240 }
5241
5242 /* We don't support assignments to system columns. */
5243 if (recfield->finfo.fnumber <= 0)
5244 ereport(ERROR,
5246 errmsg("cannot assign to system column \"%s\"",
5247 recfield->fieldname)));
5248
5249 /* Cast the new value to the right type, if needed. */
5250 value = exec_cast_value(estate,
5251 value,
5252 &isNull,
5253 valtype,
5254 valtypmod,
5255 recfield->finfo.ftypeid,
5256 recfield->finfo.ftypmod);
5257
5258 /* And assign it. */
5259 expanded_record_set_field(erh, recfield->finfo.fnumber,
5260 value, isNull, !estate->atomic);
5261 break;
5262 }
5263
5264 default:
5265 elog(ERROR, "unrecognized dtype: %d", target->dtype);
5266 }
5267}

References assign_simple_var(), PLpgSQL_execstate::atomic, PLpgSQL_type::atttypmod, PLpgSQL_var::datatype, PLpgSQL_execstate::datum_context, DatumGetPointer(), PLpgSQL_execstate::datums, datumTransfer(), PLpgSQL_datum::dtype, elog, ExpandedRecordHeader::er_tupdesc_id, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, exec_cast_value(), exec_move_row(), exec_move_row_from_datum(), expand_array(), expanded_record_lookup_field(), expanded_record_set_field, fb(), instantiate_empty_record_variable(), PLpgSQL_var::isnull, PLpgSQL_var::notnull, PLpgSQL_rec::notnull, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, PLPGSQL_PROMISE_NONE, PLpgSQL_var::promise, PLpgSQL_var::refname, PLpgSQL_rec::refname, PLpgSQL_type::typbyval, type_is_rowtype(), PLpgSQL_type::typisarray, PLpgSQL_type::typlen, PLpgSQL_type::typoid, unlikely, value, PLpgSQL_var::value, and VARATT_IS_EXTERNAL_EXPANDED_RW().

Referenced by exec_assign_c_string(), exec_assign_expr(), exec_move_row_from_fields(), exec_stmt_block(), exec_stmt_case(), exec_stmt_foreach_a(), exec_stmt_getdiag(), and plpgsql_estate_setup().

◆ exec_cast_value()

static Datum exec_cast_value ( PLpgSQL_execstate estate,
Datum  value,
bool isnull,
Oid  valtype,
int32  valtypmod,
Oid  reqtype,
int32  reqtypmod 
)
inlinestatic

Definition at line 7873 of file pl_exec.c.

7877{
7878 /*
7879 * If the type of the given value isn't what's requested, convert it.
7880 */
7881 if (valtype != reqtype ||
7882 (valtypmod != reqtypmod && reqtypmod != -1))
7883 {
7884 /* We keep the slow path out-of-line. */
7885 value = do_cast_value(estate, value, isnull, valtype, valtypmod,
7887 }
7888
7889 return value;
7890}

References do_cast_value(), fb(), and value.

Referenced by exec_assign_value(), exec_eval_boolean(), exec_eval_integer(), exec_move_row_from_fields(), exec_stmt_fori(), exec_stmt_return_next(), plpgsql_estate_setup(), and plpgsql_exec_function().

◆ exec_check_assignable()

static void exec_check_assignable ( PLpgSQL_execstate estate,
int  dno 
)
static

Definition at line 8557 of file pl_exec.c.

8558{
8559 PLpgSQL_datum *datum;
8560
8561 Assert(dno >= 0 && dno < estate->ndatums);
8562 datum = estate->datums[dno];
8563 switch (datum->dtype)
8564 {
8565 case PLPGSQL_DTYPE_VAR:
8567 case PLPGSQL_DTYPE_REC:
8568 if (((PLpgSQL_variable *) datum)->isconst)
8569 ereport(ERROR,
8571 errmsg("variable \"%s\" is declared CONSTANT",
8572 ((PLpgSQL_variable *) datum)->refname)));
8573 break;
8574 case PLPGSQL_DTYPE_ROW:
8575 /* always assignable; member vars were checked at compile time */
8576 break;
8578 /* assignable if parent record is */
8579 exec_check_assignable(estate,
8580 ((PLpgSQL_recfield *) datum)->recparentno);
8581 break;
8582 default:
8583 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
8584 break;
8585 }
8586}

References Assert, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, PLpgSQL_variable::dtype, elog, ereport, errcode(), errmsg(), ERROR, exec_check_assignable(), fb(), PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, and PLPGSQL_DTYPE_VAR.

Referenced by exec_check_assignable(), exec_stmt_forc(), exec_stmt_open(), and make_callstmt_target().

◆ exec_check_rw_parameter()

static void exec_check_rw_parameter ( PLpgSQL_expr expr,
int  paramid 
)
static

Definition at line 8400 of file pl_exec.c.

8401{
8402 Expr *sexpr = expr->expr_simple_expr;
8403 Oid funcid;
8404 List *fargs;
8406
8407 /* Assume unsafe */
8409 expr->expr_rw_param = NULL;
8410
8411 /* Shouldn't be here for non-simple expression */
8412 Assert(sexpr != NULL);
8413
8414 /* Param should match the expression's assignment target, too */
8415 Assert(paramid == expr->target_param + 1);
8416
8417 /*
8418 * If the assignment is to a "local" variable (one whose value won't
8419 * matter anymore if expression evaluation fails), and this Param is the
8420 * only reference to that variable in the expression, then we can
8421 * unconditionally optimize using the "transfer" method.
8422 */
8423 if (expr->target_is_local)
8424 {
8426
8427 /* See how many references there are, and find one of them */
8428 context.paramid = paramid;
8429 context.count = 0;
8430 context.last_param = NULL;
8431 (void) count_param_references((Node *) sexpr, &context);
8432
8433 /* If we're here, the expr must contain some reference to the var */
8434 Assert(context.count > 0);
8435
8436 /* If exactly one reference, success! */
8437 if (context.count == 1)
8438 {
8440 expr->expr_rw_param = context.last_param;
8441 return;
8442 }
8443 }
8444
8445 /*
8446 * Otherwise, see if we can trust the expression's top-level function to
8447 * apply the "inplace" method.
8448 *
8449 * Top level of expression must be a simple FuncExpr, OpExpr, or
8450 * SubscriptingRef, else we can't identify which function is relevant. But
8451 * it's okay to look through any RelabelType above that, since that can't
8452 * fail.
8453 */
8454 if (IsA(sexpr, RelabelType))
8455 sexpr = ((RelabelType *) sexpr)->arg;
8456 if (IsA(sexpr, FuncExpr))
8457 {
8459
8460 funcid = fexpr->funcid;
8461 fargs = fexpr->args;
8462 }
8463 else if (IsA(sexpr, OpExpr))
8464 {
8465 OpExpr *opexpr = (OpExpr *) sexpr;
8466
8467 funcid = opexpr->opfuncid;
8468 fargs = opexpr->args;
8469 }
8470 else if (IsA(sexpr, SubscriptingRef))
8471 {
8473
8474 funcid = get_typsubscript(sbsref->refcontainertype, NULL);
8475
8476 /*
8477 * We assume that only the refexpr and refassgnexpr (if any) are
8478 * relevant to the support function's decision. If that turns out to
8479 * be a bad idea, we could incorporate the subscript expressions into
8480 * the fargs list somehow.
8481 */
8482 fargs = list_make2(sbsref->refexpr, sbsref->refassgnexpr);
8483 }
8484 else
8485 return;
8486
8487 /*
8488 * The top-level function must be one that can handle in-place update
8489 * safely. We allow functions to declare their ability to do that via a
8490 * support function request.
8491 */
8492 prosupport = get_func_support(funcid);
8494 {
8496 Param *param;
8497
8499 req.funcid = funcid;
8500 req.args = fargs;
8501 req.paramid = paramid;
8502
8503 param = (Param *)
8505 PointerGetDatum(&req)));
8506
8507 if (param == NULL)
8508 return; /* support function fails */
8509
8510 /* Verify support function followed the API */
8511 Assert(IsA(param, Param));
8512 Assert(param->paramkind == PARAM_EXTERN);
8513 Assert(param->paramid == paramid);
8514
8515 /* Found the Param we want to pass as read/write */
8517 expr->expr_rw_param = param;
8518 return;
8519 }
8520}

References OpExpr::args, Assert, count_param_references_context::count, count_param_references(), DatumGetPointer(), PLpgSQL_expr::expr_rw_param, PLpgSQL_expr::expr_rwopt, PLpgSQL_expr::expr_simple_expr, fb(), FuncExpr::funcid, get_func_support(), get_typsubscript(), IsA, count_param_references_context::last_param, list_make2, OidFunctionCall1, OidIsValid, PARAM_EXTERN, Param::paramid, count_param_references_context::paramid, Param::paramkind, PLPGSQL_RWOPT_INPLACE, PLPGSQL_RWOPT_NOPE, PLPGSQL_RWOPT_TRANSFER, PointerGetDatum(), SubscriptingRef::refassgnexpr, SubscriptingRef::refexpr, PLpgSQL_expr::target_is_local, and PLpgSQL_expr::target_param.

Referenced by plpgsql_param_eval_var_check().

◆ exec_dynquery_with_params()

static Portal exec_dynquery_with_params ( PLpgSQL_execstate estate,
PLpgSQL_expr dynquery,
List params,
const char portalname,
int  cursorOptions 
)
static

Definition at line 8959 of file pl_exec.c.

8964{
8965 Portal portal;
8966 Datum query;
8967 bool isnull;
8968 Oid restype;
8970 char *querystr;
8972 MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
8973
8974 /*
8975 * Evaluate the string expression after the EXECUTE keyword. Its result is
8976 * the querystring we have to execute.
8977 */
8978 query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod);
8979 if (isnull)
8980 ereport(ERROR,
8982 errmsg("query string argument of EXECUTE is null")));
8983
8984 /* Get the C-String representation */
8985 querystr = convert_value_to_string(estate, query, restype);
8986
8987 /* copy it into the stmt_mcontext before we clean up */
8988 querystr = MemoryContextStrdup(stmt_mcontext, querystr);
8989
8990 exec_eval_cleanup(estate);
8991
8992 /*
8993 * Open an implicit cursor for the query. We use SPI_cursor_parse_open
8994 * even when there are no params, because this avoids making and freeing
8995 * one copy of the plan.
8996 */
8997 memset(&options, 0, sizeof(options));
8998 options.params = exec_eval_using_params(estate, params);
8999 options.cursorOptions = cursorOptions;
9000 options.read_only = estate->readonly_func;
9001
9002 portal = SPI_cursor_parse_open(portalname, querystr, &options);
9003
9004 if (portal == NULL)
9005 elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
9007
9008 /* Release transient data */
9009 MemoryContextReset(stmt_mcontext);
9010
9011 return portal;
9012}

References convert_value_to_string(), elog, ereport, errcode(), errmsg(), ERROR, exec_eval_cleanup(), exec_eval_expr(), exec_eval_using_params(), fb(), get_stmt_mcontext(), MemoryContextReset(), MemoryContextStrdup(), PLpgSQL_execstate::readonly_func, SPI_cursor_parse_open(), SPI_result, and SPI_result_code_string().

Referenced by exec_stmt_dynfors(), and exec_stmt_open().

◆ exec_eval_boolean()

static bool exec_eval_boolean ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull 
)
static

Definition at line 5641 of file pl_exec.c.

5644{
5648
5649 exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5650 exprdatum = exec_cast_value(estate, exprdatum, isNull,
5652 BOOLOID, -1);
5653 return DatumGetBool(exprdatum);
5654}

References DatumGetBool(), exec_cast_value(), exec_eval_expr(), and fb().

Referenced by exec_stmt_assert(), exec_stmt_case(), exec_stmt_exit(), exec_stmt_if(), and exec_stmt_while().

◆ exec_eval_cleanup()

◆ exec_eval_datum()

static void exec_eval_datum ( PLpgSQL_execstate estate,
PLpgSQL_datum datum,
Oid typeid,
int32 typetypmod,
Datum value,
bool isnull 
)
static

Definition at line 5287 of file pl_exec.c.

5293{
5294 MemoryContext oldcontext;
5295
5296 switch (datum->dtype)
5297 {
5299 /* fulfill promise if needed, then handle like regular var */
5300 plpgsql_fulfill_promise(estate, (PLpgSQL_var *) datum);
5301
5303
5304 case PLPGSQL_DTYPE_VAR:
5305 {
5306 PLpgSQL_var *var = (PLpgSQL_var *) datum;
5307
5308 *typeid = var->datatype->typoid;
5309 *typetypmod = var->datatype->atttypmod;
5310 *value = var->value;
5311 *isnull = var->isnull;
5312 break;
5313 }
5314
5315 case PLPGSQL_DTYPE_ROW:
5316 {
5317 PLpgSQL_row *row = (PLpgSQL_row *) datum;
5318 HeapTuple tup;
5319
5320 /* We get here if there are multiple OUT parameters */
5321 if (!row->rowtupdesc) /* should not happen */
5322 elog(ERROR, "row variable has no tupdesc");
5323 /* Make sure we have a valid type/typmod setting */
5325 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5326 tup = make_tuple_from_row(estate, row, row->rowtupdesc);
5327 if (tup == NULL) /* should not happen */
5328 elog(ERROR, "row not compatible with its own tupdesc");
5329 *typeid = row->rowtupdesc->tdtypeid;
5332 *isnull = false;
5333 MemoryContextSwitchTo(oldcontext);
5334 break;
5335 }
5336
5337 case PLPGSQL_DTYPE_REC:
5338 {
5339 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5340
5341 if (rec->erh == NULL)
5342 {
5343 /* Treat uninstantiated record as a simple NULL */
5344 *value = (Datum) 0;
5345 *isnull = true;
5346 /* Report variable's declared type */
5347 *typeid = rec->rectypeid;
5348 *typetypmod = -1;
5349 }
5350 else
5351 {
5352 if (ExpandedRecordIsEmpty(rec->erh))
5353 {
5354 /* Empty record is also a NULL */
5355 *value = (Datum) 0;
5356 *isnull = true;
5357 }
5358 else
5359 {
5361 *isnull = false;
5362 }
5363 if (rec->rectypeid != RECORDOID)
5364 {
5365 /* Report variable's declared type, if not RECORD */
5366 *typeid = rec->rectypeid;
5367 *typetypmod = -1;
5368 }
5369 else
5370 {
5371 /* Report record's actual type if declared RECORD */
5372 *typeid = rec->erh->er_typeid;
5373 *typetypmod = rec->erh->er_typmod;
5374 }
5375 }
5376 break;
5377 }
5378
5380 {
5382 PLpgSQL_rec *rec;
5384
5385 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5386 erh = rec->erh;
5387
5388 /*
5389 * If record variable is NULL, instantiate it if it has a
5390 * named composite type, else complain. (This won't change
5391 * the logical state of the record: it's still NULL.)
5392 */
5393 if (erh == NULL)
5394 {
5396 erh = rec->erh;
5397 }
5398
5399 /*
5400 * Look up the field's properties if we have not already, or
5401 * if the tuple descriptor ID changed since last time.
5402 */
5403 if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
5404 {
5406 recfield->fieldname,
5407 &recfield->finfo))
5408 ereport(ERROR,
5410 errmsg("record \"%s\" has no field \"%s\"",
5411 rec->refname, recfield->fieldname)));
5412 recfield->rectupledescid = erh->er_tupdesc_id;
5413 }
5414
5415 /* Report type data. */
5416 *typeid = recfield->finfo.ftypeid;
5417 *typetypmod = recfield->finfo.ftypmod;
5418
5419 /* And fetch the field value. */
5421 recfield->finfo.fnumber,
5422 isnull);
5423 break;
5424 }
5425
5426 default:
5427 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5428 }
5429}

References PLpgSQL_type::atttypmod, BlessTupleDesc(), PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, PLpgSQL_var::dtype, elog, ExpandedRecordHeader::er_tupdesc_id, ExpandedRecordHeader::er_typeid, ExpandedRecordHeader::er_typmod, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, expanded_record_get_field(), expanded_record_lookup_field(), ExpandedRecordGetDatum(), ExpandedRecordIsEmpty, fb(), get_eval_mcontext, HeapTupleGetDatum(), instantiate_empty_record_variable(), PLpgSQL_var::isnull, make_tuple_from_row(), MemoryContextSwitchTo(), pg_fallthrough, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, plpgsql_fulfill_promise(), PLpgSQL_rec::rectypeid, PLpgSQL_rec::refname, PLpgSQL_row::rowtupdesc, TupleDescData::tdtypeid, TupleDescData::tdtypmod, PLpgSQL_type::typoid, unlikely, value, and PLpgSQL_var::value.

Referenced by exec_stmt_return(), format_expr_params(), make_tuple_from_row(), plpgsql_estate_setup(), plpgsql_param_eval_generic(), plpgsql_param_eval_generic_ro(), and plpgsql_param_fetch().

◆ exec_eval_expr()

static Datum exec_eval_expr ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull,
Oid rettype,
int32 rettypmod 
)
static

Definition at line 5664 of file pl_exec.c.

5669{
5670 Datum result = 0;
5671 int rc;
5672 Form_pg_attribute attr;
5673
5674 /*
5675 * If first time through, create a plan for this expression.
5676 */
5677 if (expr->plan == NULL)
5679
5680 /*
5681 * If this is a simple expression, bypass SPI and use the executor
5682 * directly
5683 */
5684 if (exec_eval_simple_expr(estate, expr,
5685 &result, isNull, rettype, rettypmod))
5686 return result;
5687
5688 /*
5689 * Else do it the hard way via exec_run_select
5690 */
5691 rc = exec_run_select(estate, expr, 0, NULL);
5692 if (rc != SPI_OK_SELECT)
5693 ereport(ERROR,
5695 errmsg("query did not return data"),
5696 errcontext("query: %s", expr->query)));
5697
5698 /*
5699 * Check that the expression returns exactly one column...
5700 */
5701 if (estate->eval_tuptable->tupdesc->natts != 1)
5702 ereport(ERROR,
5704 errmsg_plural("query returned %d column",
5705 "query returned %d columns",
5706 estate->eval_tuptable->tupdesc->natts,
5707 estate->eval_tuptable->tupdesc->natts),
5708 errcontext("query: %s", expr->query)));
5709
5710 /*
5711 * ... and get the column's datatype.
5712 */
5713 attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0);
5714 *rettype = attr->atttypid;
5715 *rettypmod = attr->atttypmod;
5716
5717 /*
5718 * If there are no rows selected, the result is a NULL of that type.
5719 */
5720 if (estate->eval_processed == 0)
5721 {
5722 *isNull = true;
5723 return (Datum) 0;
5724 }
5725
5726 /*
5727 * Check that the expression returned no more than one row.
5728 */
5729 if (estate->eval_processed != 1)
5730 ereport(ERROR,
5732 errmsg("query returned more than one row"),
5733 errcontext("query: %s", expr->query)));
5734
5735 /*
5736 * Return the single result Datum.
5737 */
5738 return SPI_getbinval(estate->eval_tuptable->vals[0],
5739 estate->eval_tuptable->tupdesc, 1, isNull);
5740}

References CURSOR_OPT_PARALLEL_OK, ereport, errcode(), errcontext, errmsg(), errmsg_plural(), ERROR, PLpgSQL_execstate::eval_processed, PLpgSQL_execstate::eval_tuptable, exec_eval_simple_expr(), exec_prepare_plan(), exec_run_select(), fb(), TupleDescData::natts, PLpgSQL_expr::plan, PLpgSQL_expr::query, SPI_getbinval(), SPI_OK_SELECT, SPITupleTable::tupdesc, TupleDescAttr(), and SPITupleTable::vals.

Referenced by exec_assign_expr(), exec_dynquery_with_params(), exec_eval_boolean(), exec_eval_integer(), exec_eval_using_params(), exec_stmt_assert(), exec_stmt_case(), exec_stmt_dynexecute(), exec_stmt_foreach_a(), exec_stmt_fori(), exec_stmt_raise(), exec_stmt_return(), exec_stmt_return_next(), and exec_stmt_return_query().

◆ exec_eval_integer()

static int exec_eval_integer ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull 
)
static

Definition at line 5618 of file pl_exec.c.

5621{
5625
5626 exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5627 exprdatum = exec_cast_value(estate, exprdatum, isNull,
5629 INT4OID, -1);
5630 return DatumGetInt32(exprdatum);
5631}

References DatumGetInt32(), exec_cast_value(), exec_eval_expr(), and fb().

Referenced by exec_stmt_fetch().

◆ exec_eval_simple_expr()

static bool exec_eval_simple_expr ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
Datum result,
bool isNull,
Oid rettype,
int32 rettypmod 
)
static

Definition at line 6018 of file pl_exec.c.

6024{
6025 ExprContext *econtext = estate->eval_econtext;
6027 ParamListInfo paramLI;
6028 void *save_setup_arg;
6029 bool need_snapshot;
6030 MemoryContext oldcontext;
6031
6032 /*
6033 * Forget it if expression wasn't simple before.
6034 */
6035 if (expr->expr_simple_expr == NULL)
6036 return false;
6037
6038 /*
6039 * If expression is in use in current xact, don't touch it.
6040 */
6041 if (unlikely(expr->expr_simple_in_use) &&
6042 expr->expr_simple_lxid == curlxid)
6043 return false;
6044
6045 /*
6046 * Ensure that there's a portal-level snapshot, in case this simple
6047 * expression is the first thing evaluated after a COMMIT or ROLLBACK.
6048 * We'd have to do this anyway before executing the expression, so we
6049 * might as well do it now to ensure that any possible replanning doesn't
6050 * need to take a new snapshot.
6051 */
6053
6054 /*
6055 * Check to see if the cached plan has been invalidated. If not, and this
6056 * is the first use in the current transaction, save a plan refcount in
6057 * the simple-expression resowner.
6058 */
6060 expr->expr_simple_plan,
6061 (expr->expr_simple_plan_lxid != curlxid ?
6062 estate->simple_eval_resowner : NULL))))
6063 {
6064 /*
6065 * It's still good, so just remember that we have a refcount on the
6066 * plan in the current transaction. (If we already had one, this
6067 * assignment is a no-op.)
6068 */
6070 }
6071 else
6072 {
6073 /* Need to replan */
6074 CachedPlan *cplan;
6075
6076 /*
6077 * If we have a valid refcount on some previous version of the plan,
6078 * release it, so we don't leak plans intra-transaction.
6079 */
6080 if (expr->expr_simple_plan_lxid == curlxid)
6082 estate->simple_eval_resowner);
6083
6084 /*
6085 * Reset to "not simple" to leave sane state (with no dangling
6086 * pointers) in case we fail while replanning. We'll need to
6087 * re-determine simplicity and R/W optimizability anyway, since those
6088 * could change with the new plan. expr_simple_plansource can be left
6089 * alone however, as that cannot move.
6090 */
6091 expr->expr_simple_expr = NULL;
6093 expr->expr_rw_param = NULL;
6094 expr->expr_simple_plan = NULL;
6096
6097 /* Do the replanning work in the eval_mcontext */
6098 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6099 cplan = SPI_plan_get_cached_plan(expr->plan);
6100 MemoryContextSwitchTo(oldcontext);
6101
6102 /*
6103 * We can't get a failure here, because the number of
6104 * CachedPlanSources in the SPI plan can't change from what
6105 * exec_simple_check_plan saw; it's a property of the raw parsetree
6106 * generated from the query text.
6107 */
6108 Assert(cplan != NULL);
6109
6110 /*
6111 * Recheck exec_is_simple_query, which could now report false in
6112 * edge-case scenarios such as a non-SRF having been replaced with a
6113 * SRF. Also recheck CachedPlanAllowsSimpleValidityCheck, just to be
6114 * sure. If either test fails, cope by declaring the plan to be
6115 * non-simple. On success, we'll acquire a refcount on the new plan,
6116 * stored in simple_eval_resowner.
6117 */
6118 if (exec_is_simple_query(expr) &&
6120 cplan,
6121 estate->simple_eval_resowner))
6122 {
6123 /* Remember that we have the refcount */
6124 expr->expr_simple_plan = cplan;
6126 }
6127 else
6128 {
6129 /* Release SPI_plan_get_cached_plan's refcount */
6131 return false;
6132 }
6133
6134 /*
6135 * SPI_plan_get_cached_plan acquired a plan refcount stored in the
6136 * active resowner. We don't need that anymore, so release it.
6137 */
6139
6140 /* Extract desired scalar expression from cached plan */
6141 exec_save_simple_expr(expr, cplan);
6142 }
6143
6144 /*
6145 * Pass back previously-determined result type.
6146 */
6147 *rettype = expr->expr_simple_type;
6149
6150 /*
6151 * Set up ParamListInfo to pass to executor. For safety, save and restore
6152 * estate->paramLI->parserSetupArg around our use of the param list.
6153 */
6154 paramLI = estate->paramLI;
6155 save_setup_arg = paramLI->parserSetupArg;
6156
6157 /*
6158 * We can skip using setup_param_list() in favor of just doing this
6159 * unconditionally, because there's no need for the optimization of
6160 * possibly setting ecxt_param_list_info to NULL; we've already forced use
6161 * of a generic plan.
6162 */
6163 paramLI->parserSetupArg = expr;
6164 econtext->ecxt_param_list_info = paramLI;
6165
6166 /*
6167 * Prepare the expression for execution, if it's not been done already in
6168 * the current transaction. (This will be forced to happen if we called
6169 * exec_save_simple_expr above.)
6170 */
6171 if (unlikely(expr->expr_simple_lxid != curlxid))
6172 {
6174 expr->expr_simple_state =
6176 econtext->ecxt_param_list_info);
6177 expr->expr_simple_in_use = false;
6178 expr->expr_simple_lxid = curlxid;
6179 MemoryContextSwitchTo(oldcontext);
6180 }
6181
6182 /*
6183 * We have to do some of the things SPI_execute_plan would do, in
6184 * particular push a new snapshot so that stable functions within the
6185 * expression can see updates made so far by our own function. However,
6186 * we can skip doing that (and just invoke the expression with the same
6187 * snapshot passed to our function) in some cases, which is useful because
6188 * it's quite expensive relative to the cost of a simple expression. We
6189 * can skip it if the expression contains no stable or volatile functions;
6190 * immutable functions shouldn't need to see our updates. Also, if this
6191 * is a read-only function, we haven't made any updates so again it's okay
6192 * to skip.
6193 */
6194 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6195 need_snapshot = (expr->expr_simple_mutable && !estate->readonly_func);
6196 if (need_snapshot)
6197 {
6200 }
6201
6202 /*
6203 * Mark expression as busy for the duration of the ExecEvalExpr call.
6204 */
6205 expr->expr_simple_in_use = true;
6206
6207 /*
6208 * Finally we can call the executor to evaluate the expression
6209 */
6210 *result = ExecEvalExpr(expr->expr_simple_state,
6211 econtext,
6212 isNull);
6213
6214 /* Assorted cleanup */
6215 expr->expr_simple_in_use = false;
6216
6217 econtext->ecxt_param_list_info = NULL;
6218
6219 paramLI->parserSetupArg = save_setup_arg;
6220
6221 if (need_snapshot)
6223
6224 MemoryContextSwitchTo(oldcontext);
6225
6226 /*
6227 * That's it.
6228 */
6229 return true;
6230}

References Assert, CachedPlanAllowsSimpleValidityCheck(), CachedPlanIsSimplyValid(), CommandCounterIncrement(), CurrentResourceOwner, ExprContext::ecxt_param_list_info, EnsurePortalSnapshotExists(), EState::es_query_cxt, PLpgSQL_execstate::eval_econtext, exec_is_simple_query(), exec_save_simple_expr(), ExecEvalExpr(), ExecInitExprWithParams(), PLpgSQL_expr::expr_rw_param, PLpgSQL_expr::expr_rwopt, PLpgSQL_expr::expr_simple_expr, PLpgSQL_expr::expr_simple_in_use, PLpgSQL_expr::expr_simple_lxid, PLpgSQL_expr::expr_simple_mutable, PLpgSQL_expr::expr_simple_plan, PLpgSQL_expr::expr_simple_plan_lxid, PLpgSQL_expr::expr_simple_plansource, PLpgSQL_expr::expr_simple_state, PLpgSQL_expr::expr_simple_type, PLpgSQL_expr::expr_simple_typmod, fb(), get_eval_mcontext, GetTransactionSnapshot(), InvalidLocalTransactionId, likely, PGPROC::lxid, MemoryContextSwitchTo(), MyProc, PLpgSQL_execstate::paramLI, ParamListInfoData::parserSetupArg, PLpgSQL_expr::plan, PLPGSQL_RWOPT_UNKNOWN, PopActiveSnapshot(), PushActiveSnapshot(), PLpgSQL_execstate::readonly_func, ReleaseCachedPlan(), PLpgSQL_execstate::simple_eval_estate, PLpgSQL_execstate::simple_eval_resowner, SPI_plan_get_cached_plan(), unlikely, and PGPROC::vxid.

Referenced by exec_eval_expr().

◆ exec_eval_using_params()

static ParamListInfo exec_eval_using_params ( PLpgSQL_execstate estate,
List params 
)
static

Definition at line 8877 of file pl_exec.c.

8878{
8879 ParamListInfo paramLI;
8880 int nargs;
8881 MemoryContext stmt_mcontext;
8882 MemoryContext oldcontext;
8883 int i;
8884 ListCell *lc;
8885
8886 /* Fast path for no parameters: we can just return NULL */
8887 if (params == NIL)
8888 return NULL;
8889
8890 nargs = list_length(params);
8891 stmt_mcontext = get_stmt_mcontext(estate);
8892 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
8893 paramLI = makeParamList(nargs);
8894 MemoryContextSwitchTo(oldcontext);
8895
8896 i = 0;
8897 foreach(lc, params)
8898 {
8899 PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
8900 ParamExternData *prm = &paramLI->params[i];
8902
8903 /*
8904 * Always mark params as const, since we only use the result with
8905 * one-shot plans.
8906 */
8908
8909 prm->value = exec_eval_expr(estate, param,
8910 &prm->isnull,
8911 &prm->ptype,
8912 &ppdtypmod);
8913
8914 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
8915
8916 if (prm->ptype == UNKNOWNOID)
8917 {
8918 /*
8919 * Treat 'unknown' parameters as text, since that's what most
8920 * people would expect. The SPI functions can coerce unknown
8921 * constants in a more intelligent way, but not unknown Params.
8922 * This code also takes care of copying into the right context.
8923 * Note we assume 'unknown' has the representation of C-string.
8924 */
8925 prm->ptype = TEXTOID;
8926 if (!prm->isnull)
8927 prm->value = CStringGetTextDatum(DatumGetCString(prm->value));
8928 }
8929 /* pass-by-ref non null values must be copied into stmt_mcontext */
8930 else if (!prm->isnull)
8931 {
8932 int16 typLen;
8933 bool typByVal;
8934
8935 get_typlenbyval(prm->ptype, &typLen, &typByVal);
8936 if (!typByVal)
8937 prm->value = datumCopy(prm->value, typByVal, typLen);
8938 }
8939
8940 MemoryContextSwitchTo(oldcontext);
8941
8942 exec_eval_cleanup(estate);
8943
8944 i++;
8945 }
8946
8947 return paramLI;
8948}

References CStringGetTextDatum, datumCopy(), DatumGetCString(), exec_eval_cleanup(), exec_eval_expr(), fb(), get_stmt_mcontext(), get_typlenbyval(), i, lfirst, list_length(), makeParamList(), MemoryContextSwitchTo(), NIL, PARAM_FLAG_CONST, ParamListInfoData::params, and ParamExternData::pflags.

Referenced by exec_dynquery_with_params(), exec_stmt_dynexecute(), and exec_stmt_return_query().

◆ exec_for_query()

static int exec_for_query ( PLpgSQL_execstate estate,
PLpgSQL_stmt_forq stmt,
Portal  portal,
bool  prefetch_ok 
)
static

Definition at line 5836 of file pl_exec.c.

5838{
5839 PLpgSQL_variable *var;
5841 bool found = false;
5842 int rc = PLPGSQL_RC_OK;
5844 bool tupdescs_match = true;
5845 uint64 n;
5846
5847 /* Fetch loop variable's datum entry */
5848 var = (PLpgSQL_variable *) estate->datums[stmt->var->dno];
5849
5850 /*
5851 * Make sure the portal doesn't get closed by the user statements we
5852 * execute.
5853 */
5854 PinPortal(portal);
5855
5856 /*
5857 * In a non-atomic context, we dare not prefetch, even if it would
5858 * otherwise be safe. Aside from any semantic hazards that that might
5859 * create, if we prefetch toasted data and then the user commits the
5860 * transaction, the toast references could turn into dangling pointers.
5861 * (Rows we haven't yet fetched from the cursor are safe, because the
5862 * PersistHoldablePortal mechanism handles this scenario.)
5863 */
5864 if (!estate->atomic)
5865 prefetch_ok = false;
5866
5867 /*
5868 * Fetch the initial tuple(s). If prefetching is allowed then we grab a
5869 * few more rows to avoid multiple trips through executor startup
5870 * overhead.
5871 */
5872 SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1);
5874 n = SPI_processed;
5875
5876 /*
5877 * If the query didn't return any rows, set the target to NULL and fall
5878 * through with found = false.
5879 */
5880 if (n == 0)
5881 {
5882 exec_move_row(estate, var, NULL, tuptab->tupdesc);
5883 exec_eval_cleanup(estate);
5884 }
5885 else
5886 found = true; /* processed at least one tuple */
5887
5888 /*
5889 * Now do the loop
5890 */
5891 while (n > 0)
5892 {
5893 uint64 i;
5894
5895 for (i = 0; i < n; i++)
5896 {
5897 /*
5898 * Assign the tuple to the target. Here, because we know that all
5899 * loop iterations should be assigning the same tupdesc, we can
5900 * optimize away repeated creations of expanded records with
5901 * identical tupdescs. Testing for changes of er_tupdesc_id is
5902 * reliable even if the loop body contains assignments that
5903 * replace the target's value entirely, because it's assigned from
5904 * a process-global counter. The case where the tupdescs don't
5905 * match could possibly be handled more efficiently than this
5906 * coding does, but it's not clear extra effort is worthwhile.
5907 */
5908 if (var->dtype == PLPGSQL_DTYPE_REC)
5909 {
5910 PLpgSQL_rec *rec = (PLpgSQL_rec *) var;
5911
5912 if (rec->erh &&
5913 rec->erh->er_tupdesc_id == previous_id &&
5915 {
5916 /* Only need to assign a new tuple value */
5918 true, !estate->atomic);
5919 }
5920 else
5921 {
5922 /*
5923 * First time through, or var's tupdesc changed in loop,
5924 * or we have to do it the hard way because type coercion
5925 * is needed.
5926 */
5927 exec_move_row(estate, var,
5928 tuptab->vals[i], tuptab->tupdesc);
5929
5930 /*
5931 * Check to see if physical assignment is OK next time.
5932 * Once the tupdesc comparison has failed once, we don't
5933 * bother rechecking in subsequent loop iterations.
5934 */
5935 if (tupdescs_match)
5936 {
5938 (rec->rectypeid == RECORDOID ||
5939 rec->rectypeid == tuptab->tupdesc->tdtypeid ||
5940 compatible_tupdescs(tuptab->tupdesc,
5942 }
5944 }
5945 }
5946 else
5947 exec_move_row(estate, var, tuptab->vals[i], tuptab->tupdesc);
5948
5949 exec_eval_cleanup(estate);
5950
5951 /*
5952 * Execute the statements
5953 */
5954 rc = exec_stmts(estate, stmt->body);
5955
5956 LOOP_RC_PROCESSING(stmt->label, goto loop_exit);
5957 }
5958
5960
5961 /*
5962 * Fetch more tuples. If prefetching is allowed, grab 50 at a time.
5963 */
5964 SPI_cursor_fetch(portal, true, prefetch_ok ? 50 : 1);
5966 n = SPI_processed;
5967 }
5968
5969loop_exit:
5970
5971 /*
5972 * Release last group of tuples (if any)
5973 */
5975
5976 UnpinPortal(portal);
5977
5978 /*
5979 * Set the FOUND variable to indicate the result of executing the loop
5980 * (namely, whether we looped one or more times). This must be set last so
5981 * that it does not interfere with the value of the FOUND variable inside
5982 * the loop processing itself.
5983 */
5984 exec_set_found(estate, found);
5985
5986 return rc;
5987}

References PLpgSQL_execstate::atomic, compatible_tupdescs(), PLpgSQL_execstate::datums, PLpgSQL_variable::dtype, ExpandedRecordHeader::er_tupdesc_id, PLpgSQL_rec::erh, exec_eval_cleanup(), exec_move_row(), exec_set_found(), exec_stmts(), expanded_record_get_tupdesc(), expanded_record_set_tuple(), fb(), i, INVALID_TUPLEDESC_IDENTIFIER, LOOP_RC_PROCESSING, PinPortal(), PLPGSQL_DTYPE_REC, PLPGSQL_RC_OK, PLpgSQL_rec::rectypeid, SPI_cursor_fetch(), SPI_freetuptable(), SPI_processed, SPI_tuptable, stmt, and UnpinPortal().

Referenced by exec_stmt_dynfors(), exec_stmt_forc(), and exec_stmt_fors().

◆ exec_init_tuple_store()

static void exec_init_tuple_store ( PLpgSQL_execstate estate)
static

Definition at line 3668 of file pl_exec.c.

3669{
3670 ReturnSetInfo *rsi = estate->rsi;
3672 ResourceOwner oldowner;
3673
3674 /*
3675 * Check caller can handle a set result in the way we want
3676 */
3677 if (!rsi || !IsA(rsi, ReturnSetInfo))
3678 ereport(ERROR,
3680 errmsg("set-valued function called in context that cannot accept a set")));
3681
3682 if (!(rsi->allowedModes & SFRM_Materialize) ||
3683 rsi->expectedDesc == NULL)
3684 ereport(ERROR,
3686 errmsg("materialize mode required, but it is not allowed in this context")));
3687
3688 /*
3689 * Switch to the right memory context and resource owner for storing the
3690 * tuplestore for return set. If we're within a subtransaction opened for
3691 * an exception-block, for example, we must still create the tuplestore in
3692 * the resource owner that was active when this function was entered, and
3693 * not in the subtransaction resource owner.
3694 */
3696 oldowner = CurrentResourceOwner;
3698
3699 estate->tuple_store =
3701 false, work_mem);
3702
3703 CurrentResourceOwner = oldowner;
3705
3706 estate->tuple_store_desc = rsi->expectedDesc;
3707}

References ReturnSetInfo::allowedModes, CurrentResourceOwner, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, fb(), IsA, MemoryContextSwitchTo(), PLpgSQL_execstate::rsi, SFRM_Materialize, SFRM_Materialize_Random, PLpgSQL_execstate::tuple_store, PLpgSQL_execstate::tuple_store_cxt, PLpgSQL_execstate::tuple_store_desc, PLpgSQL_execstate::tuple_store_owner, tuplestore_begin_heap(), and work_mem.

Referenced by exec_stmt_return_next(), and exec_stmt_return_query().

◆ exec_is_simple_query()

static bool exec_is_simple_query ( PLpgSQL_expr expr)
static

Definition at line 8204 of file pl_exec.c.

8205{
8207 CachedPlanSource *plansource;
8208 Query *query;
8209
8210 /*
8211 * We can only test queries that resulted in exactly one CachedPlanSource.
8212 */
8214 if (list_length(plansources) != 1)
8215 return false;
8216 plansource = (CachedPlanSource *) linitial(plansources);
8217
8218 /*
8219 * 1. There must be one single querytree.
8220 */
8221 if (list_length(plansource->query_list) != 1)
8222 return false;
8223 query = (Query *) linitial(plansource->query_list);
8224
8225 /*
8226 * 2. It must be a plain SELECT query without any input tables.
8227 */
8228 if (!IsA(query, Query))
8229 return false;
8230 if (query->commandType != CMD_SELECT)
8231 return false;
8232 if (query->rtable != NIL)
8233 return false;
8234
8235 /*
8236 * 3. Can't have any subplans, aggregates, qual clauses either. (These
8237 * tests should generally match what inline_function() checks before
8238 * inlining a SQL function; otherwise, inlining could change our
8239 * conclusion about whether an expression is simple, which we don't want.)
8240 */
8241 if (query->hasAggs ||
8242 query->hasWindowFuncs ||
8243 query->hasTargetSRFs ||
8244 query->hasSubLinks ||
8245 query->cteList ||
8246 query->jointree->fromlist ||
8247 query->jointree->quals ||
8248 query->groupClause ||
8249 query->groupingSets ||
8250 query->havingQual ||
8251 query->windowClause ||
8252 query->distinctClause ||
8253 query->sortClause ||
8254 query->limitOffset ||
8255 query->limitCount ||
8256 query->setOperations)
8257 return false;
8258
8259 /*
8260 * 4. The query must have a single attribute as result.
8261 */
8262 if (list_length(query->targetList) != 1)
8263 return false;
8264
8265 /*
8266 * OK, we can treat it as a simple plan.
8267 */
8268 return true;
8269}

References CMD_SELECT, Query::commandType, Query::cteList, Query::distinctClause, fb(), FromExpr::fromlist, Query::groupClause, Query::groupingSets, Query::havingQual, IsA, Query::jointree, Query::limitCount, Query::limitOffset, linitial, list_length(), NIL, PLpgSQL_expr::plan, FromExpr::quals, CachedPlanSource::query_list, Query::rtable, Query::setOperations, Query::sortClause, SPI_plan_get_plan_sources(), Query::targetList, and Query::windowClause.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

◆ exec_move_row()

static void exec_move_row ( PLpgSQL_execstate estate,
PLpgSQL_variable target,
HeapTuple  tup,
TupleDesc  tupdesc 
)
static

Definition at line 6902 of file pl_exec.c.

6905{
6907
6908 /*
6909 * If target is RECORD, we may be able to avoid field-by-field processing.
6910 */
6911 if (target->dtype == PLPGSQL_DTYPE_REC)
6912 {
6913 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
6914
6915 /*
6916 * If we have no source tupdesc, just set the record variable to NULL.
6917 * (If we have a source tupdesc but not a tuple, we'll set the
6918 * variable to a row of nulls, instead. This is odd perhaps, but
6919 * backwards compatible.)
6920 */
6921 if (tupdesc == NULL)
6922 {
6923 if (rec->datatype &&
6925 {
6926 /*
6927 * If it's a composite domain, NULL might not be a legal
6928 * value, so we instead need to make an empty expanded record
6929 * and ensure that domain type checking gets done. If there
6930 * is already an expanded record, piggyback on its lookups.
6931 */
6933 NULL, rec->erh);
6934 expanded_record_set_tuple(newerh, NULL, false, false);
6935 assign_record_var(estate, rec, newerh);
6936 }
6937 else
6938 {
6939 /* Just clear it to NULL */
6940 if (rec->erh)
6942 rec->erh = NULL;
6943 }
6944 return;
6945 }
6946
6947 /*
6948 * Build a new expanded record with appropriate tupdesc.
6949 */
6950 newerh = make_expanded_record_for_rec(estate, rec, tupdesc, NULL);
6951
6952 /*
6953 * If the rowtypes match, or if we have no tuple anyway, we can
6954 * complete the assignment without field-by-field processing.
6955 *
6956 * The tests here are ordered more or less in order of cheapness. We
6957 * can easily detect it will work if the target is declared RECORD or
6958 * has the same typeid as the source. But when assigning from a query
6959 * result, it's common to have a source tupdesc that's labeled RECORD
6960 * but is actually physically compatible with a named-composite-type
6961 * target, so it's worth spending extra cycles to check for that.
6962 */
6963 if (rec->rectypeid == RECORDOID ||
6964 rec->rectypeid == tupdesc->tdtypeid ||
6967 {
6968 if (!HeapTupleIsValid(tup))
6969 {
6970 /* No data, so force the record into all-nulls state */
6972 }
6973 else
6974 {
6975 /* No coercion is needed, so just assign the row value */
6976 expanded_record_set_tuple(newerh, tup, true, !estate->atomic);
6977 }
6978
6979 /* Complete the assignment */
6980 assign_record_var(estate, rec, newerh);
6981
6982 return;
6983 }
6984 }
6985
6986 /*
6987 * Otherwise, deconstruct the tuple and do field-by-field assignment,
6988 * using exec_move_row_from_fields.
6989 */
6990 if (tupdesc && HeapTupleIsValid(tup))
6991 {
6992 int td_natts = tupdesc->natts;
6993 Datum *values;
6994 bool *nulls;
6995 Datum values_local[64];
6996 bool nulls_local[64];
6997
6998 /*
6999 * Need workspace arrays. If td_natts is small enough, use local
7000 * arrays to save doing a palloc. Even if it's not small, we can
7001 * allocate both the Datum and isnull arrays in one palloc chunk.
7002 */
7004 {
7006 nulls = nulls_local;
7007 }
7008 else
7009 {
7010 char *chunk;
7011
7012 chunk = eval_mcontext_alloc(estate,
7013 td_natts * (sizeof(Datum) + sizeof(bool)));
7014 values = (Datum *) chunk;
7015 nulls = (bool *) (chunk + td_natts * sizeof(Datum));
7016 }
7017
7018 heap_deform_tuple(tup, tupdesc, values, nulls);
7019
7020 exec_move_row_from_fields(estate, target, newerh,
7021 values, nulls, tupdesc);
7022 }
7023 else
7024 {
7025 /*
7026 * Assign all-nulls.
7027 */
7028 exec_move_row_from_fields(estate, target, newerh,
7029 NULL, NULL, NULL);
7030 }
7031}

References assign_record_var(), PLpgSQL_execstate::atomic, compatible_tupdescs(), PLpgSQL_rec::datatype, deconstruct_expanded_record(), DeleteExpandedObject(), PLpgSQL_variable::dtype, PLpgSQL_rec::erh, eval_mcontext_alloc, exec_move_row_from_fields(), expanded_record_get_tupdesc(), expanded_record_set_tuple(), ExpandedRecordGetDatum(), fb(), heap_deform_tuple(), HeapTupleIsValid, lengthof, make_expanded_record_for_rec(), TupleDescData::natts, PLPGSQL_DTYPE_REC, PLpgSQL_rec::rectypeid, TupleDescData::tdtypeid, PLpgSQL_type::typtype, and values.

Referenced by exec_assign_value(), exec_for_query(), exec_move_row_from_datum(), exec_stmt_block(), exec_stmt_call(), exec_stmt_dynexecute(), exec_stmt_execsql(), exec_stmt_fetch(), and plpgsql_exec_function().

◆ exec_move_row_from_datum()

static void exec_move_row_from_datum ( PLpgSQL_execstate estate,
PLpgSQL_variable target,
Datum  value 
)
static

Definition at line 7576 of file pl_exec.c.

7579{
7580 /* Check to see if source is an expanded record */
7582 {
7585
7586 Assert(erh->er_magic == ER_MAGIC);
7587
7588 /* These cases apply if the target is record not row... */
7589 if (target->dtype == PLPGSQL_DTYPE_REC)
7590 {
7591 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7592
7593 /*
7594 * If it's the same record already stored in the variable, do
7595 * nothing. This would happen only in silly cases like "r := r",
7596 * but we need some check to avoid possibly freeing the variable's
7597 * live value below. Note that this applies even if what we have
7598 * is a R/O pointer.
7599 */
7600 if (erh == rec->erh)
7601 return;
7602
7603 /*
7604 * Make sure rec->rectypeid is up-to-date before using it.
7605 */
7607
7608 /*
7609 * If we have a R/W pointer, we're allowed to just commandeer
7610 * ownership of the expanded record. If it's of the right type to
7611 * put into the record variable, do that. (Note we don't accept
7612 * an expanded record of a composite-domain type as a RECORD
7613 * value. We'll treat it as the base composite type instead;
7614 * compare logic in make_expanded_record_for_rec.)
7615 */
7617 (rec->rectypeid == erh->er_decltypeid ||
7618 (rec->rectypeid == RECORDOID &&
7619 !ExpandedRecordIsDomain(erh))))
7620 {
7621 assign_record_var(estate, rec, erh);
7622 return;
7623 }
7624
7625 /*
7626 * If we already have an expanded record object in the target
7627 * variable, and the source record contains a valid tuple
7628 * representation with the right rowtype, then we can skip making
7629 * a new expanded record and just assign the tuple with
7630 * expanded_record_set_tuple. (We can't do the equivalent if we
7631 * have to do field-by-field assignment, since that wouldn't be
7632 * atomic if there's an error.) We consider that there's a
7633 * rowtype match only if it's the same named composite type or
7634 * same registered rowtype; checking for matches of anonymous
7635 * rowtypes would be more expensive than this is worth.
7636 */
7637 if (rec->erh &&
7638 (erh->flags & ER_FLAG_FVALUE_VALID) &&
7639 erh->er_typeid == rec->erh->er_typeid &&
7640 (erh->er_typeid != RECORDOID ||
7641 (erh->er_typmod == rec->erh->er_typmod &&
7642 erh->er_typmod >= 0)))
7643 {
7645 true, !estate->atomic);
7646 return;
7647 }
7648
7649 /*
7650 * Otherwise we're gonna need a new expanded record object. Make
7651 * it here in hopes of piggybacking on the source object's
7652 * previous typcache lookup.
7653 */
7654 newerh = make_expanded_record_for_rec(estate, rec, NULL, erh);
7655
7656 /*
7657 * If the expanded record contains a valid tuple representation,
7658 * and we don't need rowtype conversion, then just copying the
7659 * tuple is probably faster than field-by-field processing. (This
7660 * isn't duplicative of the previous check, since here we will
7661 * catch the case where the record variable was previously empty.)
7662 */
7663 if ((erh->flags & ER_FLAG_FVALUE_VALID) &&
7664 (rec->rectypeid == RECORDOID ||
7665 rec->rectypeid == erh->er_typeid))
7666 {
7668 true, !estate->atomic);
7669 assign_record_var(estate, rec, newerh);
7670 return;
7671 }
7672
7673 /*
7674 * Need to special-case empty source record, else code below would
7675 * leak newerh.
7676 */
7677 if (ExpandedRecordIsEmpty(erh))
7678 {
7679 /* Set newerh to a row of NULLs */
7681 assign_record_var(estate, rec, newerh);
7682 return;
7683 }
7684 } /* end of record-target-only cases */
7685
7686 /*
7687 * If the source expanded record is empty, we should treat that like a
7688 * NULL tuple value. (We're unlikely to see such a case, but we must
7689 * check this; deconstruct_expanded_record would cause a change of
7690 * logical state, which is not OK.)
7691 */
7692 if (ExpandedRecordIsEmpty(erh))
7693 {
7694 exec_move_row(estate, target, NULL,
7696 return;
7697 }
7698
7699 /*
7700 * Otherwise, ensure that the source record is deconstructed, and
7701 * assign from its field values.
7702 */
7704 exec_move_row_from_fields(estate, target, newerh,
7705 erh->dvalues, erh->dnulls,
7707 }
7708 else
7709 {
7710 /*
7711 * Nope, we've got a plain composite Datum. Deconstruct it; but we
7712 * don't use deconstruct_composite_datum(), because we may be able to
7713 * skip calling lookup_rowtype_tupdesc().
7714 */
7715 HeapTupleHeader td;
7717 Oid tupType;
7719 TupleDesc tupdesc;
7720 MemoryContext oldcontext;
7721
7722 /* Ensure that any detoasted data winds up in the eval_mcontext */
7723 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7724 /* Get tuple body (note this could involve detoasting) */
7726 MemoryContextSwitchTo(oldcontext);
7727
7728 /* Build a temporary HeapTuple control structure */
7730 ItemPointerSetInvalid(&(tmptup.t_self));
7731 tmptup.t_tableOid = InvalidOid;
7732 tmptup.t_data = td;
7733
7734 /* Extract rowtype info */
7737
7738 /* Now, if the target is record not row, maybe we can optimize ... */
7739 if (target->dtype == PLPGSQL_DTYPE_REC)
7740 {
7741 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7742
7743 /*
7744 * If we already have an expanded record object in the target
7745 * variable, and the source datum has a matching rowtype, then we
7746 * can skip making a new expanded record and just assign the tuple
7747 * with expanded_record_set_tuple. We consider that there's a
7748 * rowtype match only if it's the same named composite type or
7749 * same registered rowtype. (Checking to reject an anonymous
7750 * rowtype here should be redundant, but let's be safe.)
7751 */
7752 if (rec->erh &&
7753 tupType == rec->erh->er_typeid &&
7754 (tupType != RECORDOID ||
7755 (tupTypmod == rec->erh->er_typmod &&
7756 tupTypmod >= 0)))
7757 {
7759 true, !estate->atomic);
7760 return;
7761 }
7762
7763 /*
7764 * If the source datum has a rowtype compatible with the target
7765 * variable, just build a new expanded record and assign the tuple
7766 * into it. Using make_expanded_record_from_typeid() here saves
7767 * one typcache lookup compared to the code below.
7768 */
7769 if (rec->rectypeid == RECORDOID || rec->rectypeid == tupType)
7770 {
7772 MemoryContext mcontext = get_eval_mcontext(estate);
7773
7775 mcontext);
7777 true, !estate->atomic);
7778 assign_record_var(estate, rec, newerh);
7779 return;
7780 }
7781
7782 /*
7783 * Otherwise, we're going to need conversion, so fall through to
7784 * do it the hard way.
7785 */
7786 }
7787
7788 /*
7789 * ROW target, or unoptimizable RECORD target, so we have to expend a
7790 * lookup to obtain the source datum's tupdesc.
7791 */
7793
7794 /* Do the move */
7795 exec_move_row(estate, target, &tmptup, tupdesc);
7796
7797 /* Release tupdesc usage count */
7798 ReleaseTupleDesc(tupdesc);
7799 }
7800}

References Assert, assign_record_var(), PLpgSQL_execstate::atomic, DatumGetEOHP(), DatumGetHeapTupleHeader, DatumGetPointer(), deconstruct_expanded_record(), ExpandedRecordHeader::dnulls, PLpgSQL_variable::dtype, ExpandedRecordHeader::dvalues, ExpandedRecordHeader::er_decltypeid, ER_FLAG_FVALUE_VALID, ER_MAGIC, ExpandedRecordHeader::er_magic, ExpandedRecordHeader::er_typeid, ExpandedRecordHeader::er_typmod, PLpgSQL_rec::erh, exec_move_row(), exec_move_row_from_fields(), expanded_record_get_tupdesc(), expanded_record_set_tuple(), ExpandedRecordIsDomain, ExpandedRecordIsEmpty, fb(), ExpandedRecordHeader::flags, ExpandedRecordHeader::fvalue, get_eval_mcontext, HeapTupleHeaderGetDatumLength(), HeapTupleHeaderGetTypeId(), HeapTupleHeaderGetTypMod(), InvalidOid, ItemPointerSetInvalid(), lookup_rowtype_tupdesc(), make_expanded_record_for_rec(), make_expanded_record_from_typeid(), MemoryContextSwitchTo(), PLPGSQL_DTYPE_REC, PLpgSQL_rec::rectypeid, ReleaseTupleDesc, revalidate_rectypeid(), value, VARATT_IS_EXTERNAL_EXPANDED(), and VARATT_IS_EXTERNAL_EXPANDED_RW().

Referenced by exec_assign_value(), and plpgsql_exec_function().

◆ exec_move_row_from_fields()

static void exec_move_row_from_fields ( PLpgSQL_execstate estate,
PLpgSQL_variable target,
ExpandedRecordHeader newerh,
Datum values,
bool nulls,
TupleDesc  tupdesc 
)
static

Definition at line 7180 of file pl_exec.c.

7185{
7186 int td_natts = tupdesc ? tupdesc->natts : 0;
7187 int fnum;
7188 int anum;
7190
7191 /*
7192 * The extra check strict strict_multi_assignment can be active, only when
7193 * input tupdesc is specified.
7194 */
7195 if (tupdesc != NULL)
7196 {
7201 }
7202
7203 /* Handle RECORD-target case */
7204 if (target->dtype == PLPGSQL_DTYPE_REC)
7205 {
7206 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7209 bool newnulls_local[64];
7210
7211 Assert(newerh != NULL); /* caller must have built new object */
7212
7214
7215 /*
7216 * Coerce field values if needed. This might involve dealing with
7217 * different sets of dropped columns and/or coercing individual column
7218 * types. That's sort of a pain, but historically plpgsql has allowed
7219 * it, so we preserve the behavior. However, it's worth a quick check
7220 * to see if the tupdescs are identical. (Since expandedrecord.c
7221 * prefers to use refcounted tupdescs from the typcache, expanded
7222 * records with the same rowtype will have pointer-equal tupdescs.)
7223 */
7224 if (var_tupdesc != tupdesc)
7225 {
7226 int vtd_natts = var_tupdesc->natts;
7228 bool *newnulls;
7229
7230 /*
7231 * Need workspace arrays. If vtd_natts is small enough, use local
7232 * arrays to save doing a palloc. Even if it's not small, we can
7233 * allocate both the Datum and isnull arrays in one palloc chunk.
7234 */
7236 {
7239 }
7240 else
7241 {
7242 char *chunk;
7243
7244 chunk = eval_mcontext_alloc(estate,
7245 vtd_natts * (sizeof(Datum) + sizeof(bool)));
7246 newvalues = (Datum *) chunk;
7247 newnulls = (bool *) (chunk + vtd_natts * sizeof(Datum));
7248 }
7249
7250 /* Walk over destination columns */
7251 anum = 0;
7252 for (fnum = 0; fnum < vtd_natts; fnum++)
7253 {
7255 Datum value;
7256 bool isnull;
7257 Oid valtype;
7259
7260 if (attr->attisdropped)
7261 {
7262 /* expanded_record_set_fields should ignore this column */
7263 continue; /* skip dropped column in record */
7264 }
7265
7266 while (anum < td_natts &&
7267 TupleDescAttr(tupdesc, anum)->attisdropped)
7268 anum++; /* skip dropped column in tuple */
7269
7270 if (anum < td_natts)
7271 {
7272 value = values[anum];
7273 isnull = nulls[anum];
7274 valtype = TupleDescAttr(tupdesc, anum)->atttypid;
7275 valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
7276 anum++;
7277 }
7278 else
7279 {
7280 /* no source for destination column */
7281 value = (Datum) 0;
7282 isnull = true;
7284 valtypmod = -1;
7285
7286 /* When source value is missing */
7290 errmsg("number of source and target fields in assignment does not match"),
7291 /* translator: %s represents a name of an extra check */
7292 errdetail("%s check of %s is active.",
7293 "strict_multi_assignment",
7294 strict_multiassignment_level == ERROR ? "extra_errors" :
7295 "extra_warnings"),
7296 errhint("Make sure the query returns the exact list of columns.")));
7297 }
7298
7299 /* Cast the new value to the right type, if needed. */
7300 newvalues[fnum] = exec_cast_value(estate,
7301 value,
7302 &isnull,
7303 valtype,
7304 valtypmod,
7305 attr->atttypid,
7306 attr->atttypmod);
7307 newnulls[fnum] = isnull;
7308 }
7309
7310 /*
7311 * When strict_multiassignment extra check is active, then ensure
7312 * there are no unassigned source attributes.
7313 */
7315 {
7316 /* skip dropped columns in the source descriptor */
7317 while (anum < td_natts &&
7318 TupleDescAttr(tupdesc, anum)->attisdropped)
7319 anum++;
7320
7321 if (anum < td_natts)
7324 errmsg("number of source and target fields in assignment does not match"),
7325 /* translator: %s represents a name of an extra check */
7326 errdetail("%s check of %s is active.",
7327 "strict_multi_assignment",
7328 strict_multiassignment_level == ERROR ? "extra_errors" :
7329 "extra_warnings"),
7330 errhint("Make sure the query returns the exact list of columns.")));
7331 }
7332
7333 values = newvalues;
7334 nulls = newnulls;
7335 }
7336
7337 /* Insert the coerced field values into the new expanded record */
7339
7340 /* Complete the assignment */
7341 assign_record_var(estate, rec, newerh);
7342
7343 return;
7344 }
7345
7346 /* newerh should not have been passed in non-RECORD cases */
7347 Assert(newerh == NULL);
7348
7349 /*
7350 * For a row, we assign the individual field values to the variables the
7351 * row points to.
7352 *
7353 * NOTE: both this code and the record code above silently ignore extra
7354 * columns in the source and assume NULL for missing columns. This is
7355 * pretty dubious but it's the historical behavior.
7356 *
7357 * If we have no input data at all, we'll assign NULL to all columns of
7358 * the row variable.
7359 */
7360 if (target->dtype == PLPGSQL_DTYPE_ROW)
7361 {
7362 PLpgSQL_row *row = (PLpgSQL_row *) target;
7363
7364 anum = 0;
7365 for (fnum = 0; fnum < row->nfields; fnum++)
7366 {
7367 PLpgSQL_var *var;
7368 Datum value;
7369 bool isnull;
7370 Oid valtype;
7372
7373 var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
7374
7375 while (anum < td_natts &&
7376 TupleDescAttr(tupdesc, anum)->attisdropped)
7377 anum++; /* skip dropped column in tuple */
7378
7379 if (anum < td_natts)
7380 {
7381 value = values[anum];
7382 isnull = nulls[anum];
7383 valtype = TupleDescAttr(tupdesc, anum)->atttypid;
7384 valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
7385 anum++;
7386 }
7387 else
7388 {
7389 /* no source for destination column */
7390 value = (Datum) 0;
7391 isnull = true;
7393 valtypmod = -1;
7394
7398 errmsg("number of source and target fields in assignment does not match"),
7399 /* translator: %s represents a name of an extra check */
7400 errdetail("%s check of %s is active.",
7401 "strict_multi_assignment",
7402 strict_multiassignment_level == ERROR ? "extra_errors" :
7403 "extra_warnings"),
7404 errhint("Make sure the query returns the exact list of columns.")));
7405 }
7406
7407 exec_assign_value(estate, (PLpgSQL_datum *) var,
7408 value, isnull, valtype, valtypmod);
7409 }
7410
7411 /*
7412 * When strict_multiassignment extra check is active, ensure there are
7413 * no unassigned source attributes.
7414 */
7416 {
7417 while (anum < td_natts &&
7418 TupleDescAttr(tupdesc, anum)->attisdropped)
7419 anum++; /* skip dropped column in tuple */
7420
7421 if (anum < td_natts)
7424 errmsg("number of source and target fields in assignment does not match"),
7425 /* translator: %s represents a name of an extra check */
7426 errdetail("%s check of %s is active.",
7427 "strict_multi_assignment",
7428 strict_multiassignment_level == ERROR ? "extra_errors" :
7429 "extra_warnings"),
7430 errhint("Make sure the query returns the exact list of columns.")));
7431 }
7432
7433 return;
7434 }
7435
7436 elog(ERROR, "unsupported target type: %d", target->dtype);
7437}

References Assert, assign_record_var(), PLpgSQL_execstate::atomic, PLpgSQL_execstate::datums, PLpgSQL_variable::dtype, elog, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, eval_mcontext_alloc, exec_assign_value(), exec_cast_value(), expanded_record_get_tupdesc(), expanded_record_set_fields(), fb(), lengthof, TupleDescData::natts, PLpgSQL_row::nfields, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_ROW, plpgsql_extra_errors, plpgsql_extra_warnings, PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT, TupleDescAttr(), value, values, PLpgSQL_row::varnos, and WARNING.

Referenced by exec_move_row(), and exec_move_row_from_datum().

◆ exec_prepare_plan()

static void exec_prepare_plan ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
int  cursorOptions 
)
static

Definition at line 4172 of file pl_exec.c.

4174{
4177
4178 /*
4179 * Generate and save the plan
4180 */
4181 memset(&options, 0, sizeof(options));
4183 options.parserSetupArg = expr;
4184 options.parseMode = expr->parseMode;
4185 options.cursorOptions = cursorOptions;
4187 if (plan == NULL)
4188 elog(ERROR, "SPI_prepare_extended failed for \"%s\": %s",
4190
4192 expr->plan = plan;
4193
4194 /* Check to see if it's a simple expression */
4195 exec_simple_check_plan(estate, expr);
4196}

References elog, ERROR, exec_simple_check_plan(), fb(), PLpgSQL_expr::parseMode, PLpgSQL_expr::plan, plan, plpgsql_parser_setup(), PLpgSQL_expr::query, SPI_keepplan(), SPI_prepare_extended(), SPI_result, and SPI_result_code_string().

Referenced by exec_assign_expr(), exec_eval_expr(), exec_run_select(), exec_stmt_call(), exec_stmt_execsql(), exec_stmt_forc(), exec_stmt_open(), and exec_stmt_return_query().

◆ exec_run_select()

static int exec_run_select ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
long  maxtuples,
Portal portalP 
)
static

Definition at line 5752 of file pl_exec.c.

5754{
5755 ParamListInfo paramLI;
5756 int rc;
5757
5758 /*
5759 * On the first call for this expression generate the plan.
5760 *
5761 * If we don't need to return a portal, then we're just going to execute
5762 * the query immediately, which means it's OK to use a parallel plan, even
5763 * if the number of rows being fetched is limited. If we do need to
5764 * return a portal (i.e., this is for a FOR loop), the user's code might
5765 * invoke additional operations inside the FOR loop, making parallel query
5766 * unsafe. In any case, we don't expect any cursor operations to be done,
5767 * so specify NO_SCROLL for efficiency and semantic safety.
5768 */
5769 if (expr->plan == NULL)
5770 {
5771 int cursorOptions = CURSOR_OPT_NO_SCROLL;
5772
5773 if (portalP == NULL)
5774 cursorOptions |= CURSOR_OPT_PARALLEL_OK;
5775 exec_prepare_plan(estate, expr, cursorOptions);
5776 }
5777
5778 /*
5779 * Set up ParamListInfo to pass to executor
5780 */
5781 paramLI = setup_param_list(estate, expr);
5782
5783 /*
5784 * If a portal was requested, put the query and paramlist into the portal
5785 */
5786 if (portalP != NULL)
5787 {
5789 paramLI,
5790 estate->readonly_func);
5791 if (*portalP == NULL)
5792 elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
5794 exec_eval_cleanup(estate);
5795 return SPI_OK_CURSOR;
5796 }
5797
5798 /*
5799 * Execute the query
5800 */
5801 rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
5802 estate->readonly_func, maxtuples);
5803 if (rc != SPI_OK_SELECT)
5804 {
5805 /*
5806 * SELECT INTO deserves a special error message, because "query is not
5807 * a SELECT" is not very helpful in that case.
5808 */
5809 if (rc == SPI_OK_SELINTO)
5810 ereport(ERROR,
5812 errmsg("query is SELECT INTO, but it should be plain SELECT"),
5813 errcontext("query: %s", expr->query)));
5814 else
5815 ereport(ERROR,
5817 errmsg("query is not a SELECT"),
5818 errcontext("query: %s", expr->query)));
5819 }
5820
5821 /* Save query results for eventual cleanup */
5822 Assert(estate->eval_tuptable == NULL);
5823 estate->eval_tuptable = SPI_tuptable;
5824 estate->eval_processed = SPI_processed;
5825
5826 return rc;
5827}

References Assert, CURSOR_OPT_NO_SCROLL, CURSOR_OPT_PARALLEL_OK, elog, ereport, errcode(), errcontext, errmsg(), ERROR, PLpgSQL_execstate::eval_processed, PLpgSQL_execstate::eval_tuptable, exec_eval_cleanup(), exec_prepare_plan(), fb(), PLpgSQL_expr::plan, PLpgSQL_expr::query, PLpgSQL_execstate::readonly_func, setup_param_list(), SPI_cursor_open_with_paramlist(), SPI_execute_plan_with_paramlist(), SPI_OK_CURSOR, SPI_OK_SELECT, SPI_OK_SELINTO, SPI_processed, SPI_result, SPI_result_code_string(), and SPI_tuptable.

Referenced by exec_eval_expr(), exec_stmt_fors(), and exec_stmt_perform().

◆ exec_save_simple_expr()

static void exec_save_simple_expr ( PLpgSQL_expr expr,
CachedPlan cplan 
)
static

Definition at line 8275 of file pl_exec.c.

8276{
8278 Plan *plan;
8279 Expr *tle_expr;
8280
8281 /*
8282 * Given the checks that exec_simple_check_plan did, none of the Asserts
8283 * here should ever fail.
8284 */
8285
8286 /* Extract the single PlannedStmt */
8287 Assert(list_length(cplan->stmt_list) == 1);
8289 Assert(stmt->commandType == CMD_SELECT);
8290
8291 /*
8292 * Ordinarily, the plan node should be a simple Result. However, if
8293 * debug_parallel_query is on, the planner might've stuck a Gather node
8294 * atop that; and/or if this plan is for a scrollable cursor, the planner
8295 * might've stuck a Material node atop it. The simplest way to deal with
8296 * this is to look through the Gather and/or Material nodes. The upper
8297 * node's tlist would normally contain a Var referencing the child node's
8298 * output ... but setrefs.c might also have copied a Const as-is.
8299 */
8300 plan = stmt->planTree;
8301 for (;;)
8302 {
8303 /* Extract the single tlist expression */
8304 Assert(list_length(plan->targetlist) == 1);
8305 tle_expr = linitial_node(TargetEntry, plan->targetlist)->expr;
8306
8307 if (IsA(plan, Result))
8308 {
8309 Assert(plan->lefttree == NULL &&
8310 plan->righttree == NULL &&
8311 plan->initPlan == NULL &&
8312 plan->qual == NULL &&
8313 ((Result *) plan)->resconstantqual == NULL);
8314 break;
8315 }
8316 else if (IsA(plan, Gather) || IsA(plan, Material))
8317 {
8318 Assert(plan->lefttree != NULL &&
8319 plan->righttree == NULL &&
8320 plan->initPlan == NULL &&
8321 plan->qual == NULL);
8322 /* If setrefs.c copied up a Const, no need to look further */
8323 if (IsA(tle_expr, Const))
8324 break;
8325 /* Otherwise, it better be an outer Var */
8327 Assert(((Var *) tle_expr)->varno == OUTER_VAR);
8328 /* Descend to the child node */
8329 plan = plan->lefttree;
8330 }
8331 else
8332 elog(ERROR, "unexpected plan node type: %d",
8333 (int) nodeTag(plan));
8334 }
8335
8336 /*
8337 * Save the simple expression, and initialize state to "not valid in
8338 * current transaction".
8339 */
8340 expr->expr_simple_expr = tle_expr;
8341 expr->expr_simple_state = NULL;
8342 expr->expr_simple_in_use = false;
8344 /* Also stash away the expression result type */
8347 /* We also want to remember if it is immutable or not */
8349}

References Assert, CMD_SELECT, contain_mutable_functions(), elog, ERROR, PLpgSQL_expr::expr_simple_expr, PLpgSQL_expr::expr_simple_in_use, PLpgSQL_expr::expr_simple_lxid, PLpgSQL_expr::expr_simple_mutable, PLpgSQL_expr::expr_simple_state, PLpgSQL_expr::expr_simple_type, PLpgSQL_expr::expr_simple_typmod, exprType(), exprTypmod(), fb(), InvalidLocalTransactionId, IsA, linitial_node, list_length(), nodeTag, OUTER_VAR, plan, stmt, and CachedPlan::stmt_list.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

◆ exec_set_found()

static void exec_set_found ( PLpgSQL_execstate estate,
bool  state 
)
static

Definition at line 8593 of file pl_exec.c.

8594{
8595 PLpgSQL_var *var;
8596
8597 var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
8598
8599 /*
8600 * Use pg_assume() to avoid a spurious warning with some compilers, by
8601 * telling the compiler that the VARATT_IS_EXTERNAL_NON_EXPANDED() branch
8602 * in assign_simple_var() will never be reached when called from here, due
8603 * to "found" being a boolean (i.e. a byvalue type), not a varlena.
8604 */
8605 pg_assume(var->datatype->typlen != -1);
8606
8607 assign_simple_var(estate, var, BoolGetDatum(state), false, false);
8608}

References assign_simple_var(), BoolGetDatum(), PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_execstate::found_varno, pg_assume, and PLpgSQL_type::typlen.

Referenced by exec_for_query(), exec_stmt_execsql(), exec_stmt_fetch(), exec_stmt_foreach_a(), exec_stmt_fori(), exec_stmt_perform(), exec_stmt_return_query(), plpgsql_exec_function(), and plpgsql_exec_trigger().

◆ exec_simple_check_plan()

static void exec_simple_check_plan ( PLpgSQL_execstate estate,
PLpgSQL_expr expr 
)
static

Definition at line 8132 of file pl_exec.c.

8133{
8135 CachedPlanSource *plansource;
8136 CachedPlan *cplan;
8137 MemoryContext oldcontext;
8138
8139 /*
8140 * Initialize to "not simple", and reset R/W optimizability.
8141 */
8142 expr->expr_simple_expr = NULL;
8144 expr->expr_rw_param = NULL;
8145
8146 /*
8147 * Check the analyzed-and-rewritten form of the query to see if we will be
8148 * able to treat it as a simple expression. Since this function is only
8149 * called immediately after creating the CachedPlanSource, we need not
8150 * worry about the query being stale.
8151 */
8152 if (!exec_is_simple_query(expr))
8153 return;
8154
8155 /* exec_is_simple_query verified that there's just one CachedPlanSource */
8157 plansource = (CachedPlanSource *) linitial(plansources);
8158
8159 /*
8160 * Get the generic plan for the query. If replanning is needed, do that
8161 * work in the eval_mcontext. (Note that replanning could throw an error,
8162 * in which case the expr is left marked "not simple", which is fine.)
8163 */
8164 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8165 cplan = SPI_plan_get_cached_plan(expr->plan);
8166 MemoryContextSwitchTo(oldcontext);
8167
8168 /* Can't fail, because we checked for a single CachedPlanSource above */
8169 Assert(cplan != NULL);
8170
8171 /*
8172 * Verify that plancache.c thinks the plan is simple enough to use
8173 * CachedPlanIsSimplyValid. Given the restrictions above, it's unlikely
8174 * that this could fail, but if it does, just treat plan as not simple. On
8175 * success, save a refcount on the plan in the simple-expression resowner.
8176 */
8177 if (CachedPlanAllowsSimpleValidityCheck(plansource, cplan,
8178 estate->simple_eval_resowner))
8179 {
8180 /* Remember that we have the refcount */
8181 expr->expr_simple_plansource = plansource;
8182 expr->expr_simple_plan = cplan;
8184
8185 /* Share the remaining work with the replan code path */
8186 exec_save_simple_expr(expr, cplan);
8187 }
8188
8189 /*
8190 * Release the plan refcount obtained by SPI_plan_get_cached_plan. (This
8191 * refcount is held by the wrong resowner, so we can't just repurpose it.)
8192 */
8194}

References Assert, CachedPlanAllowsSimpleValidityCheck(), CurrentResourceOwner, exec_is_simple_query(), exec_save_simple_expr(), PLpgSQL_expr::expr_rw_param, PLpgSQL_expr::expr_rwopt, PLpgSQL_expr::expr_simple_expr, PLpgSQL_expr::expr_simple_plan, PLpgSQL_expr::expr_simple_plan_lxid, PLpgSQL_expr::expr_simple_plansource, fb(), get_eval_mcontext, linitial, PGPROC::lxid, MemoryContextSwitchTo(), MyProc, PLpgSQL_expr::plan, PLPGSQL_RWOPT_UNKNOWN, ReleaseCachedPlan(), PLpgSQL_execstate::simple_eval_resowner, SPI_plan_get_cached_plan(), SPI_plan_get_plan_sources(), and PGPROC::vxid.

Referenced by exec_prepare_plan().

◆ exec_stmt_assert()

static int exec_stmt_assert ( PLpgSQL_execstate estate,
PLpgSQL_stmt_assert stmt 
)
static

Definition at line 3935 of file pl_exec.c.

3936{
3937 bool value;
3938 bool isnull;
3939
3940 /* do nothing when asserts are not enabled */
3942 return PLPGSQL_RC_OK;
3943
3944 value = exec_eval_boolean(estate, stmt->cond, &isnull);
3945 exec_eval_cleanup(estate);
3946
3947 if (isnull || !value)
3948 {
3949 char *message = NULL;
3950
3951 if (stmt->message != NULL)
3952 {
3953 Datum val;
3954 Oid typeid;
3955 int32 typmod;
3956
3957 val = exec_eval_expr(estate, stmt->message,
3958 &isnull, &typeid, &typmod);
3959 if (!isnull)
3960 message = convert_value_to_string(estate, val, typeid);
3961 /* we mustn't do exec_eval_cleanup here */
3962 }
3963
3964 ereport(ERROR,
3966 message ? errmsg_internal("%s", message) :
3967 errmsg("assertion failed")));
3968 }
3969
3970 return PLPGSQL_RC_OK;
3971}

References convert_value_to_string(), ereport, errcode(), errmsg(), errmsg_internal(), ERROR, exec_eval_boolean(), exec_eval_cleanup(), exec_eval_expr(), fb(), plpgsql_check_asserts, PLPGSQL_RC_OK, stmt, val, and value.

Referenced by exec_stmts().

◆ exec_stmt_assign()

static int exec_stmt_assign ( PLpgSQL_execstate estate,
PLpgSQL_stmt_assign stmt 
)
static

Definition at line 2163 of file pl_exec.c.

2164{
2165 Assert(stmt->varno >= 0);
2166
2167 exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
2168
2169 return PLPGSQL_RC_OK;
2170}

References Assert, PLpgSQL_execstate::datums, exec_assign_expr(), PLPGSQL_RC_OK, and stmt.

Referenced by exec_stmts().

◆ exec_stmt_block()

static int exec_stmt_block ( PLpgSQL_execstate estate,
PLpgSQL_stmt_block block 
)
static

Definition at line 1662 of file pl_exec.c.

1663{
1664 volatile int rc = -1;
1665 int i;
1666
1667 /*
1668 * First initialize all variables declared in this block
1669 */
1670 estate->err_text = gettext_noop("during statement block local variable initialization");
1671
1672 for (i = 0; i < block->n_initvars; i++)
1673 {
1674 int n = block->initvarnos[i];
1675 PLpgSQL_datum *datum = estate->datums[n];
1676
1677 /*
1678 * The set of dtypes handled here must match plpgsql_add_initdatums().
1679 *
1680 * Note that we currently don't support promise datums within blocks,
1681 * only at a function's outermost scope, so we needn't handle those
1682 * here.
1683 *
1684 * Since RECFIELD isn't a supported case either, it's okay to cast the
1685 * PLpgSQL_datum to PLpgSQL_variable.
1686 */
1687 estate->err_var = (PLpgSQL_variable *) datum;
1688
1689 switch (datum->dtype)
1690 {
1691 case PLPGSQL_DTYPE_VAR:
1692 {
1693 PLpgSQL_var *var = (PLpgSQL_var *) datum;
1694
1695 /*
1696 * Free any old value, in case re-entering block, and
1697 * initialize to NULL
1698 */
1699 assign_simple_var(estate, var, (Datum) 0, true, false);
1700
1701 if (var->default_val == NULL)
1702 {
1703 /*
1704 * If needed, give the datatype a chance to reject
1705 * NULLs, by assigning a NULL to the variable. We
1706 * claim the value is of type UNKNOWN, not the var's
1707 * datatype, else coercion will be skipped.
1708 */
1709 if (var->datatype->typtype == TYPTYPE_DOMAIN)
1710 exec_assign_value(estate,
1711 (PLpgSQL_datum *) var,
1712 (Datum) 0,
1713 true,
1714 UNKNOWNOID,
1715 -1);
1716
1717 /* parser should have rejected NOT NULL */
1718 Assert(!var->notnull);
1719 }
1720 else
1721 {
1722 exec_assign_expr(estate, (PLpgSQL_datum *) var,
1723 var->default_val);
1724 }
1725 }
1726 break;
1727
1728 case PLPGSQL_DTYPE_REC:
1729 {
1730 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
1731
1732 /*
1733 * Deletion of any existing object will be handled during
1734 * the assignments below, and in some cases it's more
1735 * efficient for us not to get rid of it beforehand.
1736 */
1737 if (rec->default_val == NULL)
1738 {
1739 /*
1740 * If needed, give the datatype a chance to reject
1741 * NULLs, by assigning a NULL to the variable.
1742 */
1743 exec_move_row(estate, (PLpgSQL_variable *) rec,
1744 NULL, NULL);
1745
1746 /* parser should have rejected NOT NULL */
1747 Assert(!rec->notnull);
1748 }
1749 else
1750 {
1751 exec_assign_expr(estate, (PLpgSQL_datum *) rec,
1752 rec->default_val);
1753 }
1754 }
1755 break;
1756
1757 default:
1758 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
1759 }
1760 }
1761
1762 estate->err_var = NULL;
1763
1764 if (block->exceptions)
1765 {
1766 /*
1767 * Execute the statements in the block's body inside a sub-transaction
1768 */
1773 MemoryContext stmt_mcontext;
1774
1775 estate->err_text = gettext_noop("during statement block entry");
1776
1777 /*
1778 * We will need a stmt_mcontext to hold the error data if an error
1779 * occurs. It seems best to force it to exist before entering the
1780 * subtransaction, so that we reduce the risk of out-of-memory during
1781 * error recovery, and because this greatly simplifies restoring the
1782 * stmt_mcontext stack to the correct state after an error. We can
1783 * ameliorate the cost of this by allowing the called statements to
1784 * use this mcontext too; so we don't push it down here.
1785 */
1786 stmt_mcontext = get_stmt_mcontext(estate);
1787
1789 /* Want to run statements inside function's memory context */
1790 MemoryContextSwitchTo(oldcontext);
1791
1792 PG_TRY();
1793 {
1794 /*
1795 * We need to run the block's statements with a new eval_econtext
1796 * that belongs to the current subtransaction; if we try to use
1797 * the outer econtext then ExprContext shutdown callbacks will be
1798 * called at the wrong times.
1799 */
1801
1802 estate->err_text = NULL;
1803
1804 /* Run the block's statements */
1805 rc = exec_stmts(estate, block->body);
1806
1807 estate->err_text = gettext_noop("during statement block exit");
1808
1809 /*
1810 * If the block ended with RETURN, we may need to copy the return
1811 * value out of the subtransaction eval_context. We can avoid a
1812 * physical copy if the value happens to be a R/W expanded object.
1813 */
1814 if (rc == PLPGSQL_RC_RETURN &&
1815 !estate->retisset &&
1816 !estate->retisnull)
1817 {
1819 bool resTypByVal;
1820
1822 estate->retval = datumTransfer(estate->retval,
1824 }
1825
1826 /* Commit the inner transaction, return to outer xact context */
1828 MemoryContextSwitchTo(oldcontext);
1829 CurrentResourceOwner = oldowner;
1830
1831 /* Assert that the stmt_mcontext stack is unchanged */
1832 Assert(stmt_mcontext == estate->stmt_mcontext);
1833
1834 /*
1835 * Revert to outer eval_econtext. (The inner one was
1836 * automatically cleaned up during subxact exit.)
1837 */
1839 }
1840 PG_CATCH();
1841 {
1843 ListCell *e;
1844
1845 estate->err_text = gettext_noop("during exception cleanup");
1846
1847 /* Save error info in our stmt_mcontext */
1848 MemoryContextSwitchTo(stmt_mcontext);
1849 edata = CopyErrorData();
1851
1852 /* Abort the inner transaction */
1854 MemoryContextSwitchTo(oldcontext);
1855 CurrentResourceOwner = oldowner;
1856
1857 /*
1858 * Set up the stmt_mcontext stack as though we had restored our
1859 * previous state and then done push_stmt_mcontext(). The push is
1860 * needed so that statements in the exception handler won't
1861 * clobber the error data that's in our stmt_mcontext.
1862 */
1863 estate->stmt_mcontext_parent = stmt_mcontext;
1864 estate->stmt_mcontext = NULL;
1865
1866 /*
1867 * Now we can delete any nested stmt_mcontexts that might have
1868 * been created as children of ours. (Note: we do not immediately
1869 * release any statement-lifespan data that might have been left
1870 * behind in stmt_mcontext itself. We could attempt that by doing
1871 * a MemoryContextReset on it before collecting the error data
1872 * above, but it seems too risky to do any significant amount of
1873 * work before collecting the error.)
1874 */
1875 MemoryContextDeleteChildren(stmt_mcontext);
1876
1877 /* Revert to outer eval_econtext */
1879
1880 /*
1881 * Must clean up the econtext too. However, any tuple table made
1882 * in the subxact will have been thrown away by SPI during subxact
1883 * abort, so we don't need to (and mustn't try to) free the
1884 * eval_tuptable.
1885 */
1886 estate->eval_tuptable = NULL;
1887 exec_eval_cleanup(estate);
1888
1889 /* Look for a matching exception handler */
1890 foreach(e, block->exceptions->exc_list)
1891 {
1893
1895 {
1896 /*
1897 * Initialize the magic SQLSTATE and SQLERRM variables for
1898 * the exception block; this also frees values from any
1899 * prior use of the same exception. We needn't do this
1900 * until we have found a matching exception.
1901 */
1904
1906 estate->datums[block->exceptions->sqlstate_varno];
1907 errm_var = (PLpgSQL_var *)
1908 estate->datums[block->exceptions->sqlerrm_varno];
1909
1910 assign_text_var(estate, state_var,
1911 unpack_sql_state(edata->sqlerrcode));
1912 assign_text_var(estate, errm_var, edata->message);
1913
1914 /*
1915 * Also set up cur_error so the error data is accessible
1916 * inside the handler.
1917 */
1918 estate->cur_error = edata;
1919
1920 estate->err_text = NULL;
1921
1922 rc = exec_stmts(estate, exception->action);
1923
1924 break;
1925 }
1926 }
1927
1928 /*
1929 * Restore previous state of cur_error, whether or not we executed
1930 * a handler. This is needed in case an error got thrown from
1931 * some inner block's exception handler.
1932 */
1933 estate->cur_error = save_cur_error;
1934
1935 /* If no match found, re-throw the error */
1936 if (e == NULL)
1938
1939 /* Restore stmt_mcontext stack and release the error data */
1940 pop_stmt_mcontext(estate);
1941 MemoryContextReset(stmt_mcontext);
1942 }
1943 PG_END_TRY();
1944
1945 Assert(save_cur_error == estate->cur_error);
1946 }
1947 else
1948 {
1949 /*
1950 * Just execute the statements in the block's body
1951 */
1952 estate->err_text = NULL;
1953
1954 rc = exec_stmts(estate, block->body);
1955 }
1956
1957 estate->err_text = NULL;
1958
1959 /*
1960 * Handle the return code. This is intentionally different from
1961 * LOOP_RC_PROCESSING(): CONTINUE never matches a block, and EXIT matches
1962 * a block only if there is a label match.
1963 */
1964 switch (rc)
1965 {
1966 case PLPGSQL_RC_OK:
1967 case PLPGSQL_RC_RETURN:
1969 return rc;
1970
1971 case PLPGSQL_RC_EXIT:
1972 if (estate->exitlabel == NULL)
1973 return PLPGSQL_RC_EXIT;
1974 if (block->label == NULL)
1975 return PLPGSQL_RC_EXIT;
1976 if (strcmp(block->label, estate->exitlabel) != 0)
1977 return PLPGSQL_RC_EXIT;
1978 estate->exitlabel = NULL;
1979 return PLPGSQL_RC_OK;
1980
1981 default:
1982 elog(ERROR, "unrecognized rc: %d", rc);
1983 }
1984
1985 return PLPGSQL_RC_OK;
1986}

References Assert, assign_simple_var(), assign_text_var(), BeginInternalSubTransaction(), PLpgSQL_stmt_block::body, CopyErrorData(), PLpgSQL_execstate::cur_error, CurrentMemoryContext, CurrentResourceOwner, PLpgSQL_var::datatype, PLpgSQL_execstate::datums, datumTransfer(), PLpgSQL_var::default_val, PLpgSQL_rec::default_val, PLpgSQL_datum::dtype, elog, PLpgSQL_execstate::err_text, PLpgSQL_execstate::err_var, ERROR, PLpgSQL_execstate::eval_econtext, PLpgSQL_execstate::eval_tuptable, PLpgSQL_exception_block::exc_list, exception_matches_conditions(), PLpgSQL_stmt_block::exceptions, exec_assign_expr(), exec_assign_value(), exec_eval_cleanup(), exec_move_row(), exec_stmts(), PLpgSQL_execstate::exitlabel, fb(), FlushErrorState(), get_stmt_mcontext(), get_typlenbyval(), gettext_noop, i, PLpgSQL_stmt_block::initvarnos, PLpgSQL_stmt_block::label, lfirst, MemoryContextDeleteChildren(), MemoryContextReset(), MemoryContextSwitchTo(), PLpgSQL_stmt_block::n_initvars, PLpgSQL_variable::notnull, PG_CATCH, PG_END_TRY, PG_TRY, plpgsql_create_econtext(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, PLPGSQL_RC_CONTINUE, PLPGSQL_RC_EXIT, PLPGSQL_RC_OK, PLPGSQL_RC_RETURN, pop_stmt_mcontext(), ReleaseCurrentSubTransaction(), ReThrowError(), PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::rettype, PLpgSQL_execstate::retval, RollbackAndReleaseCurrentSubTransaction(), PLpgSQL_exception_block::sqlerrm_varno, PLpgSQL_exception_block::sqlstate_varno, PLpgSQL_execstate::stmt_mcontext, PLpgSQL_execstate::stmt_mcontext_parent, PLpgSQL_type::typtype, and unpack_sql_state().

Referenced by exec_stmts(), and exec_toplevel_block().

◆ exec_stmt_call()

static int exec_stmt_call ( PLpgSQL_execstate estate,
PLpgSQL_stmt_call stmt 
)
static

Definition at line 2196 of file pl_exec.c.

2197{
2198 PLpgSQL_expr *expr = stmt->expr;
2201 ParamListInfo paramLI;
2203 int rc;
2204
2205 /*
2206 * Make a plan if we don't have one already.
2207 */
2208 if (expr->plan == NULL)
2209 exec_prepare_plan(estate, expr, 0);
2210
2211 /*
2212 * A CALL or DO can never be a simple expression.
2213 */
2214 Assert(!expr->expr_simple_expr);
2215
2216 /*
2217 * Also construct a DTYPE_ROW datum representing the plpgsql variables
2218 * associated with the procedure's output arguments. Then we can use
2219 * exec_move_row() to do the assignments.
2220 */
2221 if (stmt->is_call && stmt->target == NULL)
2222 stmt->target = make_callstmt_target(estate, expr);
2223
2224 paramLI = setup_param_list(estate, expr);
2225
2227
2228 /*
2229 * If we have a procedure-lifespan resowner, use that to hold the refcount
2230 * for the plan. This avoids refcount leakage complaints if the called
2231 * procedure ends the current transaction.
2232 *
2233 * Also, tell SPI to allow non-atomic execution.
2234 */
2235 memset(&options, 0, sizeof(options));
2236 options.params = paramLI;
2237 options.read_only = estate->readonly_func;
2238 options.allow_nonatomic = true;
2239 options.owner = estate->procedure_resowner;
2240
2242
2243 if (rc < 0)
2244 elog(ERROR, "SPI_execute_plan_extended failed executing query \"%s\": %s",
2245 expr->query, SPI_result_code_string(rc));
2246
2248
2249 if (before_lxid != after_lxid)
2250 {
2251 /*
2252 * If we are in a new transaction after the call, we need to build new
2253 * simple-expression infrastructure.
2254 */
2255 estate->simple_eval_estate = NULL;
2256 estate->simple_eval_resowner = NULL;
2258 }
2259
2260 /*
2261 * Check result rowcount; if there's one row, assign procedure's output
2262 * values back to the appropriate variables.
2263 */
2264 if (SPI_processed == 1)
2265 {
2267
2268 if (!stmt->is_call)
2269 elog(ERROR, "DO statement returned a row");
2270
2271 exec_move_row(estate, stmt->target, tuptab->vals[0], tuptab->tupdesc);
2272 }
2273 else if (SPI_processed > 1)
2274 elog(ERROR, "procedure call returned more than one row");
2275
2276 exec_eval_cleanup(estate);
2278
2279 return PLPGSQL_RC_OK;
2280}

References Assert, elog, ERROR, exec_eval_cleanup(), exec_move_row(), exec_prepare_plan(), PLpgSQL_expr::expr_simple_expr, fb(), PGPROC::lxid, make_callstmt_target(), MyProc, PLpgSQL_expr::plan, plpgsql_create_econtext(), PLPGSQL_RC_OK, PLpgSQL_execstate::procedure_resowner, PLpgSQL_expr::query, PLpgSQL_execstate::readonly_func, setup_param_list(), PLpgSQL_execstate::simple_eval_estate, PLpgSQL_execstate::simple_eval_resowner, SPI_execute_plan_extended(), SPI_freetuptable(), SPI_processed, SPI_result_code_string(), SPI_tuptable, stmt, and PGPROC::vxid.

Referenced by exec_stmts().

◆ exec_stmt_case()

static int exec_stmt_case ( PLpgSQL_execstate estate,
PLpgSQL_stmt_case stmt 
)
static

Definition at line 2555 of file pl_exec.c.

2556{
2558 bool isnull;
2559 ListCell *l;
2560
2561 if (stmt->t_expr != NULL)
2562 {
2563 /* simple case */
2564 Datum t_val;
2565 Oid t_typoid;
2567
2568 t_val = exec_eval_expr(estate, stmt->t_expr,
2569 &isnull, &t_typoid, &t_typmod);
2570
2571 t_var = (PLpgSQL_var *) estate->datums[stmt->t_varno];
2572
2573 /*
2574 * When expected datatype is different from real, change it. Note that
2575 * what we're modifying here is an execution copy of the datum, so
2576 * this doesn't affect the originally stored function parse tree. (In
2577 * theory, if the expression datatype keeps changing during execution,
2578 * this could cause a function-lifespan memory leak. Doesn't seem
2579 * worth worrying about though.)
2580 */
2581 if (t_var->datatype->typoid != t_typoid ||
2582 t_var->datatype->atttypmod != t_typmod)
2584 t_typmod,
2585 estate->func->fn_input_collation,
2586 NULL);
2587
2588 /* now we can assign to the variable */
2589 exec_assign_value(estate,
2590 (PLpgSQL_datum *) t_var,
2591 t_val,
2592 isnull,
2593 t_typoid,
2594 t_typmod);
2595
2596 exec_eval_cleanup(estate);
2597 }
2598
2599 /* Now search for a successful WHEN clause */
2600 foreach(l, stmt->case_when_list)
2601 {
2603 bool value;
2604
2605 value = exec_eval_boolean(estate, cwt->expr, &isnull);
2606 exec_eval_cleanup(estate);
2607 if (!isnull && value)
2608 {
2609 /* Found it */
2610
2611 /* We can now discard any value we had for the temp variable */
2612 if (t_var != NULL)
2613 assign_simple_var(estate, t_var, (Datum) 0, true, false);
2614
2615 /* Evaluate the statement(s), and we're done */
2616 return exec_stmts(estate, cwt->stmts);
2617 }
2618 }
2619
2620 /* We can now discard any value we had for the temp variable */
2621 if (t_var != NULL)
2622 assign_simple_var(estate, t_var, (Datum) 0, true, false);
2623
2624 /* SQL2003 mandates this error if there was no ELSE clause */
2625 if (!stmt->have_else)
2626 ereport(ERROR,
2628 errmsg("case not found"),
2629 errhint("CASE statement is missing ELSE part.")));
2630
2631 /* Evaluate the ELSE statements, and we're done */
2632 return exec_stmts(estate, stmt->else_stmts);
2633}

References assign_simple_var(), PLpgSQL_execstate::datums, ereport, errcode(), errhint(), errmsg(), ERROR, exec_assign_value(), exec_eval_boolean(), exec_eval_cleanup(), exec_eval_expr(), exec_stmts(), fb(), PLpgSQL_function::fn_input_collation, PLpgSQL_execstate::func, lfirst, plpgsql_build_datatype(), stmt, and value.

Referenced by exec_stmts().

◆ exec_stmt_close()

static int exec_stmt_close ( PLpgSQL_execstate estate,
PLpgSQL_stmt_close stmt 
)
static

Definition at line 4912 of file pl_exec.c.

4913{
4914 PLpgSQL_var *curvar;
4915 Portal portal;
4916 char *curname;
4917 MemoryContext oldcontext;
4918
4919 /* ----------
4920 * Get the portal of the cursor by name
4921 * ----------
4922 */
4923 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4924 if (curvar->isnull)
4925 ereport(ERROR,
4927 errmsg("cursor variable \"%s\" is null", curvar->refname)));
4928
4929 /* Use eval_mcontext for short-lived string */
4930 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4932 MemoryContextSwitchTo(oldcontext);
4933
4934 portal = SPI_cursor_find(curname);
4935 if (portal == NULL)
4936 ereport(ERROR,
4938 errmsg("cursor \"%s\" does not exist", curname)));
4939
4940 /* ----------
4941 * And close it.
4942 * ----------
4943 */
4944 SPI_cursor_close(portal);
4945
4946 return PLPGSQL_RC_OK;
4947}

References PLpgSQL_execstate::datums, ereport, errcode(), errmsg(), ERROR, fb(), get_eval_mcontext, PLpgSQL_var::isnull, MemoryContextSwitchTo(), PLPGSQL_RC_OK, PLpgSQL_var::refname, SPI_cursor_close(), SPI_cursor_find(), stmt, TextDatumGetCString, and PLpgSQL_var::value.

Referenced by exec_stmts().

◆ exec_stmt_commit()

static int exec_stmt_commit ( PLpgSQL_execstate estate,
PLpgSQL_stmt_commit stmt 
)
static

Definition at line 4955 of file pl_exec.c.

4956{
4957 if (stmt->chain)
4959 else
4960 SPI_commit();
4961
4962 /*
4963 * We need to build new simple-expression infrastructure, since the old
4964 * data structures are gone.
4965 */
4966 estate->simple_eval_estate = NULL;
4967 estate->simple_eval_resowner = NULL;
4969
4970 return PLPGSQL_RC_OK;
4971}

References fb(), plpgsql_create_econtext(), PLPGSQL_RC_OK, PLpgSQL_execstate::simple_eval_estate, PLpgSQL_execstate::simple_eval_resowner, SPI_commit(), SPI_commit_and_chain(), and stmt.

Referenced by exec_stmts().

◆ exec_stmt_dynexecute()

static int exec_stmt_dynexecute ( PLpgSQL_execstate estate,
PLpgSQL_stmt_dynexecute stmt 
)
static

Definition at line 4439 of file pl_exec.c.

4441{
4442 Datum query;
4443 bool isnull;
4444 Oid restype;
4446 char *querystr;
4447 int exec_res;
4448 ParamListInfo paramLI;
4450 MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
4451
4452 /*
4453 * First we evaluate the string expression after the EXECUTE keyword. Its
4454 * result is the querystring we have to execute.
4455 */
4456 query = exec_eval_expr(estate, stmt->query, &isnull, &restype, &restypmod);
4457 if (isnull)
4458 ereport(ERROR,
4460 errmsg("query string argument of EXECUTE is null")));
4461
4462 /* Get the C-String representation */
4463 querystr = convert_value_to_string(estate, query, restype);
4464
4465 /* copy it into the stmt_mcontext before we clean up */
4466 querystr = MemoryContextStrdup(stmt_mcontext, querystr);
4467
4468 exec_eval_cleanup(estate);
4469
4470 /*
4471 * Execute the query without preparing a saved plan.
4472 */
4473 paramLI = exec_eval_using_params(estate, stmt->params);
4474
4475 memset(&options, 0, sizeof(options));
4476 options.params = paramLI;
4477 options.read_only = estate->readonly_func;
4478
4480
4481 switch (exec_res)
4482 {
4483 case SPI_OK_SELECT:
4484 case SPI_OK_INSERT:
4485 case SPI_OK_UPDATE:
4486 case SPI_OK_DELETE:
4487 case SPI_OK_MERGE:
4492 case SPI_OK_UTILITY:
4493 case SPI_OK_REWRITTEN:
4494 break;
4495
4496 case 0:
4497
4498 /*
4499 * Also allow a zero return, which implies the querystring
4500 * contained no commands.
4501 */
4502 break;
4503
4504 case SPI_OK_SELINTO:
4505
4506 /*
4507 * We want to disallow SELECT INTO for now, because its behavior
4508 * is not consistent with SELECT INTO in a normal plpgsql context.
4509 * (We need to reimplement EXECUTE to parse the string as a
4510 * plpgsql command, not just feed it to SPI_execute.) This is not
4511 * a functional limitation because CREATE TABLE AS is allowed.
4512 */
4513 ereport(ERROR,
4515 errmsg("EXECUTE of SELECT ... INTO is not implemented"),
4516 errhint("You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.")));
4517 break;
4518
4519 /* Some SPI errors deserve specific error messages */
4520 case SPI_ERROR_COPY:
4521 ereport(ERROR,
4523 errmsg("cannot COPY to/from client in PL/pgSQL")));
4524 break;
4525
4527 ereport(ERROR,
4529 errmsg("EXECUTE of transaction commands is not implemented")));
4530 break;
4531
4532 default:
4533 elog(ERROR, "SPI_execute_extended failed executing query \"%s\": %s",
4535 break;
4536 }
4537
4538 /* Save result info for GET DIAGNOSTICS */
4539 estate->eval_processed = SPI_processed;
4540
4541 /* Process INTO if present */
4542 if (stmt->into)
4543 {
4546 PLpgSQL_variable *target;
4547
4548 /* If the statement did not return a tuple table, complain */
4549 if (tuptab == NULL)
4550 ereport(ERROR,
4552 errmsg("INTO used with a command that cannot return data")));
4553
4554 /* Fetch target's datum entry */
4555 target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4556
4557 /*
4558 * If SELECT ... INTO specified STRICT, and the query didn't find
4559 * exactly one row, throw an error. If STRICT was not specified, then
4560 * allow the query to find any number of rows.
4561 */
4562 if (n == 0)
4563 {
4564 if (stmt->strict)
4565 {
4566 char *errdetail;
4567
4568 if (estate->func->print_strict_params)
4569 errdetail = format_preparedparamsdata(estate, paramLI);
4570 else
4571 errdetail = NULL;
4572
4573 ereport(ERROR,
4575 errmsg("query returned no rows"),
4576 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4577 }
4578 /* set the target to NULL(s) */
4579 exec_move_row(estate, target, NULL, tuptab->tupdesc);
4580 }
4581 else
4582 {
4583 if (n > 1 && stmt->strict)
4584 {
4585 char *errdetail;
4586
4587 if (estate->func->print_strict_params)
4588 errdetail = format_preparedparamsdata(estate, paramLI);
4589 else
4590 errdetail = NULL;
4591
4592 ereport(ERROR,
4594 errmsg("query returned more than one row"),
4595 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4596 }
4597
4598 /* Put the first result row into the target */
4599 exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4600 }
4601 /* clean up after exec_move_row() */
4602 exec_eval_cleanup(estate);
4603 }
4604 else
4605 {
4606 /*
4607 * It might be a good idea to raise an error if the query returned
4608 * tuples that are being ignored, but historically we have not done
4609 * that.
4610 */
4611 }
4612
4613 /* Release any result from SPI_execute, as well as transient data */
4615 MemoryContextReset(stmt_mcontext);
4616
4617 return PLPGSQL_RC_OK;
4618}

References convert_value_to_string(), PLpgSQL_execstate::datums, elog, ereport, errcode(), errdetail(), errdetail_internal(), errhint(), errmsg(), ERROR, PLpgSQL_execstate::eval_processed, exec_eval_cleanup(), exec_eval_expr(), exec_eval_using_params(), exec_move_row(), fb(), format_preparedparamsdata(), PLpgSQL_execstate::func, get_stmt_mcontext(), MemoryContextReset(), MemoryContextStrdup(), PLPGSQL_RC_OK, PLpgSQL_function::print_strict_params, PLpgSQL_execstate::readonly_func, SPI_ERROR_COPY, SPI_ERROR_TRANSACTION, SPI_execute_extended(), SPI_freetuptable(), SPI_OK_DELETE, SPI_OK_DELETE_RETURNING, SPI_OK_INSERT, SPI_OK_INSERT_RETURNING, SPI_OK_MERGE, SPI_OK_MERGE_RETURNING, SPI_OK_REWRITTEN, SPI_OK_SELECT, SPI_OK_SELINTO, SPI_OK_UPDATE, SPI_OK_UPDATE_RETURNING, SPI_OK_UTILITY, SPI_processed, SPI_result_code_string(), SPI_tuptable, and stmt.

Referenced by exec_stmts().

◆ exec_stmt_dynfors()

static int exec_stmt_dynfors ( PLpgSQL_execstate estate,
PLpgSQL_stmt_dynfors stmt 
)
static

Definition at line 4629 of file pl_exec.c.

4630{
4631 Portal portal;
4632 int rc;
4633
4634 portal = exec_dynquery_with_params(estate, stmt->query, stmt->params,
4636
4637 /*
4638 * Execute the loop
4639 */
4640 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
4641
4642 /*
4643 * Close the implicit cursor
4644 */
4645 SPI_cursor_close(portal);
4646
4647 return rc;
4648}

References CURSOR_OPT_NO_SCROLL, exec_dynquery_with_params(), exec_for_query(), fb(), SPI_cursor_close(), and stmt.

Referenced by exec_stmts().

◆ exec_stmt_execsql()

static int exec_stmt_execsql ( PLpgSQL_execstate estate,
PLpgSQL_stmt_execsql stmt 
)
static

Definition at line 4207 of file pl_exec.c.

4209{
4210 ParamListInfo paramLI;
4211 long tcount;
4212 int rc;
4213 PLpgSQL_expr *expr = stmt->sqlstmt;
4214 int too_many_rows_level = 0;
4215
4220
4221 /*
4222 * On the first call for this statement generate the plan, and detect
4223 * whether the statement is INSERT/UPDATE/DELETE/MERGE
4224 */
4225 if (expr->plan == NULL)
4227
4228 if (!stmt->mod_stmt_set)
4229 {
4230 ListCell *l;
4231
4232 stmt->mod_stmt = false;
4233 foreach(l, SPI_plan_get_plan_sources(expr->plan))
4234 {
4235 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l);
4236
4237 /*
4238 * We could look at the raw_parse_tree, but it seems simpler to
4239 * check the command tag. Note we should *not* look at the Query
4240 * tree(s), since those are the result of rewriting and could be
4241 * stale, or could have been transmogrified into something else
4242 * entirely.
4243 */
4244 if (plansource->commandTag == CMDTAG_INSERT ||
4245 plansource->commandTag == CMDTAG_UPDATE ||
4246 plansource->commandTag == CMDTAG_DELETE ||
4247 plansource->commandTag == CMDTAG_MERGE)
4248 {
4249 stmt->mod_stmt = true;
4250 break;
4251 }
4252 }
4253 stmt->mod_stmt_set = true;
4254 }
4255
4256 /*
4257 * Set up ParamListInfo to pass to executor
4258 */
4259 paramLI = setup_param_list(estate, expr);
4260
4261 /*
4262 * If we have INTO, then we only need one row back ... but if we have INTO
4263 * STRICT or extra check too_many_rows, ask for two rows, so that we can
4264 * verify the statement returns only one. INSERT/UPDATE/DELETE/MERGE are
4265 * always treated strictly. Without INTO, just run the statement to
4266 * completion (tcount = 0).
4267 *
4268 * We could just ask for two rows always when using INTO, but there are
4269 * some cases where demanding the extra row costs significant time, eg by
4270 * forcing completion of a sequential scan. So don't do it unless we need
4271 * to enforce strictness.
4272 */
4273 if (stmt->into)
4274 {
4275 if (stmt->strict || stmt->mod_stmt || too_many_rows_level)
4276 tcount = 2;
4277 else
4278 tcount = 1;
4279 }
4280 else
4281 tcount = 0;
4282
4283 /*
4284 * Execute the plan
4285 */
4286 rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
4287 estate->readonly_func, tcount);
4288
4289 /*
4290 * Check for error, and set FOUND if appropriate (for historical reasons
4291 * we set FOUND only for certain query types). Also Assert that we
4292 * identified the statement type the same as SPI did.
4293 */
4294 switch (rc)
4295 {
4296 case SPI_OK_SELECT:
4297 Assert(!stmt->mod_stmt);
4298 exec_set_found(estate, (SPI_processed != 0));
4299 break;
4300
4301 case SPI_OK_INSERT:
4302 case SPI_OK_UPDATE:
4303 case SPI_OK_DELETE:
4304 case SPI_OK_MERGE:
4309 Assert(stmt->mod_stmt);
4310 exec_set_found(estate, (SPI_processed != 0));
4311 break;
4312
4313 case SPI_OK_SELINTO:
4314 case SPI_OK_UTILITY:
4315 Assert(!stmt->mod_stmt);
4316 break;
4317
4318 case SPI_OK_REWRITTEN:
4319
4320 /*
4321 * The command was rewritten into another kind of command. It's
4322 * not clear what FOUND would mean in that case (and SPI doesn't
4323 * return the row count either), so just set it to false. Note
4324 * that we can't assert anything about mod_stmt here.
4325 */
4326 exec_set_found(estate, false);
4327 break;
4328
4329 /* Some SPI errors deserve specific error messages */
4330 case SPI_ERROR_COPY:
4331 ereport(ERROR,
4333 errmsg("cannot COPY to/from client in PL/pgSQL")));
4334 break;
4335
4337 ereport(ERROR,
4339 errmsg("unsupported transaction command in PL/pgSQL")));
4340 break;
4341
4342 default:
4343 elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s",
4344 expr->query, SPI_result_code_string(rc));
4345 break;
4346 }
4347
4348 /* All variants should save result info for GET DIAGNOSTICS */
4349 estate->eval_processed = SPI_processed;
4350
4351 /* Process INTO if present */
4352 if (stmt->into)
4353 {
4356 PLpgSQL_variable *target;
4357
4358 /* If the statement did not return a tuple table, complain */
4359 if (tuptab == NULL)
4360 ereport(ERROR,
4362 errmsg("INTO used with a command that cannot return data")));
4363
4364 /* Fetch target's datum entry */
4365 target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4366
4367 /*
4368 * If SELECT ... INTO specified STRICT, and the query didn't find
4369 * exactly one row, throw an error. If STRICT was not specified, then
4370 * allow the query to find any number of rows.
4371 */
4372 if (n == 0)
4373 {
4374 if (stmt->strict)
4375 {
4376 char *errdetail;
4377
4378 if (estate->func->print_strict_params)
4379 errdetail = format_expr_params(estate, expr);
4380 else
4381 errdetail = NULL;
4382
4383 ereport(ERROR,
4385 errmsg("query returned no rows"),
4386 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4387 }
4388 /* set the target to NULL(s) */
4389 exec_move_row(estate, target, NULL, tuptab->tupdesc);
4390 }
4391 else
4392 {
4393 if (n > 1 && (stmt->strict || stmt->mod_stmt || too_many_rows_level))
4394 {
4395 char *errdetail;
4396 int errlevel;
4397
4398 if (estate->func->print_strict_params)
4399 errdetail = format_expr_params(estate, expr);
4400 else
4401 errdetail = NULL;
4402
4403 errlevel = (stmt->strict || stmt->mod_stmt) ? ERROR : too_many_rows_level;
4404
4407 errmsg("query returned more than one row"),
4408 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0,
4409 errhint("Make sure the query returns a single row, or use LIMIT 1.")));
4410 }
4411 /* Put the first result row into the target */
4412 exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4413 }
4414
4415 /* Clean up */
4416 exec_eval_cleanup(estate);
4418 }
4419 else
4420 {
4421 /* If the statement returned a tuple table, complain */
4422 if (SPI_tuptable != NULL)
4423 ereport(ERROR,
4425 errmsg("query has no destination for result data"),
4426 (rc == SPI_OK_SELECT) ? errhint("If you want to discard the results of a SELECT, use PERFORM instead.") : 0));
4427 }
4428
4429 return PLPGSQL_RC_OK;
4430}

References Assert, CachedPlanSource::commandTag, CURSOR_OPT_PARALLEL_OK, PLpgSQL_execstate::datums, elog, ereport, errcode(), errdetail(), errdetail_internal(), errhint(), errmsg(), ERROR, PLpgSQL_execstate::eval_processed, exec_eval_cleanup(), exec_move_row(), exec_prepare_plan(), exec_set_found(), fb(), format_expr_params(), PLpgSQL_execstate::func, lfirst, PLpgSQL_expr::plan, plpgsql_extra_errors, plpgsql_extra_warnings, PLPGSQL_RC_OK, PLPGSQL_XCHECK_TOOMANYROWS, PLpgSQL_function::print_strict_params, PLpgSQL_expr::query, PLpgSQL_execstate::readonly_func, setup_param_list(), SPI_ERROR_COPY, SPI_ERROR_TRANSACTION, SPI_execute_plan_with_paramlist(), SPI_freetuptable(), SPI_OK_DELETE, SPI_OK_DELETE_RETURNING, SPI_OK_INSERT, SPI_OK_INSERT_RETURNING, SPI_OK_MERGE, SPI_OK_MERGE_RETURNING, SPI_OK_REWRITTEN, SPI_OK_SELECT, SPI_OK_SELINTO, SPI_OK_UPDATE, SPI_OK_UPDATE_RETURNING, SPI_OK_UTILITY, SPI_plan_get_plan_sources(), SPI_processed, SPI_result_code_string(), SPI_tuptable, stmt, and WARNING.

Referenced by exec_stmt_forc(), exec_stmt_open(), and exec_stmts().

◆ exec_stmt_exit()

static int exec_stmt_exit ( PLpgSQL_execstate estate,
PLpgSQL_stmt_exit stmt 
)
static

Definition at line 3163 of file pl_exec.c.

3164{
3165 /*
3166 * If the exit / continue has a condition, evaluate it
3167 */
3168 if (stmt->cond != NULL)
3169 {
3170 bool value;
3171 bool isnull;
3172
3173 value = exec_eval_boolean(estate, stmt->cond, &isnull);
3174 exec_eval_cleanup(estate);
3175 if (isnull || value == false)
3176 return PLPGSQL_RC_OK;
3177 }
3178
3179 estate->exitlabel = stmt->label;
3180 if (stmt->is_exit)
3181 return PLPGSQL_RC_EXIT;
3182 else
3183 return PLPGSQL_RC_CONTINUE;
3184}

References exec_eval_boolean(), exec_eval_cleanup(), PLpgSQL_execstate::exitlabel, fb(), PLPGSQL_RC_CONTINUE, PLPGSQL_RC_EXIT, PLPGSQL_RC_OK, stmt, and value.

Referenced by exec_stmts().

◆ exec_stmt_fetch()

static int exec_stmt_fetch ( PLpgSQL_execstate estate,
PLpgSQL_stmt_fetch stmt 
)
static

Definition at line 4821 of file pl_exec.c.

4822{
4823 PLpgSQL_var *curvar;
4824 long how_many = stmt->how_many;
4826 Portal portal;
4827 char *curname;
4828 uint64 n;
4829 MemoryContext oldcontext;
4830
4831 /* ----------
4832 * Get the portal of the cursor by name
4833 * ----------
4834 */
4835 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4836 if (curvar->isnull)
4837 ereport(ERROR,
4839 errmsg("cursor variable \"%s\" is null", curvar->refname)));
4840
4841 /* Use eval_mcontext for short-lived string */
4842 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4844 MemoryContextSwitchTo(oldcontext);
4845
4846 portal = SPI_cursor_find(curname);
4847 if (portal == NULL)
4848 ereport(ERROR,
4850 errmsg("cursor \"%s\" does not exist", curname)));
4851
4852 /* Calculate position for FETCH_RELATIVE or FETCH_ABSOLUTE */
4853 if (stmt->expr)
4854 {
4855 bool isnull;
4856
4857 /* XXX should be doing this in LONG not INT width */
4858 how_many = exec_eval_integer(estate, stmt->expr, &isnull);
4859
4860 if (isnull)
4861 ereport(ERROR,
4863 errmsg("relative or absolute cursor position is null")));
4864
4865 exec_eval_cleanup(estate);
4866 }
4867
4868 if (!stmt->is_move)
4869 {
4870 PLpgSQL_variable *target;
4871
4872 /* ----------
4873 * Fetch 1 tuple from the cursor
4874 * ----------
4875 */
4876 SPI_scroll_cursor_fetch(portal, stmt->direction, how_many);
4878 n = SPI_processed;
4879
4880 /* ----------
4881 * Set the target appropriately.
4882 * ----------
4883 */
4884 target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4885 if (n == 0)
4886 exec_move_row(estate, target, NULL, tuptab->tupdesc);
4887 else
4888 exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4889
4890 exec_eval_cleanup(estate);
4892 }
4893 else
4894 {
4895 /* Move the cursor */
4896 SPI_scroll_cursor_move(portal, stmt->direction, how_many);
4897 n = SPI_processed;
4898 }
4899
4900 /* Set the ROW_COUNT and the global FOUND variable appropriately. */
4901 estate->eval_processed = n;
4902 exec_set_found(estate, n != 0);
4903
4904 return PLPGSQL_RC_OK;
4905}

References PLpgSQL_execstate::datums, ereport, errcode(), errmsg(), ERROR, PLpgSQL_execstate::eval_processed, exec_eval_cleanup(), exec_eval_integer(), exec_move_row(), exec_set_found(), fb(), get_eval_mcontext, PLpgSQL_var::isnull, MemoryContextSwitchTo(), PLPGSQL_RC_OK, PLpgSQL_var::refname, SPI_cursor_find(), SPI_freetuptable(), SPI_processed, SPI_scroll_cursor_fetch(), SPI_scroll_cursor_move(), SPI_tuptable, stmt, TextDatumGetCString, and PLpgSQL_var::value.

Referenced by exec_stmts().

◆ exec_stmt_forc()

static int exec_stmt_forc ( PLpgSQL_execstate estate,
PLpgSQL_stmt_forc stmt 
)
static

Definition at line 2867 of file pl_exec.c.

2868{
2869 PLpgSQL_var *curvar;
2870 MemoryContext stmt_mcontext = NULL;
2871 char *curname = NULL;
2872 PLpgSQL_expr *query;
2873 ParamListInfo paramLI;
2874 Portal portal;
2875 int rc;
2876
2877 /* ----------
2878 * Get the cursor variable and if it has an assigned name, check
2879 * that it's not in use currently.
2880 * ----------
2881 */
2882 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
2883 if (!curvar->isnull)
2884 {
2885 MemoryContext oldcontext;
2886
2887 /* We only need stmt_mcontext to hold the cursor name string */
2888 stmt_mcontext = get_stmt_mcontext(estate);
2889 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
2891 MemoryContextSwitchTo(oldcontext);
2892
2894 ereport(ERROR,
2896 errmsg("cursor \"%s\" already in use", curname)));
2897 }
2898
2899 /* ----------
2900 * Open the cursor just like an OPEN command
2901 *
2902 * Note: parser should already have checked that statement supplies
2903 * args iff cursor needs them, but we check again to be safe.
2904 * ----------
2905 */
2906 if (stmt->argquery != NULL)
2907 {
2908 /* ----------
2909 * OPEN CURSOR with args. We fake a SELECT ... INTO ...
2910 * statement to evaluate the args and put 'em into the
2911 * internal row.
2912 * ----------
2913 */
2915
2916 if (curvar->cursor_explicit_argrow < 0)
2917 ereport(ERROR,
2919 errmsg("arguments given for cursor without arguments")));
2920
2921 memset(&set_args, 0, sizeof(set_args));
2922 set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
2923 set_args.lineno = stmt->lineno;
2924 set_args.sqlstmt = stmt->argquery;
2925 set_args.into = true;
2926 /* XXX historically this has not been STRICT */
2927 set_args.target = (PLpgSQL_variable *)
2928 (estate->datums[curvar->cursor_explicit_argrow]);
2929
2930 if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
2931 elog(ERROR, "open cursor failed during argument processing");
2932 }
2933 else
2934 {
2935 if (curvar->cursor_explicit_argrow >= 0)
2936 ereport(ERROR,
2938 errmsg("arguments required for cursor")));
2939 }
2940
2941 query = curvar->cursor_explicit_expr;
2942 Assert(query);
2943
2944 if (query->plan == NULL)
2945 exec_prepare_plan(estate, query, curvar->cursor_options);
2946
2947 /*
2948 * Set up ParamListInfo for this query
2949 */
2950 paramLI = setup_param_list(estate, query);
2951
2952 /*
2953 * Open the cursor (the paramlist will get copied into the portal)
2954 */
2956 paramLI,
2957 estate->readonly_func);
2958 if (portal == NULL)
2959 elog(ERROR, "could not open cursor: %s",
2961
2962 /*
2963 * If cursor variable was NULL, store the generated portal name in it,
2964 * after verifying it's okay to assign to.
2965 */
2966 if (curname == NULL)
2967 {
2968 exec_check_assignable(estate, stmt->curvar);
2969 assign_text_var(estate, curvar, portal->name);
2970 }
2971
2972 /*
2973 * Clean up before entering exec_for_query
2974 */
2975 exec_eval_cleanup(estate);
2976 if (stmt_mcontext)
2977 MemoryContextReset(stmt_mcontext);
2978
2979 /*
2980 * Execute the loop. We can't prefetch because the cursor is accessible
2981 * to the user, for instance via UPDATE WHERE CURRENT OF within the loop.
2982 */
2983 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, false);
2984
2985 /* ----------
2986 * Close portal, and restore cursor variable if it was initially NULL.
2987 * ----------
2988 */
2989 SPI_cursor_close(portal);
2990
2991 if (curname == NULL)
2992 assign_simple_var(estate, curvar, (Datum) 0, true, false);
2993
2994 return rc;
2995}

References Assert, assign_simple_var(), assign_text_var(), PLpgSQL_var::cursor_explicit_argrow, PLpgSQL_var::cursor_explicit_expr, PLpgSQL_var::cursor_options, PLpgSQL_execstate::datums, elog, ereport, errcode(), errmsg(), ERROR, exec_check_assignable(), exec_eval_cleanup(), exec_for_query(), exec_prepare_plan(), exec_stmt_execsql(), fb(), get_stmt_mcontext(), PLpgSQL_var::isnull, MemoryContextReset(), MemoryContextSwitchTo(), PortalData::name, PLpgSQL_expr::plan, PLPGSQL_RC_OK, PLPGSQL_STMT_EXECSQL, PLpgSQL_execstate::readonly_func, setup_param_list(), SPI_cursor_close(), SPI_cursor_find(), SPI_cursor_open_with_paramlist(), SPI_result, SPI_result_code_string(), stmt, TextDatumGetCString, and PLpgSQL_var::value.

Referenced by exec_stmts().

◆ exec_stmt_foreach_a()

static int exec_stmt_foreach_a ( PLpgSQL_execstate estate,
PLpgSQL_stmt_foreach_a stmt 
)
static

Definition at line 3007 of file pl_exec.c.

3008{
3009 ArrayType *arr;
3010 Oid arrtype;
3014 bool found = false;
3015 int rc = PLPGSQL_RC_OK;
3016 MemoryContext stmt_mcontext;
3017 MemoryContext oldcontext;
3021 Datum value;
3022 bool isnull;
3023
3024 /* get the value of the array expression */
3025 value = exec_eval_expr(estate, stmt->expr, &isnull, &arrtype, &arrtypmod);
3026 if (isnull)
3027 ereport(ERROR,
3029 errmsg("FOREACH expression must not be null")));
3030
3031 /*
3032 * Do as much as possible of the code below in stmt_mcontext, to avoid any
3033 * leaks from called subroutines. We need a private stmt_mcontext since
3034 * we'll be calling arbitrary statement code.
3035 */
3036 stmt_mcontext = get_stmt_mcontext(estate);
3037 push_stmt_mcontext(estate);
3038 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3039
3040 /* check the type of the expression - must be an array */
3042 ereport(ERROR,
3044 errmsg("FOREACH expression must yield an array, not type %s",
3046
3047 /*
3048 * We must copy the array into stmt_mcontext, else it will disappear in
3049 * exec_eval_cleanup. This is annoying, but cleanup will certainly happen
3050 * while running the loop body, so we have little choice.
3051 */
3053
3054 /* Clean up any leftover temporary memory */
3055 exec_eval_cleanup(estate);
3056
3057 /* Slice dimension must be less than or equal to array dimension */
3058 if (stmt->slice < 0 || stmt->slice > ARR_NDIM(arr))
3059 ereport(ERROR,
3061 errmsg("slice dimension (%d) is out of the valid range 0..%d",
3062 stmt->slice, ARR_NDIM(arr))));
3063
3064 /* Set up the loop variable and see if it is of an array type */
3065 loop_var = estate->datums[stmt->varno];
3066 if (loop_var->dtype == PLPGSQL_DTYPE_REC ||
3067 loop_var->dtype == PLPGSQL_DTYPE_ROW)
3068 {
3069 /*
3070 * Record/row variable is certainly not of array type, and might not
3071 * be initialized at all yet, so don't try to get its type
3072 */
3074 }
3075 else
3077 loop_var));
3078
3079 /*
3080 * Sanity-check the loop variable type. We don't try very hard here, and
3081 * should not be too picky since it's possible that exec_assign_value can
3082 * coerce values of different types. But it seems worthwhile to complain
3083 * if the array-ness of the loop variable is not right.
3084 */
3085 if (stmt->slice > 0 && loop_var_elem_type == InvalidOid)
3086 ereport(ERROR,
3088 errmsg("FOREACH ... SLICE loop variable must be of an array type")));
3089 if (stmt->slice == 0 && loop_var_elem_type != InvalidOid)
3090 ereport(ERROR,
3092 errmsg("FOREACH loop variable must not be of an array type")));
3093
3094 /* Create an iterator to step through the array */
3096
3097 /* Identify iterator result type */
3098 if (stmt->slice > 0)
3099 {
3100 /* When slicing, nominal type of result is same as array type */
3103 }
3104 else
3105 {
3106 /* Without slicing, results are individual array elements */
3109 }
3110
3111 /* Iterate over the array elements or slices */
3112 while (array_iterate(array_iterator, &value, &isnull))
3113 {
3114 found = true; /* looped at least once */
3115
3116 /* exec_assign_value and exec_stmts must run in the main context */
3117 MemoryContextSwitchTo(oldcontext);
3118
3119 /* Assign current element/slice to the loop variable */
3120 exec_assign_value(estate, loop_var, value, isnull,
3122
3123 /* In slice case, value is temporary; must free it to avoid leakage */
3124 if (stmt->slice > 0)
3126
3127 /*
3128 * Execute the statements
3129 */
3130 rc = exec_stmts(estate, stmt->body);
3131
3132 LOOP_RC_PROCESSING(stmt->label, break);
3133
3134 MemoryContextSwitchTo(stmt_mcontext);
3135 }
3136
3137 /* Restore memory context state */
3138 MemoryContextSwitchTo(oldcontext);
3139 pop_stmt_mcontext(estate);
3140
3141 /* Release temporary memory, including the array value */
3142 MemoryContextReset(stmt_mcontext);
3143
3144 /*
3145 * Set the FOUND variable to indicate the result of executing the loop
3146 * (namely, whether we looped one or more times). This must be set here so
3147 * that it does not interfere with the value of the FOUND variable inside
3148 * the loop processing itself.
3149 */
3150 exec_set_found(estate, found);
3151
3152 return rc;
3153}

References ARR_ELEMTYPE, ARR_NDIM, array_create_iterator(), array_iterate(), array_iterator(), DatumGetArrayTypePCopy, DatumGetPointer(), PLpgSQL_execstate::datums, ereport, errcode(), errmsg(), ERROR, exec_assign_value(), exec_eval_cleanup(), exec_eval_expr(), exec_set_found(), exec_stmts(), fb(), format_type_be(), get_element_type(), get_stmt_mcontext(), InvalidOid, LOOP_RC_PROCESSING, MemoryContextReset(), MemoryContextSwitchTo(), OidIsValid, pfree(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_ROW, plpgsql_exec_get_datum_type(), PLPGSQL_RC_OK, pop_stmt_mcontext(), push_stmt_mcontext(), stmt, and value.

Referenced by exec_stmts().

◆ exec_stmt_fori()

static int exec_stmt_fori ( PLpgSQL_execstate estate,
PLpgSQL_stmt_fori stmt 
)
static

Definition at line 2695 of file pl_exec.c.

2696{
2697 PLpgSQL_var *var;
2698 Datum value;
2699 bool isnull;
2700 Oid valtype;
2705 bool found = false;
2706 int rc = PLPGSQL_RC_OK;
2707
2708 var = (PLpgSQL_var *) (estate->datums[stmt->var->dno]);
2709
2710 /*
2711 * Get the value of the lower bound
2712 */
2713 value = exec_eval_expr(estate, stmt->lower,
2714 &isnull, &valtype, &valtypmod);
2715 value = exec_cast_value(estate, value, &isnull,
2717 var->datatype->typoid,
2718 var->datatype->atttypmod);
2719 if (isnull)
2720 ereport(ERROR,
2722 errmsg("lower bound of FOR loop cannot be null")));
2724 exec_eval_cleanup(estate);
2725
2726 /*
2727 * Get the value of the upper bound
2728 */
2729 value = exec_eval_expr(estate, stmt->upper,
2730 &isnull, &valtype, &valtypmod);
2731 value = exec_cast_value(estate, value, &isnull,
2733 var->datatype->typoid,
2734 var->datatype->atttypmod);
2735 if (isnull)
2736 ereport(ERROR,
2738 errmsg("upper bound of FOR loop cannot be null")));
2740 exec_eval_cleanup(estate);
2741
2742 /*
2743 * Get the step value
2744 */
2745 if (stmt->step)
2746 {
2747 value = exec_eval_expr(estate, stmt->step,
2748 &isnull, &valtype, &valtypmod);
2749 value = exec_cast_value(estate, value, &isnull,
2751 var->datatype->typoid,
2752 var->datatype->atttypmod);
2753 if (isnull)
2754 ereport(ERROR,
2756 errmsg("BY value of FOR loop cannot be null")));
2758 exec_eval_cleanup(estate);
2759 if (step_value <= 0)
2760 ereport(ERROR,
2762 errmsg("BY value of FOR loop must be greater than zero")));
2763 }
2764 else
2765 step_value = 1;
2766
2767 /*
2768 * Now do the loop
2769 */
2770 for (;;)
2771 {
2772 /*
2773 * Check against upper bound
2774 */
2775 if (stmt->reverse)
2776 {
2777 if (loop_value < end_value)
2778 break;
2779 }
2780 else
2781 {
2782 if (loop_value > end_value)
2783 break;
2784 }
2785
2786 found = true; /* looped at least once */
2787
2788 /*
2789 * Assign current value to loop var
2790 */
2791 assign_simple_var(estate, var, Int32GetDatum(loop_value), false, false);
2792
2793 /*
2794 * Execute the statements
2795 */
2796 rc = exec_stmts(estate, stmt->body);
2797
2798 LOOP_RC_PROCESSING(stmt->label, break);
2799
2800 /*
2801 * Increase/decrease loop value, unless it would overflow, in which
2802 * case exit the loop.
2803 */
2804 if (stmt->reverse)
2805 {
2807 break;
2809 }
2810 else
2811 {
2813 break;
2815 }
2816 }
2817
2818 /*
2819 * Set the FOUND variable to indicate the result of executing the loop
2820 * (namely, whether we looped one or more times). This must be set here so
2821 * that it does not interfere with the value of the FOUND variable inside
2822 * the loop processing itself.
2823 */
2824 exec_set_found(estate, found);
2825
2826 return rc;
2827}

References assign_simple_var(), PLpgSQL_type::atttypmod, PLpgSQL_var::datatype, DatumGetInt32(), PLpgSQL_execstate::datums, ereport, errcode(), errmsg(), ERROR, exec_cast_value(), exec_eval_cleanup(), exec_eval_expr(), exec_set_found(), exec_stmts(), fb(), Int32GetDatum(), LOOP_RC_PROCESSING, PG_INT32_MAX, PG_INT32_MIN, PLPGSQL_RC_OK, stmt, PLpgSQL_type::typoid, and value.

Referenced by exec_stmts().

◆ exec_stmt_fors()

static int exec_stmt_fors ( PLpgSQL_execstate estate,
PLpgSQL_stmt_fors stmt 
)
static

Definition at line 2838 of file pl_exec.c.

2839{
2840 Portal portal;
2841 int rc;
2842
2843 /*
2844 * Open the implicit cursor for the statement using exec_run_select
2845 */
2846 exec_run_select(estate, stmt->query, 0, &portal);
2847
2848 /*
2849 * Execute the loop
2850 */
2851 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
2852
2853 /*
2854 * Close the implicit cursor
2855 */
2856 SPI_cursor_close(portal);
2857
2858 return rc;
2859}

References exec_for_query(), exec_run_select(), SPI_cursor_close(), and stmt.

Referenced by exec_stmts().

◆ exec_stmt_getdiag()

static int exec_stmt_getdiag ( PLpgSQL_execstate estate,
PLpgSQL_stmt_getdiag stmt 
)
static

Definition at line 2409 of file pl_exec.c.

2410{
2411 ListCell *lc;
2412
2413 /*
2414 * GET STACKED DIAGNOSTICS is only valid inside an exception handler.
2415 *
2416 * Note: we trust the grammar to have disallowed the relevant item kinds
2417 * if not is_stacked, otherwise we'd dump core below.
2418 */
2419 if (stmt->is_stacked && estate->cur_error == NULL)
2420 ereport(ERROR,
2422 errmsg("GET STACKED DIAGNOSTICS cannot be used outside an exception handler")));
2423
2424 foreach(lc, stmt->diag_items)
2425 {
2427 PLpgSQL_datum *var = estate->datums[diag_item->target];
2428
2429 switch (diag_item->kind)
2430 {
2432 exec_assign_value(estate, var,
2434 false, INT8OID, -1);
2435 break;
2436
2438 exec_assign_value(estate, var,
2439 ObjectIdGetDatum(estate->func->fn_oid),
2440 false, OIDOID, -1);
2441 break;
2442
2444 exec_assign_c_string(estate, var,
2445 estate->cur_error->context);
2446 break;
2447
2449 exec_assign_c_string(estate, var,
2450 estate->cur_error->detail);
2451 break;
2452
2454 exec_assign_c_string(estate, var,
2455 estate->cur_error->hint);
2456 break;
2457
2459 exec_assign_c_string(estate, var,
2461 break;
2462
2464 exec_assign_c_string(estate, var,
2465 estate->cur_error->column_name);
2466 break;
2467
2469 exec_assign_c_string(estate, var,
2470 estate->cur_error->constraint_name);
2471 break;
2472
2474 exec_assign_c_string(estate, var,
2475 estate->cur_error->datatype_name);
2476 break;
2477
2479 exec_assign_c_string(estate, var,
2480 estate->cur_error->message);
2481 break;
2482
2484 exec_assign_c_string(estate, var,
2485 estate->cur_error->table_name);
2486 break;
2487
2489 exec_assign_c_string(estate, var,
2490 estate->cur_error->schema_name);
2491 break;
2492
2494 {
2495 char *contextstackstr;
2496 MemoryContext oldcontext;
2497
2498 /* Use eval_mcontext for short-lived string */
2499 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2501 MemoryContextSwitchTo(oldcontext);
2502
2504 }
2505 break;
2506
2507 default:
2508 elog(ERROR, "unrecognized diagnostic item kind: %d",
2509 diag_item->kind);
2510 }
2511 }
2512
2513 exec_eval_cleanup(estate);
2514
2515 return PLPGSQL_RC_OK;
2516}

References ErrorData::column_name, ErrorData::constraint_name, ErrorData::context, PLpgSQL_execstate::cur_error, ErrorData::datatype_name, PLpgSQL_execstate::datums, ErrorData::detail, elog, ereport, errcode(), errmsg(), ERROR, PLpgSQL_execstate::eval_processed, exec_assign_c_string(), exec_assign_value(), exec_eval_cleanup(), fb(), PLpgSQL_function::fn_oid, PLpgSQL_execstate::func, get_eval_mcontext, GetErrorContextStack(), ErrorData::hint, lfirst, MemoryContextSwitchTo(), ErrorData::message, ObjectIdGetDatum(), PLPGSQL_GETDIAG_COLUMN_NAME, PLPGSQL_GETDIAG_CONSTRAINT_NAME, PLPGSQL_GETDIAG_CONTEXT, PLPGSQL_GETDIAG_DATATYPE_NAME, PLPGSQL_GETDIAG_ERROR_CONTEXT, PLPGSQL_GETDIAG_ERROR_DETAIL, PLPGSQL_GETDIAG_ERROR_HINT, PLPGSQL_GETDIAG_MESSAGE_TEXT, PLPGSQL_GETDIAG_RETURNED_SQLSTATE, PLPGSQL_GETDIAG_ROUTINE_OID, PLPGSQL_GETDIAG_ROW_COUNT, PLPGSQL_GETDIAG_SCHEMA_NAME, PLPGSQL_GETDIAG_TABLE_NAME, PLPGSQL_RC_OK, ErrorData::schema_name, ErrorData::sqlerrcode, stmt, ErrorData::table_name, UInt64GetDatum(), and unpack_sql_state().

Referenced by exec_stmts().

◆ exec_stmt_if()

static int exec_stmt_if ( PLpgSQL_execstate estate,
PLpgSQL_stmt_if stmt 
)
static

Definition at line 2525 of file pl_exec.c.

2526{
2527 bool value;
2528 bool isnull;
2529 ListCell *lc;
2530
2531 value = exec_eval_boolean(estate, stmt->cond, &isnull);
2532 exec_eval_cleanup(estate);
2533 if (!isnull && value)
2534 return exec_stmts(estate, stmt->then_body);
2535
2536 foreach(lc, stmt->elsif_list)
2537 {
2539
2540 value = exec_eval_boolean(estate, elif->cond, &isnull);
2541 exec_eval_cleanup(estate);
2542 if (!isnull && value)
2543 return exec_stmts(estate, elif->stmts);
2544 }
2545
2546 return exec_stmts(estate, stmt->else_body);
2547}

References exec_eval_boolean(), exec_eval_cleanup(), exec_stmts(), fb(), lfirst, stmt, and value.

Referenced by exec_stmts().

◆ exec_stmt_loop()

static int exec_stmt_loop ( PLpgSQL_execstate estate,
PLpgSQL_stmt_loop stmt 
)
static

Definition at line 2642 of file pl_exec.c.

2643{
2644 int rc = PLPGSQL_RC_OK;
2645
2646 for (;;)
2647 {
2648 rc = exec_stmts(estate, stmt->body);
2649
2650 LOOP_RC_PROCESSING(stmt->label, break);
2651 }
2652
2653 return rc;
2654}

References exec_stmts(), LOOP_RC_PROCESSING, PLPGSQL_RC_OK, and stmt.

Referenced by exec_stmts().

◆ exec_stmt_open()

static int exec_stmt_open ( PLpgSQL_execstate estate,
PLpgSQL_stmt_open stmt 
)
static

Definition at line 4656 of file pl_exec.c.

4657{
4658 PLpgSQL_var *curvar;
4659 MemoryContext stmt_mcontext = NULL;
4660 char *curname = NULL;
4661 PLpgSQL_expr *query;
4662 Portal portal;
4663 ParamListInfo paramLI;
4664
4665 /* ----------
4666 * Get the cursor variable and if it has an assigned name, check
4667 * that it's not in use currently.
4668 * ----------
4669 */
4670 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4671 if (!curvar->isnull)
4672 {
4673 MemoryContext oldcontext;
4674
4675 /* We only need stmt_mcontext to hold the cursor name string */
4676 stmt_mcontext = get_stmt_mcontext(estate);
4677 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
4679 MemoryContextSwitchTo(oldcontext);
4680
4682 ereport(ERROR,
4684 errmsg("cursor \"%s\" already in use", curname)));
4685 }
4686
4687 /* ----------
4688 * Process the OPEN according to its type.
4689 * ----------
4690 */
4691 if (stmt->query != NULL)
4692 {
4693 /* ----------
4694 * This is an OPEN refcursor FOR SELECT ...
4695 *
4696 * We just make sure the query is planned. The real work is
4697 * done downstairs.
4698 * ----------
4699 */
4700 query = stmt->query;
4701 if (query->plan == NULL)
4702 exec_prepare_plan(estate, query, stmt->cursor_options);
4703 }
4704 else if (stmt->dynquery != NULL)
4705 {
4706 /* ----------
4707 * This is an OPEN refcursor FOR EXECUTE ...
4708 * ----------
4709 */
4710 portal = exec_dynquery_with_params(estate,
4711 stmt->dynquery,
4712 stmt->params,
4713 curname,
4714 stmt->cursor_options);
4715
4716 /*
4717 * If cursor variable was NULL, store the generated portal name in it,
4718 * after verifying it's okay to assign to.
4719 *
4720 * Note: exec_dynquery_with_params already reset the stmt_mcontext, so
4721 * curname is a dangling pointer here; but testing it for nullness is
4722 * OK.
4723 */
4724 if (curname == NULL)
4725 {
4726 exec_check_assignable(estate, stmt->curvar);
4727 assign_text_var(estate, curvar, portal->name);
4728 }
4729
4730 return PLPGSQL_RC_OK;
4731 }
4732 else
4733 {
4734 /* ----------
4735 * This is an OPEN cursor
4736 *
4737 * Note: parser should already have checked that statement supplies
4738 * args iff cursor needs them, but we check again to be safe.
4739 * ----------
4740 */
4741 if (stmt->argquery != NULL)
4742 {
4743 /* ----------
4744 * OPEN CURSOR with args. We fake a SELECT ... INTO ...
4745 * statement to evaluate the args and put 'em into the
4746 * internal row.
4747 * ----------
4748 */
4750
4751 if (curvar->cursor_explicit_argrow < 0)
4752 ereport(ERROR,
4754 errmsg("arguments given for cursor without arguments")));
4755
4756 memset(&set_args, 0, sizeof(set_args));
4757 set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
4758 set_args.lineno = stmt->lineno;
4759 set_args.sqlstmt = stmt->argquery;
4760 set_args.into = true;
4761 /* XXX historically this has not been STRICT */
4762 set_args.target = (PLpgSQL_variable *)
4763 (estate->datums[curvar->cursor_explicit_argrow]);
4764
4765 if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
4766 elog(ERROR, "open cursor failed during argument processing");
4767 }
4768 else
4769 {
4770 if (curvar->cursor_explicit_argrow >= 0)
4771 ereport(ERROR,
4773 errmsg("arguments required for cursor")));
4774 }
4775
4776 query = curvar->cursor_explicit_expr;
4777 if (query->plan == NULL)
4778 exec_prepare_plan(estate, query, curvar->cursor_options);
4779 }
4780
4781 /*
4782 * Set up ParamListInfo for this query
4783 */
4784 paramLI = setup_param_list(estate, query);
4785
4786 /*
4787 * Open the cursor (the paramlist will get copied into the portal)
4788 */
4790 paramLI,
4791 estate->readonly_func);
4792 if (portal == NULL)
4793 elog(ERROR, "could not open cursor: %s",
4795
4796 /*
4797 * If cursor variable was NULL, store the generated portal name in it,
4798 * after verifying it's okay to assign to.
4799 */
4800 if (curname == NULL)
4801 {
4802 exec_check_assignable(estate, stmt->curvar);
4803 assign_text_var(estate, curvar, portal->name);
4804 }
4805
4806 /* If we had any transient data, clean it up */
4807 exec_eval_cleanup(estate);
4808 if (stmt_mcontext)
4809 MemoryContextReset(stmt_mcontext);
4810
4811 return PLPGSQL_RC_OK;
4812}

References assign_text_var(), PLpgSQL_var::cursor_explicit_argrow, PLpgSQL_var::cursor_explicit_expr, PLpgSQL_var::cursor_options, PLpgSQL_execstate::datums, elog, ereport, errcode(), errmsg(), ERROR, exec_check_assignable(), exec_dynquery_with_params(), exec_eval_cleanup(), exec_prepare_plan(), exec_stmt_execsql(), fb(), get_stmt_mcontext(), PLpgSQL_var::isnull, MemoryContextReset(), MemoryContextSwitchTo(), PortalData::name, PLpgSQL_expr::plan, PLPGSQL_RC_OK, PLPGSQL_STMT_EXECSQL, PLpgSQL_expr::query, PLpgSQL_execstate::readonly_func, setup_param_list(), SPI_cursor_find(), SPI_cursor_open_with_paramlist(), SPI_result, SPI_result_code_string(), stmt, TextDatumGetCString, and PLpgSQL_var::value.

Referenced by exec_stmts().

◆ exec_stmt_perform()

static int exec_stmt_perform ( PLpgSQL_execstate estate,
PLpgSQL_stmt_perform stmt 
)
static

Definition at line 2179 of file pl_exec.c.

2180{
2181 PLpgSQL_expr *expr = stmt->expr;
2182
2183 (void) exec_run_select(estate, expr, 0, NULL);
2184 exec_set_found(estate, (estate->eval_processed != 0));
2185 exec_eval_cleanup(estate);
2186
2187 return PLPGSQL_RC_OK;
2188}

References PLpgSQL_execstate::eval_processed, exec_eval_cleanup(), exec_run_select(), exec_set_found(), fb(), PLPGSQL_RC_OK, and stmt.

Referenced by exec_stmts().

◆ exec_stmt_raise()

static int exec_stmt_raise ( PLpgSQL_execstate estate,
PLpgSQL_stmt_raise stmt 
)
static

Definition at line 3724 of file pl_exec.c.

3725{
3726 int err_code = 0;
3727 char *condname = NULL;
3728 char *err_message = NULL;
3729 char *err_detail = NULL;
3730 char *err_hint = NULL;
3731 char *err_column = NULL;
3732 char *err_constraint = NULL;
3733 char *err_datatype = NULL;
3734 char *err_table = NULL;
3735 char *err_schema = NULL;
3736 MemoryContext stmt_mcontext;
3737 ListCell *lc;
3738
3739 /* RAISE with no parameters: re-throw current exception */
3740 if (stmt->condname == NULL && stmt->message == NULL &&
3741 stmt->options == NIL)
3742 {
3743 if (estate->cur_error != NULL)
3744 ReThrowError(estate->cur_error);
3745 /* oops, we're not inside a handler */
3746 ereport(ERROR,
3748 errmsg("RAISE without parameters cannot be used outside an exception handler")));
3749 }
3750
3751 /* We'll need to accumulate the various strings in stmt_mcontext */
3752 stmt_mcontext = get_stmt_mcontext(estate);
3753
3754 if (stmt->condname)
3755 {
3757 condname = MemoryContextStrdup(stmt_mcontext, stmt->condname);
3758 }
3759
3760 if (stmt->message)
3761 {
3764 char *cp;
3765 MemoryContext oldcontext;
3766
3767 /* build string in stmt_mcontext */
3768 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3770 MemoryContextSwitchTo(oldcontext);
3771
3772 current_param = list_head(stmt->params);
3773
3774 for (cp = stmt->message; *cp; cp++)
3775 {
3776 /*
3777 * Occurrences of a single % are replaced by the next parameter's
3778 * external representation. Double %'s are converted to one %.
3779 */
3780 if (cp[0] == '%')
3781 {
3783 int32 paramtypmod;
3785 bool paramisnull;
3786 char *extval;
3787
3788 if (cp[1] == '%')
3789 {
3790 appendStringInfoChar(&ds, '%');
3791 cp++;
3792 continue;
3793 }
3794
3795 /* should have been checked at compile time */
3796 if (current_param == NULL)
3797 elog(ERROR, "unexpected RAISE parameter list length");
3798
3799 paramvalue = exec_eval_expr(estate,
3801 &paramisnull,
3802 &paramtypeid,
3803 &paramtypmod);
3804
3805 if (paramisnull)
3806 extval = "<NULL>";
3807 else
3809 paramvalue,
3810 paramtypeid);
3813 exec_eval_cleanup(estate);
3814 }
3815 else
3817 }
3818
3819 /* should have been checked at compile time */
3820 if (current_param != NULL)
3821 elog(ERROR, "unexpected RAISE parameter list length");
3822
3823 err_message = ds.data;
3824 }
3825
3826 foreach(lc, stmt->options)
3827 {
3830 bool optionisnull;
3833 char *extval;
3834
3835 optionvalue = exec_eval_expr(estate, opt->expr,
3836 &optionisnull,
3837 &optiontypeid,
3838 &optiontypmod);
3839 if (optionisnull)
3840 ereport(ERROR,
3842 errmsg("RAISE statement option cannot be null")));
3843
3845
3846 switch (opt->opt_type)
3847 {
3849 if (err_code)
3850 ereport(ERROR,
3852 errmsg("RAISE option already specified: %s",
3853 "ERRCODE")));
3855 condname = MemoryContextStrdup(stmt_mcontext, extval);
3856 break;
3859 break;
3862 break;
3865 break;
3868 break;
3871 break;
3874 break;
3877 break;
3880 break;
3881 default:
3882 elog(ERROR, "unrecognized raise option: %d", opt->opt_type);
3883 }
3884
3885 exec_eval_cleanup(estate);
3886 }
3887
3888 /* Default code if nothing specified */
3889 if (err_code == 0 && stmt->elog_level >= ERROR)
3891
3892 /* Default error message if nothing specified */
3893 if (err_message == NULL)
3894 {
3895 if (condname)
3896 {
3897 err_message = condname;
3898 condname = NULL;
3899 }
3900 else
3901 err_message = MemoryContextStrdup(stmt_mcontext,
3903 }
3904
3905 /*
3906 * Throw the error (may or may not come back)
3907 */
3908 ereport(stmt->elog_level,
3909 (err_code ? errcode(err_code) : 0,
3911 (err_detail != NULL) ? errdetail_internal("%s", err_detail) : 0,
3912 (err_hint != NULL) ? errhint("%s", err_hint) : 0,
3913 (err_column != NULL) ?
3915 (err_constraint != NULL) ?
3917 (err_datatype != NULL) ?
3919 (err_table != NULL) ?
3921 (err_schema != NULL) ?
3923
3924 /* Clean up transient strings */
3925 MemoryContextReset(stmt_mcontext);
3926
3927 return PLPGSQL_RC_OK;
3928}

References appendStringInfoChar(), appendStringInfoString(), convert_value_to_string(), PLpgSQL_execstate::cur_error, elog, ereport, err_generic_string(), errcode(), errdetail_internal(), errhint(), errmsg(), errmsg_internal(), ERROR, exec_eval_cleanup(), exec_eval_expr(), PLpgSQL_raise_option::expr, fb(), get_stmt_mcontext(), initStringInfo(), lfirst, list_head(), lnext(), MemoryContextReset(), MemoryContextStrdup(), MemoryContextSwitchTo(), NIL, PLpgSQL_raise_option::opt_type, PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_DATATYPE_NAME, PG_DIAG_SCHEMA_NAME, PG_DIAG_TABLE_NAME, PLPGSQL_RAISEOPTION_COLUMN, PLPGSQL_RAISEOPTION_CONSTRAINT, PLPGSQL_RAISEOPTION_DATATYPE, PLPGSQL_RAISEOPTION_DETAIL, PLPGSQL_RAISEOPTION_ERRCODE, PLPGSQL_RAISEOPTION_HINT, PLPGSQL_RAISEOPTION_MESSAGE, PLPGSQL_RAISEOPTION_SCHEMA, PLPGSQL_RAISEOPTION_TABLE, PLPGSQL_RC_OK, plpgsql_recognize_err_condition(), ReThrowError(), SET_RAISE_OPTION_TEXT, stmt, and unpack_sql_state().

Referenced by exec_stmts().

◆ exec_stmt_return()

static int exec_stmt_return ( PLpgSQL_execstate estate,
PLpgSQL_stmt_return stmt 
)
static

Definition at line 3196 of file pl_exec.c.

3197{
3198 /*
3199 * If processing a set-returning PL/pgSQL function, the final RETURN
3200 * indicates that the function is finished producing tuples. The rest of
3201 * the work will be done at the top level.
3202 */
3203 if (estate->retisset)
3204 return PLPGSQL_RC_RETURN;
3205
3206 /* initialize for null result */
3207 estate->retval = (Datum) 0;
3208 estate->retisnull = true;
3209 estate->rettype = InvalidOid;
3210
3211 /*
3212 * Special case path when the RETURN expression is a simple variable
3213 * reference; in particular, this path is always taken in functions with
3214 * one or more OUT parameters.
3215 *
3216 * This special case is especially efficient for returning variables that
3217 * have R/W expanded values: we can put the R/W pointer directly into
3218 * estate->retval, leading to transferring the value to the caller's
3219 * context cheaply. If we went through exec_eval_expr we'd end up with a
3220 * R/O pointer. It's okay to skip MakeExpandedObjectReadOnly here since
3221 * we know we won't need the variable's value within the function anymore.
3222 */
3223 if (stmt->retvarno >= 0)
3224 {
3225 PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
3226
3227 switch (retvar->dtype)
3228 {
3230 /* fulfill promise if needed, then handle like regular var */
3232
3234
3235 case PLPGSQL_DTYPE_VAR:
3236 {
3237 PLpgSQL_var *var = (PLpgSQL_var *) retvar;
3238
3239 estate->retval = var->value;
3240 estate->retisnull = var->isnull;
3241 estate->rettype = var->datatype->typoid;
3242
3243 /*
3244 * A PLpgSQL_var could not be of composite type, so
3245 * conversion must fail if retistuple. We throw a custom
3246 * error mainly for consistency with historical behavior.
3247 * For the same reason, we don't throw error if the result
3248 * is NULL. (Note that plpgsql_exec_trigger assumes that
3249 * any non-null result has been verified to be composite.)
3250 */
3251 if (estate->retistuple && !estate->retisnull)
3252 ereport(ERROR,
3254 errmsg("cannot return non-composite value from function returning composite type")));
3255 }
3256 break;
3257
3258 case PLPGSQL_DTYPE_ROW:
3259 case PLPGSQL_DTYPE_REC:
3260 {
3261 /* exec_eval_datum can handle these cases */
3263
3264 exec_eval_datum(estate,
3265 retvar,
3266 &estate->rettype,
3267 &rettypmod,
3268 &estate->retval,
3269 &estate->retisnull);
3270 }
3271 break;
3272
3273 default:
3274 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
3275 }
3276
3277 return PLPGSQL_RC_RETURN;
3278 }
3279
3280 if (stmt->expr != NULL)
3281 {
3283
3284 estate->retval = exec_eval_expr(estate, stmt->expr,
3285 &(estate->retisnull),
3286 &(estate->rettype),
3287 &rettypmod);
3288
3289 /*
3290 * As in the DTYPE_VAR case above, throw a custom error if a non-null,
3291 * non-composite value is returned in a function returning tuple.
3292 */
3293 if (estate->retistuple && !estate->retisnull &&
3294 !type_is_rowtype(estate->rettype))
3295 ereport(ERROR,
3297 errmsg("cannot return non-composite value from function returning composite type")));
3298
3299 return PLPGSQL_RC_RETURN;
3300 }
3301
3302 /*
3303 * Special hack for function returning VOID: instead of NULL, return a
3304 * non-null VOID value. This is of dubious importance but is kept for
3305 * backwards compatibility. We don't do it for procedures, though.
3306 */
3307 if (estate->fn_rettype == VOIDOID &&
3308 estate->func->fn_prokind != PROKIND_PROCEDURE)
3309 {
3310 estate->retval = (Datum) 0;
3311 estate->retisnull = false;
3312 estate->rettype = VOIDOID;
3313 }
3314
3315 return PLPGSQL_RC_RETURN;
3316}

References PLpgSQL_var::datatype, PLpgSQL_execstate::datums, elog, ereport, errcode(), errmsg(), ERROR, exec_eval_datum(), exec_eval_expr(), fb(), PLpgSQL_function::fn_prokind, PLpgSQL_execstate::fn_rettype, PLpgSQL_execstate::func, InvalidOid, PLpgSQL_var::isnull, pg_fallthrough, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, plpgsql_fulfill_promise(), PLPGSQL_RC_RETURN, PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::retistuple, PLpgSQL_execstate::rettype, PLpgSQL_execstate::retval, stmt, type_is_rowtype(), PLpgSQL_type::typoid, and PLpgSQL_var::value.

Referenced by exec_stmts().

◆ exec_stmt_return_next()

static int exec_stmt_return_next ( PLpgSQL_execstate estate,
PLpgSQL_stmt_return_next stmt 
)
static

Definition at line 3325 of file pl_exec.c.

3327{
3328 TupleDesc tupdesc;
3329 int natts;
3330 HeapTuple tuple;
3331 MemoryContext oldcontext;
3332
3333 if (!estate->retisset)
3334 ereport(ERROR,
3336 errmsg("cannot use RETURN NEXT in a non-SETOF function")));
3337
3338 if (estate->tuple_store == NULL)
3339 exec_init_tuple_store(estate);
3340
3341 /* tuple_store_desc will be filled by exec_init_tuple_store */
3342 tupdesc = estate->tuple_store_desc;
3343 natts = tupdesc->natts;
3344
3345 /*
3346 * Special case path when the RETURN NEXT expression is a simple variable
3347 * reference; in particular, this path is always taken in functions with
3348 * one or more OUT parameters.
3349 *
3350 * Unlike exec_stmt_return, there's no special win here for R/W expanded
3351 * values, since they'll have to get flattened to go into the tuplestore.
3352 * Indeed, we'd better make them R/O to avoid any risk of the casting step
3353 * changing them in-place.
3354 */
3355 if (stmt->retvarno >= 0)
3356 {
3357 PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
3358
3359 switch (retvar->dtype)
3360 {
3362 /* fulfill promise if needed, then handle like regular var */
3364
3366
3367 case PLPGSQL_DTYPE_VAR:
3368 {
3369 PLpgSQL_var *var = (PLpgSQL_var *) retvar;
3370 Datum retval = var->value;
3371 bool isNull = var->isnull;
3372 Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
3373
3374 if (natts != 1)
3375 ereport(ERROR,
3377 errmsg("wrong result type supplied in RETURN NEXT")));
3378
3379 /* let's be very paranoid about the cast step */
3380 retval = MakeExpandedObjectReadOnly(retval,
3381 isNull,
3382 var->datatype->typlen);
3383
3384 /* coerce type if needed */
3385 retval = exec_cast_value(estate,
3386 retval,
3387 &isNull,
3388 var->datatype->typoid,
3389 var->datatype->atttypmod,
3390 attr->atttypid,
3391 attr->atttypmod);
3392
3393 tuplestore_putvalues(estate->tuple_store, tupdesc,
3394 &retval, &isNull);
3395 }
3396 break;
3397
3398 case PLPGSQL_DTYPE_REC:
3399 {
3400 PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
3402 TupleConversionMap *tupmap;
3403
3404 /* If rec is null, try to convert it to a row of nulls */
3405 if (rec->erh == NULL)
3407 if (ExpandedRecordIsEmpty(rec->erh))
3409
3410 /* Use eval_mcontext for tuple conversion work */
3411 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3414 tupdesc,
3415 gettext_noop("wrong record type supplied in RETURN NEXT"));
3416 tuple = expanded_record_get_tuple(rec->erh);
3417 if (tupmap)
3418 tuple = execute_attr_map_tuple(tuple, tupmap);
3419 tuplestore_puttuple(estate->tuple_store, tuple);
3420 MemoryContextSwitchTo(oldcontext);
3421 }
3422 break;
3423
3424 case PLPGSQL_DTYPE_ROW:
3425 {
3426 PLpgSQL_row *row = (PLpgSQL_row *) retvar;
3427
3428 /* We get here if there are multiple OUT parameters */
3429
3430 /* Use eval_mcontext for tuple conversion work */
3431 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3432 tuple = make_tuple_from_row(estate, row, tupdesc);
3433 if (tuple == NULL) /* should not happen */
3434 ereport(ERROR,
3436 errmsg("wrong record type supplied in RETURN NEXT")));
3437 tuplestore_puttuple(estate->tuple_store, tuple);
3438 MemoryContextSwitchTo(oldcontext);
3439 }
3440 break;
3441
3442 default:
3443 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
3444 break;
3445 }
3446 }
3447 else if (stmt->expr)
3448 {
3449 Datum retval;
3450 bool isNull;
3451 Oid rettype;
3453
3454 retval = exec_eval_expr(estate,
3455 stmt->expr,
3456 &isNull,
3457 &rettype,
3458 &rettypmod);
3459
3460 if (estate->retistuple)
3461 {
3462 /* Expression should be of RECORD or composite type */
3463 if (!isNull)
3464 {
3467 TupleConversionMap *tupmap;
3468
3469 if (!type_is_rowtype(rettype))
3470 ereport(ERROR,
3472 errmsg("cannot return non-composite value from function returning composite type")));
3473
3474 /* Use eval_mcontext for tuple conversion work */
3475 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3477 tuple = &tmptup;
3478 tupmap = convert_tuples_by_position(retvaldesc, tupdesc,
3479 gettext_noop("returned record type does not match expected record type"));
3480 if (tupmap)
3481 tuple = execute_attr_map_tuple(tuple, tupmap);
3482 tuplestore_puttuple(estate->tuple_store, tuple);
3484 MemoryContextSwitchTo(oldcontext);
3485 }
3486 else
3487 {
3488 /* Composite NULL --- store a row of nulls */
3490 bool *nullflags;
3491
3492 nulldatums = (Datum *)
3493 eval_mcontext_alloc0(estate, natts * sizeof(Datum));
3494 nullflags = (bool *)
3495 eval_mcontext_alloc(estate, natts * sizeof(bool));
3496 memset(nullflags, true, natts * sizeof(bool));
3497 tuplestore_putvalues(estate->tuple_store, tupdesc,
3499 }
3500 }
3501 else
3502 {
3503 Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
3504
3505 /* Simple scalar result */
3506 if (natts != 1)
3507 ereport(ERROR,
3509 errmsg("wrong result type supplied in RETURN NEXT")));
3510
3511 /* coerce type if needed */
3512 retval = exec_cast_value(estate,
3513 retval,
3514 &isNull,
3515 rettype,
3516 rettypmod,
3517 attr->atttypid,
3518 attr->atttypmod);
3519
3520 tuplestore_putvalues(estate->tuple_store, tupdesc,
3521 &retval, &isNull);
3522 }
3523 }
3524 else
3525 {
3526 ereport(ERROR,
3528 errmsg("RETURN NEXT must have a parameter")));
3529 }
3530
3531 exec_eval_cleanup(estate);
3532
3533 return PLPGSQL_RC_OK;
3534}

References PLpgSQL_type::atttypmod, convert_tuples_by_position(), PLpgSQL_var::datatype, PLpgSQL_execstate::datums, deconstruct_composite_datum(), deconstruct_expanded_record(), elog, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, eval_mcontext_alloc, eval_mcontext_alloc0, exec_cast_value(), exec_eval_cleanup(), exec_eval_expr(), exec_init_tuple_store(), execute_attr_map_tuple(), expanded_record_get_tupdesc(), expanded_record_get_tuple(), ExpandedRecordIsEmpty, fb(), get_eval_mcontext, gettext_noop, instantiate_empty_record_variable(), PLpgSQL_var::isnull, make_tuple_from_row(), MakeExpandedObjectReadOnly, MemoryContextSwitchTo(), TupleDescData::natts, pg_fallthrough, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, plpgsql_fulfill_promise(), PLPGSQL_RC_OK, ReleaseTupleDesc, PLpgSQL_execstate::retisset, PLpgSQL_execstate::retistuple, stmt, PLpgSQL_execstate::tuple_store, PLpgSQL_execstate::tuple_store_desc, TupleDescAttr(), tuplestore_puttuple(), tuplestore_putvalues(), type_is_rowtype(), PLpgSQL_type::typlen, PLpgSQL_type::typoid, and PLpgSQL_var::value.

Referenced by exec_stmts().

◆ exec_stmt_return_query()

static int exec_stmt_return_query ( PLpgSQL_execstate estate,
PLpgSQL_stmt_return_query stmt 
)
static

Definition at line 3543 of file pl_exec.c.

3545{
3546 int64 tcount;
3548 int rc;
3549 uint64 processed;
3550 MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
3551 MemoryContext oldcontext;
3552
3553 if (!estate->retisset)
3554 ereport(ERROR,
3556 errmsg("cannot use RETURN QUERY in a non-SETOF function")));
3557
3558 if (estate->tuple_store == NULL)
3559 exec_init_tuple_store(estate);
3560 /* There might be some tuples in the tuplestore already */
3561 tcount = tuplestore_tuple_count(estate->tuple_store);
3562
3563 /*
3564 * Set up DestReceiver to transfer results directly to tuplestore,
3565 * converting rowtype if necessary. DestReceiver lives in mcontext.
3566 */
3567 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3570 estate->tuple_store,
3571 estate->tuple_store_cxt,
3572 false,
3573 estate->tuple_store_desc,
3574 gettext_noop("structure of query does not match function result type"));
3575 MemoryContextSwitchTo(oldcontext);
3576
3577 if (stmt->query != NULL)
3578 {
3579 /* static query */
3580 PLpgSQL_expr *expr = stmt->query;
3581 ParamListInfo paramLI;
3583
3584 /*
3585 * On the first call for this expression generate the plan.
3586 */
3587 if (expr->plan == NULL)
3589
3590 /*
3591 * Set up ParamListInfo to pass to executor
3592 */
3593 paramLI = setup_param_list(estate, expr);
3594
3595 /*
3596 * Execute the query
3597 */
3598 memset(&options, 0, sizeof(options));
3599 options.params = paramLI;
3600 options.read_only = estate->readonly_func;
3601 options.must_return_tuples = true;
3602 options.dest = treceiver;
3603
3605 if (rc < 0)
3606 elog(ERROR, "SPI_execute_plan_extended failed executing query \"%s\": %s",
3607 expr->query, SPI_result_code_string(rc));
3608 }
3609 else
3610 {
3611 /* RETURN QUERY EXECUTE */
3612 Datum query;
3613 bool isnull;
3614 Oid restype;
3616 char *querystr;
3618
3619 /*
3620 * Evaluate the string expression after the EXECUTE keyword. Its
3621 * result is the querystring we have to execute.
3622 */
3623 Assert(stmt->dynquery != NULL);
3624 query = exec_eval_expr(estate, stmt->dynquery,
3625 &isnull, &restype, &restypmod);
3626 if (isnull)
3627 ereport(ERROR,
3629 errmsg("query string argument of EXECUTE is null")));
3630
3631 /* Get the C-String representation */
3632 querystr = convert_value_to_string(estate, query, restype);
3633
3634 /* copy it into the stmt_mcontext before we clean up */
3635 querystr = MemoryContextStrdup(stmt_mcontext, querystr);
3636
3637 exec_eval_cleanup(estate);
3638
3639 /* Execute query, passing params if necessary */
3640 memset(&options, 0, sizeof(options));
3641 options.params = exec_eval_using_params(estate,
3642 stmt->params);
3643 options.read_only = estate->readonly_func;
3644 options.must_return_tuples = true;
3645 options.dest = treceiver;
3646
3648 if (rc < 0)
3649 elog(ERROR, "SPI_execute_extended failed executing query \"%s\": %s",
3651 }
3652
3653 /* Clean up */
3654 treceiver->rDestroy(treceiver);
3655 exec_eval_cleanup(estate);
3656 MemoryContextReset(stmt_mcontext);
3657
3658 /* Count how many tuples we got */
3659 processed = tuplestore_tuple_count(estate->tuple_store) - tcount;
3660
3661 estate->eval_processed = processed;
3662 exec_set_found(estate, processed != 0);
3663
3664 return PLPGSQL_RC_OK;
3665}

References Assert, convert_value_to_string(), CreateDestReceiver(), CURSOR_OPT_PARALLEL_OK, DestTuplestore, elog, ereport, errcode(), errmsg(), ERROR, PLpgSQL_execstate::eval_processed, exec_eval_cleanup(), exec_eval_expr(), exec_eval_using_params(), exec_init_tuple_store(), exec_prepare_plan(), exec_set_found(), fb(), get_stmt_mcontext(), gettext_noop, MemoryContextReset(), MemoryContextStrdup(), MemoryContextSwitchTo(), PLpgSQL_expr::plan, PLPGSQL_RC_OK, PLpgSQL_expr::query, PLpgSQL_execstate::readonly_func, PLpgSQL_execstate::retisset, SetTuplestoreDestReceiverParams(), setup_param_list(), SPI_execute_extended(), SPI_execute_plan_extended(), SPI_result_code_string(), stmt, PLpgSQL_execstate::tuple_store, PLpgSQL_execstate::tuple_store_cxt, PLpgSQL_execstate::tuple_store_desc, and tuplestore_tuple_count().

Referenced by exec_stmts().

◆ exec_stmt_rollback()

static int exec_stmt_rollback ( PLpgSQL_execstate estate,
PLpgSQL_stmt_rollback stmt 
)
static

Definition at line 4979 of file pl_exec.c.

4980{
4981 if (stmt->chain)
4983 else
4984 SPI_rollback();
4985
4986 /*
4987 * We need to build new simple-expression infrastructure, since the old
4988 * data structures are gone.
4989 */
4990 estate->simple_eval_estate = NULL;
4991 estate->simple_eval_resowner = NULL;
4993
4994 return PLPGSQL_RC_OK;
4995}

References fb(), plpgsql_create_econtext(), PLPGSQL_RC_OK, PLpgSQL_execstate::simple_eval_estate, PLpgSQL_execstate::simple_eval_resowner, SPI_rollback(), SPI_rollback_and_chain(), and stmt.

Referenced by exec_stmts().

◆ exec_stmt_while()

static int exec_stmt_while ( PLpgSQL_execstate estate,
PLpgSQL_stmt_while stmt 
)
static

Definition at line 2664 of file pl_exec.c.

2665{
2666 int rc = PLPGSQL_RC_OK;
2667
2668 for (;;)
2669 {
2670 bool value;
2671 bool isnull;
2672
2673 value = exec_eval_boolean(estate, stmt->cond, &isnull);
2674 exec_eval_cleanup(estate);
2675
2676 if (isnull || !value)
2677 break;
2678
2679 rc = exec_stmts(estate, stmt->body);
2680
2681 LOOP_RC_PROCESSING(stmt->label, break);
2682 }
2683
2684 return rc;
2685}

References exec_eval_boolean(), exec_eval_cleanup(), exec_stmts(), LOOP_RC_PROCESSING, PLPGSQL_RC_OK, stmt, and value.

Referenced by exec_stmts().

◆ exec_stmts()

static int exec_stmts ( PLpgSQL_execstate estate,
List stmts 
)
static

Definition at line 1995 of file pl_exec.c.

1996{
1997 PLpgSQL_stmt *save_estmt = estate->err_stmt;
1998 ListCell *s;
1999
2000 if (stmts == NIL)
2001 {
2002 /*
2003 * Ensure we do a CHECK_FOR_INTERRUPTS() even though there is no
2004 * statement. This prevents hangup in a tight loop if, for instance,
2005 * there is a LOOP construct with an empty body.
2006 */
2008 return PLPGSQL_RC_OK;
2009 }
2010
2011 foreach(s, stmts)
2012 {
2014 int rc;
2015
2016 estate->err_stmt = stmt;
2017
2018 /* Let the plugin know that we are about to execute this statement */
2019 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
2020 ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
2021
2023
2024 switch (stmt->cmd_type)
2025 {
2026 case PLPGSQL_STMT_BLOCK:
2027 rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
2028 break;
2029
2031 rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
2032 break;
2033
2036 break;
2037
2038 case PLPGSQL_STMT_CALL:
2039 rc = exec_stmt_call(estate, (PLpgSQL_stmt_call *) stmt);
2040 break;
2041
2044 break;
2045
2046 case PLPGSQL_STMT_IF:
2047 rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
2048 break;
2049
2050 case PLPGSQL_STMT_CASE:
2051 rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
2052 break;
2053
2054 case PLPGSQL_STMT_LOOP:
2055 rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
2056 break;
2057
2058 case PLPGSQL_STMT_WHILE:
2059 rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
2060 break;
2061
2062 case PLPGSQL_STMT_FORI:
2063 rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
2064 break;
2065
2066 case PLPGSQL_STMT_FORS:
2067 rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
2068 break;
2069
2070 case PLPGSQL_STMT_FORC:
2071 rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
2072 break;
2073
2076 break;
2077
2078 case PLPGSQL_STMT_EXIT:
2079 rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
2080 break;
2081
2083 rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
2084 break;
2085
2088 break;
2089
2092 break;
2093
2094 case PLPGSQL_STMT_RAISE:
2095 rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
2096 break;
2097
2099 rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
2100 break;
2101
2104 break;
2105
2108 break;
2109
2112 break;
2113
2114 case PLPGSQL_STMT_OPEN:
2115 rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
2116 break;
2117
2118 case PLPGSQL_STMT_FETCH:
2119 rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
2120 break;
2121
2122 case PLPGSQL_STMT_CLOSE:
2123 rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
2124 break;
2125
2127 rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit *) stmt);
2128 break;
2129
2132 break;
2133
2134 default:
2135 /* point err_stmt to parent, since this one seems corrupt */
2136 estate->err_stmt = save_estmt;
2137 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
2138 rc = -1; /* keep compiler quiet */
2139 }
2140
2141 /* Let the plugin know that we have finished executing this statement */
2142 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
2143 ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
2144
2145 if (rc != PLPGSQL_RC_OK)
2146 {
2147 estate->err_stmt = save_estmt;
2148 return rc;
2149 }
2150 } /* end of loop over statements */
2151
2152 estate->err_stmt = save_estmt;
2153 return PLPGSQL_RC_OK;
2154}

References CHECK_FOR_INTERRUPTS, elog, PLpgSQL_execstate::err_stmt, ERROR, exec_stmt_assert(), exec_stmt_assign(), exec_stmt_block(), exec_stmt_call(), exec_stmt_case(), exec_stmt_close(), exec_stmt_commit(), exec_stmt_dynexecute(), exec_stmt_dynfors(), exec_stmt_execsql(), exec_stmt_exit(), exec_stmt_fetch(), exec_stmt_forc(), exec_stmt_foreach_a(), exec_stmt_fori(), exec_stmt_fors(), exec_stmt_getdiag(), exec_stmt_if(), exec_stmt_loop(), exec_stmt_open(), exec_stmt_perform(), exec_stmt_raise(), exec_stmt_return(), exec_stmt_return_next(), exec_stmt_return_query(), exec_stmt_rollback(), exec_stmt_while(), fb(), lfirst, NIL, plpgsql_plugin_ptr, PLPGSQL_RC_OK, PLPGSQL_STMT_ASSERT, PLPGSQL_STMT_ASSIGN, PLPGSQL_STMT_BLOCK, PLPGSQL_STMT_CALL, PLPGSQL_STMT_CASE, PLPGSQL_STMT_CLOSE, PLPGSQL_STMT_COMMIT, PLPGSQL_STMT_DYNEXECUTE, PLPGSQL_STMT_DYNFORS, PLPGSQL_STMT_EXECSQL, PLPGSQL_STMT_EXIT, PLPGSQL_STMT_FETCH, PLPGSQL_STMT_FORC, PLPGSQL_STMT_FOREACH_A, PLPGSQL_STMT_FORI, PLPGSQL_STMT_FORS, PLPGSQL_STMT_GETDIAG, PLPGSQL_STMT_IF, PLPGSQL_STMT_LOOP, PLPGSQL_STMT_OPEN, PLPGSQL_STMT_PERFORM, PLPGSQL_STMT_RAISE, PLPGSQL_STMT_RETURN, PLPGSQL_STMT_RETURN_NEXT, PLPGSQL_STMT_RETURN_QUERY, PLPGSQL_STMT_ROLLBACK, PLPGSQL_STMT_WHILE, stmt, PLpgSQL_plugin::stmt_beg, and PLpgSQL_plugin::stmt_end.

Referenced by exec_for_query(), exec_stmt_block(), exec_stmt_case(), exec_stmt_foreach_a(), exec_stmt_fori(), exec_stmt_if(), exec_stmt_loop(), and exec_stmt_while().

◆ exec_toplevel_block()

static int exec_toplevel_block ( PLpgSQL_execstate estate,
PLpgSQL_stmt_block block 
)
static

Definition at line 1633 of file pl_exec.c.

1634{
1635 int rc;
1636
1637 estate->err_stmt = (PLpgSQL_stmt *) block;
1638
1639 /* Let the plugin know that we are about to execute this statement */
1640 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
1641 ((*plpgsql_plugin_ptr)->stmt_beg) (estate, (PLpgSQL_stmt *) block);
1642
1644
1645 rc = exec_stmt_block(estate, block);
1646
1647 /* Let the plugin know that we have finished executing this statement */
1648 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
1649 ((*plpgsql_plugin_ptr)->stmt_end) (estate, (PLpgSQL_stmt *) block);
1650
1651 estate->err_stmt = NULL;
1652
1653 return rc;
1654}

References CHECK_FOR_INTERRUPTS, PLpgSQL_execstate::err_stmt, exec_stmt_block(), fb(), plpgsql_plugin_ptr, PLpgSQL_plugin::stmt_beg, and PLpgSQL_plugin::stmt_end.

Referenced by plpgsql_exec_event_trigger(), plpgsql_exec_function(), and plpgsql_exec_trigger().

◆ format_expr_params()

static char * format_expr_params ( PLpgSQL_execstate estate,
const PLpgSQL_expr expr 
)
static

Definition at line 9020 of file pl_exec.c.

9022{
9023 int paramno;
9024 int dno;
9026 MemoryContext oldcontext;
9027
9028 if (!expr->paramnos)
9029 return NULL;
9030
9031 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
9032
9034 paramno = 0;
9035 dno = -1;
9036 while ((dno = bms_next_member(expr->paramnos, dno)) >= 0)
9037 {
9040 bool paramisnull;
9041 int32 paramtypmod;
9042 PLpgSQL_var *curvar;
9043
9044 curvar = (PLpgSQL_var *) estate->datums[dno];
9045
9046 exec_eval_datum(estate, (PLpgSQL_datum *) curvar,
9047 &paramtypeid, &paramtypmod,
9049
9050 appendStringInfo(&paramstr, "%s%s = ",
9051 paramno > 0 ? ", " : "",
9052 curvar->refname);
9053
9054 if (paramisnull)
9056 else
9059 paramdatum,
9060 paramtypeid),
9061 -1);
9062
9063 paramno++;
9064 }
9065
9066 MemoryContextSwitchTo(oldcontext);
9067
9068 return paramstr.data;
9069}

References appendStringInfo(), appendStringInfoString(), appendStringInfoStringQuoted(), bms_next_member(), convert_value_to_string(), PLpgSQL_execstate::datums, exec_eval_datum(), fb(), get_eval_mcontext, initStringInfo(), MemoryContextSwitchTo(), PLpgSQL_expr::paramnos, and PLpgSQL_var::refname.

Referenced by exec_stmt_execsql().

◆ format_preparedparamsdata()

static char * format_preparedparamsdata ( PLpgSQL_execstate estate,
ParamListInfo  paramLI 
)
static

Definition at line 9077 of file pl_exec.c.

9079{
9080 int paramno;
9082 MemoryContext oldcontext;
9083
9084 if (!paramLI)
9085 return NULL;
9086
9087 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
9088
9090 for (paramno = 0; paramno < paramLI->numParams; paramno++)
9091 {
9092 ParamExternData *prm = &paramLI->params[paramno];
9093
9094 /*
9095 * Note: for now, this is only used on ParamListInfos produced by
9096 * exec_eval_using_params(), so we don't worry about invoking the
9097 * paramFetch hook or skipping unused parameters.
9098 */
9099 appendStringInfo(&paramstr, "%s$%d = ",
9100 paramno > 0 ? ", " : "",
9101 paramno + 1);
9102
9103 if (prm->isnull)
9105 else
9108 prm->value,
9109 prm->ptype),
9110 -1);
9111 }
9112
9113 MemoryContextSwitchTo(oldcontext);
9114
9115 return paramstr.data;
9116}

References appendStringInfo(), appendStringInfoString(), appendStringInfoStringQuoted(), convert_value_to_string(), fb(), get_eval_mcontext, initStringInfo(), MemoryContextSwitchTo(), ParamListInfoData::numParams, and ParamListInfoData::params.

Referenced by exec_stmt_dynexecute().

◆ get_cast_hashentry()

static plpgsql_CastHashEntry * get_cast_hashentry ( PLpgSQL_execstate estate,
Oid  srctype,
int32  srctypmod,
Oid  dsttype,
int32  dsttypmod 
)
static

Definition at line 7941 of file pl_exec.c.

7944{
7948 bool found;
7950 MemoryContext oldcontext;
7951
7952 /* Look for existing entry */
7953 cast_key.srctype = srctype;
7954 cast_key.dsttype = dsttype;
7955 cast_key.srctypmod = srctypmod;
7956 cast_key.dsttypmod = dsttypmod;
7958 &cast_key,
7959 HASH_ENTER, &found);
7960 if (!found) /* initialize if new entry */
7961 {
7962 /* We need a second lookup to see if a cast_expr_hash entry exists */
7964 &cast_key,
7965 HASH_ENTER,
7966 &found);
7967 if (!found) /* initialize if new expr entry */
7968 expr_entry->cast_cexpr = NULL;
7969
7970 cast_entry->cast_centry = expr_entry;
7971 cast_entry->cast_exprstate = NULL;
7972 cast_entry->cast_in_use = false;
7974 }
7975 else
7976 {
7977 /* Use always-valid link to avoid a second hash lookup */
7978 expr_entry = cast_entry->cast_centry;
7979 }
7980
7981 if (expr_entry->cast_cexpr == NULL ||
7982 !expr_entry->cast_cexpr->is_valid)
7983 {
7984 /*
7985 * We've not looked up this coercion before, or we have but the cached
7986 * expression has been invalidated.
7987 */
7988 Node *cast_expr;
7989 CachedExpression *cast_cexpr;
7991
7992 /*
7993 * Drop old cached expression if there is one.
7994 */
7995 if (expr_entry->cast_cexpr)
7996 {
7997 FreeCachedExpression(expr_entry->cast_cexpr);
7998 expr_entry->cast_cexpr = NULL;
7999 }
8000
8001 /*
8002 * Since we could easily fail (no such coercion), construct a
8003 * temporary coercion expression tree in the short-lived
8004 * eval_mcontext, then if successful save it as a CachedExpression.
8005 */
8006 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8007
8008 /*
8009 * We use a CaseTestExpr as the base of the coercion tree, since it's
8010 * very cheap to insert the source value for that.
8011 */
8013 placeholder->typeId = srctype;
8014 placeholder->typeMod = srctypmod;
8015 placeholder->collation = get_typcollation(srctype);
8016
8017 /*
8018 * Apply coercion. We use the special coercion context
8019 * COERCION_PLPGSQL to match plpgsql's historical behavior, namely
8020 * that any cast not available at ASSIGNMENT level will be implemented
8021 * as an I/O coercion. (It's somewhat dubious that we prefer I/O
8022 * coercion over cast pathways that exist at EXPLICIT level. Changing
8023 * that would cause assorted minor behavioral differences though, and
8024 * a user who wants the explicit-cast behavior can always write an
8025 * explicit cast.)
8026 *
8027 * If source type is UNKNOWN, coerce_to_target_type will fail (it only
8028 * expects to see that for Const input nodes), so don't call it; we'll
8029 * apply CoerceViaIO instead. Likewise, it doesn't currently work for
8030 * coercing RECORD to some other type, so skip for that too.
8031 */
8032 if (srctype == UNKNOWNOID || srctype == RECORDOID)
8033 cast_expr = NULL;
8034 else
8035 cast_expr = coerce_to_target_type(NULL,
8036 (Node *) placeholder, srctype,
8037 dsttype, dsttypmod,
8040 -1);
8041
8042 /*
8043 * If there's no cast path according to the parser, fall back to using
8044 * an I/O coercion; this is semantically dubious but matches plpgsql's
8045 * historical behavior. We would need something of the sort for
8046 * UNKNOWN literals in any case. (This is probably now only reachable
8047 * in the case where srctype is UNKNOWN/RECORD.)
8048 */
8049 if (cast_expr == NULL)
8050 {
8051 CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
8052
8053 iocoerce->arg = (Expr *) placeholder;
8054 iocoerce->resulttype = dsttype;
8055 iocoerce->resultcollid = InvalidOid;
8056 iocoerce->coerceformat = COERCE_IMPLICIT_CAST;
8057 iocoerce->location = -1;
8058 cast_expr = (Node *) iocoerce;
8059 if (dsttypmod != -1)
8060 cast_expr = coerce_to_target_type(NULL,
8061 cast_expr, dsttype,
8062 dsttype, dsttypmod,
8065 -1);
8066 }
8067
8068 /* Note: we don't bother labeling the expression tree with collation */
8069
8070 /* Plan the expression and build a CachedExpression */
8071 cast_cexpr = GetCachedExpression(cast_expr);
8072 cast_expr = cast_cexpr->expr;
8073
8074 /* Detect whether we have a no-op (RelabelType) coercion */
8075 if (IsA(cast_expr, RelabelType) &&
8076 ((RelabelType *) cast_expr)->arg == (Expr *) placeholder)
8077 cast_expr = NULL;
8078
8079 /* Now we can fill in the expression hashtable entry. */
8080 expr_entry->cast_cexpr = cast_cexpr;
8081 expr_entry->cast_expr = (Expr *) cast_expr;
8082
8083 /* Be sure to reset the exprstate hashtable entry, too. */
8084 cast_entry->cast_exprstate = NULL;
8085 cast_entry->cast_in_use = false;
8087
8088 MemoryContextSwitchTo(oldcontext);
8089 }
8090
8091 /* Done if we have determined that this is a no-op cast. */
8092 if (expr_entry->cast_expr == NULL)
8093 return NULL;
8094
8095 /*
8096 * Prepare the expression for execution, if it's not been done already in
8097 * the current transaction; also, if it's marked busy in the current
8098 * transaction, abandon that expression tree and build a new one, so as to
8099 * avoid potential problems with recursive cast expressions and failed
8100 * executions. (We will leak some memory intra-transaction if that
8101 * happens a lot, but we don't expect it to.) It's okay to update the
8102 * hash table with the new tree because all plpgsql functions within a
8103 * given transaction share the same simple_eval_estate. (Well, regular
8104 * functions do; DO blocks have private simple_eval_estates, and private
8105 * cast hash tables to go with them.)
8106 */
8108 if (cast_entry->cast_lxid != curlxid || cast_entry->cast_in_use)
8109 {
8111 cast_entry->cast_exprstate = ExecInitExpr(expr_entry->cast_expr, NULL);
8112 cast_entry->cast_in_use = false;
8113 cast_entry->cast_lxid = curlxid;
8114 MemoryContextSwitchTo(oldcontext);
8115 }
8116
8117 return cast_entry;
8118}

References arg, CoerceViaIO::arg, cast_expr_hash, PLpgSQL_execstate::cast_hash, COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, COERCION_PLPGSQL, EState::es_query_cxt, ExecInitExpr(), CachedExpression::expr, fb(), FreeCachedExpression(), get_eval_mcontext, get_typcollation(), GetCachedExpression(), HASH_ENTER, hash_search(), InvalidLocalTransactionId, InvalidOid, IsA, CoerceViaIO::location, PGPROC::lxid, makeNode, MemoryContextSwitchTo(), MyProc, CoerceViaIO::resulttype, PLpgSQL_execstate::simple_eval_estate, and PGPROC::vxid.

Referenced by do_cast_value().

◆ get_stmt_mcontext()

◆ instantiate_empty_record_variable()

static void instantiate_empty_record_variable ( PLpgSQL_execstate estate,
PLpgSQL_rec rec 
)
static

Definition at line 7809 of file pl_exec.c.

7810{
7811 Assert(rec->erh == NULL); /* else caller error */
7812
7813 /* If declared type is RECORD, we can't instantiate */
7814 if (rec->rectypeid == RECORDOID)
7815 ereport(ERROR,
7817 errmsg("record \"%s\" is not assigned yet", rec->refname),
7818 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
7819
7820 /* Make sure rec->rectypeid is up-to-date before using it */
7822
7823 /* OK, do it */
7825 estate->datum_context);
7826}

References Assert, PLpgSQL_execstate::datum_context, ereport, PLpgSQL_rec::erh, errcode(), errdetail(), errmsg(), ERROR, fb(), make_expanded_record_from_typeid(), PLpgSQL_rec::rectypeid, PLpgSQL_rec::refname, and revalidate_rectypeid().

Referenced by exec_assign_value(), exec_eval_datum(), exec_stmt_return_next(), plpgsql_exec_get_datum_type(), plpgsql_exec_get_datum_type_info(), and plpgsql_param_eval_recfield().

◆ make_callstmt_target()

static PLpgSQL_variable * make_callstmt_target ( PLpgSQL_execstate estate,
PLpgSQL_expr expr 
)
static

Definition at line 2288 of file pl_exec.c.

2289{
2290 CachedPlan *cplan;
2291 PlannedStmt *pstmt;
2292 CallStmt *stmt;
2293 FuncExpr *funcexpr;
2295 Oid *argtypes;
2296 char **argnames;
2297 char *argmodes;
2298 int numargs;
2299 MemoryContext oldcontext;
2300 PLpgSQL_row *row;
2301 int nfields;
2302 int i;
2303
2304 /* Use eval_mcontext for any cruft accumulated here */
2305 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2306
2307 /*
2308 * Get the parsed CallStmt, and look up the called procedure. We use
2309 * SPI_plan_get_cached_plan to cover the edge case where expr->plan is
2310 * already stale and needs to be updated.
2311 */
2312 cplan = SPI_plan_get_cached_plan(expr->plan);
2313 if (cplan == NULL || list_length(cplan->stmt_list) != 1)
2314 elog(ERROR, "query for CALL statement is not a CallStmt");
2315 pstmt = linitial_node(PlannedStmt, cplan->stmt_list);
2316 stmt = (CallStmt *) pstmt->utilityStmt;
2317 if (stmt == NULL || !IsA(stmt, CallStmt))
2318 elog(ERROR, "query for CALL statement is not a CallStmt");
2319
2320 funcexpr = stmt->funcexpr;
2321
2323 ObjectIdGetDatum(funcexpr->funcid));
2325 elog(ERROR, "cache lookup failed for function %u",
2326 funcexpr->funcid);
2327
2328 /*
2329 * Get the argument names and modes, so that we can deliver on-point error
2330 * messages when something is wrong.
2331 */
2332 numargs = get_func_arg_info(func_tuple, &argtypes, &argnames, &argmodes);
2333
2335
2336 /*
2337 * Begin constructing row Datum; keep it in fn_cxt so it's adequately
2338 * long-lived.
2339 */
2341
2343 row->dtype = PLPGSQL_DTYPE_ROW;
2344 row->refname = "(unnamed row)";
2345 row->lineno = -1;
2346 row->varnos = palloc_array(int, numargs);
2347
2349
2350 /*
2351 * Examine procedure's argument list. Each output arg position should be
2352 * an unadorned plpgsql variable (Datum), which we can insert into the row
2353 * Datum.
2354 */
2355 nfields = 0;
2356 for (i = 0; i < numargs; i++)
2357 {
2358 if (argmodes &&
2361 {
2362 Node *n = list_nth(stmt->outargs, nfields);
2363
2364 if (IsA(n, Param))
2365 {
2366 Param *param = (Param *) n;
2367 int dno;
2368
2369 /* paramid is offset by 1 (see make_datum_param()) */
2370 dno = param->paramid - 1;
2371 /* must check assignability now, because grammar can't */
2372 exec_check_assignable(estate, dno);
2373 row->varnos[nfields++] = dno;
2374 }
2375 else
2376 {
2377 /* report error using parameter name, if available */
2378 if (argnames && argnames[i] && argnames[i][0])
2379 ereport(ERROR,
2381 errmsg("procedure parameter \"%s\" is an output parameter but corresponding argument is not writable",
2382 argnames[i])));
2383 else
2384 ereport(ERROR,
2386 errmsg("procedure parameter %d is an output parameter but corresponding argument is not writable",
2387 i + 1)));
2388 }
2389 }
2390 }
2391
2392 Assert(nfields == list_length(stmt->outargs));
2393
2394 row->nfields = nfields;
2395
2397
2398 MemoryContextSwitchTo(oldcontext);
2399
2400 return (PLpgSQL_variable *) row;
2401}

References Assert, CurrentResourceOwner, PLpgSQL_row::dtype, elog, ereport, errcode(), errmsg(), ERROR, exec_check_assignable(), fb(), PLpgSQL_function::fn_cxt, PLpgSQL_execstate::func, FuncExpr::funcid, get_eval_mcontext, get_func_arg_info(), HeapTupleIsValid, i, IsA, PLpgSQL_row::lineno, linitial_node, list_length(), list_nth(), MemoryContextSwitchTo(), PLpgSQL_row::nfields, ObjectIdGetDatum(), palloc0_object, palloc_array, Param::paramid, PLpgSQL_expr::plan, PLPGSQL_DTYPE_ROW, PLpgSQL_row::refname, ReleaseCachedPlan(), ReleaseSysCache(), SearchSysCache1(), SPI_plan_get_cached_plan(), stmt, CachedPlan::stmt_list, PlannedStmt::utilityStmt, and PLpgSQL_row::varnos.

Referenced by exec_stmt_call().

◆ make_expanded_record_for_rec()

static ExpandedRecordHeader * make_expanded_record_for_rec ( PLpgSQL_execstate estate,
PLpgSQL_rec rec,
TupleDesc  srctupdesc,
ExpandedRecordHeader srcerh 
)
static

Definition at line 7117 of file pl_exec.c.

7121{
7123 MemoryContext mcontext = get_eval_mcontext(estate);
7124
7125 if (rec->rectypeid != RECORDOID)
7126 {
7127 /*
7128 * Make sure rec->rectypeid is up-to-date before using it.
7129 */
7131
7132 /*
7133 * New record must be of desired type, but maybe srcerh has already
7134 * done all the same lookups.
7135 */
7136 if (srcerh && rec->rectypeid == srcerh->er_decltypeid)
7138 mcontext);
7139 else
7141 mcontext);
7142 }
7143 else
7144 {
7145 /*
7146 * We'll adopt the input tupdesc. We can still use
7147 * make_expanded_record_from_exprecord, if srcerh isn't a composite
7148 * domain. (If it is, we effectively adopt its base type.)
7149 */
7152 mcontext);
7153 else
7154 {
7155 if (!srctupdesc)
7158 mcontext);
7159 }
7160 }
7161
7162 return newerh;
7163}

References expanded_record_get_tupdesc(), ExpandedRecordIsDomain, fb(), get_eval_mcontext, make_expanded_record_from_exprecord(), make_expanded_record_from_tupdesc(), make_expanded_record_from_typeid(), PLpgSQL_rec::rectypeid, and revalidate_rectypeid().

Referenced by exec_move_row(), and exec_move_row_from_datum().

◆ make_tuple_from_row()

static HeapTuple make_tuple_from_row ( PLpgSQL_execstate estate,
PLpgSQL_row row,
TupleDesc  tupdesc 
)
static

Definition at line 7490 of file pl_exec.c.

7493{
7494 int natts = tupdesc->natts;
7495 HeapTuple tuple;
7496 Datum *dvalues;
7497 bool *nulls;
7498 int i;
7499
7500 if (natts != row->nfields)
7501 return NULL;
7502
7503 dvalues = (Datum *) eval_mcontext_alloc0(estate, natts * sizeof(Datum));
7504 nulls = (bool *) eval_mcontext_alloc(estate, natts * sizeof(bool));
7505
7506 for (i = 0; i < natts; i++)
7507 {
7510
7511 if (TupleDescAttr(tupdesc, i)->attisdropped)
7512 {
7513 nulls[i] = true; /* leave the column as null */
7514 continue;
7515 }
7516
7517 exec_eval_datum(estate, estate->datums[row->varnos[i]],
7519 &dvalues[i], &nulls[i]);
7520 if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid)
7521 return NULL;
7522 /* XXX should we insist on typmod match, too? */
7523 }
7524
7525 tuple = heap_form_tuple(tupdesc, dvalues, nulls);
7526
7527 return tuple;
7528}

References PLpgSQL_execstate::datums, eval_mcontext_alloc, eval_mcontext_alloc0, exec_eval_datum(), fb(), heap_form_tuple(), i, TupleDescData::natts, PLpgSQL_row::nfields, TupleDescAttr(), and PLpgSQL_row::varnos.

Referenced by exec_eval_datum(), and exec_stmt_return_next().

◆ plpgsql_create_econtext()

static void plpgsql_create_econtext ( PLpgSQL_execstate estate)
static

Definition at line 8618 of file pl_exec.c.

8619{
8621
8622 /*
8623 * Create an EState for evaluation of simple expressions, if there's not
8624 * one already in the current transaction. The EState is made a child of
8625 * TopTransactionContext so it will have the right lifespan.
8626 *
8627 * Note that this path is never taken when beginning a DO block; the
8628 * required EState was already made by plpgsql_inline_handler. However,
8629 * if the DO block executes COMMIT or ROLLBACK, then we'll come here and
8630 * make a shared EState to use for the rest of the DO block. That's OK;
8631 * see the comments for shared_simple_eval_estate. (Note also that a DO
8632 * block will continue to use its private cast hash table for the rest of
8633 * the block. That's okay for now, but it might cause problems someday.)
8634 */
8635 if (estate->simple_eval_estate == NULL)
8636 {
8637 MemoryContext oldcontext;
8638
8640 {
8643 MemoryContextSwitchTo(oldcontext);
8644 }
8646 }
8647
8648 /*
8649 * Likewise for the simple-expression resource owner.
8650 */
8651 if (estate->simple_eval_resowner == NULL)
8652 {
8656 "PL/pgSQL simple expressions");
8658 }
8659
8660 /*
8661 * Create a child econtext for the current function.
8662 */
8664
8665 /*
8666 * Make a stack entry so we can clean up the econtext at subxact end.
8667 * Stack entries are kept in TopTransactionContext for simplicity.
8668 */
8669 entry = (SimpleEcontextStackEntry *)
8671 sizeof(SimpleEcontextStackEntry));
8672
8673 entry->stack_econtext = estate->eval_econtext;
8675
8676 entry->next = simple_econtext_stack;
8677 simple_econtext_stack = entry;
8678}

References CreateExecutorState(), CreateExprContext(), PLpgSQL_execstate::eval_econtext, fb(), GetCurrentSubTransactionId(), MemoryContextAlloc(), MemoryContextSwitchTo(), SimpleEcontextStackEntry::next, ResourceOwnerCreate(), shared_simple_eval_estate, shared_simple_eval_resowner, simple_econtext_stack, PLpgSQL_execstate::simple_eval_estate, PLpgSQL_execstate::simple_eval_resowner, SimpleEcontextStackEntry::stack_econtext, TopTransactionContext, TopTransactionResourceOwner, and SimpleEcontextStackEntry::xact_subxid.

Referenced by exec_stmt_block(), exec_stmt_call(), exec_stmt_commit(), exec_stmt_rollback(), and plpgsql_estate_setup().

◆ plpgsql_destroy_econtext()

◆ plpgsql_estate_setup()

static void plpgsql_estate_setup ( PLpgSQL_execstate estate,
PLpgSQL_function func,
ReturnSetInfo rsi,
EState simple_eval_estate,
ResourceOwner  simple_eval_resowner 
)
static

Definition at line 3978 of file pl_exec.c.

3983{
3984 HASHCTL ctl;
3985
3986 /* this link will be restored at exit from plpgsql_call_handler */
3987 func->cur_estate = estate;
3988
3989 estate->func = func;
3990 estate->trigdata = NULL;
3991 estate->evtrigdata = NULL;
3992
3993 estate->retval = (Datum) 0;
3994 estate->retisnull = true;
3995 estate->rettype = InvalidOid;
3996
3997 estate->fn_rettype = func->fn_rettype;
3998 estate->retistuple = func->fn_retistuple;
3999 estate->retisset = func->fn_retset;
4000
4001 estate->readonly_func = func->fn_readonly;
4002 estate->atomic = true;
4003
4004 estate->exitlabel = NULL;
4005 estate->cur_error = NULL;
4006
4007 estate->tuple_store = NULL;
4008 estate->tuple_store_desc = NULL;
4009 if (rsi)
4010 {
4013 }
4014 else
4015 {
4016 estate->tuple_store_cxt = NULL;
4017 estate->tuple_store_owner = NULL;
4018 }
4019 estate->rsi = rsi;
4020
4021 estate->found_varno = func->found_varno;
4022 estate->ndatums = func->ndatums;
4023 estate->datums = NULL;
4024 /* the datums array will be filled by copy_plpgsql_datums() */
4026
4027 /* initialize our ParamListInfo with appropriate hook functions */
4028 estate->paramLI = makeParamList(0);
4030 estate->paramLI->paramFetchArg = estate;
4032 estate->paramLI->paramCompileArg = NULL; /* not needed */
4034 estate->paramLI->parserSetupArg = NULL; /* filled during use */
4035 estate->paramLI->numParams = estate->ndatums;
4036
4037 /* Create the session-wide cast-expression hash if we didn't already */
4038 if (cast_expr_hash == NULL)
4039 {
4040 ctl.keysize = sizeof(plpgsql_CastHashKey);
4041 ctl.entrysize = sizeof(plpgsql_CastExprHashEntry);
4042 cast_expr_hash = hash_create("PLpgSQL cast expressions",
4043 16, /* start small and extend */
4044 &ctl,
4046 }
4047
4048 /* set up for use of appropriate simple-expression EState and cast hash */
4049 if (simple_eval_estate)
4050 {
4051 estate->simple_eval_estate = simple_eval_estate;
4052 /* Private cast hash just lives in function's main context */
4053 ctl.keysize = sizeof(plpgsql_CastHashKey);
4054 ctl.entrysize = sizeof(plpgsql_CastHashEntry);
4056 estate->cast_hash = hash_create("PLpgSQL private cast cache",
4057 16, /* start small and extend */
4058 &ctl,
4060 }
4061 else
4062 {
4064 /* Create the session-wide cast-info hash table if we didn't already */
4065 if (shared_cast_hash == NULL)
4066 {
4067 ctl.keysize = sizeof(plpgsql_CastHashKey);
4068 ctl.entrysize = sizeof(plpgsql_CastHashEntry);
4069 shared_cast_hash = hash_create("PLpgSQL cast cache",
4070 16, /* start small and extend */
4071 &ctl,
4073 }
4074 estate->cast_hash = shared_cast_hash;
4075 }
4076 /* likewise for the simple-expression resource owner */
4077 if (simple_eval_resowner)
4078 estate->simple_eval_resowner = simple_eval_resowner;
4079 else
4081
4082 /* if there's a procedure resowner, it'll be filled in later */
4083 estate->procedure_resowner = NULL;
4084
4085 /*
4086 * We start with no stmt_mcontext; one will be created only if needed.
4087 * That context will be a direct child of the function's main execution
4088 * context. Additional stmt_mcontexts might be created as children of it.
4089 */
4090 estate->stmt_mcontext = NULL;
4092
4093 estate->eval_tuptable = NULL;
4094 estate->eval_processed = 0;
4095 estate->eval_econtext = NULL;
4096
4097 estate->err_stmt = NULL;
4098 estate->err_var = NULL;
4099 estate->err_text = NULL;
4100
4101 estate->plugin_info = NULL;
4102
4103 /*
4104 * Create an EState and ExprContext for evaluation of simple expressions.
4105 */
4107
4108 /*
4109 * Let the plugin, if any, see this function before we initialize local
4110 * PL/pgSQL variables. Note that we also give the plugin a few function
4111 * pointers, so it can call back into PL/pgSQL for doing things like
4112 * variable assignments and stack traces.
4113 */
4114 if (*plpgsql_plugin_ptr)
4115 {
4116 (*plpgsql_plugin_ptr)->error_callback = plpgsql_exec_error_callback;
4117 (*plpgsql_plugin_ptr)->assign_expr = exec_assign_expr;
4118 (*plpgsql_plugin_ptr)->assign_value = exec_assign_value;
4119 (*plpgsql_plugin_ptr)->eval_datum = exec_eval_datum;
4120 (*plpgsql_plugin_ptr)->cast_value = exec_cast_value;
4121
4122 if ((*plpgsql_plugin_ptr)->func_setup)
4123 ((*plpgsql_plugin_ptr)->func_setup) (estate, func);
4124 }
4125}

References PLpgSQL_execstate::atomic, cast_expr_hash, PLpgSQL_execstate::cast_hash, ctl, PLpgSQL_execstate::cur_error, PLpgSQL_function::cur_estate, CurrentMemoryContext, CurrentResourceOwner, PLpgSQL_execstate::datum_context, PLpgSQL_execstate::datums, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, PLpgSQL_execstate::err_stmt, PLpgSQL_execstate::err_text, PLpgSQL_execstate::err_var, PLpgSQL_execstate::eval_econtext, PLpgSQL_execstate::eval_processed, PLpgSQL_execstate::eval_tuptable, PLpgSQL_execstate::evtrigdata, exec_assign_expr(), exec_assign_value(), exec_cast_value(), exec_eval_datum(), PLpgSQL_execstate::exitlabel, fb(), PLpgSQL_function::fn_readonly, PLpgSQL_function::fn_retistuple, PLpgSQL_function::fn_retset, PLpgSQL_function::fn_rettype, PLpgSQL_execstate::fn_rettype, PLpgSQL_function::found_varno, PLpgSQL_execstate::found_varno, PLpgSQL_execstate::func, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, InvalidOid, makeParamList(), PLpgSQL_function::ndatums, PLpgSQL_execstate::ndatums, ParamListInfoData::numParams, ParamListInfoData::paramCompile, ParamListInfoData::paramCompileArg, ParamListInfoData::paramFetch, ParamListInfoData::paramFetchArg, PLpgSQL_execstate::paramLI, ParamListInfoData::parserSetup, ParamListInfoData::parserSetupArg, plpgsql_create_econtext(), plpgsql_exec_error_callback(), plpgsql_param_compile(), plpgsql_param_fetch(), plpgsql_parser_setup(), plpgsql_plugin_ptr, PLpgSQL_execstate::plugin_info, PLpgSQL_execstate::procedure_resowner, PLpgSQL_execstate::readonly_func, PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::retistuple, PLpgSQL_execstate::rettype, PLpgSQL_execstate::retval, PLpgSQL_execstate::rsi, shared_cast_hash, shared_simple_eval_estate, shared_simple_eval_resowner, PLpgSQL_execstate::simple_eval_estate, PLpgSQL_execstate::simple_eval_resowner, PLpgSQL_execstate::stmt_mcontext, PLpgSQL_execstate::stmt_mcontext_parent, PLpgSQL_execstate::trigdata, PLpgSQL_execstate::tuple_store, PLpgSQL_execstate::tuple_store_cxt, PLpgSQL_execstate::tuple_store_desc, and PLpgSQL_execstate::tuple_store_owner.

Referenced by plpgsql_exec_event_trigger(), plpgsql_exec_function(), and plpgsql_exec_trigger().

◆ plpgsql_exec_error_callback()

static void plpgsql_exec_error_callback ( void arg)
static

Definition at line 1243 of file pl_exec.c.

1244{
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 if (estate->err_var != NULL)
1255 err_lineno = estate->err_var->lineno;
1256 else if (estate->err_stmt != NULL)
1257 err_lineno = estate->err_stmt->lineno;
1258 else
1259 err_lineno = 0;
1260
1261 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 if (err_lineno > 0)
1270 {
1271 /*
1272 * translator: last %s is a phrase such as "during statement block
1273 * local variable initialization"
1274 */
1275 errcontext("PL/pgSQL function %s line %d %s",
1276 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 errcontext("PL/pgSQL function %s %s",
1287 estate->func->fn_signature,
1288 _(estate->err_text));
1289 }
1290 }
1291 else if (estate->err_stmt != NULL && err_lineno > 0)
1292 {
1293 /* translator: last %s is a plpgsql statement type name */
1294 errcontext("PL/pgSQL function %s line %d at %s",
1295 estate->func->fn_signature,
1296 err_lineno,
1298 }
1299 else
1300 errcontext("PL/pgSQL function %s",
1301 estate->func->fn_signature);
1302}

References _, arg, PLpgSQL_execstate::err_stmt, PLpgSQL_execstate::err_text, PLpgSQL_execstate::err_var, errcontext, fb(), PLpgSQL_function::fn_signature, PLpgSQL_execstate::func, PLpgSQL_variable::lineno, PLpgSQL_stmt::lineno, and plpgsql_stmt_typename().

Referenced by plpgsql_estate_setup(), plpgsql_exec_event_trigger(), plpgsql_exec_function(), and plpgsql_exec_trigger().

◆ plpgsql_exec_event_trigger()

void plpgsql_exec_event_trigger ( PLpgSQL_function func,
EventTriggerData trigdata 
)

Definition at line 1175 of file pl_exec.c.

1176{
1177 PLpgSQL_execstate estate;
1179 int rc;
1180
1181 /*
1182 * Setup the execution state
1183 */
1184 plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
1185 estate.evtrigdata = trigdata;
1186
1187 /*
1188 * Setup error traceback support for ereport()
1189 */
1191 plerrcontext.arg = &estate;
1194
1195 /*
1196 * Make local execution copies of all the datums
1197 */
1198 estate.err_text = gettext_noop("during initialization of execution state");
1199 copy_plpgsql_datums(&estate, func);
1200
1201 /*
1202 * Let the instrumentation plugin peek at this function
1203 */
1204 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1205 ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1206
1207 /*
1208 * Now call the toplevel block of statements
1209 */
1210 estate.err_text = NULL;
1211 rc = exec_toplevel_block(&estate, func->action);
1212 if (rc != PLPGSQL_RC_RETURN)
1213 {
1214 estate.err_text = NULL;
1215 ereport(ERROR,
1217 errmsg("control reached end of trigger procedure without RETURN")));
1218 }
1219
1220 estate.err_text = gettext_noop("during function exit");
1221
1222 /*
1223 * Let the instrumentation plugin peek at this function
1224 */
1225 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1226 ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1227
1228 /* Clean up any leftover temporary memory */
1229 plpgsql_destroy_econtext(&estate);
1230 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 */
1237}

References PLpgSQL_function::action, copy_plpgsql_datums(), ereport, PLpgSQL_execstate::err_text, errcode(), errmsg(), ERROR, error_context_stack, PLpgSQL_execstate::evtrigdata, exec_eval_cleanup(), exec_toplevel_block(), fb(), PLpgSQL_plugin::func_beg, PLpgSQL_plugin::func_end, gettext_noop, plpgsql_destroy_econtext(), plpgsql_estate_setup(), plpgsql_exec_error_callback(), plpgsql_plugin_ptr, PLPGSQL_RC_RETURN, and ErrorContextCallback::previous.

Referenced by plpgsql_call_handler().

◆ plpgsql_exec_function()

Datum plpgsql_exec_function ( PLpgSQL_function func,
FunctionCallInfo  fcinfo,
EState simple_eval_estate,
ResourceOwner  simple_eval_resowner,
ResourceOwner  procedure_resowner,
bool  atomic 
)

Definition at line 493 of file pl_exec.c.

498{
499 PLpgSQL_execstate estate;
501 int i;
502 int rc;
503
504 /*
505 * Setup the execution state
506 */
507 plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo,
508 simple_eval_estate, simple_eval_resowner);
509 estate.procedure_resowner = procedure_resowner;
510 estate.atomic = atomic;
511
512 /*
513 * Setup error traceback support for ereport()
514 */
516 plerrcontext.arg = &estate;
519
520 /*
521 * Make local execution copies of all the datums
522 */
523 estate.err_text = gettext_noop("during initialization of execution state");
524 copy_plpgsql_datums(&estate, func);
525
526 /*
527 * Store the actual call argument values into the appropriate variables
528 */
529 estate.err_text = gettext_noop("while storing call arguments into local variables");
530 for (i = 0; i < func->fn_nargs; i++)
531 {
532 int n = func->fn_argvarnos[i];
533
534 switch (estate.datums[n]->dtype)
535 {
537 {
538 PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
539
540 assign_simple_var(&estate, var,
541 fcinfo->args[i].value,
542 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 if (!var->isnull && var->datatype->typlen == -1)
562 {
564 {
565 /* take ownership of R/W object */
566 assign_simple_var(&estate, var,
567 TransferExpandedObject(var->value,
568 estate.datum_context),
569 false,
570 true);
571 }
573 {
574 /* R/O pointer, keep it as-is until assigned to */
575 }
576 else if (var->datatype->typisarray)
577 {
578 /* flat array, so force to expanded form */
579 assign_simple_var(&estate, var,
580 expand_array(var->value,
581 estate.datum_context,
582 NULL),
583 false,
584 true);
585 }
586 }
587 }
588 break;
589
591 {
592 PLpgSQL_rec *rec = (PLpgSQL_rec *) estate.datums[n];
593
594 if (!fcinfo->args[i].isnull)
595 {
596 /* Assign row value from composite datum */
598 (PLpgSQL_variable *) rec,
599 fcinfo->args[i].value);
600 }
601 else
602 {
603 /* If arg is null, set variable to null */
604 exec_move_row(&estate, (PLpgSQL_variable *) rec,
605 NULL, NULL);
606 }
607 /* clean up after exec_move_row() */
608 exec_eval_cleanup(&estate);
609 }
610 break;
611
612 default:
613 /* Anything else should not be an argument variable */
614 elog(ERROR, "unrecognized dtype: %d", func->datums[i]->dtype);
615 }
616 }
617
618 estate.err_text = gettext_noop("during function entry");
619
620 /*
621 * Set the magic variable FOUND to false
622 */
623 exec_set_found(&estate, false);
624
625 /*
626 * Let the instrumentation plugin peek at this function
627 */
628 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
629 ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
630
631 /*
632 * Now call the toplevel block of statements
633 */
634 estate.err_text = NULL;
635 rc = exec_toplevel_block(&estate, func->action);
636 if (rc != PLPGSQL_RC_RETURN)
637 {
638 estate.err_text = NULL;
641 errmsg("control reached end of function without RETURN")));
642 }
643
644 /*
645 * We got a return value - process it
646 */
647 estate.err_text = gettext_noop("while casting return value to function's return type");
648
649 fcinfo->isnull = estate.retisnull;
650
651 if (estate.retisset)
652 {
653 ReturnSetInfo *rsi = estate.rsi;
654
655 /* Check caller can handle a set result */
656 if (!rsi || !IsA(rsi, ReturnSetInfo))
659 errmsg("set-valued function called in context that cannot accept a set")));
660
661 if (!(rsi->allowedModes & SFRM_Materialize))
664 errmsg("materialize mode required, but it is not allowed in this context")));
665
667
668 /* If we produced any tuples, send back the result */
669 if (estate.tuple_store)
670 {
672
673 rsi->setResult = estate.tuple_store;
677 }
678 estate.retval = (Datum) 0;
679 fcinfo->isnull = true;
680 }
681 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 if (estate.retistuple)
690 {
691 /* Don't need coercion if rowtype is known to match */
692 if (func->fn_rettype == estate.rettype &&
693 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 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 */
715 TupleDesc tupdesc;
716
717 switch (get_call_result_type(fcinfo, &resultTypeId, &tupdesc))
718 {
720 /* got the expected result rowtype, now coerce it */
721 coerce_function_result_tuple(&estate, tupdesc);
722 break;
724 /* got the expected result rowtype, now coerce it */
725 coerce_function_result_tuple(&estate, tupdesc);
726 /* and check domain constraints */
727 /* XXX allowing caching here would be good, too */
728 domain_check(estate.retval, false, resultTypeId,
729 NULL, NULL);
730 break;
731 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 estate.retval = SPI_datumTransfer(estate.retval,
741 false,
742 -1);
743 break;
744 default:
745 /* shouldn't get here if retistuple is true ... */
746 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 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 if (!fcinfo->isnull && !func->fn_retbyval)
769 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 if (func->fn_retisdomain)
782 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 estate.err_text = gettext_noop("during function exit");
792
793 /*
794 * Let the instrumentation plugin peek at this function
795 */
796 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
797 ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
798
799 /* Clean up any leftover temporary memory */
801 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 */
808
809 /*
810 * Return the function's result
811 */
812 return estate.retval;
813}

References PLpgSQL_function::action, ReturnSetInfo::allowedModes, FunctionCallInfoBaseData::args, assign_simple_var(), PLpgSQL_execstate::atomic, coerce_function_result_tuple(), copy_plpgsql_datums(), CreateTupleDescCopy(), PLpgSQL_var::datatype, PLpgSQL_execstate::datum_context, DatumGetPointer(), PLpgSQL_function::datums, PLpgSQL_execstate::datums, domain_check(), PLpgSQL_datum::dtype, elog, ereport, PLpgSQL_execstate::err_text, errcode(), errmsg(), ERROR, error_context_stack, exec_cast_value(), exec_eval_cleanup(), exec_move_row(), exec_move_row_from_datum(), exec_set_found(), exec_toplevel_block(), expand_array(), fb(), PLpgSQL_function::fn_argvarnos, PLpgSQL_function::fn_nargs, PLpgSQL_function::fn_retbyval, PLpgSQL_function::fn_retisdomain, PLpgSQL_function::fn_rettype, PLpgSQL_function::fn_rettyplen, PLpgSQL_plugin::func_beg, PLpgSQL_plugin::func_end, get_call_result_type(), gettext_noop, i, IsA, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, PLpgSQL_var::isnull, MemoryContextSwitchTo(), plpgsql_destroy_econtext(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, plpgsql_estate_setup(), plpgsql_exec_error_callback(), plpgsql_plugin_ptr, PLPGSQL_RC_RETURN, ErrorContextCallback::previous, PLpgSQL_execstate::procedure_resowner, FunctionCallInfoBaseData::resultinfo, PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::retistuple, PLpgSQL_execstate::rettype, ReturnSetInfo::returnMode, PLpgSQL_execstate::retval, PLpgSQL_execstate::rsi, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SPI_datumTransfer(), TransferExpandedObject(), PLpgSQL_execstate::tuple_store, PLpgSQL_execstate::tuple_store_cxt, PLpgSQL_execstate::tuple_store_desc, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, TYPEFUNC_RECORD, PLpgSQL_type::typisarray, PLpgSQL_type::typlen, NullableDatum::value, PLpgSQL_var::value, VARATT_IS_EXTERNAL_EXPANDED_RO(), and VARATT_IS_EXTERNAL_EXPANDED_RW().

Referenced by plpgsql_call_handler(), and plpgsql_inline_handler().

◆ plpgsql_exec_get_datum_type()

Oid plpgsql_exec_get_datum_type ( PLpgSQL_execstate estate,
PLpgSQL_datum datum 
)

Definition at line 5438 of file pl_exec.c.

5440{
5441 Oid typeid;
5442
5443 switch (datum->dtype)
5444 {
5445 case PLPGSQL_DTYPE_VAR:
5447 {
5448 PLpgSQL_var *var = (PLpgSQL_var *) datum;
5449
5450 typeid = var->datatype->typoid;
5451 break;
5452 }
5453
5454 case PLPGSQL_DTYPE_REC:
5455 {
5456 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5457
5458 if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5459 {
5460 /* Report variable's declared type */
5461 typeid = rec->rectypeid;
5462 }
5463 else
5464 {
5465 /* Report record's actual type if declared RECORD */
5466 typeid = rec->erh->er_typeid;
5467 }
5468 break;
5469 }
5470
5472 {
5474 PLpgSQL_rec *rec;
5475
5476 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5477
5478 /*
5479 * If record variable is NULL, instantiate it if it has a
5480 * named composite type, else complain. (This won't change
5481 * the logical state of the record: it's still NULL.)
5482 */
5483 if (rec->erh == NULL)
5485
5486 /*
5487 * Look up the field's properties if we have not already, or
5488 * if the tuple descriptor ID changed since last time.
5489 */
5490 if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5491 {
5493 recfield->fieldname,
5494 &recfield->finfo))
5495 ereport(ERROR,
5497 errmsg("record \"%s\" has no field \"%s\"",
5498 rec->refname, recfield->fieldname)));
5499 recfield->rectupledescid = rec->erh->er_tupdesc_id;
5500 }
5501
5502 typeid = recfield->finfo.ftypeid;
5503 break;
5504 }
5505
5506 default:
5507 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5508 typeid = InvalidOid; /* keep compiler quiet */
5509 break;
5510 }
5511
5512 return typeid;
5513}

References PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, elog, ExpandedRecordHeader::er_tupdesc_id, ExpandedRecordHeader::er_typeid, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, expanded_record_lookup_field(), fb(), instantiate_empty_record_variable(), InvalidOid, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_VAR, PLpgSQL_rec::rectypeid, PLpgSQL_rec::refname, PLpgSQL_type::typoid, and unlikely.

Referenced by exec_stmt_foreach_a().

◆ plpgsql_exec_get_datum_type_info()

void plpgsql_exec_get_datum_type_info ( PLpgSQL_execstate estate,
PLpgSQL_datum datum,
Oid typeId,
int32 typMod,
Oid collation 
)

Definition at line 5523 of file pl_exec.c.

5526{
5527 switch (datum->dtype)
5528 {
5529 case PLPGSQL_DTYPE_VAR:
5531 {
5532 PLpgSQL_var *var = (PLpgSQL_var *) datum;
5533
5534 *typeId = var->datatype->typoid;
5535 *typMod = var->datatype->atttypmod;
5536 *collation = var->datatype->collation;
5537 break;
5538 }
5539
5540 case PLPGSQL_DTYPE_REC:
5541 {
5542 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5543
5544 if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5545 {
5546 /* Report variable's declared type */
5547 *typeId = rec->rectypeid;
5548 *typMod = -1;
5549 }
5550 else
5551 {
5552 /* Report record's actual type if declared RECORD */
5553 *typeId = rec->erh->er_typeid;
5554 /* do NOT return the mutable typmod of a RECORD variable */
5555 *typMod = -1;
5556 }
5557 /* composite types are never collatable */
5558 *collation = InvalidOid;
5559 break;
5560 }
5561
5563 {
5565 PLpgSQL_rec *rec;
5566
5567 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5568
5569 /*
5570 * If record variable is NULL, instantiate it if it has a
5571 * named composite type, else complain. (This won't change
5572 * the logical state of the record: it's still NULL.)
5573 */
5574 if (rec->erh == NULL)
5576
5577 /*
5578 * Look up the field's properties if we have not already, or
5579 * if the tuple descriptor ID changed since last time.
5580 */
5581 if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5582 {
5584 recfield->fieldname,
5585 &recfield->finfo))
5586 ereport(ERROR,
5588 errmsg("record \"%s\" has no field \"%s\"",
5589 rec->refname, recfield->fieldname)));
5590 recfield->rectupledescid = rec->erh->er_tupdesc_id;
5591 }
5592
5593 *typeId = recfield->finfo.ftypeid;
5594 *typMod = recfield->finfo.ftypmod;
5595 *collation = recfield->finfo.fcollation;
5596 break;
5597 }
5598
5599 default:
5600 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5601 *typeId = InvalidOid; /* keep compiler quiet */
5602 *typMod = -1;
5603 *collation = InvalidOid;
5604 break;
5605 }
5606}

References PLpgSQL_type::atttypmod, PLpgSQL_type::collation, PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, elog, ExpandedRecordHeader::er_tupdesc_id, ExpandedRecordHeader::er_typeid, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, expanded_record_lookup_field(), fb(), instantiate_empty_record_variable(), InvalidOid, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_VAR, PLpgSQL_rec::rectypeid, PLpgSQL_rec::refname, PLpgSQL_type::typoid, and unlikely.

Referenced by make_datum_param().

◆ plpgsql_exec_trigger()

HeapTuple plpgsql_exec_trigger ( PLpgSQL_function func,
TriggerData trigdata 
)

Definition at line 935 of file pl_exec.c.

937{
938 PLpgSQL_execstate estate;
940 int rc;
941 TupleDesc tupdesc;
943 *rec_old;
945
946 /*
947 * Setup the execution state
948 */
949 plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
950 estate.trigdata = trigdata;
951
952 /*
953 * Setup error traceback support for ereport()
954 */
956 plerrcontext.arg = &estate;
959
960 /*
961 * Make local execution copies of all the datums
962 */
963 estate.err_text = gettext_noop("during initialization of execution state");
964 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 tupdesc = RelationGetDescr(trigdata->tg_relation);
977
978 rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
979 rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
980
982 estate.datum_context);
984 estate.datum_context);
985
986 if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
987 {
988 /*
989 * Per-statement triggers don't use OLD/NEW variables
990 */
991 }
992 else if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
993 {
995 false, false);
996 }
997 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
998 {
1000 false, false);
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 if (tupdesc->constr && tupdesc->constr->has_generated_stored &&
1013 TRIGGER_FIRED_BEFORE(trigdata->tg_event))
1014 {
1015 for (int i = 0; i < tupdesc->natts; i++)
1016 if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED)
1018 i + 1,
1019 (Datum) 0,
1020 true, /* isnull */
1021 false, false);
1022 }
1023 }
1024 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
1025 {
1027 false, false);
1028 }
1029 else
1030 elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
1031
1032 /* Make transition tables visible to this SPI connection */
1033 rc = SPI_register_trigger_data(trigdata);
1034 Assert(rc >= 0);
1035
1036 estate.err_text = gettext_noop("during function entry");
1037
1038 /*
1039 * Set the magic variable FOUND to false
1040 */
1041 exec_set_found(&estate, false);
1042
1043 /*
1044 * Let the instrumentation plugin peek at this function
1045 */
1046 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1047 ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1048
1049 /*
1050 * Now call the toplevel block of statements
1051 */
1052 estate.err_text = NULL;
1053 rc = exec_toplevel_block(&estate, func->action);
1054 if (rc != PLPGSQL_RC_RETURN)
1055 {
1056 estate.err_text = NULL;
1057 ereport(ERROR,
1059 errmsg("control reached end of trigger procedure without RETURN")));
1060 }
1061
1062 estate.err_text = gettext_noop("during function exit");
1063
1064 if (estate.retisset)
1065 ereport(ERROR,
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 if (estate.retisnull || !TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
1080 rettup = NULL;
1081 else
1082 {
1084 TupleConversionMap *tupmap;
1085
1086 /* We assume exec_stmt_return verified that result is composite */
1088
1089 /* We can special-case expanded records for speed */
1091 {
1093
1094 Assert(erh->er_magic == ER_MAGIC);
1095
1096 /* Extract HeapTuple and TupleDesc */
1098 Assert(rettup);
1100
1101 if (retdesc != RelationGetDescr(trigdata->tg_relation))
1102 {
1103 /* check rowtype compatibility */
1105 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 if (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 if (rettup != trigdata->tg_newtuple &&
1120 rettup != trigdata->tg_trigtuple)
1122 }
1123 else
1124 {
1125 /* Convert composite datum to a HeapTuple and TupleDesc */
1127
1129 rettup = &tmptup;
1130
1131 /* check rowtype compatibility */
1133 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 if (tupmap)
1138
1140 /* no need to free map, we're about to return anyway */
1141
1142 /* Copy tuple to upper executor memory */
1144 }
1145 }
1146
1147 /*
1148 * Let the instrumentation plugin peek at this function
1149 */
1150 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1151 ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1152
1153 /* Clean up any leftover temporary memory */
1154 plpgsql_destroy_econtext(&estate);
1155 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 */
1162
1163 /*
1164 * Return the trigger's result
1165 */
1166 return rettup;
1167}

References PLpgSQL_function::action, Assert, TupleDescData::constr, convert_tuples_by_position(), copy_plpgsql_datums(), PLpgSQL_execstate::datum_context, DatumGetEOHP(), DatumGetPointer(), PLpgSQL_execstate::datums, deconstruct_composite_datum(), elog, ER_MAGIC, ExpandedRecordHeader::er_magic, ereport, PLpgSQL_execstate::err_text, errcode(), errmsg(), ERROR, error_context_stack, exec_eval_cleanup(), exec_set_found(), exec_toplevel_block(), execute_attr_map_tuple(), expanded_record_get_tupdesc(), expanded_record_get_tuple(), expanded_record_set_field_internal(), expanded_record_set_tuple(), fb(), PLpgSQL_plugin::func_beg, PLpgSQL_plugin::func_end, gettext_noop, TupleConstr::has_generated_stored, i, make_expanded_record_from_exprecord(), make_expanded_record_from_tupdesc(), TupleDescData::natts, PLpgSQL_function::new_varno, PLpgSQL_function::old_varno, plpgsql_destroy_econtext(), plpgsql_estate_setup(), plpgsql_exec_error_callback(), plpgsql_plugin_ptr, PLPGSQL_RC_RETURN, ErrorContextCallback::previous, RelationGetDescr, ReleaseTupleDesc, PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::rettype, PLpgSQL_execstate::retval, SPI_copytuple(), SPI_register_trigger_data(), TriggerData::tg_event, TriggerData::tg_newtuple, TriggerData::tg_relation, TriggerData::tg_trigtuple, PLpgSQL_execstate::trigdata, TRIGGER_FIRED_BEFORE, TRIGGER_FIRED_BY_DELETE, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_UPDATE, TRIGGER_FIRED_FOR_ROW, TupleDescAttr(), type_is_rowtype(), and VARATT_IS_EXTERNAL_EXPANDED().

Referenced by plpgsql_call_handler().

◆ plpgsql_fulfill_promise()

static void plpgsql_fulfill_promise ( PLpgSQL_execstate estate,
PLpgSQL_var var 
)
static

Definition at line 1383 of file pl_exec.c.

1385{
1386 MemoryContext oldcontext;
1387
1388 if (var->promise == PLPGSQL_PROMISE_NONE)
1389 return; /* nothing to do */
1390
1391 /*
1392 * This will typically be invoked in a short-lived context such as the
1393 * mcontext. We must create variable values in the estate's datum
1394 * context. This quick-and-dirty solution risks leaking some additional
1395 * cruft there, but since any one promise is honored at most once per
1396 * function call, it's probably not worth being more careful.
1397 */
1398 oldcontext = MemoryContextSwitchTo(estate->datum_context);
1399
1400 switch (var->promise)
1401 {
1403 if (estate->trigdata == NULL)
1404 elog(ERROR, "trigger promise is not in a trigger function");
1405 assign_simple_var(estate, var,
1408 false, true);
1409 break;
1410
1412 if (estate->trigdata == NULL)
1413 elog(ERROR, "trigger promise is not in a trigger function");
1415 assign_text_var(estate, var, "BEFORE");
1416 else if (TRIGGER_FIRED_AFTER(estate->trigdata->tg_event))
1417 assign_text_var(estate, var, "AFTER");
1418 else if (TRIGGER_FIRED_INSTEAD(estate->trigdata->tg_event))
1419 assign_text_var(estate, var, "INSTEAD OF");
1420 else
1421 elog(ERROR, "unrecognized trigger execution time: not BEFORE, AFTER, or INSTEAD OF");
1422 break;
1423
1425 if (estate->trigdata == NULL)
1426 elog(ERROR, "trigger promise is not in a trigger function");
1428 assign_text_var(estate, var, "ROW");
1430 assign_text_var(estate, var, "STATEMENT");
1431 else
1432 elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
1433 break;
1434
1436 if (estate->trigdata == NULL)
1437 elog(ERROR, "trigger promise is not in a trigger function");
1439 assign_text_var(estate, var, "INSERT");
1440 else if (TRIGGER_FIRED_BY_UPDATE(estate->trigdata->tg_event))
1441 assign_text_var(estate, var, "UPDATE");
1442 else if (TRIGGER_FIRED_BY_DELETE(estate->trigdata->tg_event))
1443 assign_text_var(estate, var, "DELETE");
1444 else if (TRIGGER_FIRED_BY_TRUNCATE(estate->trigdata->tg_event))
1445 assign_text_var(estate, var, "TRUNCATE");
1446 else
1447 elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, UPDATE, or TRUNCATE");
1448 break;
1449
1451 if (estate->trigdata == NULL)
1452 elog(ERROR, "trigger promise is not in a trigger function");
1453 assign_simple_var(estate, var,
1455 false, false);
1456 break;
1457
1459 if (estate->trigdata == NULL)
1460 elog(ERROR, "trigger promise is not in a trigger function");
1461 assign_simple_var(estate, var,
1464 false, true);
1465 break;
1466
1468 if (estate->trigdata == NULL)
1469 elog(ERROR, "trigger promise is not in a trigger function");
1470 assign_simple_var(estate, var,
1473 false, true);
1474 break;
1475
1477 if (estate->trigdata == NULL)
1478 elog(ERROR, "trigger promise is not in a trigger function");
1479 assign_simple_var(estate, var,
1481 false, false);
1482 break;
1483
1485 if (estate->trigdata == NULL)
1486 elog(ERROR, "trigger promise is not in a trigger function");
1487 if (estate->trigdata->tg_trigger->tgnargs > 0)
1488 {
1489 /*
1490 * For historical reasons, tg_argv[] subscripts start at zero
1491 * not one. So we can't use construct_array().
1492 */
1493 int nelems = estate->trigdata->tg_trigger->tgnargs;
1494 Datum *elems;
1495 int dims[1];
1496 int lbs[1];
1497 int i;
1498
1499 elems = palloc_array(Datum, nelems);
1500 for (i = 0; i < nelems; i++)
1501 elems[i] = CStringGetTextDatum(estate->trigdata->tg_trigger->tgargs[i]);
1502 dims[0] = nelems;
1503 lbs[0] = 0;
1504
1505 assign_simple_var(estate, var,
1507 1, dims, lbs,
1508 TEXTOID,
1509 -1, false, TYPALIGN_INT)),
1510 false, true);
1511 }
1512 else
1513 {
1514 assign_simple_var(estate, var, (Datum) 0, true, false);
1515 }
1516 break;
1517
1519 if (estate->evtrigdata == NULL)
1520 elog(ERROR, "event trigger promise is not in an event trigger function");
1521 assign_text_var(estate, var, estate->evtrigdata->event);
1522 break;
1523
1525 if (estate->evtrigdata == NULL)
1526 elog(ERROR, "event trigger promise is not in an event trigger function");
1527 assign_text_var(estate, var, GetCommandTagName(estate->evtrigdata->tag));
1528 break;
1529
1530 default:
1531 elog(ERROR, "unrecognized promise type: %d", var->promise);
1532 }
1533
1534 MemoryContextSwitchTo(oldcontext);
1535}

References assign_simple_var(), assign_text_var(), construct_md_array(), CStringGetDatum(), CStringGetTextDatum, PLpgSQL_execstate::datum_context, DirectFunctionCall1, elog, ERROR, EventTriggerData::event, PLpgSQL_execstate::evtrigdata, fb(), get_namespace_name(), GetCommandTagName(), i, Int16GetDatum(), MemoryContextSwitchTo(), namein(), ObjectIdGetDatum(), palloc_array, PLPGSQL_PROMISE_NONE, PLPGSQL_PROMISE_TG_ARGV, PLPGSQL_PROMISE_TG_EVENT, PLPGSQL_PROMISE_TG_LEVEL, PLPGSQL_PROMISE_TG_NAME, PLPGSQL_PROMISE_TG_NARGS, PLPGSQL_PROMISE_TG_OP, PLPGSQL_PROMISE_TG_RELID, PLPGSQL_PROMISE_TG_TABLE_NAME, PLPGSQL_PROMISE_TG_TABLE_SCHEMA, PLPGSQL_PROMISE_TG_TAG, PLPGSQL_PROMISE_TG_WHEN, PointerGetDatum(), PLpgSQL_var::promise, RelationData::rd_id, RelationGetNamespace, RelationGetRelationName, EventTriggerData::tag, TriggerData::tg_event, TriggerData::tg_relation, TriggerData::tg_trigger, Trigger::tgargs, Trigger::tgname, Trigger::tgnargs, PLpgSQL_execstate::trigdata, TRIGGER_FIRED_AFTER, TRIGGER_FIRED_BEFORE, TRIGGER_FIRED_BY_DELETE, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_TRUNCATE, TRIGGER_FIRED_BY_UPDATE, TRIGGER_FIRED_FOR_ROW, TRIGGER_FIRED_FOR_STATEMENT, and TRIGGER_FIRED_INSTEAD.

Referenced by exec_eval_datum(), exec_stmt_return(), and exec_stmt_return_next().

◆ plpgsql_param_compile()

static void plpgsql_param_compile ( ParamListInfo  params,
Param param,
ExprState state,
Datum resv,
bool resnull 
)
static

Definition at line 6424 of file pl_exec.c.

6427{
6428 PLpgSQL_execstate *estate;
6429 PLpgSQL_expr *expr;
6430 int dno;
6431 PLpgSQL_datum *datum;
6433
6434 /* fetch back the hook data */
6435 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6436 expr = (PLpgSQL_expr *) params->parserSetupArg;
6437
6438 /* paramid's are 1-based, but dnos are 0-based */
6439 dno = param->paramid - 1;
6440 Assert(dno >= 0 && dno < estate->ndatums);
6441
6442 /* now we can access the target datum */
6443 datum = estate->datums[dno];
6444
6446 scratch.resvalue = resv;
6447 scratch.resnull = resnull;
6448
6449 /*
6450 * Select appropriate eval function.
6451 *
6452 * First, if this Param references the same varlena-type DTYPE_VAR datum
6453 * that is the target of the assignment containing this simple expression,
6454 * then it's possible we will be able to optimize handling of R/W expanded
6455 * datums. We don't want to do the work needed to determine that unless
6456 * we actually see a R/W expanded datum at runtime, so install a checking
6457 * function that will figure that out when needed.
6458 *
6459 * Otherwise, it seems worth special-casing DTYPE_VAR and DTYPE_RECFIELD
6460 * for performance. Also, we can determine in advance whether
6461 * MakeExpandedObjectReadOnly() will be required. Currently, only
6462 * VAR/PROMISE and REC datums could contain read/write expanded objects.
6463 */
6464 if (datum->dtype == PLPGSQL_DTYPE_VAR)
6465 {
6466 bool isvarlena = (((PLpgSQL_var *) datum)->datatype->typlen == -1);
6467
6468 if (isvarlena && dno == expr->target_param && expr->expr_simple_expr)
6469 scratch.d.cparam.paramfunc = plpgsql_param_eval_var_check;
6470 else if (isvarlena)
6471 scratch.d.cparam.paramfunc = plpgsql_param_eval_var_ro;
6472 else
6473 scratch.d.cparam.paramfunc = plpgsql_param_eval_var;
6474 }
6475 else if (datum->dtype == PLPGSQL_DTYPE_RECFIELD)
6476 scratch.d.cparam.paramfunc = plpgsql_param_eval_recfield;
6477 else if (datum->dtype == PLPGSQL_DTYPE_PROMISE)
6478 {
6479 if (((PLpgSQL_var *) datum)->datatype->typlen == -1)
6480 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro;
6481 else
6482 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic;
6483 }
6484 else if (datum->dtype == PLPGSQL_DTYPE_REC)
6485 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro;
6486 else
6487 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic;
6488
6489 /*
6490 * Note: it's tempting to use paramarg to store the estate pointer and
6491 * thereby save an indirection or two in the eval functions. But that
6492 * doesn't work because the compiled expression might be used with
6493 * different estates for the same PL/pgSQL function. Instead, store
6494 * pointers to the PLpgSQL_expr as well as this specific Param, to support
6495 * plpgsql_param_eval_var_check().
6496 */
6497 scratch.d.cparam.paramarg = expr;
6498 scratch.d.cparam.paramarg2 = param;
6499 scratch.d.cparam.paramid = param->paramid;
6500 scratch.d.cparam.paramtype = param->paramtype;
6502}
Oid paramtype
Definition primnodes.h:398

References Assert, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, EEOP_PARAM_CALLBACK, PLpgSQL_expr::expr_simple_expr, ExprEvalPushStep(), fb(), ParamListInfoData::paramFetchArg, Param::paramid, Param::paramtype, ParamListInfoData::parserSetupArg, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_VAR, plpgsql_param_eval_generic(), plpgsql_param_eval_generic_ro(), plpgsql_param_eval_recfield(), plpgsql_param_eval_var(), plpgsql_param_eval_var_check(), plpgsql_param_eval_var_ro(), and PLpgSQL_expr::target_param.

Referenced by plpgsql_estate_setup().

◆ plpgsql_param_eval_generic()

static void plpgsql_param_eval_generic ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 6812 of file pl_exec.c.

6814{
6815 ParamListInfo params;
6816 PLpgSQL_execstate *estate;
6817 int dno = op->d.cparam.paramid - 1;
6818 PLpgSQL_datum *datum;
6819 Oid datumtype;
6821
6822 /* fetch back the hook data */
6823 params = econtext->ecxt_param_list_info;
6824 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6825 Assert(dno >= 0 && dno < estate->ndatums);
6826
6827 /* now we can access the target datum */
6828 datum = estate->datums[dno];
6829
6830 /* fetch datum's value */
6831 exec_eval_datum(estate, datum,
6833 op->resvalue, op->resnull);
6834
6835 /* safety check -- needed for, eg, record fields */
6836 if (unlikely(datumtype != op->d.cparam.paramtype))
6837 ereport(ERROR,
6839 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6840 op->d.cparam.paramid,
6843}
Datum * resvalue
Definition execExpr.h:310
bool * resnull
Definition execExpr.h:311

References Assert, ExprEvalStep::cparam, ExprEvalStep::d, PLpgSQL_execstate::datums, ExprContext::ecxt_param_list_info, ereport, errcode(), errmsg(), ERROR, exec_eval_datum(), fb(), format_type_be(), ParamListInfoData::paramFetchArg, ExprEvalStep::paramid, ExprEvalStep::paramtype, ExprEvalStep::resnull, ExprEvalStep::resvalue, and unlikely.

Referenced by plpgsql_param_compile().

◆ plpgsql_param_eval_generic_ro()

static void plpgsql_param_eval_generic_ro ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 6852 of file pl_exec.c.

6854{
6855 ParamListInfo params;
6856 PLpgSQL_execstate *estate;
6857 int dno = op->d.cparam.paramid - 1;
6858 PLpgSQL_datum *datum;
6859 Oid datumtype;
6861
6862 /* fetch back the hook data */
6863 params = econtext->ecxt_param_list_info;
6864 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6865 Assert(dno >= 0 && dno < estate->ndatums);
6866
6867 /* now we can access the target datum */
6868 datum = estate->datums[dno];
6869
6870 /* fetch datum's value */
6871 exec_eval_datum(estate, datum,
6873 op->resvalue, op->resnull);
6874
6875 /* safety check -- needed for, eg, record fields */
6876 if (unlikely(datumtype != op->d.cparam.paramtype))
6877 ereport(ERROR,
6879 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6880 op->d.cparam.paramid,
6883
6884 /* force the value to read-only */
6886 *op->resnull,
6887 -1);
6888}

References Assert, ExprEvalStep::cparam, ExprEvalStep::d, PLpgSQL_execstate::datums, ExprContext::ecxt_param_list_info, ereport, errcode(), errmsg(), ERROR, exec_eval_datum(), fb(), format_type_be(), MakeExpandedObjectReadOnly, ParamListInfoData::paramFetchArg, ExprEvalStep::paramid, ExprEvalStep::paramtype, ExprEvalStep::resnull, ExprEvalStep::resvalue, and unlikely.

Referenced by plpgsql_param_compile().

◆ plpgsql_param_eval_recfield()

static void plpgsql_param_eval_recfield ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 6740 of file pl_exec.c.

6742{
6743 ParamListInfo params;
6744 PLpgSQL_execstate *estate;
6745 int dno = op->d.cparam.paramid - 1;
6747 PLpgSQL_rec *rec;
6749
6750 /* fetch back the hook data */
6751 params = econtext->ecxt_param_list_info;
6752 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6753 Assert(dno >= 0 && dno < estate->ndatums);
6754
6755 /* now we can access the target datum */
6756 recfield = (PLpgSQL_recfield *) estate->datums[dno];
6758
6759 /* inline the relevant part of exec_eval_datum */
6760 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
6761 erh = rec->erh;
6762
6763 /*
6764 * If record variable is NULL, instantiate it if it has a named composite
6765 * type, else complain. (This won't change the logical state of the
6766 * record: it's still NULL.)
6767 */
6768 if (erh == NULL)
6769 {
6771 erh = rec->erh;
6772 }
6773
6774 /*
6775 * Look up the field's properties if we have not already, or if the tuple
6776 * descriptor ID changed since last time.
6777 */
6778 if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
6779 {
6781 recfield->fieldname,
6782 &recfield->finfo))
6783 ereport(ERROR,
6785 errmsg("record \"%s\" has no field \"%s\"",
6786 rec->refname, recfield->fieldname)));
6787 recfield->rectupledescid = erh->er_tupdesc_id;
6788 }
6789
6790 /* OK to fetch the field value. */
6792 recfield->finfo.fnumber,
6793 op->resnull);
6794
6795 /* safety check -- needed for, eg, record fields */
6796 if (unlikely(recfield->finfo.ftypeid != op->d.cparam.paramtype))
6797 ereport(ERROR,
6799 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6800 op->d.cparam.paramid,
6801 format_type_be(recfield->finfo.ftypeid),
6803}

References Assert, ExprEvalStep::cparam, ExprEvalStep::d, PLpgSQL_execstate::datums, ExprContext::ecxt_param_list_info, ExpandedRecordHeader::er_tupdesc_id, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, expanded_record_get_field(), expanded_record_lookup_field(), fb(), format_type_be(), instantiate_empty_record_variable(), ParamListInfoData::paramFetchArg, ExprEvalStep::paramid, ExprEvalStep::paramtype, PLPGSQL_DTYPE_RECFIELD, PLpgSQL_rec::refname, ExprEvalStep::resnull, ExprEvalStep::resvalue, and unlikely.

Referenced by plpgsql_param_compile().

◆ plpgsql_param_eval_var()

static void plpgsql_param_eval_var ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 6671 of file pl_exec.c.

6673{
6674 ParamListInfo params;
6675 PLpgSQL_execstate *estate;
6676 int dno = op->d.cparam.paramid - 1;
6677 PLpgSQL_var *var;
6678
6679 /* fetch back the hook data */
6680 params = econtext->ecxt_param_list_info;
6681 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6682 Assert(dno >= 0 && dno < estate->ndatums);
6683
6684 /* now we can access the target datum */
6685 var = (PLpgSQL_var *) estate->datums[dno];
6686 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6687
6688 /* inlined version of exec_eval_datum() */
6689 *op->resvalue = var->value;
6690 *op->resnull = var->isnull;
6691
6692 /* safety check -- an assertion should be sufficient */
6693 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6694}

References Assert, ExprEvalStep::cparam, ExprEvalStep::d, PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_var::dtype, ExprContext::ecxt_param_list_info, fb(), PLpgSQL_var::isnull, ParamListInfoData::paramFetchArg, ExprEvalStep::paramid, ExprEvalStep::paramtype, PLPGSQL_DTYPE_VAR, ExprEvalStep::resnull, ExprEvalStep::resvalue, PLpgSQL_type::typoid, and PLpgSQL_var::value.

Referenced by plpgsql_param_compile(), and plpgsql_param_eval_var_check().

◆ plpgsql_param_eval_var_check()

static void plpgsql_param_eval_var_check ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 6518 of file pl_exec.c.

6520{
6521 ParamListInfo params;
6522 PLpgSQL_execstate *estate;
6523 int dno = op->d.cparam.paramid - 1;
6524 PLpgSQL_var *var;
6525
6526 /* fetch back the hook data */
6527 params = econtext->ecxt_param_list_info;
6528 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6529 Assert(dno >= 0 && dno < estate->ndatums);
6530
6531 /* now we can access the target datum */
6532 var = (PLpgSQL_var *) estate->datums[dno];
6533 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6534
6535 /*
6536 * If the variable's current value is a R/W expanded object, it's time to
6537 * decide whether/how to optimize the assignment.
6538 */
6539 if (!var->isnull &&
6541 {
6542 PLpgSQL_expr *expr = (PLpgSQL_expr *) op->d.cparam.paramarg;
6543 Param *param = (Param *) op->d.cparam.paramarg2;
6544
6545 /*
6546 * We might have already figured this out while evaluating some other
6547 * Param referencing the same variable, so check expr_rwopt first.
6548 */
6549 if (expr->expr_rwopt == PLPGSQL_RWOPT_UNKNOWN)
6551
6552 /*
6553 * Update the callback pointer to match what we decided to do, so that
6554 * this function will not be called again. Then pass off this
6555 * execution to the newly-selected function.
6556 */
6557 switch (expr->expr_rwopt)
6558 {
6560 Assert(false);
6561 break;
6562 case PLPGSQL_RWOPT_NOPE:
6563 /* Force the value to read-only in all future executions */
6565 plpgsql_param_eval_var_ro(state, op, econtext);
6566 break;
6568 /* There can be only one matching Param in this case */
6569 Assert(param == expr->expr_rw_param);
6570 /* When the value is read/write, transfer to exec context */
6573 break;
6575 if (param == expr->expr_rw_param)
6576 {
6577 /* When the value is read/write, deliver it as-is */
6579 plpgsql_param_eval_var(state, op, econtext);
6580 }
6581 else
6582 {
6583 /* Not the optimizable reference, so force to read-only */
6585 plpgsql_param_eval_var_ro(state, op, econtext);
6586 }
6587 break;
6588 }
6589 return;
6590 }
6591
6592 /*
6593 * Otherwise, continue to postpone that decision, and execute an inlined
6594 * version of exec_eval_datum(). Although this value could potentially
6595 * need MakeExpandedObjectReadOnly, we know it doesn't right now.
6596 */
6597 *op->resvalue = var->value;
6598 *op->resnull = var->isnull;
6599
6600 /* safety check -- an assertion should be sufficient */
6601 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6602}
void * paramarg
Definition execExpr.h:433
void * paramarg2
Definition execExpr.h:434
ExecEvalSubroutine paramfunc
Definition execExpr.h:432

References Assert, ExprEvalStep::cparam, ExprEvalStep::d, PLpgSQL_var::datatype, DatumGetPointer(), PLpgSQL_execstate::datums, PLpgSQL_var::dtype, ExprContext::ecxt_param_list_info, exec_check_rw_parameter(), PLpgSQL_expr::expr_rw_param, PLpgSQL_expr::expr_rwopt, fb(), PLpgSQL_var::isnull, ExprEvalStep::paramarg, ExprEvalStep::paramarg2, ParamListInfoData::paramFetchArg, ExprEvalStep::paramfunc, ExprEvalStep::paramid, ExprEvalStep::paramtype, PLPGSQL_DTYPE_VAR, plpgsql_param_eval_var(), plpgsql_param_eval_var_ro(), plpgsql_param_eval_var_transfer(), PLPGSQL_RWOPT_INPLACE, PLPGSQL_RWOPT_NOPE, PLPGSQL_RWOPT_TRANSFER, PLPGSQL_RWOPT_UNKNOWN, ExprEvalStep::resnull, ExprEvalStep::resvalue, PLpgSQL_type::typoid, PLpgSQL_var::value, and VARATT_IS_EXTERNAL_EXPANDED_RW().

Referenced by plpgsql_param_compile().

◆ plpgsql_param_eval_var_ro()

static void plpgsql_param_eval_var_ro ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 6703 of file pl_exec.c.

6705{
6706 ParamListInfo params;
6707 PLpgSQL_execstate *estate;
6708 int dno = op->d.cparam.paramid - 1;
6709 PLpgSQL_var *var;
6710
6711 /* fetch back the hook data */
6712 params = econtext->ecxt_param_list_info;
6713 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6714 Assert(dno >= 0 && dno < estate->ndatums);
6715
6716 /* now we can access the target datum */
6717 var = (PLpgSQL_var *) estate->datums[dno];
6718 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6719
6720 /*
6721 * Inlined version of exec_eval_datum() ... and while we're at it, force
6722 * expanded datums to read-only.
6723 */
6724 *op->resvalue = MakeExpandedObjectReadOnly(var->value,
6725 var->isnull,
6726 -1);
6727 *op->resnull = var->isnull;
6728
6729 /* safety check -- an assertion should be sufficient */
6730 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6731}

References Assert, ExprEvalStep::cparam, ExprEvalStep::d, PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_var::dtype, ExprContext::ecxt_param_list_info, fb(), PLpgSQL_var::isnull, MakeExpandedObjectReadOnly, ParamListInfoData::paramFetchArg, ExprEvalStep::paramid, ExprEvalStep::paramtype, PLPGSQL_DTYPE_VAR, ExprEvalStep::resnull, ExprEvalStep::resvalue, PLpgSQL_type::typoid, and PLpgSQL_var::value.

Referenced by plpgsql_param_compile(), and plpgsql_param_eval_var_check().

◆ plpgsql_param_eval_var_transfer()

static void plpgsql_param_eval_var_transfer ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 6615 of file pl_exec.c.

6617{
6618 ParamListInfo params;
6619 PLpgSQL_execstate *estate;
6620 int dno = op->d.cparam.paramid - 1;
6621 PLpgSQL_var *var;
6622
6623 /* fetch back the hook data */
6624 params = econtext->ecxt_param_list_info;
6625 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6626 Assert(dno >= 0 && dno < estate->ndatums);
6627
6628 /* now we can access the target datum */
6629 var = (PLpgSQL_var *) estate->datums[dno];
6630 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6631
6632 /*
6633 * If the variable's current value is a R/W expanded object, transfer its
6634 * ownership into the expression execution context, then drop our own
6635 * reference to the value by setting the variable to NULL. That'll be
6636 * overwritten (perhaps with this same object) when control comes back
6637 * from the expression.
6638 */
6639 if (!var->isnull &&
6641 {
6642 *op->resvalue = TransferExpandedObject(var->value,
6643 get_eval_mcontext(estate));
6644 *op->resnull = false;
6645
6646 var->value = (Datum) 0;
6647 var->isnull = true;
6648 var->freeval = false;
6649 }
6650 else
6651 {
6652 /*
6653 * Otherwise we can pass the variable's value directly; we now know
6654 * that MakeExpandedObjectReadOnly isn't needed.
6655 */
6656 *op->resvalue = var->value;
6657 *op->resnull = var->isnull;
6658 }
6659
6660 /* safety check -- an assertion should be sufficient */
6661 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6662}

References Assert, ExprEvalStep::cparam, ExprEvalStep::d, PLpgSQL_var::datatype, DatumGetPointer(), PLpgSQL_execstate::datums, PLpgSQL_var::dtype, ExprContext::ecxt_param_list_info, fb(), PLpgSQL_var::freeval, get_eval_mcontext, PLpgSQL_var::isnull, ParamListInfoData::paramFetchArg, ExprEvalStep::paramid, ExprEvalStep::paramtype, PLPGSQL_DTYPE_VAR, ExprEvalStep::resnull, ExprEvalStep::resvalue, TransferExpandedObject(), PLpgSQL_type::typoid, PLpgSQL_var::value, and VARATT_IS_EXTERNAL_EXPANDED_RW().

Referenced by plpgsql_param_eval_var_check().

◆ plpgsql_param_fetch()

static ParamExternData * plpgsql_param_fetch ( ParamListInfo  params,
int  paramid,
bool  speculative,
ParamExternData prm 
)
static

Definition at line 6297 of file pl_exec.c.

6300{
6301 int dno;
6302 PLpgSQL_execstate *estate;
6303 PLpgSQL_expr *expr;
6304 PLpgSQL_datum *datum;
6305 bool ok = true;
6307
6308 /* paramid's are 1-based, but dnos are 0-based */
6309 dno = paramid - 1;
6310 Assert(dno >= 0 && dno < params->numParams);
6311
6312 /* fetch back the hook data */
6313 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6314 expr = (PLpgSQL_expr *) params->parserSetupArg;
6315 Assert(params->numParams == estate->ndatums);
6316
6317 /* now we can access the target datum */
6318 datum = estate->datums[dno];
6319
6320 /*
6321 * Since copyParamList() or SerializeParamList() will try to materialize
6322 * every single parameter slot, it's important to return a dummy param
6323 * when asked for a datum that's not supposed to be used by this SQL
6324 * expression. Otherwise we risk failures in exec_eval_datum(), or
6325 * copying a lot more data than necessary.
6326 */
6327 if (!bms_is_member(dno, expr->paramnos))
6328 ok = false;
6329
6330 /*
6331 * If the access is speculative, we prefer to return no data rather than
6332 * to fail in exec_eval_datum(). Check the likely failure cases.
6333 */
6334 else if (speculative)
6335 {
6336 switch (datum->dtype)
6337 {
6338 case PLPGSQL_DTYPE_VAR:
6340 /* always safe */
6341 break;
6342
6343 case PLPGSQL_DTYPE_ROW:
6344 /* should be safe in all interesting cases */
6345 break;
6346
6347 case PLPGSQL_DTYPE_REC:
6348 /* always safe (might return NULL, that's fine) */
6349 break;
6350
6352 {
6354 PLpgSQL_rec *rec;
6355
6356 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
6357
6358 /*
6359 * If record variable is NULL, don't risk anything.
6360 */
6361 if (rec->erh == NULL)
6362 ok = false;
6363
6364 /*
6365 * Look up the field's properties if we have not already,
6366 * or if the tuple descriptor ID changed since last time.
6367 */
6368 else if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
6369 {
6371 recfield->fieldname,
6372 &recfield->finfo))
6373 recfield->rectupledescid = rec->erh->er_tupdesc_id;
6374 else
6375 ok = false;
6376 }
6377 break;
6378 }
6379
6380 default:
6381 ok = false;
6382 break;
6383 }
6384 }
6385
6386 /* Return "no such parameter" if not ok */
6387 if (!ok)
6388 {
6389 prm->value = (Datum) 0;
6390 prm->isnull = true;
6391 prm->pflags = 0;
6392 prm->ptype = InvalidOid;
6393 return prm;
6394 }
6395
6396 /* OK, evaluate the value and store into the return struct */
6397 exec_eval_datum(estate, datum,
6398 &prm->ptype, &prmtypmod,
6399 &prm->value, &prm->isnull);
6400 /* We can always mark params as "const" for executor's purposes */
6401 prm->pflags = PARAM_FLAG_CONST;
6402
6403 /*
6404 * If it's a read/write expanded datum, convert reference to read-only.
6405 * (There's little point in trying to optimize read/write parameters,
6406 * given the cases in which this function is used.)
6407 */
6408 if (datum->dtype == PLPGSQL_DTYPE_VAR)
6409 prm->value = MakeExpandedObjectReadOnly(prm->value,
6410 prm->isnull,
6411 ((PLpgSQL_var *) datum)->datatype->typlen);
6412 else if (datum->dtype == PLPGSQL_DTYPE_REC)
6413 prm->value = MakeExpandedObjectReadOnly(prm->value,
6414 prm->isnull,
6415 -1);
6416
6417 return prm;
6418}

References Assert, bms_is_member(), PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, ExpandedRecordHeader::er_tupdesc_id, PLpgSQL_rec::erh, exec_eval_datum(), expanded_record_lookup_field(), fb(), InvalidOid, MakeExpandedObjectReadOnly, PLpgSQL_execstate::ndatums, ParamListInfoData::numParams, PARAM_FLAG_CONST, ParamListInfoData::paramFetchArg, PLpgSQL_expr::paramnos, ParamListInfoData::parserSetupArg, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, and unlikely.

Referenced by plpgsql_estate_setup().

◆ plpgsql_subxact_cb()

◆ plpgsql_xact_cb()

void plpgsql_xact_cb ( XactEvent  event,
void arg 
)

Definition at line 8709 of file pl_exec.c.

8710{
8711 /*
8712 * If we are doing a clean transaction shutdown, free the EState and tell
8713 * the resowner to release whatever plancache references it has, so that
8714 * all remaining resources will be released correctly. (We don't need to
8715 * actually delete the resowner here; deletion of the
8716 * TopTransactionResourceOwner will take care of that.)
8717 *
8718 * In an abort, we expect the regular abort recovery procedures to release
8719 * everything of interest, so just clear our pointers.
8720 */
8721 if (event == XACT_EVENT_COMMIT ||
8722 event == XACT_EVENT_PARALLEL_COMMIT ||
8723 event == XACT_EVENT_PREPARE)
8724 {
8726
8733 }
8734 else if (event == XACT_EVENT_ABORT ||
8736 {
8740 }
8741}

References fb(), FreeExecutorState(), ReleaseAllPlanCacheRefsInOwner(), shared_simple_eval_estate, shared_simple_eval_resowner, simple_econtext_stack, XACT_EVENT_ABORT, XACT_EVENT_COMMIT, XACT_EVENT_PARALLEL_ABORT, XACT_EVENT_PARALLEL_COMMIT, and XACT_EVENT_PREPARE.

Referenced by _PG_init().

◆ pop_stmt_mcontext()

static void pop_stmt_mcontext ( PLpgSQL_execstate estate)
static

Definition at line 1581 of file pl_exec.c.

1582{
1583 /* We need only pop the stack */
1584 estate->stmt_mcontext = estate->stmt_mcontext_parent;
1586}

References MemoryContextGetParent(), PLpgSQL_execstate::stmt_mcontext, and PLpgSQL_execstate::stmt_mcontext_parent.

Referenced by exec_stmt_block(), and exec_stmt_foreach_a().

◆ push_stmt_mcontext()

static void push_stmt_mcontext ( PLpgSQL_execstate estate)
static

Definition at line 1562 of file pl_exec.c.

1563{
1564 /* Should have done get_stmt_mcontext() first */
1565 Assert(estate->stmt_mcontext != NULL);
1566 /* Assert we've not messed up the stack linkage */
1568 /* Push it down to become the parent of any nested stmt mcontext */
1569 estate->stmt_mcontext_parent = estate->stmt_mcontext;
1570 /* And make it not available for use directly */
1571 estate->stmt_mcontext = NULL;
1572}

References Assert, fb(), MemoryContextGetParent(), PLpgSQL_execstate::stmt_mcontext, and PLpgSQL_execstate::stmt_mcontext_parent.

Referenced by exec_stmt_foreach_a().

◆ revalidate_rectypeid()

static void revalidate_rectypeid ( PLpgSQL_rec rec)
static

Definition at line 7037 of file pl_exec.c.

7038{
7039 PLpgSQL_type *typ = rec->datatype;
7040 TypeCacheEntry *typentry;
7041
7042 if (rec->rectypeid == RECORDOID)
7043 return; /* it's RECORD, so nothing to do */
7044 Assert(typ != NULL);
7045 if (typ->tcache &&
7046 typ->tcache->tupDesc_identifier == typ->tupdesc_id)
7047 {
7048 /*
7049 * Although *typ is known up-to-date, it's possible that rectypeid
7050 * isn't, because *rec is cloned during each function startup from a
7051 * copy that we don't have a good way to update. Hence, forcibly fix
7052 * rectypeid before returning.
7053 */
7054 rec->rectypeid = typ->typoid;
7055 return;
7056 }
7057
7058 /*
7059 * typcache entry has suffered invalidation, so re-look-up the type name
7060 * if possible, and then recheck the type OID. If we don't have a
7061 * TypeName, then we just have to soldier on with the OID we've got.
7062 */
7063 if (typ->origtypname != NULL)
7064 {
7065 /* this bit should match parse_datatype() in pl_gram.y */
7066 typenameTypeIdAndMod(NULL, typ->origtypname,
7067 &typ->typoid,
7068 &typ->atttypmod);
7069 }
7070
7071 /* this bit should match build_datatype() in pl_comp.c */
7072 typentry = lookup_type_cache(typ->typoid,
7075 if (typentry->typtype == TYPTYPE_DOMAIN)
7076 typentry = lookup_type_cache(typentry->domainBaseType,
7078 if (typentry->tupDesc == NULL)
7079 {
7080 /*
7081 * If we get here, user tried to replace a composite type with a
7082 * non-composite one. We're not gonna support that.
7083 */
7084 ereport(ERROR,
7086 errmsg("type %s is not composite",
7087 format_type_be(typ->typoid))));
7088 }
7089
7090 /*
7091 * Update tcache and tupdesc_id. Since we don't support changing to a
7092 * non-composite type, none of the rest of *typ needs to change.
7093 */
7094 typ->tcache = typentry;
7095 typ->tupdesc_id = typentry->tupDesc_identifier;
7096
7097 /*
7098 * Update *rec, too. (We'll deal with subsidiary RECFIELDs as needed.)
7099 */
7100 rec->rectypeid = typ->typoid;
7101}

References Assert, PLpgSQL_rec::datatype, TypeCacheEntry::domainBaseType, ereport, errcode(), errmsg(), ERROR, fb(), format_type_be(), lookup_type_cache(), PLpgSQL_rec::rectypeid, TypeCacheEntry::tupDesc, TypeCacheEntry::tupDesc_identifier, TYPECACHE_DOMAIN_BASE_INFO, TYPECACHE_TUPDESC, typenameTypeIdAndMod(), and TypeCacheEntry::typtype.

Referenced by exec_move_row_from_datum(), instantiate_empty_record_variable(), and make_expanded_record_for_rec().

◆ setup_param_list()

static ParamListInfo setup_param_list ( PLpgSQL_execstate estate,
PLpgSQL_expr expr 
)
static

Definition at line 6249 of file pl_exec.c.

6250{
6251 ParamListInfo paramLI;
6252
6253 /*
6254 * We must have created the SPIPlan already (hence, query text has been
6255 * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
6256 */
6257 Assert(expr->plan != NULL);
6258
6259 /*
6260 * We only need a ParamListInfo if the expression has parameters.
6261 */
6262 if (!bms_is_empty(expr->paramnos))
6263 {
6264 /* Use the common ParamListInfo */
6265 paramLI = estate->paramLI;
6266
6267 /*
6268 * Set up link to active expr where the hook functions can find it.
6269 * Callers must save and restore parserSetupArg if there is any chance
6270 * that they are interrupting an active use of parameters.
6271 */
6272 paramLI->parserSetupArg = expr;
6273 }
6274 else
6275 {
6276 /*
6277 * Expression requires no parameters. Be sure we represent this case
6278 * as a NULL ParamListInfo, so that plancache.c knows there is no
6279 * point in a custom plan.
6280 */
6281 paramLI = NULL;
6282 }
6283 return paramLI;
6284}

References Assert, bms_is_empty, fb(), PLpgSQL_execstate::paramLI, PLpgSQL_expr::paramnos, ParamListInfoData::parserSetupArg, and PLpgSQL_expr::plan.

Referenced by exec_run_select(), exec_stmt_call(), exec_stmt_execsql(), exec_stmt_forc(), exec_stmt_open(), and exec_stmt_return_query().

Variable Documentation

◆ cast_expr_hash

HTAB* cast_expr_hash = NULL
static

Definition at line 178 of file pl_exec.c.

Referenced by get_cast_hashentry(), and plpgsql_estate_setup().

◆ shared_cast_hash

HTAB* shared_cast_hash = NULL
static

Definition at line 179 of file pl_exec.c.

Referenced by plpgsql_estate_setup().

◆ shared_simple_eval_estate

EState* shared_simple_eval_estate = NULL
static

Definition at line 91 of file pl_exec.c.

Referenced by plpgsql_create_econtext(), plpgsql_estate_setup(), and plpgsql_xact_cb().

◆ shared_simple_eval_resowner

ResourceOwner shared_simple_eval_resowner = NULL
static

Definition at line 102 of file pl_exec.c.

Referenced by plpgsql_create_econtext(), plpgsql_estate_setup(), and plpgsql_xact_cb().

◆ simple_econtext_stack

SimpleEcontextStackEntry* simple_econtext_stack = NULL
static