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

3744 { \
3745 if (opt) \
3746 ereport(ERROR, \
3748 errmsg("RAISE option already specified: %s", \
3749 name))); \
3750 opt = MemoryContextStrdup(stmt_mcontext, extval); \
3751} 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 8956 of file pl_exec.c.

8958{
8960
8961 /* Transfer new record object into datum_context */
8963
8964 /* Free the old value ... */
8965 if (rec->erh)
8967
8968 /* ... and install the new */
8969 rec->erh = erh;
8970}

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 8880 of file pl_exec.c.

8882{
8883 Assert(var->dtype == PLPGSQL_DTYPE_VAR ||
8885
8886 /*
8887 * In non-atomic contexts, we do not want to store TOAST pointers in
8888 * variables, because such pointers might become stale after a commit.
8889 * Forcibly detoast in such cases. We don't want to detoast (flatten)
8890 * expanded objects, however; those should be OK across a transaction
8891 * boundary since they're just memory-resident objects. (Elsewhere in
8892 * this module, operations on expanded records likewise need to request
8893 * detoasting of record fields when !estate->atomic. Expanded arrays are
8894 * not a problem since all array entries are always detoasted.)
8895 */
8896 if (!estate->atomic && !isnull && var->datatype->typlen == -1 &&
8898 {
8901
8902 /*
8903 * Do the detoasting in the eval_mcontext to avoid long-term leakage
8904 * of whatever memory toast fetching might leak. Then we have to copy
8905 * the detoasted datum to the function's main context, which is a
8906 * pain, but there's little choice.
8907 */
8911 /* Now's a good time to not leak the input value if it's freeable */
8912 if (freeable)
8914 /* Once we copy the value, it's definitely freeable */
8915 newvalue = datumCopy(detoasted, false, -1);
8916 freeable = true;
8917 /* Can't clean up eval_mcontext here, but it'll happen before long */
8918 }
8919
8920 /* Free the old value if needed */
8921 if (var->freeval)
8922 {
8924 var->isnull,
8925 var->datatype->typlen))
8927 else
8929 }
8930 /* Assign new value to datum */
8931 var->value = newvalue;
8932 var->isnull = isnull;
8933 var->freeval = freeable;
8934
8935 /*
8936 * If it's a promise variable, then either we just assigned the promised
8937 * value, or the user explicitly assigned an overriding value. Either
8938 * way, cancel the promise.
8939 */
8941}

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 8947 of file pl_exec.c.

8948{
8949 assign_simple_var(estate, var, CStringGetTextDatum(str), false, true);
8950}

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 825 of file pl_exec.c.

826{
829 TupleConversionMap *tupmap;
830
831 /* We assume exec_stmt_return verified that result is composite */
833
834 /* We can special-case expanded records for speed */
836 {
838
839 Assert(erh->er_magic == ER_MAGIC);
840
841 /* Extract record's TupleDesc */
843
844 /* check rowtype compatibility */
846 tupdesc,
847 gettext_noop("returned record type does not match expected record type"));
848
849 /* it might need conversion */
850 if (tupmap)
851 {
853 Assert(rettup);
855
856 /*
857 * Copy tuple to upper executor memory, as a tuple Datum. Make
858 * sure it is labeled with the caller-supplied tuple type.
859 */
860 estate->retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
861 /* no need to free map, we're about to return anyway */
862 }
863 else if (!(tupdesc->tdtypeid == erh->er_decltypeid ||
864 (tupdesc->tdtypeid == RECORDOID &&
866 {
867 /*
868 * The expanded record has the right physical tupdesc, but the
869 * wrong type ID. (Typically, the expanded record is RECORDOID
870 * but the function is declared to return a named composite type.
871 * As in exec_move_row_from_datum, we don't allow returning a
872 * composite-domain record from a function declared to return
873 * RECORD.) So we must flatten the record to a tuple datum and
874 * overwrite its type fields with the right thing. spi.c doesn't
875 * provide any easy way to deal with this case, so we end up
876 * duplicating the guts of datumCopy() :-(
877 */
879 HeapTupleHeader tuphdr;
880
883 EOH_flatten_into(&erh->hdr, tuphdr, resultsize);
884 HeapTupleHeaderSetTypeId(tuphdr, tupdesc->tdtypeid);
885 HeapTupleHeaderSetTypMod(tuphdr, tupdesc->tdtypmod);
886 estate->retval = PointerGetDatum(tuphdr);
887 }
888 else
889 {
890 /*
891 * We need only copy result into upper executor memory context.
892 * However, if we have a R/W expanded datum, we can just transfer
893 * its ownership out to the upper executor context.
894 */
895 estate->retval = SPI_datumTransfer(estate->retval,
896 false,
897 -1);
898 }
899 }
900 else
901 {
902 /* Convert composite datum to a HeapTuple and TupleDesc */
904
906 rettup = &tmptup;
907
908 /* check rowtype compatibility */
910 tupdesc,
911 gettext_noop("returned record type does not match expected record type"));
912
913 /* it might need conversion */
914 if (tupmap)
916
917 /*
918 * Copy tuple to upper executor memory, as a tuple Datum. Make sure
919 * it is labeled with the caller-supplied tuple type.
920 */
921 estate->retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
922
923 /* no need to free map, we're about to return anyway */
924
926 }
927}

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 7548 of file pl_exec.c.

7549{
7550 int i;
7551
7552 /* Possibly we could allow src_tupdesc to have extra columns? */
7553 if (dst_tupdesc->natts != src_tupdesc->natts)
7554 return false;
7555
7556 for (i = 0; i < dst_tupdesc->natts; i++)
7557 {
7560
7561 if (dattr->attisdropped != sattr->attisdropped)
7562 return false;
7563 if (!dattr->attisdropped)
7564 {
7565 /* Normal columns must match by type and typmod */
7566 if (dattr->atttypid != sattr->atttypid ||
7567 (dattr->atttypmod >= 0 &&
7568 dattr->atttypmod != sattr->atttypmod))
7569 return false;
7570 }
7571 else
7572 {
7573 /* Dropped columns are OK as long as length/alignment match */
7574 if (dattr->attlen != sattr->attlen ||
7575 dattr->attalign != sattr->attalign)
7576 return false;
7577 }
7578 }
7579 return true;
7580}

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

◆ copy_plpgsql_datums()

static void copy_plpgsql_datums ( PLpgSQL_execstate estate,
PLpgSQL_function func 
)
static

Definition at line 1342 of file pl_exec.c.

1344{
1345 int ndatums = estate->ndatums;
1348 char *workspace;
1349 char *ws_next;
1350 int i;
1351
1352 /* Allocate local datum-pointer array */
1353 estate->datums = palloc_array(PLpgSQL_datum *, ndatums);
1354
1355 /*
1356 * To reduce palloc overhead, we make a single palloc request for all the
1357 * space needed for locally-instantiated datums.
1358 */
1359 workspace = palloc(func->copiable_size);
1360 ws_next = workspace;
1361
1362 /* Fill datum-pointer array, copying datums into workspace as needed */
1363 indatums = func->datums;
1364 outdatums = estate->datums;
1365 for (i = 0; i < ndatums; i++)
1366 {
1369
1370 /* This must agree with plpgsql_finish_datums on what is copiable */
1371 switch (indatum->dtype)
1372 {
1373 case PLPGSQL_DTYPE_VAR:
1377 ws_next += MAXALIGN(sizeof(PLpgSQL_var));
1378 break;
1379
1380 case PLPGSQL_DTYPE_REC:
1383 ws_next += MAXALIGN(sizeof(PLpgSQL_rec));
1384 break;
1385
1386 case PLPGSQL_DTYPE_ROW:
1388
1389 /*
1390 * These datum records are read-only at runtime, so no need to
1391 * copy them (well, RECFIELD contains cached data, but we'd
1392 * just as soon centralize the caching anyway).
1393 */
1394 outdatum = indatum;
1395 break;
1396
1397 default:
1398 elog(ERROR, "unrecognized dtype: %d", indatum->dtype);
1399 outdatum = NULL; /* keep compiler quiet */
1400 break;
1401 }
1402
1403 outdatums[i] = outdatum;
1404 }
1405
1406 Assert(ws_next == workspace + func->copiable_size);
1407}

References Assert, PLpgSQL_function::copiable_size, PLpgSQL_function::datums, PLpgSQL_execstate::datums, elog, ERROR, fb(), i, MAXALIGN, memcpy(), 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 8632 of file pl_exec.c.

8633{
8634 if (node == NULL)
8635 return false;
8636 else if (IsA(node, Param))
8637 {
8638 Param *param = (Param *) node;
8639
8640 if (param->paramkind == PARAM_EXTERN &&
8641 param->paramid == context->paramid)
8642 {
8643 context->last_param = param;
8644 if (++(context->count) > 1)
8645 return true; /* abort tree traversal */
8646 }
8647 return false;
8648 }
8649 else
8650 return expression_tree_walker(node, count_param_references, context);
8651}

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 7647 of file pl_exec.c.

7648{
7649 HeapTupleHeader td;
7650 Oid tupType;
7652
7653 /* Get tuple body (note this could involve detoasting) */
7655
7656 /* Build a temporary HeapTuple control structure */
7658 ItemPointerSetInvalid(&(tmptup->t_self));
7659 tmptup->t_tableOid = InvalidOid;
7660 tmptup->t_data = td;
7661
7662 /* Extract rowtype info and find a tupdesc */
7666}

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 7999 of file pl_exec.c.

8003{
8005
8009 if (cast_entry)
8010 {
8011 ExprContext *econtext = estate->eval_econtext;
8012 MemoryContext oldcontext;
8013
8014 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8015
8016 econtext->caseValue_datum = value;
8017 econtext->caseValue_isNull = *isnull;
8018
8019 cast_entry->cast_in_use = true;
8020
8021 value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
8022 isnull);
8023
8024 cast_entry->cast_in_use = false;
8025
8026 MemoryContextSwitchTo(oldcontext);
8027 }
8028
8029 return value;
8030}

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 1626 of file pl_exec.c.

1627{
1628 for (; cond != NULL; cond = cond->next)
1629 {
1630 int sqlerrstate = cond->sqlerrstate;
1631
1632 /*
1633 * OTHERS matches everything *except* query-canceled and
1634 * assert-failure. If you're foolish enough, you can match those
1635 * explicitly.
1636 */
1637 if (sqlerrstate == PLPGSQL_OTHERS)
1638 {
1639 if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED &&
1640 edata->sqlerrcode != ERRCODE_ASSERT_FAILURE)
1641 return true;
1642 }
1643 /* Exact match? */
1644 else if (edata->sqlerrcode == sqlerrstate)
1645 return true;
1646 /* Category match? */
1647 else if (ERRCODE_IS_CATEGORY(sqlerrstate) &&
1648 ERRCODE_TO_CATEGORY(edata->sqlerrcode) == sqlerrstate)
1649 return true;
1650 }
1651 return false;
1652}

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 5134 of file pl_exec.c.

5136{
5137 text *value;
5138 MemoryContext oldcontext;
5139
5140 /* Use eval_mcontext for short-lived text value */
5141 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5142 if (str != NULL)
5144 else
5145 value = cstring_to_text("");
5146 MemoryContextSwitchTo(oldcontext);
5147
5148 exec_assign_value(estate, target, PointerGetDatum(value), false,
5149 TEXTOID, -1);
5150}

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 5104 of file pl_exec.c.

5106{
5107 Datum value;
5108 bool isnull;
5109 Oid valtype;
5111
5112 /*
5113 * If first time through, create a plan for this expression.
5114 */
5115 if (expr->plan == NULL)
5116 exec_prepare_plan(estate, expr, 0);
5117
5118 value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
5119 exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
5120 exec_eval_cleanup(estate);
5121}

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 5162 of file pl_exec.c.

5166{
5167 switch (target->dtype)
5168 {
5169 case PLPGSQL_DTYPE_VAR:
5171 {
5172 /*
5173 * Target is a variable
5174 */
5175 PLpgSQL_var *var = (PLpgSQL_var *) target;
5177
5178 newvalue = exec_cast_value(estate,
5179 value,
5180 &isNull,
5181 valtype,
5182 valtypmod,
5183 var->datatype->typoid,
5184 var->datatype->atttypmod);
5185
5186 if (isNull && var->notnull)
5187 ereport(ERROR,
5189 errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
5190 var->refname)));
5191
5192 /*
5193 * If type is by-reference, copy the new value (which is
5194 * probably in the eval_mcontext) into the procedure's main
5195 * memory context. But if it's a read/write reference to an
5196 * expanded object, no physical copy needs to happen; at most
5197 * we need to reparent the object's memory context.
5198 *
5199 * If it's an array, we force the value to be stored in R/W
5200 * expanded form. This wins if the function later does, say,
5201 * a lot of array subscripting operations on the variable, and
5202 * otherwise might lose. We might need to use a different
5203 * heuristic, but it's too soon to tell. Also, are there
5204 * cases where it'd be useful to force non-array values into
5205 * expanded form?
5206 */
5207 if (!var->datatype->typbyval && !isNull)
5208 {
5209 if (var->datatype->typisarray &&
5211 {
5212 /* array and not already R/W, so apply expand_array */
5214 estate->datum_context,
5215 NULL);
5216 }
5217 else
5218 {
5219 /* else transfer value if R/W, else just datumCopy */
5221 false,
5222 var->datatype->typlen);
5223 }
5224 }
5225
5226 /*
5227 * Now free the old value, if any, and assign the new one. But
5228 * skip the assignment if old and new values are the same.
5229 * Note that for expanded objects, this test is necessary and
5230 * cannot reliably be made any earlier; we have to be looking
5231 * at the object's standard R/W pointer to be sure pointer
5232 * equality is meaningful.
5233 *
5234 * Also, if it's a promise variable, we should disarm the
5235 * promise in any case --- otherwise, assigning null to an
5236 * armed promise variable would fail to disarm the promise.
5237 */
5238 if (var->value != newvalue || var->isnull || isNull)
5239 assign_simple_var(estate, var, newvalue, isNull,
5240 (!var->datatype->typbyval && !isNull));
5241 else
5243 break;
5244 }
5245
5246 case PLPGSQL_DTYPE_ROW:
5247 {
5248 /*
5249 * Target is a row variable
5250 */
5251 PLpgSQL_row *row = (PLpgSQL_row *) target;
5252
5253 if (isNull)
5254 {
5255 /* If source is null, just assign nulls to the row */
5256 exec_move_row(estate, (PLpgSQL_variable *) row,
5257 NULL, NULL);
5258 }
5259 else
5260 {
5261 /* Source must be of RECORD or composite type */
5263 ereport(ERROR,
5265 errmsg("cannot assign non-composite value to a row variable")));
5267 value);
5268 }
5269 break;
5270 }
5271
5272 case PLPGSQL_DTYPE_REC:
5273 {
5274 /*
5275 * Target is a record variable
5276 */
5277 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
5278
5279 if (isNull)
5280 {
5281 if (rec->notnull)
5282 ereport(ERROR,
5284 errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
5285 rec->refname)));
5286
5287 /* Set variable to a simple NULL */
5288 exec_move_row(estate, (PLpgSQL_variable *) rec,
5289 NULL, NULL);
5290 }
5291 else
5292 {
5293 /* Source must be of RECORD or composite type */
5295 ereport(ERROR,
5297 errmsg("cannot assign non-composite value to a record variable")));
5299 value);
5300 }
5301 break;
5302 }
5303
5305 {
5306 /*
5307 * Target is a field of a record
5308 */
5310 PLpgSQL_rec *rec;
5312
5313 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5314 erh = rec->erh;
5315
5316 /*
5317 * If record variable is NULL, instantiate it if it has a
5318 * named composite type, else complain. (This won't change
5319 * the logical state of the record, but if we successfully
5320 * assign below, the unassigned fields will all become NULLs.)
5321 */
5322 if (erh == NULL)
5323 {
5325 erh = rec->erh;
5326 }
5327
5328 /*
5329 * Look up the field's properties if we have not already, or
5330 * if the tuple descriptor ID changed since last time.
5331 */
5332 if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
5333 {
5335 recfield->fieldname,
5336 &recfield->finfo))
5337 ereport(ERROR,
5339 errmsg("record \"%s\" has no field \"%s\"",
5340 rec->refname, recfield->fieldname)));
5341 recfield->rectupledescid = erh->er_tupdesc_id;
5342 }
5343
5344 /* We don't support assignments to system columns. */
5345 if (recfield->finfo.fnumber <= 0)
5346 ereport(ERROR,
5348 errmsg("cannot assign to system column \"%s\"",
5349 recfield->fieldname)));
5350
5351 /* Cast the new value to the right type, if needed. */
5352 value = exec_cast_value(estate,
5353 value,
5354 &isNull,
5355 valtype,
5356 valtypmod,
5357 recfield->finfo.ftypeid,
5358 recfield->finfo.ftypmod);
5359
5360 /* And assign it. */
5361 expanded_record_set_field(erh, recfield->finfo.fnumber,
5362 value, isNull, !estate->atomic);
5363 break;
5364 }
5365
5366 default:
5367 elog(ERROR, "unrecognized dtype: %d", target->dtype);
5368 }
5369}

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_execsql(), 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 7975 of file pl_exec.c.

7979{
7980 /*
7981 * If the type of the given value isn't what's requested, convert it.
7982 */
7983 if (valtype != reqtype ||
7984 (valtypmod != reqtypmod && reqtypmod != -1))
7985 {
7986 /* We keep the slow path out-of-line. */
7987 value = do_cast_value(estate, value, isnull, valtype, valtypmod,
7989 }
7990
7991 return value;
7992}

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 8659 of file pl_exec.c.

8660{
8661 PLpgSQL_datum *datum;
8662
8663 Assert(dno >= 0 && dno < estate->ndatums);
8664 datum = estate->datums[dno];
8665 switch (datum->dtype)
8666 {
8667 case PLPGSQL_DTYPE_VAR:
8669 case PLPGSQL_DTYPE_REC:
8670 if (((PLpgSQL_variable *) datum)->isconst)
8671 ereport(ERROR,
8673 errmsg("variable \"%s\" is declared CONSTANT",
8674 ((PLpgSQL_variable *) datum)->refname)));
8675 break;
8676 case PLPGSQL_DTYPE_ROW:
8677 /* always assignable; member vars were checked at compile time */
8678 break;
8680 /* assignable if parent record is */
8681 exec_check_assignable(estate,
8682 ((PLpgSQL_recfield *) datum)->recparentno);
8683 break;
8684 default:
8685 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
8686 break;
8687 }
8688}

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 8502 of file pl_exec.c.

8503{
8504 Expr *sexpr = expr->expr_simple_expr;
8505 Oid funcid;
8506 List *fargs;
8508
8509 /* Assume unsafe */
8511 expr->expr_rw_param = NULL;
8512
8513 /* Shouldn't be here for non-simple expression */
8514 Assert(sexpr != NULL);
8515
8516 /* Param should match the expression's assignment target, too */
8517 Assert(paramid == expr->target_param + 1);
8518
8519 /*
8520 * If the assignment is to a "local" variable (one whose value won't
8521 * matter anymore if expression evaluation fails), and this Param is the
8522 * only reference to that variable in the expression, then we can
8523 * unconditionally optimize using the "transfer" method.
8524 */
8525 if (expr->target_is_local)
8526 {
8528
8529 /* See how many references there are, and find one of them */
8530 context.paramid = paramid;
8531 context.count = 0;
8532 context.last_param = NULL;
8533 (void) count_param_references((Node *) sexpr, &context);
8534
8535 /* If we're here, the expr must contain some reference to the var */
8536 Assert(context.count > 0);
8537
8538 /* If exactly one reference, success! */
8539 if (context.count == 1)
8540 {
8542 expr->expr_rw_param = context.last_param;
8543 return;
8544 }
8545 }
8546
8547 /*
8548 * Otherwise, see if we can trust the expression's top-level function to
8549 * apply the "inplace" method.
8550 *
8551 * Top level of expression must be a simple FuncExpr, OpExpr, or
8552 * SubscriptingRef, else we can't identify which function is relevant. But
8553 * it's okay to look through any RelabelType above that, since that can't
8554 * fail.
8555 */
8556 if (IsA(sexpr, RelabelType))
8557 sexpr = ((RelabelType *) sexpr)->arg;
8558 if (IsA(sexpr, FuncExpr))
8559 {
8561
8562 funcid = fexpr->funcid;
8563 fargs = fexpr->args;
8564 }
8565 else if (IsA(sexpr, OpExpr))
8566 {
8567 OpExpr *opexpr = (OpExpr *) sexpr;
8568
8569 funcid = opexpr->opfuncid;
8570 fargs = opexpr->args;
8571 }
8572 else if (IsA(sexpr, SubscriptingRef))
8573 {
8575
8576 funcid = get_typsubscript(sbsref->refcontainertype, NULL);
8577
8578 /*
8579 * We assume that only the refexpr and refassgnexpr (if any) are
8580 * relevant to the support function's decision. If that turns out to
8581 * be a bad idea, we could incorporate the subscript expressions into
8582 * the fargs list somehow.
8583 */
8584 fargs = list_make2(sbsref->refexpr, sbsref->refassgnexpr);
8585 }
8586 else
8587 return;
8588
8589 /*
8590 * The top-level function must be one that can handle in-place update
8591 * safely. We allow functions to declare their ability to do that via a
8592 * support function request.
8593 */
8594 prosupport = get_func_support(funcid);
8596 {
8598 Param *param;
8599
8601 req.funcid = funcid;
8602 req.args = fargs;
8603 req.paramid = paramid;
8604
8605 param = (Param *)
8607 PointerGetDatum(&req)));
8608
8609 if (param == NULL)
8610 return; /* support function fails */
8611
8612 /* Verify support function followed the API */
8613 Assert(IsA(param, Param));
8614 Assert(param->paramkind == PARAM_EXTERN);
8615 Assert(param->paramid == paramid);
8616
8617 /* Found the Param we want to pass as read/write */
8619 expr->expr_rw_param = param;
8620 return;
8621 }
8622}

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 9061 of file pl_exec.c.

9066{
9067 Portal portal;
9068 Datum query;
9069 bool isnull;
9070 Oid restype;
9072 char *querystr;
9074 MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
9075
9076 /*
9077 * Evaluate the string expression after the EXECUTE keyword. Its result is
9078 * the querystring we have to execute.
9079 */
9080 query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod);
9081 if (isnull)
9082 ereport(ERROR,
9084 errmsg("query string argument of EXECUTE is null")));
9085
9086 /* Get the C-String representation */
9087 querystr = convert_value_to_string(estate, query, restype);
9088
9089 /* copy it into the stmt_mcontext before we clean up */
9090 querystr = MemoryContextStrdup(stmt_mcontext, querystr);
9091
9092 exec_eval_cleanup(estate);
9093
9094 /*
9095 * Open an implicit cursor for the query. We use SPI_cursor_parse_open
9096 * even when there are no params, because this avoids making and freeing
9097 * one copy of the plan.
9098 */
9099 memset(&options, 0, sizeof(options));
9100 options.params = exec_eval_using_params(estate, params);
9101 options.cursorOptions = cursorOptions;
9102 options.read_only = estate->readonly_func;
9103
9104 portal = SPI_cursor_parse_open(portalname, querystr, &options);
9105
9106 if (portal == NULL)
9107 elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
9109
9110 /* Release transient data */
9111 MemoryContextReset(stmt_mcontext);
9112
9113 return portal;
9114}

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 5743 of file pl_exec.c.

5746{
5750
5751 exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5752 exprdatum = exec_cast_value(estate, exprdatum, isNull,
5754 BOOLOID, -1);
5755 return DatumGetBool(exprdatum);
5756}

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 5389 of file pl_exec.c.

5395{
5396 MemoryContext oldcontext;
5397
5398 switch (datum->dtype)
5399 {
5401 /* fulfill promise if needed, then handle like regular var */
5402 plpgsql_fulfill_promise(estate, (PLpgSQL_var *) datum);
5403
5405
5406 case PLPGSQL_DTYPE_VAR:
5407 {
5408 PLpgSQL_var *var = (PLpgSQL_var *) datum;
5409
5410 *typeid = var->datatype->typoid;
5411 *typetypmod = var->datatype->atttypmod;
5412 *value = var->value;
5413 *isnull = var->isnull;
5414 break;
5415 }
5416
5417 case PLPGSQL_DTYPE_ROW:
5418 {
5419 PLpgSQL_row *row = (PLpgSQL_row *) datum;
5420 HeapTuple tup;
5421
5422 /* We get here if there are multiple OUT parameters */
5423 if (!row->rowtupdesc) /* should not happen */
5424 elog(ERROR, "row variable has no tupdesc");
5425 /* Make sure we have a valid type/typmod setting */
5427 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5428 tup = make_tuple_from_row(estate, row, row->rowtupdesc);
5429 if (tup == NULL) /* should not happen */
5430 elog(ERROR, "row not compatible with its own tupdesc");
5431 *typeid = row->rowtupdesc->tdtypeid;
5434 *isnull = false;
5435 MemoryContextSwitchTo(oldcontext);
5436 break;
5437 }
5438
5439 case PLPGSQL_DTYPE_REC:
5440 {
5441 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5442
5443 if (rec->erh == NULL)
5444 {
5445 /* Treat uninstantiated record as a simple NULL */
5446 *value = (Datum) 0;
5447 *isnull = true;
5448 /* Report variable's declared type */
5449 *typeid = rec->rectypeid;
5450 *typetypmod = -1;
5451 }
5452 else
5453 {
5454 if (ExpandedRecordIsEmpty(rec->erh))
5455 {
5456 /* Empty record is also a NULL */
5457 *value = (Datum) 0;
5458 *isnull = true;
5459 }
5460 else
5461 {
5463 *isnull = false;
5464 }
5465 if (rec->rectypeid != RECORDOID)
5466 {
5467 /* Report variable's declared type, if not RECORD */
5468 *typeid = rec->rectypeid;
5469 *typetypmod = -1;
5470 }
5471 else
5472 {
5473 /* Report record's actual type if declared RECORD */
5474 *typeid = rec->erh->er_typeid;
5475 *typetypmod = rec->erh->er_typmod;
5476 }
5477 }
5478 break;
5479 }
5480
5482 {
5484 PLpgSQL_rec *rec;
5486
5487 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5488 erh = rec->erh;
5489
5490 /*
5491 * If record variable is NULL, instantiate it if it has a
5492 * named composite type, else complain. (This won't change
5493 * the logical state of the record: it's still NULL.)
5494 */
5495 if (erh == NULL)
5496 {
5498 erh = rec->erh;
5499 }
5500
5501 /*
5502 * Look up the field's properties if we have not already, or
5503 * if the tuple descriptor ID changed since last time.
5504 */
5505 if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
5506 {
5508 recfield->fieldname,
5509 &recfield->finfo))
5510 ereport(ERROR,
5512 errmsg("record \"%s\" has no field \"%s\"",
5513 rec->refname, recfield->fieldname)));
5514 recfield->rectupledescid = erh->er_tupdesc_id;
5515 }
5516
5517 /* Report type data. */
5518 *typeid = recfield->finfo.ftypeid;
5519 *typetypmod = recfield->finfo.ftypmod;
5520
5521 /* And fetch the field value. */
5523 recfield->finfo.fnumber,
5524 isnull);
5525 break;
5526 }
5527
5528 default:
5529 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5530 }
5531}

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 5766 of file pl_exec.c.

5771{
5772 Datum result = 0;
5773 int rc;
5774 Form_pg_attribute attr;
5775
5776 /*
5777 * If first time through, create a plan for this expression.
5778 */
5779 if (expr->plan == NULL)
5781
5782 /*
5783 * If this is a simple expression, bypass SPI and use the executor
5784 * directly
5785 */
5786 if (exec_eval_simple_expr(estate, expr,
5787 &result, isNull, rettype, rettypmod))
5788 return result;
5789
5790 /*
5791 * Else do it the hard way via exec_run_select
5792 */
5793 rc = exec_run_select(estate, expr, 0, NULL);
5794 if (rc != SPI_OK_SELECT)
5795 ereport(ERROR,
5797 errmsg("query did not return data"),
5798 errcontext("query: %s", expr->query)));
5799
5800 /*
5801 * Check that the expression returns exactly one column...
5802 */
5803 if (estate->eval_tuptable->tupdesc->natts != 1)
5804 ereport(ERROR,
5806 errmsg_plural("query returned %d column",
5807 "query returned %d columns",
5808 estate->eval_tuptable->tupdesc->natts,
5809 estate->eval_tuptable->tupdesc->natts),
5810 errcontext("query: %s", expr->query)));
5811
5812 /*
5813 * ... and get the column's datatype.
5814 */
5815 attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0);
5816 *rettype = attr->atttypid;
5817 *rettypmod = attr->atttypmod;
5818
5819 /*
5820 * If there are no rows selected, the result is a NULL of that type.
5821 */
5822 if (estate->eval_processed == 0)
5823 {
5824 *isNull = true;
5825 return (Datum) 0;
5826 }
5827
5828 /*
5829 * Check that the expression returned no more than one row.
5830 */
5831 if (estate->eval_processed != 1)
5832 ereport(ERROR,
5834 errmsg("query returned more than one row"),
5835 errcontext("query: %s", expr->query)));
5836
5837 /*
5838 * Return the single result Datum.
5839 */
5840 return SPI_getbinval(estate->eval_tuptable->vals[0],
5841 estate->eval_tuptable->tupdesc, 1, isNull);
5842}

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, result, 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_execsql(), 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 5720 of file pl_exec.c.

5723{
5727
5728 exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5729 exprdatum = exec_cast_value(estate, exprdatum, isNull,
5731 INT4OID, -1);
5732 return DatumGetInt32(exprdatum);
5733}

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 6120 of file pl_exec.c.

6126{
6127 ExprContext *econtext = estate->eval_econtext;
6129 ParamListInfo paramLI;
6130 void *save_setup_arg;
6131 bool need_snapshot;
6132 MemoryContext oldcontext;
6133
6134 /*
6135 * Forget it if expression wasn't simple before.
6136 */
6137 if (expr->expr_simple_expr == NULL)
6138 return false;
6139
6140 /*
6141 * If expression is in use in current xact, don't touch it.
6142 */
6143 if (unlikely(expr->expr_simple_in_use) &&
6144 expr->expr_simple_lxid == curlxid)
6145 return false;
6146
6147 /*
6148 * Ensure that there's a portal-level snapshot, in case this simple
6149 * expression is the first thing evaluated after a COMMIT or ROLLBACK.
6150 * We'd have to do this anyway before executing the expression, so we
6151 * might as well do it now to ensure that any possible replanning doesn't
6152 * need to take a new snapshot.
6153 */
6155
6156 /*
6157 * Check to see if the cached plan has been invalidated. If not, and this
6158 * is the first use in the current transaction, save a plan refcount in
6159 * the simple-expression resowner.
6160 */
6162 expr->expr_simple_plan,
6163 (expr->expr_simple_plan_lxid != curlxid ?
6164 estate->simple_eval_resowner : NULL))))
6165 {
6166 /*
6167 * It's still good, so just remember that we have a refcount on the
6168 * plan in the current transaction. (If we already had one, this
6169 * assignment is a no-op.)
6170 */
6172 }
6173 else
6174 {
6175 /* Need to replan */
6176 CachedPlan *cplan;
6177
6178 /*
6179 * If we have a valid refcount on some previous version of the plan,
6180 * release it, so we don't leak plans intra-transaction.
6181 */
6182 if (expr->expr_simple_plan_lxid == curlxid)
6184 estate->simple_eval_resowner);
6185
6186 /*
6187 * Reset to "not simple" to leave sane state (with no dangling
6188 * pointers) in case we fail while replanning. We'll need to
6189 * re-determine simplicity and R/W optimizability anyway, since those
6190 * could change with the new plan. expr_simple_plansource can be left
6191 * alone however, as that cannot move.
6192 */
6193 expr->expr_simple_expr = NULL;
6195 expr->expr_rw_param = NULL;
6196 expr->expr_simple_plan = NULL;
6198
6199 /* Do the replanning work in the eval_mcontext */
6200 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6201 cplan = SPI_plan_get_cached_plan(expr->plan);
6202 MemoryContextSwitchTo(oldcontext);
6203
6204 /*
6205 * We can't get a failure here, because the number of
6206 * CachedPlanSources in the SPI plan can't change from what
6207 * exec_simple_check_plan saw; it's a property of the raw parsetree
6208 * generated from the query text.
6209 */
6210 Assert(cplan != NULL);
6211
6212 /*
6213 * Recheck exec_is_simple_query, which could now report false in
6214 * edge-case scenarios such as a non-SRF having been replaced with a
6215 * SRF. Also recheck CachedPlanAllowsSimpleValidityCheck, just to be
6216 * sure. If either test fails, cope by declaring the plan to be
6217 * non-simple. On success, we'll acquire a refcount on the new plan,
6218 * stored in simple_eval_resowner.
6219 */
6220 if (exec_is_simple_query(expr) &&
6222 cplan,
6223 estate->simple_eval_resowner))
6224 {
6225 /* Remember that we have the refcount */
6226 expr->expr_simple_plan = cplan;
6228 }
6229 else
6230 {
6231 /* Release SPI_plan_get_cached_plan's refcount */
6233 return false;
6234 }
6235
6236 /*
6237 * SPI_plan_get_cached_plan acquired a plan refcount stored in the
6238 * active resowner. We don't need that anymore, so release it.
6239 */
6241
6242 /* Extract desired scalar expression from cached plan */
6243 exec_save_simple_expr(expr, cplan);
6244 }
6245
6246 /*
6247 * Pass back previously-determined result type.
6248 */
6249 *rettype = expr->expr_simple_type;
6251
6252 /*
6253 * Set up ParamListInfo to pass to executor. For safety, save and restore
6254 * estate->paramLI->parserSetupArg around our use of the param list.
6255 */
6256 paramLI = estate->paramLI;
6257 save_setup_arg = paramLI->parserSetupArg;
6258
6259 /*
6260 * We can skip using setup_param_list() in favor of just doing this
6261 * unconditionally, because there's no need for the optimization of
6262 * possibly setting ecxt_param_list_info to NULL; we've already forced use
6263 * of a generic plan.
6264 */
6265 paramLI->parserSetupArg = expr;
6266 econtext->ecxt_param_list_info = paramLI;
6267
6268 /*
6269 * Prepare the expression for execution, if it's not been done already in
6270 * the current transaction. (This will be forced to happen if we called
6271 * exec_save_simple_expr above.)
6272 */
6273 if (unlikely(expr->expr_simple_lxid != curlxid))
6274 {
6276 expr->expr_simple_state =
6278 econtext->ecxt_param_list_info);
6279 expr->expr_simple_in_use = false;
6280 expr->expr_simple_lxid = curlxid;
6281 MemoryContextSwitchTo(oldcontext);
6282 }
6283
6284 /*
6285 * We have to do some of the things SPI_execute_plan would do, in
6286 * particular push a new snapshot so that stable functions within the
6287 * expression can see updates made so far by our own function. However,
6288 * we can skip doing that (and just invoke the expression with the same
6289 * snapshot passed to our function) in some cases, which is useful because
6290 * it's quite expensive relative to the cost of a simple expression. We
6291 * can skip it if the expression contains no stable or volatile functions;
6292 * immutable functions shouldn't need to see our updates. Also, if this
6293 * is a read-only function, we haven't made any updates so again it's okay
6294 * to skip.
6295 */
6296 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6297 need_snapshot = (expr->expr_simple_mutable && !estate->readonly_func);
6298 if (need_snapshot)
6299 {
6302 }
6303
6304 /*
6305 * Mark expression as busy for the duration of the ExecEvalExpr call.
6306 */
6307 expr->expr_simple_in_use = true;
6308
6309 /*
6310 * Finally we can call the executor to evaluate the expression
6311 */
6313 econtext,
6314 isNull);
6315
6316 /* Assorted cleanup */
6317 expr->expr_simple_in_use = false;
6318
6319 econtext->ecxt_param_list_info = NULL;
6320
6321 paramLI->parserSetupArg = save_setup_arg;
6322
6323 if (need_snapshot)
6325
6326 MemoryContextSwitchTo(oldcontext);
6327
6328 /*
6329 * That's it.
6330 */
6331 return true;
6332}

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(), result, 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 8979 of file pl_exec.c.

8980{
8981 ParamListInfo paramLI;
8982 int nargs;
8983 MemoryContext stmt_mcontext;
8984 MemoryContext oldcontext;
8985 int i;
8986 ListCell *lc;
8987
8988 /* Fast path for no parameters: we can just return NULL */
8989 if (params == NIL)
8990 return NULL;
8991
8992 nargs = list_length(params);
8993 stmt_mcontext = get_stmt_mcontext(estate);
8994 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
8995 paramLI = makeParamList(nargs);
8996 MemoryContextSwitchTo(oldcontext);
8997
8998 i = 0;
8999 foreach(lc, params)
9000 {
9001 PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
9002 ParamExternData *prm = &paramLI->params[i];
9004
9005 /*
9006 * Always mark params as const, since we only use the result with
9007 * one-shot plans.
9008 */
9010
9011 prm->value = exec_eval_expr(estate, param,
9012 &prm->isnull,
9013 &prm->ptype,
9014 &ppdtypmod);
9015
9016 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
9017
9018 if (prm->ptype == UNKNOWNOID)
9019 {
9020 /*
9021 * Treat 'unknown' parameters as text, since that's what most
9022 * people would expect. The SPI functions can coerce unknown
9023 * constants in a more intelligent way, but not unknown Params.
9024 * This code also takes care of copying into the right context.
9025 * Note we assume 'unknown' has the representation of C-string.
9026 */
9027 prm->ptype = TEXTOID;
9028 if (!prm->isnull)
9029 prm->value = CStringGetTextDatum(DatumGetCString(prm->value));
9030 }
9031 /* pass-by-ref non null values must be copied into stmt_mcontext */
9032 else if (!prm->isnull)
9033 {
9034 int16 typLen;
9035 bool typByVal;
9036
9037 get_typlenbyval(prm->ptype, &typLen, &typByVal);
9038 if (!typByVal)
9039 prm->value = datumCopy(prm->value, typByVal, typLen);
9040 }
9041
9042 MemoryContextSwitchTo(oldcontext);
9043
9044 exec_eval_cleanup(estate);
9045
9046 i++;
9047 }
9048
9049 return paramLI;
9050}

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 5938 of file pl_exec.c.

5940{
5941 PLpgSQL_variable *var;
5943 bool found = false;
5944 int rc = PLPGSQL_RC_OK;
5946 bool tupdescs_match = true;
5947 uint64 n;
5948
5949 /* Fetch loop variable's datum entry */
5950 var = (PLpgSQL_variable *) estate->datums[stmt->var->dno];
5951
5952 /*
5953 * Make sure the portal doesn't get closed by the user statements we
5954 * execute.
5955 */
5956 PinPortal(portal);
5957
5958 /*
5959 * In a non-atomic context, we dare not prefetch, even if it would
5960 * otherwise be safe. Aside from any semantic hazards that that might
5961 * create, if we prefetch toasted data and then the user commits the
5962 * transaction, the toast references could turn into dangling pointers.
5963 * (Rows we haven't yet fetched from the cursor are safe, because the
5964 * PersistHoldablePortal mechanism handles this scenario.)
5965 */
5966 if (!estate->atomic)
5967 prefetch_ok = false;
5968
5969 /*
5970 * Fetch the initial tuple(s). If prefetching is allowed then we grab a
5971 * few more rows to avoid multiple trips through executor startup
5972 * overhead.
5973 */
5974 SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1);
5976 n = SPI_processed;
5977
5978 /*
5979 * If the query didn't return any rows, set the target to NULL and fall
5980 * through with found = false.
5981 */
5982 if (n == 0)
5983 {
5984 exec_move_row(estate, var, NULL, tuptab->tupdesc);
5985 exec_eval_cleanup(estate);
5986 }
5987 else
5988 found = true; /* processed at least one tuple */
5989
5990 /*
5991 * Now do the loop
5992 */
5993 while (n > 0)
5994 {
5995 uint64 i;
5996
5997 for (i = 0; i < n; i++)
5998 {
5999 /*
6000 * Assign the tuple to the target. Here, because we know that all
6001 * loop iterations should be assigning the same tupdesc, we can
6002 * optimize away repeated creations of expanded records with
6003 * identical tupdescs. Testing for changes of er_tupdesc_id is
6004 * reliable even if the loop body contains assignments that
6005 * replace the target's value entirely, because it's assigned from
6006 * a process-global counter. The case where the tupdescs don't
6007 * match could possibly be handled more efficiently than this
6008 * coding does, but it's not clear extra effort is worthwhile.
6009 */
6010 if (var->dtype == PLPGSQL_DTYPE_REC)
6011 {
6012 PLpgSQL_rec *rec = (PLpgSQL_rec *) var;
6013
6014 if (rec->erh &&
6015 rec->erh->er_tupdesc_id == previous_id &&
6017 {
6018 /* Only need to assign a new tuple value */
6020 true, !estate->atomic);
6021 }
6022 else
6023 {
6024 /*
6025 * First time through, or var's tupdesc changed in loop,
6026 * or we have to do it the hard way because type coercion
6027 * is needed.
6028 */
6029 exec_move_row(estate, var,
6030 tuptab->vals[i], tuptab->tupdesc);
6031
6032 /*
6033 * Check to see if physical assignment is OK next time.
6034 * Once the tupdesc comparison has failed once, we don't
6035 * bother rechecking in subsequent loop iterations.
6036 */
6037 if (tupdescs_match)
6038 {
6040 (rec->rectypeid == RECORDOID ||
6041 rec->rectypeid == tuptab->tupdesc->tdtypeid ||
6042 compatible_tupdescs(tuptab->tupdesc,
6044 }
6046 }
6047 }
6048 else
6049 exec_move_row(estate, var, tuptab->vals[i], tuptab->tupdesc);
6050
6051 exec_eval_cleanup(estate);
6052
6053 /*
6054 * Execute the statements
6055 */
6056 rc = exec_stmts(estate, stmt->body);
6057
6058 LOOP_RC_PROCESSING(stmt->label, goto loop_exit);
6059 }
6060
6062
6063 /*
6064 * Fetch more tuples. If prefetching is allowed, grab 50 at a time.
6065 */
6066 SPI_cursor_fetch(portal, true, prefetch_ok ? 50 : 1);
6068 n = SPI_processed;
6069 }
6070
6071loop_exit:
6072
6073 /*
6074 * Release last group of tuples (if any)
6075 */
6077
6078 UnpinPortal(portal);
6079
6080 /*
6081 * Set the FOUND variable to indicate the result of executing the loop
6082 * (namely, whether we looped one or more times). This must be set last so
6083 * that it does not interfere with the value of the FOUND variable inside
6084 * the loop processing itself.
6085 */
6086 exec_set_found(estate, found);
6087
6088 return rc;
6089}

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 3702 of file pl_exec.c.

3703{
3704 ReturnSetInfo *rsi = estate->rsi;
3706 ResourceOwner oldowner;
3707
3708 /*
3709 * Check caller can handle a set result in the way we want
3710 */
3711 if (!rsi || !IsA(rsi, ReturnSetInfo))
3712 ereport(ERROR,
3714 errmsg("set-valued function called in context that cannot accept a set")));
3715
3716 if (!(rsi->allowedModes & SFRM_Materialize) ||
3717 rsi->expectedDesc == NULL)
3718 ereport(ERROR,
3720 errmsg("materialize mode required, but it is not allowed in this context")));
3721
3722 /*
3723 * Switch to the right memory context and resource owner for storing the
3724 * tuplestore for return set. If we're within a subtransaction opened for
3725 * an exception-block, for example, we must still create the tuplestore in
3726 * the resource owner that was active when this function was entered, and
3727 * not in the subtransaction resource owner.
3728 */
3730 oldowner = CurrentResourceOwner;
3732
3733 estate->tuple_store =
3735 false, work_mem);
3736
3737 CurrentResourceOwner = oldowner;
3739
3740 estate->tuple_store_desc = rsi->expectedDesc;
3741}

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 8306 of file pl_exec.c.

8307{
8309 CachedPlanSource *plansource;
8310 Query *query;
8311
8312 /*
8313 * We can only test queries that resulted in exactly one CachedPlanSource.
8314 */
8316 if (list_length(plansources) != 1)
8317 return false;
8318 plansource = (CachedPlanSource *) linitial(plansources);
8319
8320 /*
8321 * 1. There must be one single querytree.
8322 */
8323 if (list_length(plansource->query_list) != 1)
8324 return false;
8325 query = (Query *) linitial(plansource->query_list);
8326
8327 /*
8328 * 2. It must be a plain SELECT query without any input tables.
8329 */
8330 if (!IsA(query, Query))
8331 return false;
8332 if (query->commandType != CMD_SELECT)
8333 return false;
8334 if (query->rtable != NIL)
8335 return false;
8336
8337 /*
8338 * 3. Can't have any subplans, aggregates, qual clauses either. (These
8339 * tests should generally match what inline_function() checks before
8340 * inlining a SQL function; otherwise, inlining could change our
8341 * conclusion about whether an expression is simple, which we don't want.)
8342 */
8343 if (query->hasAggs ||
8344 query->hasWindowFuncs ||
8345 query->hasTargetSRFs ||
8346 query->hasSubLinks ||
8347 query->cteList ||
8348 query->jointree->fromlist ||
8349 query->jointree->quals ||
8350 query->groupClause ||
8351 query->groupingSets ||
8352 query->havingQual ||
8353 query->windowClause ||
8354 query->distinctClause ||
8355 query->sortClause ||
8356 query->limitOffset ||
8357 query->limitCount ||
8358 query->setOperations)
8359 return false;
8360
8361 /*
8362 * 4. The query must have a single attribute as result.
8363 */
8364 if (list_length(query->targetList) != 1)
8365 return false;
8366
8367 /*
8368 * OK, we can treat it as a simple plan.
8369 */
8370 return true;
8371}

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 7004 of file pl_exec.c.

7007{
7009
7010 /*
7011 * If target is RECORD, we may be able to avoid field-by-field processing.
7012 */
7013 if (target->dtype == PLPGSQL_DTYPE_REC)
7014 {
7015 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7016
7017 /*
7018 * If we have no source tupdesc, just set the record variable to NULL.
7019 * (If we have a source tupdesc but not a tuple, we'll set the
7020 * variable to a row of nulls, instead. This is odd perhaps, but
7021 * backwards compatible.)
7022 */
7023 if (tupdesc == NULL)
7024 {
7025 if (rec->datatype &&
7027 {
7028 /*
7029 * If it's a composite domain, NULL might not be a legal
7030 * value, so we instead need to make an empty expanded record
7031 * and ensure that domain type checking gets done. If there
7032 * is already an expanded record, piggyback on its lookups.
7033 */
7035 NULL, rec->erh);
7036 expanded_record_set_tuple(newerh, NULL, false, false);
7037 assign_record_var(estate, rec, newerh);
7038 }
7039 else
7040 {
7041 /* Just clear it to NULL */
7042 if (rec->erh)
7044 rec->erh = NULL;
7045 }
7046 return;
7047 }
7048
7049 /*
7050 * Build a new expanded record with appropriate tupdesc.
7051 */
7052 newerh = make_expanded_record_for_rec(estate, rec, tupdesc, NULL);
7053
7054 /*
7055 * If the rowtypes match, or if we have no tuple anyway, we can
7056 * complete the assignment without field-by-field processing.
7057 *
7058 * The tests here are ordered more or less in order of cheapness. We
7059 * can easily detect it will work if the target is declared RECORD or
7060 * has the same typeid as the source. But when assigning from a query
7061 * result, it's common to have a source tupdesc that's labeled RECORD
7062 * but is actually physically compatible with a named-composite-type
7063 * target, so it's worth spending extra cycles to check for that.
7064 */
7065 if (rec->rectypeid == RECORDOID ||
7066 rec->rectypeid == tupdesc->tdtypeid ||
7069 {
7070 if (!HeapTupleIsValid(tup))
7071 {
7072 /* No data, so force the record into all-nulls state */
7074 }
7075 else
7076 {
7077 /* No coercion is needed, so just assign the row value */
7078 expanded_record_set_tuple(newerh, tup, true, !estate->atomic);
7079 }
7080
7081 /* Complete the assignment */
7082 assign_record_var(estate, rec, newerh);
7083
7084 return;
7085 }
7086 }
7087
7088 /*
7089 * Otherwise, deconstruct the tuple and do field-by-field assignment,
7090 * using exec_move_row_from_fields.
7091 */
7092 if (tupdesc && HeapTupleIsValid(tup))
7093 {
7094 int td_natts = tupdesc->natts;
7095 Datum *values;
7096 bool *nulls;
7097 Datum values_local[64];
7098 bool nulls_local[64];
7099
7100 /*
7101 * Need workspace arrays. If td_natts is small enough, use local
7102 * arrays to save doing a palloc. Even if it's not small, we can
7103 * allocate both the Datum and isnull arrays in one palloc chunk.
7104 */
7106 {
7108 nulls = nulls_local;
7109 }
7110 else
7111 {
7112 char *chunk;
7113
7114 chunk = eval_mcontext_alloc(estate,
7115 td_natts * (sizeof(Datum) + sizeof(bool)));
7116 values = (Datum *) chunk;
7117 nulls = (bool *) (chunk + td_natts * sizeof(Datum));
7118 }
7119
7120 heap_deform_tuple(tup, tupdesc, values, nulls);
7121
7122 exec_move_row_from_fields(estate, target, newerh,
7123 values, nulls, tupdesc);
7124 }
7125 else
7126 {
7127 /*
7128 * Assign all-nulls.
7129 */
7130 exec_move_row_from_fields(estate, target, newerh,
7131 NULL, NULL, NULL);
7132 }
7133}

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 7678 of file pl_exec.c.

7681{
7682 /* Check to see if source is an expanded record */
7684 {
7687
7688 Assert(erh->er_magic == ER_MAGIC);
7689
7690 /* These cases apply if the target is record not row... */
7691 if (target->dtype == PLPGSQL_DTYPE_REC)
7692 {
7693 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7694
7695 /*
7696 * If it's the same record already stored in the variable, do
7697 * nothing. This would happen only in silly cases like "r := r",
7698 * but we need some check to avoid possibly freeing the variable's
7699 * live value below. Note that this applies even if what we have
7700 * is a R/O pointer.
7701 */
7702 if (erh == rec->erh)
7703 return;
7704
7705 /*
7706 * Make sure rec->rectypeid is up-to-date before using it.
7707 */
7709
7710 /*
7711 * If we have a R/W pointer, we're allowed to just commandeer
7712 * ownership of the expanded record. If it's of the right type to
7713 * put into the record variable, do that. (Note we don't accept
7714 * an expanded record of a composite-domain type as a RECORD
7715 * value. We'll treat it as the base composite type instead;
7716 * compare logic in make_expanded_record_for_rec.)
7717 */
7719 (rec->rectypeid == erh->er_decltypeid ||
7720 (rec->rectypeid == RECORDOID &&
7721 !ExpandedRecordIsDomain(erh))))
7722 {
7723 assign_record_var(estate, rec, erh);
7724 return;
7725 }
7726
7727 /*
7728 * If we already have an expanded record object in the target
7729 * variable, and the source record contains a valid tuple
7730 * representation with the right rowtype, then we can skip making
7731 * a new expanded record and just assign the tuple with
7732 * expanded_record_set_tuple. (We can't do the equivalent if we
7733 * have to do field-by-field assignment, since that wouldn't be
7734 * atomic if there's an error.) We consider that there's a
7735 * rowtype match only if it's the same named composite type or
7736 * same registered rowtype; checking for matches of anonymous
7737 * rowtypes would be more expensive than this is worth.
7738 */
7739 if (rec->erh &&
7740 (erh->flags & ER_FLAG_FVALUE_VALID) &&
7741 erh->er_typeid == rec->erh->er_typeid &&
7742 (erh->er_typeid != RECORDOID ||
7743 (erh->er_typmod == rec->erh->er_typmod &&
7744 erh->er_typmod >= 0)))
7745 {
7747 true, !estate->atomic);
7748 return;
7749 }
7750
7751 /*
7752 * Otherwise we're gonna need a new expanded record object. Make
7753 * it here in hopes of piggybacking on the source object's
7754 * previous typcache lookup.
7755 */
7756 newerh = make_expanded_record_for_rec(estate, rec, NULL, erh);
7757
7758 /*
7759 * If the expanded record contains a valid tuple representation,
7760 * and we don't need rowtype conversion, then just copying the
7761 * tuple is probably faster than field-by-field processing. (This
7762 * isn't duplicative of the previous check, since here we will
7763 * catch the case where the record variable was previously empty.)
7764 */
7765 if ((erh->flags & ER_FLAG_FVALUE_VALID) &&
7766 (rec->rectypeid == RECORDOID ||
7767 rec->rectypeid == erh->er_typeid))
7768 {
7770 true, !estate->atomic);
7771 assign_record_var(estate, rec, newerh);
7772 return;
7773 }
7774
7775 /*
7776 * Need to special-case empty source record, else code below would
7777 * leak newerh.
7778 */
7779 if (ExpandedRecordIsEmpty(erh))
7780 {
7781 /* Set newerh to a row of NULLs */
7783 assign_record_var(estate, rec, newerh);
7784 return;
7785 }
7786 } /* end of record-target-only cases */
7787
7788 /*
7789 * If the source expanded record is empty, we should treat that like a
7790 * NULL tuple value. (We're unlikely to see such a case, but we must
7791 * check this; deconstruct_expanded_record would cause a change of
7792 * logical state, which is not OK.)
7793 */
7794 if (ExpandedRecordIsEmpty(erh))
7795 {
7796 exec_move_row(estate, target, NULL,
7798 return;
7799 }
7800
7801 /*
7802 * Otherwise, ensure that the source record is deconstructed, and
7803 * assign from its field values.
7804 */
7806 exec_move_row_from_fields(estate, target, newerh,
7807 erh->dvalues, erh->dnulls,
7809 }
7810 else
7811 {
7812 /*
7813 * Nope, we've got a plain composite Datum. Deconstruct it; but we
7814 * don't use deconstruct_composite_datum(), because we may be able to
7815 * skip calling lookup_rowtype_tupdesc().
7816 */
7817 HeapTupleHeader td;
7819 Oid tupType;
7821 TupleDesc tupdesc;
7822 MemoryContext oldcontext;
7823
7824 /* Ensure that any detoasted data winds up in the eval_mcontext */
7825 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
7826 /* Get tuple body (note this could involve detoasting) */
7828 MemoryContextSwitchTo(oldcontext);
7829
7830 /* Build a temporary HeapTuple control structure */
7832 ItemPointerSetInvalid(&(tmptup.t_self));
7833 tmptup.t_tableOid = InvalidOid;
7834 tmptup.t_data = td;
7835
7836 /* Extract rowtype info */
7839
7840 /* Now, if the target is record not row, maybe we can optimize ... */
7841 if (target->dtype == PLPGSQL_DTYPE_REC)
7842 {
7843 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7844
7845 /*
7846 * If we already have an expanded record object in the target
7847 * variable, and the source datum has a matching rowtype, then we
7848 * can skip making a new expanded record and just assign the tuple
7849 * with expanded_record_set_tuple. We consider that there's a
7850 * rowtype match only if it's the same named composite type or
7851 * same registered rowtype. (Checking to reject an anonymous
7852 * rowtype here should be redundant, but let's be safe.)
7853 */
7854 if (rec->erh &&
7855 tupType == rec->erh->er_typeid &&
7856 (tupType != RECORDOID ||
7857 (tupTypmod == rec->erh->er_typmod &&
7858 tupTypmod >= 0)))
7859 {
7861 true, !estate->atomic);
7862 return;
7863 }
7864
7865 /*
7866 * If the source datum has a rowtype compatible with the target
7867 * variable, just build a new expanded record and assign the tuple
7868 * into it. Using make_expanded_record_from_typeid() here saves
7869 * one typcache lookup compared to the code below.
7870 */
7871 if (rec->rectypeid == RECORDOID || rec->rectypeid == tupType)
7872 {
7874 MemoryContext mcontext = get_eval_mcontext(estate);
7875
7877 mcontext);
7879 true, !estate->atomic);
7880 assign_record_var(estate, rec, newerh);
7881 return;
7882 }
7883
7884 /*
7885 * Otherwise, we're going to need conversion, so fall through to
7886 * do it the hard way.
7887 */
7888 }
7889
7890 /*
7891 * ROW target, or unoptimizable RECORD target, so we have to expend a
7892 * lookup to obtain the source datum's tupdesc.
7893 */
7895
7896 /* Do the move */
7897 exec_move_row(estate, target, &tmptup, tupdesc);
7898
7899 /* Release tupdesc usage count */
7900 ReleaseTupleDesc(tupdesc);
7901 }
7902}

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 7282 of file pl_exec.c.

7287{
7288 int td_natts = tupdesc ? tupdesc->natts : 0;
7289 int fnum;
7290 int anum;
7292
7293 /*
7294 * The extra check strict strict_multi_assignment can be active, only when
7295 * input tupdesc is specified.
7296 */
7297 if (tupdesc != NULL)
7298 {
7303 }
7304
7305 /* Handle RECORD-target case */
7306 if (target->dtype == PLPGSQL_DTYPE_REC)
7307 {
7308 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
7311 bool newnulls_local[64];
7312
7313 Assert(newerh != NULL); /* caller must have built new object */
7314
7316
7317 /*
7318 * Coerce field values if needed. This might involve dealing with
7319 * different sets of dropped columns and/or coercing individual column
7320 * types. That's sort of a pain, but historically plpgsql has allowed
7321 * it, so we preserve the behavior. However, it's worth a quick check
7322 * to see if the tupdescs are identical. (Since expandedrecord.c
7323 * prefers to use refcounted tupdescs from the typcache, expanded
7324 * records with the same rowtype will have pointer-equal tupdescs.)
7325 */
7326 if (var_tupdesc != tupdesc)
7327 {
7328 int vtd_natts = var_tupdesc->natts;
7330 bool *newnulls;
7331
7332 /*
7333 * Need workspace arrays. If vtd_natts is small enough, use local
7334 * arrays to save doing a palloc. Even if it's not small, we can
7335 * allocate both the Datum and isnull arrays in one palloc chunk.
7336 */
7338 {
7341 }
7342 else
7343 {
7344 char *chunk;
7345
7346 chunk = eval_mcontext_alloc(estate,
7347 vtd_natts * (sizeof(Datum) + sizeof(bool)));
7348 newvalues = (Datum *) chunk;
7349 newnulls = (bool *) (chunk + vtd_natts * sizeof(Datum));
7350 }
7351
7352 /* Walk over destination columns */
7353 anum = 0;
7354 for (fnum = 0; fnum < vtd_natts; fnum++)
7355 {
7357 Datum value;
7358 bool isnull;
7359 Oid valtype;
7361
7362 if (attr->attisdropped)
7363 {
7364 /* expanded_record_set_fields should ignore this column */
7365 continue; /* skip dropped column in record */
7366 }
7367
7368 while (anum < td_natts &&
7369 TupleDescAttr(tupdesc, anum)->attisdropped)
7370 anum++; /* skip dropped column in tuple */
7371
7372 if (anum < td_natts)
7373 {
7374 value = values[anum];
7375 isnull = nulls[anum];
7376 valtype = TupleDescAttr(tupdesc, anum)->atttypid;
7377 valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
7378 anum++;
7379 }
7380 else
7381 {
7382 /* no source for destination column */
7383 value = (Datum) 0;
7384 isnull = true;
7386 valtypmod = -1;
7387
7388 /* When source value is missing */
7392 errmsg("number of source and target fields in assignment does not match"),
7393 /* translator: %s represents a name of an extra check */
7394 errdetail("%s check of %s is active.",
7395 "strict_multi_assignment",
7396 strict_multiassignment_level == ERROR ? "extra_errors" :
7397 "extra_warnings"),
7398 errhint("Make sure the query returns the exact list of columns.")));
7399 }
7400
7401 /* Cast the new value to the right type, if needed. */
7402 newvalues[fnum] = exec_cast_value(estate,
7403 value,
7404 &isnull,
7405 valtype,
7406 valtypmod,
7407 attr->atttypid,
7408 attr->atttypmod);
7409 newnulls[fnum] = isnull;
7410 }
7411
7412 /*
7413 * When strict_multiassignment extra check is active, then ensure
7414 * there are no unassigned source attributes.
7415 */
7417 {
7418 /* skip dropped columns in the source descriptor */
7419 while (anum < td_natts &&
7420 TupleDescAttr(tupdesc, anum)->attisdropped)
7421 anum++;
7422
7423 if (anum < td_natts)
7426 errmsg("number of source and target fields in assignment does not match"),
7427 /* translator: %s represents a name of an extra check */
7428 errdetail("%s check of %s is active.",
7429 "strict_multi_assignment",
7430 strict_multiassignment_level == ERROR ? "extra_errors" :
7431 "extra_warnings"),
7432 errhint("Make sure the query returns the exact list of columns.")));
7433 }
7434
7435 values = newvalues;
7436 nulls = newnulls;
7437 }
7438
7439 /* Insert the coerced field values into the new expanded record */
7441
7442 /* Complete the assignment */
7443 assign_record_var(estate, rec, newerh);
7444
7445 return;
7446 }
7447
7448 /* newerh should not have been passed in non-RECORD cases */
7449 Assert(newerh == NULL);
7450
7451 /*
7452 * For a row, we assign the individual field values to the variables the
7453 * row points to.
7454 *
7455 * NOTE: both this code and the record code above silently ignore extra
7456 * columns in the source and assume NULL for missing columns. This is
7457 * pretty dubious but it's the historical behavior.
7458 *
7459 * If we have no input data at all, we'll assign NULL to all columns of
7460 * the row variable.
7461 */
7462 if (target->dtype == PLPGSQL_DTYPE_ROW)
7463 {
7464 PLpgSQL_row *row = (PLpgSQL_row *) target;
7465
7466 anum = 0;
7467 for (fnum = 0; fnum < row->nfields; fnum++)
7468 {
7469 PLpgSQL_var *var;
7470 Datum value;
7471 bool isnull;
7472 Oid valtype;
7474
7475 var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
7476
7477 while (anum < td_natts &&
7478 TupleDescAttr(tupdesc, anum)->attisdropped)
7479 anum++; /* skip dropped column in tuple */
7480
7481 if (anum < td_natts)
7482 {
7483 value = values[anum];
7484 isnull = nulls[anum];
7485 valtype = TupleDescAttr(tupdesc, anum)->atttypid;
7486 valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
7487 anum++;
7488 }
7489 else
7490 {
7491 /* no source for destination column */
7492 value = (Datum) 0;
7493 isnull = true;
7495 valtypmod = -1;
7496
7500 errmsg("number of source and target fields in assignment does not match"),
7501 /* translator: %s represents a name of an extra check */
7502 errdetail("%s check of %s is active.",
7503 "strict_multi_assignment",
7504 strict_multiassignment_level == ERROR ? "extra_errors" :
7505 "extra_warnings"),
7506 errhint("Make sure the query returns the exact list of columns.")));
7507 }
7508
7509 exec_assign_value(estate, (PLpgSQL_datum *) var,
7510 value, isnull, valtype, valtypmod);
7511 }
7512
7513 /*
7514 * When strict_multiassignment extra check is active, ensure there are
7515 * no unassigned source attributes.
7516 */
7518 {
7519 while (anum < td_natts &&
7520 TupleDescAttr(tupdesc, anum)->attisdropped)
7521 anum++; /* skip dropped column in tuple */
7522
7523 if (anum < td_natts)
7526 errmsg("number of source and target fields in assignment does not match"),
7527 /* translator: %s represents a name of an extra check */
7528 errdetail("%s check of %s is active.",
7529 "strict_multi_assignment",
7530 strict_multiassignment_level == ERROR ? "extra_errors" :
7531 "extra_warnings"),
7532 errhint("Make sure the query returns the exact list of columns.")));
7533 }
7534
7535 return;
7536 }
7537
7538 elog(ERROR, "unsupported target type: %d", target->dtype);
7539}

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 4206 of file pl_exec.c.

4208{
4211
4212 /*
4213 * Generate and save the plan
4214 */
4215 memset(&options, 0, sizeof(options));
4217 options.parserSetupArg = expr;
4218 options.parseMode = expr->parseMode;
4219 options.cursorOptions = cursorOptions;
4221 if (plan == NULL)
4222 elog(ERROR, "SPI_prepare_extended failed for \"%s\": %s",
4224
4226 expr->plan = plan;
4227
4228 /* Check to see if it's a simple expression */
4229 exec_simple_check_plan(estate, expr);
4230}

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 5854 of file pl_exec.c.

5856{
5857 ParamListInfo paramLI;
5858 int rc;
5859
5860 /*
5861 * On the first call for this expression generate the plan.
5862 *
5863 * If we don't need to return a portal, then we're just going to execute
5864 * the query immediately, which means it's OK to use a parallel plan, even
5865 * if the number of rows being fetched is limited. If we do need to
5866 * return a portal (i.e., this is for a FOR loop), the user's code might
5867 * invoke additional operations inside the FOR loop, making parallel query
5868 * unsafe. In any case, we don't expect any cursor operations to be done,
5869 * so specify NO_SCROLL for efficiency and semantic safety.
5870 */
5871 if (expr->plan == NULL)
5872 {
5873 int cursorOptions = CURSOR_OPT_NO_SCROLL;
5874
5875 if (portalP == NULL)
5876 cursorOptions |= CURSOR_OPT_PARALLEL_OK;
5877 exec_prepare_plan(estate, expr, cursorOptions);
5878 }
5879
5880 /*
5881 * Set up ParamListInfo to pass to executor
5882 */
5883 paramLI = setup_param_list(estate, expr);
5884
5885 /*
5886 * If a portal was requested, put the query and paramlist into the portal
5887 */
5888 if (portalP != NULL)
5889 {
5891 paramLI,
5892 estate->readonly_func);
5893 if (*portalP == NULL)
5894 elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
5896 exec_eval_cleanup(estate);
5897 return SPI_OK_CURSOR;
5898 }
5899
5900 /*
5901 * Execute the query
5902 */
5903 rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
5904 estate->readonly_func, maxtuples);
5905 if (rc != SPI_OK_SELECT)
5906 {
5907 /*
5908 * SELECT INTO deserves a special error message, because "query is not
5909 * a SELECT" is not very helpful in that case.
5910 */
5911 if (rc == SPI_OK_SELINTO)
5912 ereport(ERROR,
5914 errmsg("query is SELECT INTO, but it should be plain SELECT"),
5915 errcontext("query: %s", expr->query)));
5916 else
5917 ereport(ERROR,
5919 errmsg("query is not a SELECT"),
5920 errcontext("query: %s", expr->query)));
5921 }
5922
5923 /* Save query results for eventual cleanup */
5924 Assert(estate->eval_tuptable == NULL);
5925 estate->eval_tuptable = SPI_tuptable;
5926 estate->eval_processed = SPI_processed;
5927
5928 return rc;
5929}

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 8377 of file pl_exec.c.

8378{
8380 Plan *plan;
8381 Expr *tle_expr;
8382
8383 /*
8384 * Given the checks that exec_simple_check_plan did, none of the Asserts
8385 * here should ever fail.
8386 */
8387
8388 /* Extract the single PlannedStmt */
8389 Assert(list_length(cplan->stmt_list) == 1);
8391 Assert(stmt->commandType == CMD_SELECT);
8392
8393 /*
8394 * Ordinarily, the plan node should be a simple Result. However, if
8395 * debug_parallel_query is on, the planner might've stuck a Gather node
8396 * atop that; and/or if this plan is for a scrollable cursor, the planner
8397 * might've stuck a Material node atop it. The simplest way to deal with
8398 * this is to look through the Gather and/or Material nodes. The upper
8399 * node's tlist would normally contain a Var referencing the child node's
8400 * output ... but setrefs.c might also have copied a Const as-is.
8401 */
8402 plan = stmt->planTree;
8403 for (;;)
8404 {
8405 /* Extract the single tlist expression */
8406 Assert(list_length(plan->targetlist) == 1);
8407 tle_expr = linitial_node(TargetEntry, plan->targetlist)->expr;
8408
8409 if (IsA(plan, Result))
8410 {
8411 Assert(plan->lefttree == NULL &&
8412 plan->righttree == NULL &&
8413 plan->initPlan == NULL &&
8414 plan->qual == NULL &&
8415 ((Result *) plan)->resconstantqual == NULL);
8416 break;
8417 }
8418 else if (IsA(plan, Gather) || IsA(plan, Material))
8419 {
8420 Assert(plan->lefttree != NULL &&
8421 plan->righttree == NULL &&
8422 plan->initPlan == NULL &&
8423 plan->qual == NULL);
8424 /* If setrefs.c copied up a Const, no need to look further */
8425 if (IsA(tle_expr, Const))
8426 break;
8427 /* Otherwise, it better be an outer Var */
8429 Assert(((Var *) tle_expr)->varno == OUTER_VAR);
8430 /* Descend to the child node */
8431 plan = plan->lefttree;
8432 }
8433 else
8434 elog(ERROR, "unexpected plan node type: %d",
8435 (int) nodeTag(plan));
8436 }
8437
8438 /*
8439 * Save the simple expression, and initialize state to "not valid in
8440 * current transaction".
8441 */
8442 expr->expr_simple_expr = tle_expr;
8443 expr->expr_simple_state = NULL;
8444 expr->expr_simple_in_use = false;
8446 /* Also stash away the expression result type */
8449 /* We also want to remember if it is immutable or not */
8451}

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 8695 of file pl_exec.c.

8696{
8697 PLpgSQL_var *var;
8698
8699 var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
8700
8701 /*
8702 * Use pg_assume() to avoid a spurious warning with some compilers, by
8703 * telling the compiler that the VARATT_IS_EXTERNAL_NON_EXPANDED() branch
8704 * in assign_simple_var() will never be reached when called from here, due
8705 * to "found" being a boolean (i.e. a byvalue type), not a varlena.
8706 */
8707 pg_assume(var->datatype->typlen != -1);
8708
8709 assign_simple_var(estate, var, BoolGetDatum(state), false, false);
8710}

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 8234 of file pl_exec.c.

8235{
8237 CachedPlanSource *plansource;
8238 CachedPlan *cplan;
8239 MemoryContext oldcontext;
8240
8241 /*
8242 * Initialize to "not simple", and reset R/W optimizability.
8243 */
8244 expr->expr_simple_expr = NULL;
8246 expr->expr_rw_param = NULL;
8247
8248 /*
8249 * Check the analyzed-and-rewritten form of the query to see if we will be
8250 * able to treat it as a simple expression. Since this function is only
8251 * called immediately after creating the CachedPlanSource, we need not
8252 * worry about the query being stale.
8253 */
8254 if (!exec_is_simple_query(expr))
8255 return;
8256
8257 /* exec_is_simple_query verified that there's just one CachedPlanSource */
8259 plansource = (CachedPlanSource *) linitial(plansources);
8260
8261 /*
8262 * Get the generic plan for the query. If replanning is needed, do that
8263 * work in the eval_mcontext. (Note that replanning could throw an error,
8264 * in which case the expr is left marked "not simple", which is fine.)
8265 */
8266 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8267 cplan = SPI_plan_get_cached_plan(expr->plan);
8268 MemoryContextSwitchTo(oldcontext);
8269
8270 /* Can't fail, because we checked for a single CachedPlanSource above */
8271 Assert(cplan != NULL);
8272
8273 /*
8274 * Verify that plancache.c thinks the plan is simple enough to use
8275 * CachedPlanIsSimplyValid. Given the restrictions above, it's unlikely
8276 * that this could fail, but if it does, just treat plan as not simple. On
8277 * success, save a refcount on the plan in the simple-expression resowner.
8278 */
8279 if (CachedPlanAllowsSimpleValidityCheck(plansource, cplan,
8280 estate->simple_eval_resowner))
8281 {
8282 /* Remember that we have the refcount */
8283 expr->expr_simple_plansource = plansource;
8284 expr->expr_simple_plan = cplan;
8286
8287 /* Share the remaining work with the replan code path */
8288 exec_save_simple_expr(expr, cplan);
8289 }
8290
8291 /*
8292 * Release the plan refcount obtained by SPI_plan_get_cached_plan. (This
8293 * refcount is held by the wrong resowner, so we can't just repurpose it.)
8294 */
8296}

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 3969 of file pl_exec.c.

3970{
3971 bool value;
3972 bool isnull;
3973
3974 /* do nothing when asserts are not enabled */
3976 return PLPGSQL_RC_OK;
3977
3978 value = exec_eval_boolean(estate, stmt->cond, &isnull);
3979 exec_eval_cleanup(estate);
3980
3981 if (isnull || !value)
3982 {
3983 char *message = NULL;
3984
3985 if (stmt->message != NULL)
3986 {
3987 Datum val;
3988 Oid typeid;
3989 int32 typmod;
3990
3991 val = exec_eval_expr(estate, stmt->message,
3992 &isnull, &typeid, &typmod);
3993 if (!isnull)
3994 message = convert_value_to_string(estate, val, typeid);
3995 /* we mustn't do exec_eval_cleanup here */
3996 }
3997
3998 ereport(ERROR,
4000 message ? errmsg_internal("%s", message) :
4001 errmsg("assertion failed")));
4002 }
4003
4004 return PLPGSQL_RC_OK;
4005}

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 2195 of file pl_exec.c.

2196{
2197 Assert(stmt->varno >= 0);
2198
2199 exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
2200
2201 return PLPGSQL_RC_OK;
2202}

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 1694 of file pl_exec.c.

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

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 2228 of file pl_exec.c.

2229{
2230 PLpgSQL_expr *expr = stmt->expr;
2233 ParamListInfo paramLI;
2235 int rc;
2236
2237 /*
2238 * Make a plan if we don't have one already.
2239 */
2240 if (expr->plan == NULL)
2241 exec_prepare_plan(estate, expr, 0);
2242
2243 /*
2244 * A CALL or DO can never be a simple expression.
2245 */
2246 Assert(!expr->expr_simple_expr);
2247
2248 /*
2249 * Also construct a DTYPE_ROW datum representing the plpgsql variables
2250 * associated with the procedure's output arguments. Then we can use
2251 * exec_move_row() to do the assignments.
2252 */
2253 if (stmt->is_call && stmt->target == NULL)
2254 stmt->target = make_callstmt_target(estate, expr);
2255
2256 paramLI = setup_param_list(estate, expr);
2257
2259
2260 /*
2261 * If we have a procedure-lifespan resowner, use that to hold the refcount
2262 * for the plan. This avoids refcount leakage complaints if the called
2263 * procedure ends the current transaction.
2264 *
2265 * Also, tell SPI to allow non-atomic execution.
2266 */
2267 memset(&options, 0, sizeof(options));
2268 options.params = paramLI;
2269 options.read_only = estate->readonly_func;
2270 options.allow_nonatomic = true;
2271 options.owner = estate->procedure_resowner;
2272
2274
2275 if (rc < 0)
2276 elog(ERROR, "SPI_execute_plan_extended failed executing query \"%s\": %s",
2277 expr->query, SPI_result_code_string(rc));
2278
2280
2281 if (before_lxid != after_lxid)
2282 {
2283 /*
2284 * If we are in a new transaction after the call, we need to build new
2285 * simple-expression infrastructure.
2286 */
2287 estate->simple_eval_estate = NULL;
2288 estate->simple_eval_resowner = NULL;
2290 }
2291
2292 /*
2293 * Check result rowcount; if there's one row, assign procedure's output
2294 * values back to the appropriate variables.
2295 */
2296 if (SPI_processed == 1)
2297 {
2299
2300 if (!stmt->is_call)
2301 elog(ERROR, "DO statement returned a row");
2302
2303 exec_move_row(estate, stmt->target, tuptab->vals[0], tuptab->tupdesc);
2304 }
2305 else if (SPI_processed > 1)
2306 elog(ERROR, "procedure call returned more than one row");
2307
2308 exec_eval_cleanup(estate);
2310
2311 return PLPGSQL_RC_OK;
2312}

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 2587 of file pl_exec.c.

2588{
2590 bool isnull;
2591 ListCell *l;
2592
2593 if (stmt->t_expr != NULL)
2594 {
2595 /* simple case */
2596 Datum t_val;
2597 Oid t_typoid;
2599
2600 t_val = exec_eval_expr(estate, stmt->t_expr,
2601 &isnull, &t_typoid, &t_typmod);
2602
2603 t_var = (PLpgSQL_var *) estate->datums[stmt->t_varno];
2604
2605 /*
2606 * When expected datatype is different from real, change it. Note that
2607 * what we're modifying here is an execution copy of the datum, so
2608 * this doesn't affect the originally stored function parse tree. (In
2609 * theory, if the expression datatype keeps changing during execution,
2610 * this could cause a function-lifespan memory leak. Doesn't seem
2611 * worth worrying about though.)
2612 */
2613 if (t_var->datatype->typoid != t_typoid ||
2614 t_var->datatype->atttypmod != t_typmod)
2616 t_typmod,
2617 estate->func->fn_input_collation,
2618 NULL);
2619
2620 /* now we can assign to the variable */
2621 exec_assign_value(estate,
2622 (PLpgSQL_datum *) t_var,
2623 t_val,
2624 isnull,
2625 t_typoid,
2626 t_typmod);
2627
2628 exec_eval_cleanup(estate);
2629 }
2630
2631 /* Now search for a successful WHEN clause */
2632 foreach(l, stmt->case_when_list)
2633 {
2635 bool value;
2636
2637 value = exec_eval_boolean(estate, cwt->expr, &isnull);
2638 exec_eval_cleanup(estate);
2639 if (!isnull && value)
2640 {
2641 /* Found it */
2642
2643 /* We can now discard any value we had for the temp variable */
2644 if (t_var != NULL)
2645 assign_simple_var(estate, t_var, (Datum) 0, true, false);
2646
2647 /* Evaluate the statement(s), and we're done */
2648 return exec_stmts(estate, cwt->stmts);
2649 }
2650 }
2651
2652 /* We can now discard any value we had for the temp variable */
2653 if (t_var != NULL)
2654 assign_simple_var(estate, t_var, (Datum) 0, true, false);
2655
2656 /* SQL2003 mandates this error if there was no ELSE clause */
2657 if (!stmt->have_else)
2658 ereport(ERROR,
2660 errmsg("case not found"),
2661 errhint("CASE statement is missing ELSE part.")));
2662
2663 /* Evaluate the ELSE statements, and we're done */
2664 return exec_stmts(estate, stmt->else_stmts);
2665}

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 5014 of file pl_exec.c.

5015{
5016 PLpgSQL_var *curvar;
5017 Portal portal;
5018 char *curname;
5019 MemoryContext oldcontext;
5020
5021 /* ----------
5022 * Get the portal of the cursor by name
5023 * ----------
5024 */
5025 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
5026 if (curvar->isnull)
5027 ereport(ERROR,
5029 errmsg("cursor variable \"%s\" is null", curvar->refname)));
5030
5031 /* Use eval_mcontext for short-lived string */
5032 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5034 MemoryContextSwitchTo(oldcontext);
5035
5036 portal = SPI_cursor_find(curname);
5037 if (portal == NULL)
5038 ereport(ERROR,
5040 errmsg("cursor \"%s\" does not exist", curname)));
5041
5042 /* ----------
5043 * And close it.
5044 * ----------
5045 */
5046 SPI_cursor_close(portal);
5047
5048 return PLPGSQL_RC_OK;
5049}

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 5057 of file pl_exec.c.

5058{
5059 if (stmt->chain)
5061 else
5062 SPI_commit();
5063
5064 /*
5065 * We need to build new simple-expression infrastructure, since the old
5066 * data structures are gone.
5067 */
5068 estate->simple_eval_estate = NULL;
5069 estate->simple_eval_resowner = NULL;
5071
5072 return PLPGSQL_RC_OK;
5073}

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 4541 of file pl_exec.c.

4543{
4544 Datum query;
4545 bool isnull;
4546 Oid restype;
4548 char *querystr;
4549 int exec_res;
4550 ParamListInfo paramLI;
4552 MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
4553
4554 /*
4555 * First we evaluate the string expression after the EXECUTE keyword. Its
4556 * result is the querystring we have to execute.
4557 */
4558 query = exec_eval_expr(estate, stmt->query, &isnull, &restype, &restypmod);
4559 if (isnull)
4560 ereport(ERROR,
4562 errmsg("query string argument of EXECUTE is null")));
4563
4564 /* Get the C-String representation */
4565 querystr = convert_value_to_string(estate, query, restype);
4566
4567 /* copy it into the stmt_mcontext before we clean up */
4568 querystr = MemoryContextStrdup(stmt_mcontext, querystr);
4569
4570 exec_eval_cleanup(estate);
4571
4572 /*
4573 * Execute the query without preparing a saved plan.
4574 */
4575 paramLI = exec_eval_using_params(estate, stmt->params);
4576
4577 memset(&options, 0, sizeof(options));
4578 options.params = paramLI;
4579 options.read_only = estate->readonly_func;
4580
4582
4583 switch (exec_res)
4584 {
4585 case SPI_OK_SELECT:
4586 case SPI_OK_INSERT:
4587 case SPI_OK_UPDATE:
4588 case SPI_OK_DELETE:
4589 case SPI_OK_MERGE:
4594 case SPI_OK_UTILITY:
4595 case SPI_OK_REWRITTEN:
4596 break;
4597
4598 case 0:
4599
4600 /*
4601 * Also allow a zero return, which implies the querystring
4602 * contained no commands.
4603 */
4604 break;
4605
4606 case SPI_OK_SELINTO:
4607
4608 /*
4609 * We want to disallow SELECT INTO for now, because its behavior
4610 * is not consistent with SELECT INTO in a normal plpgsql context.
4611 * (We need to reimplement EXECUTE to parse the string as a
4612 * plpgsql command, not just feed it to SPI_execute.) This is not
4613 * a functional limitation because CREATE TABLE AS is allowed.
4614 */
4615 ereport(ERROR,
4617 errmsg("EXECUTE of SELECT ... INTO is not implemented"),
4618 errhint("You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.")));
4619 break;
4620
4621 /* Some SPI errors deserve specific error messages */
4622 case SPI_ERROR_COPY:
4623 ereport(ERROR,
4625 errmsg("cannot COPY to/from client in PL/pgSQL")));
4626 break;
4627
4629 ereport(ERROR,
4631 errmsg("EXECUTE of transaction commands is not implemented")));
4632 break;
4633
4634 default:
4635 elog(ERROR, "SPI_execute_extended failed executing query \"%s\": %s",
4637 break;
4638 }
4639
4640 /* Save result info for GET DIAGNOSTICS */
4641 estate->eval_processed = SPI_processed;
4642
4643 /* Process INTO if present */
4644 if (stmt->into)
4645 {
4648 PLpgSQL_variable *target;
4649
4650 /* If the statement did not return a tuple table, complain */
4651 if (tuptab == NULL)
4652 ereport(ERROR,
4654 errmsg("INTO used with a command that cannot return data")));
4655
4656 /* Fetch target's datum entry */
4657 target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4658
4659 /*
4660 * If SELECT ... INTO specified STRICT, and the query didn't find
4661 * exactly one row, throw an error. If STRICT was not specified, then
4662 * allow the query to find any number of rows.
4663 */
4664 if (n == 0)
4665 {
4666 if (stmt->strict)
4667 {
4668 char *errdetail;
4669
4670 if (estate->func->print_strict_params)
4671 errdetail = format_preparedparamsdata(estate, paramLI);
4672 else
4673 errdetail = NULL;
4674
4675 ereport(ERROR,
4677 errmsg("query returned no rows"),
4678 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4679 }
4680 /* set the target to NULL(s) */
4681 exec_move_row(estate, target, NULL, tuptab->tupdesc);
4682 }
4683 else
4684 {
4685 if (n > 1 && stmt->strict)
4686 {
4687 char *errdetail;
4688
4689 if (estate->func->print_strict_params)
4690 errdetail = format_preparedparamsdata(estate, paramLI);
4691 else
4692 errdetail = NULL;
4693
4694 ereport(ERROR,
4696 errmsg("query returned more than one row"),
4697 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4698 }
4699
4700 /* Put the first result row into the target */
4701 exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4702 }
4703 /* clean up after exec_move_row() */
4704 exec_eval_cleanup(estate);
4705 }
4706 else
4707 {
4708 /*
4709 * It might be a good idea to raise an error if the query returned
4710 * tuples that are being ignored, but historically we have not done
4711 * that.
4712 */
4713 }
4714
4715 /* Release any result from SPI_execute, as well as transient data */
4717 MemoryContextReset(stmt_mcontext);
4718
4719 return PLPGSQL_RC_OK;
4720}

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 4731 of file pl_exec.c.

4732{
4733 Portal portal;
4734 int rc;
4735
4736 portal = exec_dynquery_with_params(estate, stmt->query, stmt->params,
4738
4739 /*
4740 * Execute the loop
4741 */
4742 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
4743
4744 /*
4745 * Close the implicit cursor
4746 */
4747 SPI_cursor_close(portal);
4748
4749 return rc;
4750}

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 4241 of file pl_exec.c.

4243{
4244 ParamListInfo paramLI;
4245 long tcount;
4246 int rc;
4247 PLpgSQL_expr *expr = stmt->sqlstmt;
4248 int too_many_rows_level = 0;
4249
4254
4255 /*
4256 * On the first call for this statement generate the plan, and detect
4257 * whether the statement is INSERT/UPDATE/DELETE/MERGE
4258 */
4259 if (expr->plan == NULL)
4261
4262 if (!stmt->mod_stmt_set)
4263 {
4264 ListCell *l;
4265
4266 stmt->mod_stmt = false;
4267 foreach(l, SPI_plan_get_plan_sources(expr->plan))
4268 {
4269 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l);
4270
4271 /*
4272 * We could look at the raw_parse_tree, but it seems simpler to
4273 * check the command tag. Note we should *not* look at the Query
4274 * tree(s), since those are the result of rewriting and could be
4275 * stale, or could have been transmogrified into something else
4276 * entirely.
4277 */
4278 if (plansource->commandTag == CMDTAG_INSERT ||
4279 plansource->commandTag == CMDTAG_UPDATE ||
4280 plansource->commandTag == CMDTAG_DELETE ||
4281 plansource->commandTag == CMDTAG_MERGE)
4282 {
4283 stmt->mod_stmt = true;
4284 break;
4285 }
4286 }
4287 stmt->mod_stmt_set = true;
4288 }
4289
4290 /*
4291 * Some users write "SELECT expr INTO var" instead of "var := expr". If
4292 * the expression is simple and the INTO target is a single variable, we
4293 * can bypass SPI and call ExecEvalExpr() directly. (exec_eval_expr would
4294 * actually work for non-simple expressions too, but such an expression
4295 * might return more or less than one row, complicating matters greatly.
4296 * The potential performance win is small if it's non-simple, and any
4297 * errors we might issue would likely look different, so avoid using this
4298 * code path for non-simple cases.)
4299 */
4300 if (expr->expr_simple_expr && stmt->into)
4301 {
4302 PLpgSQL_datum *target = estate->datums[stmt->target->dno];
4303
4304 if (target->dtype == PLPGSQL_DTYPE_ROW)
4305 {
4306 PLpgSQL_row *row = (PLpgSQL_row *) target;
4307
4308 if (row->nfields == 1)
4309 {
4311 Datum value;
4312 bool isnull;
4313 Oid valtype;
4315
4316 /*
4317 * Setup error traceback support for ereport(). This is so
4318 * that error reports for the expression will look similar
4319 * whether or not we take this code path.
4320 */
4322 plerrcontext.arg = expr;
4325
4326 /* If first time through, create a plan for this expression */
4327 if (expr->plan == NULL)
4328 exec_prepare_plan(estate, expr, 0);
4329
4330 /* And evaluate the expression */
4331 value = exec_eval_expr(estate, expr,
4332 &isnull, &valtype, &valtypmod);
4333
4334 /*
4335 * Pop the error context stack: the code below would not use
4336 * SPI's error handling during the assignment step.
4337 */
4339
4340 /* Assign the result to the INTO target */
4341 exec_assign_value(estate, estate->datums[row->varnos[0]],
4342 value, isnull, valtype, valtypmod);
4343 exec_eval_cleanup(estate);
4344
4345 /*
4346 * We must duplicate the other effects of the code below, as
4347 * well. We know that exactly one row was returned, so it
4348 * doesn't matter whether the INTO was STRICT or not.
4349 */
4350 exec_set_found(estate, true);
4351 estate->eval_processed = 1;
4352
4353 return PLPGSQL_RC_OK;
4354 }
4355 }
4356 }
4357
4358 /*
4359 * Set up ParamListInfo to pass to executor
4360 */
4361 paramLI = setup_param_list(estate, expr);
4362
4363 /*
4364 * If we have INTO, then we only need one row back ... but if we have INTO
4365 * STRICT or extra check too_many_rows, ask for two rows, so that we can
4366 * verify the statement returns only one. INSERT/UPDATE/DELETE/MERGE are
4367 * always treated strictly. Without INTO, just run the statement to
4368 * completion (tcount = 0).
4369 *
4370 * We could just ask for two rows always when using INTO, but there are
4371 * some cases where demanding the extra row costs significant time, eg by
4372 * forcing completion of a sequential scan. So don't do it unless we need
4373 * to enforce strictness.
4374 */
4375 if (stmt->into)
4376 {
4377 if (stmt->strict || stmt->mod_stmt || too_many_rows_level)
4378 tcount = 2;
4379 else
4380 tcount = 1;
4381 }
4382 else
4383 tcount = 0;
4384
4385 /*
4386 * Execute the plan
4387 */
4388 rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
4389 estate->readonly_func, tcount);
4390
4391 /*
4392 * Check for error, and set FOUND if appropriate (for historical reasons
4393 * we set FOUND only for certain query types). Also Assert that we
4394 * identified the statement type the same as SPI did.
4395 */
4396 switch (rc)
4397 {
4398 case SPI_OK_SELECT:
4399 Assert(!stmt->mod_stmt);
4400 exec_set_found(estate, (SPI_processed != 0));
4401 break;
4402
4403 case SPI_OK_INSERT:
4404 case SPI_OK_UPDATE:
4405 case SPI_OK_DELETE:
4406 case SPI_OK_MERGE:
4411 Assert(stmt->mod_stmt);
4412 exec_set_found(estate, (SPI_processed != 0));
4413 break;
4414
4415 case SPI_OK_SELINTO:
4416 case SPI_OK_UTILITY:
4417 Assert(!stmt->mod_stmt);
4418 break;
4419
4420 case SPI_OK_REWRITTEN:
4421
4422 /*
4423 * The command was rewritten into another kind of command. It's
4424 * not clear what FOUND would mean in that case (and SPI doesn't
4425 * return the row count either), so just set it to false. Note
4426 * that we can't assert anything about mod_stmt here.
4427 */
4428 exec_set_found(estate, false);
4429 break;
4430
4431 /* Some SPI errors deserve specific error messages */
4432 case SPI_ERROR_COPY:
4433 ereport(ERROR,
4435 errmsg("cannot COPY to/from client in PL/pgSQL")));
4436 break;
4437
4439 ereport(ERROR,
4441 errmsg("unsupported transaction command in PL/pgSQL")));
4442 break;
4443
4444 default:
4445 elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s",
4446 expr->query, SPI_result_code_string(rc));
4447 break;
4448 }
4449
4450 /* All variants should save result info for GET DIAGNOSTICS */
4451 estate->eval_processed = SPI_processed;
4452
4453 /* Process INTO if present */
4454 if (stmt->into)
4455 {
4458 PLpgSQL_variable *target;
4459
4460 /* If the statement did not return a tuple table, complain */
4461 if (tuptab == NULL)
4462 ereport(ERROR,
4464 errmsg("INTO used with a command that cannot return data")));
4465
4466 /* Fetch target's datum entry */
4467 target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4468
4469 /*
4470 * If SELECT ... INTO specified STRICT, and the query didn't find
4471 * exactly one row, throw an error. If STRICT was not specified, then
4472 * allow the query to find any number of rows.
4473 */
4474 if (n == 0)
4475 {
4476 if (stmt->strict)
4477 {
4478 char *errdetail;
4479
4480 if (estate->func->print_strict_params)
4481 errdetail = format_expr_params(estate, expr);
4482 else
4483 errdetail = NULL;
4484
4485 ereport(ERROR,
4487 errmsg("query returned no rows"),
4488 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
4489 }
4490 /* set the target to NULL(s) */
4491 exec_move_row(estate, target, NULL, tuptab->tupdesc);
4492 }
4493 else
4494 {
4495 if (n > 1 && (stmt->strict || stmt->mod_stmt || too_many_rows_level))
4496 {
4497 char *errdetail;
4498 int errlevel;
4499
4500 if (estate->func->print_strict_params)
4501 errdetail = format_expr_params(estate, expr);
4502 else
4503 errdetail = NULL;
4504
4505 errlevel = (stmt->strict || stmt->mod_stmt) ? ERROR : too_many_rows_level;
4506
4509 errmsg("query returned more than one row"),
4510 errdetail ? errdetail_internal("parameters: %s", errdetail) : 0,
4511 errhint("Make sure the query returns a single row, or use LIMIT 1.")));
4512 }
4513 /* Put the first result row into the target */
4514 exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4515 }
4516
4517 /* Clean up */
4518 exec_eval_cleanup(estate);
4520 }
4521 else
4522 {
4523 /* If the statement returned a tuple table, complain */
4524 if (SPI_tuptable != NULL)
4525 ereport(ERROR,
4527 errmsg("query has no destination for result data"),
4528 (rc == SPI_OK_SELECT) ? errhint("If you want to discard the results of a SELECT, use PERFORM instead.") : 0));
4529 }
4530
4531 return PLPGSQL_RC_OK;
4532}

References Assert, ErrorContextCallback::callback, CachedPlanSource::commandTag, CURSOR_OPT_PARALLEL_OK, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, elog, ereport, errcode(), errdetail(), errdetail_internal(), errhint(), errmsg, ERROR, error_context_stack, PLpgSQL_execstate::eval_processed, exec_assign_value(), exec_eval_cleanup(), exec_eval_expr(), exec_move_row(), exec_prepare_plan(), exec_set_found(), PLpgSQL_expr::expr_simple_expr, fb(), format_expr_params(), PLpgSQL_execstate::func, lfirst, PLpgSQL_row::nfields, PLpgSQL_expr::plan, PLPGSQL_DTYPE_ROW, plpgsql_execsql_error_callback(), plpgsql_extra_errors, plpgsql_extra_warnings, PLPGSQL_RC_OK, PLPGSQL_XCHECK_TOOMANYROWS, ErrorContextCallback::previous, 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, value, PLpgSQL_row::varnos, 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 3195 of file pl_exec.c.

3196{
3197 /*
3198 * If the exit / continue has a condition, evaluate it
3199 */
3200 if (stmt->cond != NULL)
3201 {
3202 bool value;
3203 bool isnull;
3204
3205 value = exec_eval_boolean(estate, stmt->cond, &isnull);
3206 exec_eval_cleanup(estate);
3207 if (isnull || value == false)
3208 return PLPGSQL_RC_OK;
3209 }
3210
3211 estate->exitlabel = stmt->label;
3212 if (stmt->is_exit)
3213 return PLPGSQL_RC_EXIT;
3214 else
3215 return PLPGSQL_RC_CONTINUE;
3216}

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 4923 of file pl_exec.c.

4924{
4925 PLpgSQL_var *curvar;
4926 long how_many = stmt->how_many;
4928 Portal portal;
4929 char *curname;
4930 uint64 n;
4931 MemoryContext oldcontext;
4932
4933 /* ----------
4934 * Get the portal of the cursor by name
4935 * ----------
4936 */
4937 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4938 if (curvar->isnull)
4939 ereport(ERROR,
4941 errmsg("cursor variable \"%s\" is null", curvar->refname)));
4942
4943 /* Use eval_mcontext for short-lived string */
4944 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4946 MemoryContextSwitchTo(oldcontext);
4947
4948 portal = SPI_cursor_find(curname);
4949 if (portal == NULL)
4950 ereport(ERROR,
4952 errmsg("cursor \"%s\" does not exist", curname)));
4953
4954 /* Calculate position for FETCH_RELATIVE or FETCH_ABSOLUTE */
4955 if (stmt->expr)
4956 {
4957 bool isnull;
4958
4959 /* XXX should be doing this in LONG not INT width */
4960 how_many = exec_eval_integer(estate, stmt->expr, &isnull);
4961
4962 if (isnull)
4963 ereport(ERROR,
4965 errmsg("relative or absolute cursor position is null")));
4966
4967 exec_eval_cleanup(estate);
4968 }
4969
4970 if (!stmt->is_move)
4971 {
4972 PLpgSQL_variable *target;
4973
4974 /* ----------
4975 * Fetch 1 tuple from the cursor
4976 * ----------
4977 */
4978 SPI_scroll_cursor_fetch(portal, stmt->direction, how_many);
4980 n = SPI_processed;
4981
4982 /* ----------
4983 * Set the target appropriately.
4984 * ----------
4985 */
4986 target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
4987 if (n == 0)
4988 exec_move_row(estate, target, NULL, tuptab->tupdesc);
4989 else
4990 exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
4991
4992 exec_eval_cleanup(estate);
4994 }
4995 else
4996 {
4997 /* Move the cursor */
4998 SPI_scroll_cursor_move(portal, stmt->direction, how_many);
4999 n = SPI_processed;
5000 }
5001
5002 /* Set the ROW_COUNT and the global FOUND variable appropriately. */
5003 estate->eval_processed = n;
5004 exec_set_found(estate, n != 0);
5005
5006 return PLPGSQL_RC_OK;
5007}

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 2899 of file pl_exec.c.

2900{
2901 PLpgSQL_var *curvar;
2902 MemoryContext stmt_mcontext = NULL;
2903 char *curname = NULL;
2904 PLpgSQL_expr *query;
2905 ParamListInfo paramLI;
2906 Portal portal;
2907 int rc;
2908
2909 /* ----------
2910 * Get the cursor variable and if it has an assigned name, check
2911 * that it's not in use currently.
2912 * ----------
2913 */
2914 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
2915 if (!curvar->isnull)
2916 {
2917 MemoryContext oldcontext;
2918
2919 /* We only need stmt_mcontext to hold the cursor name string */
2920 stmt_mcontext = get_stmt_mcontext(estate);
2921 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
2923 MemoryContextSwitchTo(oldcontext);
2924
2926 ereport(ERROR,
2928 errmsg("cursor \"%s\" already in use", curname)));
2929 }
2930
2931 /* ----------
2932 * Open the cursor just like an OPEN command
2933 *
2934 * Note: parser should already have checked that statement supplies
2935 * args iff cursor needs them, but we check again to be safe.
2936 * ----------
2937 */
2938 if (stmt->argquery != NULL)
2939 {
2940 /* ----------
2941 * OPEN CURSOR with args. We fake a SELECT ... INTO ...
2942 * statement to evaluate the args and put 'em into the
2943 * internal row.
2944 * ----------
2945 */
2947
2948 if (curvar->cursor_explicit_argrow < 0)
2949 ereport(ERROR,
2951 errmsg("arguments given for cursor without arguments")));
2952
2953 memset(&set_args, 0, sizeof(set_args));
2954 set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
2955 set_args.lineno = stmt->lineno;
2956 set_args.sqlstmt = stmt->argquery;
2957 set_args.into = true;
2958 /* XXX historically this has not been STRICT */
2959 set_args.target = (PLpgSQL_variable *)
2960 (estate->datums[curvar->cursor_explicit_argrow]);
2961
2962 if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
2963 elog(ERROR, "open cursor failed during argument processing");
2964 }
2965 else
2966 {
2967 if (curvar->cursor_explicit_argrow >= 0)
2968 ereport(ERROR,
2970 errmsg("arguments required for cursor")));
2971 }
2972
2973 query = curvar->cursor_explicit_expr;
2974 Assert(query);
2975
2976 if (query->plan == NULL)
2977 exec_prepare_plan(estate, query, curvar->cursor_options);
2978
2979 /*
2980 * Set up ParamListInfo for this query
2981 */
2982 paramLI = setup_param_list(estate, query);
2983
2984 /*
2985 * Open the cursor (the paramlist will get copied into the portal)
2986 */
2988 paramLI,
2989 estate->readonly_func);
2990 if (portal == NULL)
2991 elog(ERROR, "could not open cursor: %s",
2993
2994 /*
2995 * If cursor variable was NULL, store the generated portal name in it,
2996 * after verifying it's okay to assign to.
2997 */
2998 if (curname == NULL)
2999 {
3000 exec_check_assignable(estate, stmt->curvar);
3001 assign_text_var(estate, curvar, portal->name);
3002 }
3003
3004 /*
3005 * Clean up before entering exec_for_query
3006 */
3007 exec_eval_cleanup(estate);
3008 if (stmt_mcontext)
3009 MemoryContextReset(stmt_mcontext);
3010
3011 /*
3012 * Execute the loop. We can't prefetch because the cursor is accessible
3013 * to the user, for instance via UPDATE WHERE CURRENT OF within the loop.
3014 */
3015 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, false);
3016
3017 /* ----------
3018 * Close portal, and restore cursor variable if it was initially NULL.
3019 * ----------
3020 */
3021 SPI_cursor_close(portal);
3022
3023 if (curname == NULL)
3024 assign_simple_var(estate, curvar, (Datum) 0, true, false);
3025
3026 return rc;
3027}

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 3039 of file pl_exec.c.

3040{
3041 ArrayType *arr;
3042 Oid arrtype;
3046 bool found = false;
3047 int rc = PLPGSQL_RC_OK;
3048 MemoryContext stmt_mcontext;
3049 MemoryContext oldcontext;
3053 Datum value;
3054 bool isnull;
3055
3056 /* get the value of the array expression */
3057 value = exec_eval_expr(estate, stmt->expr, &isnull, &arrtype, &arrtypmod);
3058 if (isnull)
3059 ereport(ERROR,
3061 errmsg("FOREACH expression must not be null")));
3062
3063 /*
3064 * Do as much as possible of the code below in stmt_mcontext, to avoid any
3065 * leaks from called subroutines. We need a private stmt_mcontext since
3066 * we'll be calling arbitrary statement code.
3067 */
3068 stmt_mcontext = get_stmt_mcontext(estate);
3069 push_stmt_mcontext(estate);
3070 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3071
3072 /* check the type of the expression - must be an array */
3074 ereport(ERROR,
3076 errmsg("FOREACH expression must yield an array, not type %s",
3078
3079 /*
3080 * We must copy the array into stmt_mcontext, else it will disappear in
3081 * exec_eval_cleanup. This is annoying, but cleanup will certainly happen
3082 * while running the loop body, so we have little choice.
3083 */
3085
3086 /* Clean up any leftover temporary memory */
3087 exec_eval_cleanup(estate);
3088
3089 /* Slice dimension must be less than or equal to array dimension */
3090 if (stmt->slice < 0 || stmt->slice > ARR_NDIM(arr))
3091 ereport(ERROR,
3093 errmsg("slice dimension (%d) is out of the valid range 0..%d",
3094 stmt->slice, ARR_NDIM(arr))));
3095
3096 /* Set up the loop variable and see if it is of an array type */
3097 loop_var = estate->datums[stmt->varno];
3098 if (loop_var->dtype == PLPGSQL_DTYPE_REC ||
3099 loop_var->dtype == PLPGSQL_DTYPE_ROW)
3100 {
3101 /*
3102 * Record/row variable is certainly not of array type, and might not
3103 * be initialized at all yet, so don't try to get its type
3104 */
3106 }
3107 else
3109 loop_var));
3110
3111 /*
3112 * Sanity-check the loop variable type. We don't try very hard here, and
3113 * should not be too picky since it's possible that exec_assign_value can
3114 * coerce values of different types. But it seems worthwhile to complain
3115 * if the array-ness of the loop variable is not right.
3116 */
3117 if (stmt->slice > 0 && loop_var_elem_type == InvalidOid)
3118 ereport(ERROR,
3120 errmsg("FOREACH ... SLICE loop variable must be of an array type")));
3121 if (stmt->slice == 0 && loop_var_elem_type != InvalidOid)
3122 ereport(ERROR,
3124 errmsg("FOREACH loop variable must not be of an array type")));
3125
3126 /* Create an iterator to step through the array */
3128
3129 /* Identify iterator result type */
3130 if (stmt->slice > 0)
3131 {
3132 /* When slicing, nominal type of result is same as array type */
3135 }
3136 else
3137 {
3138 /* Without slicing, results are individual array elements */
3141 }
3142
3143 /* Iterate over the array elements or slices */
3144 while (array_iterate(array_iterator, &value, &isnull))
3145 {
3146 found = true; /* looped at least once */
3147
3148 /* exec_assign_value and exec_stmts must run in the main context */
3149 MemoryContextSwitchTo(oldcontext);
3150
3151 /* Assign current element/slice to the loop variable */
3152 exec_assign_value(estate, loop_var, value, isnull,
3154
3155 /* In slice case, value is temporary; must free it to avoid leakage */
3156 if (stmt->slice > 0)
3158
3159 /*
3160 * Execute the statements
3161 */
3162 rc = exec_stmts(estate, stmt->body);
3163
3164 LOOP_RC_PROCESSING(stmt->label, break);
3165
3166 MemoryContextSwitchTo(stmt_mcontext);
3167 }
3168
3169 /* Restore memory context state */
3170 MemoryContextSwitchTo(oldcontext);
3171 pop_stmt_mcontext(estate);
3172
3173 /* Release temporary memory, including the array value */
3174 MemoryContextReset(stmt_mcontext);
3175
3176 /*
3177 * Set the FOUND variable to indicate the result of executing the loop
3178 * (namely, whether we looped one or more times). This must be set here so
3179 * that it does not interfere with the value of the FOUND variable inside
3180 * the loop processing itself.
3181 */
3182 exec_set_found(estate, found);
3183
3184 return rc;
3185}

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 2727 of file pl_exec.c.

2728{
2729 PLpgSQL_var *var;
2730 Datum value;
2731 bool isnull;
2732 Oid valtype;
2737 bool found = false;
2738 int rc = PLPGSQL_RC_OK;
2739
2740 var = (PLpgSQL_var *) (estate->datums[stmt->var->dno]);
2741
2742 /*
2743 * Get the value of the lower bound
2744 */
2745 value = exec_eval_expr(estate, stmt->lower,
2746 &isnull, &valtype, &valtypmod);
2747 value = exec_cast_value(estate, value, &isnull,
2749 var->datatype->typoid,
2750 var->datatype->atttypmod);
2751 if (isnull)
2752 ereport(ERROR,
2754 errmsg("lower bound of FOR loop cannot be null")));
2756 exec_eval_cleanup(estate);
2757
2758 /*
2759 * Get the value of the upper bound
2760 */
2761 value = exec_eval_expr(estate, stmt->upper,
2762 &isnull, &valtype, &valtypmod);
2763 value = exec_cast_value(estate, value, &isnull,
2765 var->datatype->typoid,
2766 var->datatype->atttypmod);
2767 if (isnull)
2768 ereport(ERROR,
2770 errmsg("upper bound of FOR loop cannot be null")));
2772 exec_eval_cleanup(estate);
2773
2774 /*
2775 * Get the step value
2776 */
2777 if (stmt->step)
2778 {
2779 value = exec_eval_expr(estate, stmt->step,
2780 &isnull, &valtype, &valtypmod);
2781 value = exec_cast_value(estate, value, &isnull,
2783 var->datatype->typoid,
2784 var->datatype->atttypmod);
2785 if (isnull)
2786 ereport(ERROR,
2788 errmsg("BY value of FOR loop cannot be null")));
2790 exec_eval_cleanup(estate);
2791 if (step_value <= 0)
2792 ereport(ERROR,
2794 errmsg("BY value of FOR loop must be greater than zero")));
2795 }
2796 else
2797 step_value = 1;
2798
2799 /*
2800 * Now do the loop
2801 */
2802 for (;;)
2803 {
2804 /*
2805 * Check against upper bound
2806 */
2807 if (stmt->reverse)
2808 {
2809 if (loop_value < end_value)
2810 break;
2811 }
2812 else
2813 {
2814 if (loop_value > end_value)
2815 break;
2816 }
2817
2818 found = true; /* looped at least once */
2819
2820 /*
2821 * Assign current value to loop var
2822 */
2823 assign_simple_var(estate, var, Int32GetDatum(loop_value), false, false);
2824
2825 /*
2826 * Execute the statements
2827 */
2828 rc = exec_stmts(estate, stmt->body);
2829
2830 LOOP_RC_PROCESSING(stmt->label, break);
2831
2832 /*
2833 * Increase/decrease loop value, unless it would overflow, in which
2834 * case exit the loop.
2835 */
2836 if (stmt->reverse)
2837 {
2839 break;
2841 }
2842 else
2843 {
2845 break;
2847 }
2848 }
2849
2850 /*
2851 * Set the FOUND variable to indicate the result of executing the loop
2852 * (namely, whether we looped one or more times). This must be set here so
2853 * that it does not interfere with the value of the FOUND variable inside
2854 * the loop processing itself.
2855 */
2856 exec_set_found(estate, found);
2857
2858 return rc;
2859}

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 2870 of file pl_exec.c.

2871{
2872 Portal portal;
2873 int rc;
2874
2875 /*
2876 * Open the implicit cursor for the statement using exec_run_select
2877 */
2878 exec_run_select(estate, stmt->query, 0, &portal);
2879
2880 /*
2881 * Execute the loop
2882 */
2883 rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
2884
2885 /*
2886 * Close the implicit cursor
2887 */
2888 SPI_cursor_close(portal);
2889
2890 return rc;
2891}

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 2441 of file pl_exec.c.

2442{
2443 ListCell *lc;
2444
2445 /*
2446 * GET STACKED DIAGNOSTICS is only valid inside an exception handler.
2447 *
2448 * Note: we trust the grammar to have disallowed the relevant item kinds
2449 * if not is_stacked, otherwise we'd dump core below.
2450 */
2451 if (stmt->is_stacked && estate->cur_error == NULL)
2452 ereport(ERROR,
2454 errmsg("GET STACKED DIAGNOSTICS cannot be used outside an exception handler")));
2455
2456 foreach(lc, stmt->diag_items)
2457 {
2459 PLpgSQL_datum *var = estate->datums[diag_item->target];
2460
2461 switch (diag_item->kind)
2462 {
2464 exec_assign_value(estate, var,
2466 false, INT8OID, -1);
2467 break;
2468
2470 exec_assign_value(estate, var,
2471 ObjectIdGetDatum(estate->func->fn_oid),
2472 false, OIDOID, -1);
2473 break;
2474
2476 exec_assign_c_string(estate, var,
2477 estate->cur_error->context);
2478 break;
2479
2481 exec_assign_c_string(estate, var,
2482 estate->cur_error->detail);
2483 break;
2484
2486 exec_assign_c_string(estate, var,
2487 estate->cur_error->hint);
2488 break;
2489
2491 exec_assign_c_string(estate, var,
2493 break;
2494
2496 exec_assign_c_string(estate, var,
2497 estate->cur_error->column_name);
2498 break;
2499
2501 exec_assign_c_string(estate, var,
2502 estate->cur_error->constraint_name);
2503 break;
2504
2506 exec_assign_c_string(estate, var,
2507 estate->cur_error->datatype_name);
2508 break;
2509
2511 exec_assign_c_string(estate, var,
2512 estate->cur_error->message);
2513 break;
2514
2516 exec_assign_c_string(estate, var,
2517 estate->cur_error->table_name);
2518 break;
2519
2521 exec_assign_c_string(estate, var,
2522 estate->cur_error->schema_name);
2523 break;
2524
2526 {
2527 char *contextstackstr;
2528 MemoryContext oldcontext;
2529
2530 /* Use eval_mcontext for short-lived string */
2531 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2533 MemoryContextSwitchTo(oldcontext);
2534
2536 }
2537 break;
2538
2539 default:
2540 elog(ERROR, "unrecognized diagnostic item kind: %d",
2541 diag_item->kind);
2542 }
2543 }
2544
2545 exec_eval_cleanup(estate);
2546
2547 return PLPGSQL_RC_OK;
2548}

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 2557 of file pl_exec.c.

2558{
2559 bool value;
2560 bool isnull;
2561 ListCell *lc;
2562
2563 value = exec_eval_boolean(estate, stmt->cond, &isnull);
2564 exec_eval_cleanup(estate);
2565 if (!isnull && value)
2566 return exec_stmts(estate, stmt->then_body);
2567
2568 foreach(lc, stmt->elsif_list)
2569 {
2571
2572 value = exec_eval_boolean(estate, elif->cond, &isnull);
2573 exec_eval_cleanup(estate);
2574 if (!isnull && value)
2575 return exec_stmts(estate, elif->stmts);
2576 }
2577
2578 return exec_stmts(estate, stmt->else_body);
2579}

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 2674 of file pl_exec.c.

2675{
2676 int rc = PLPGSQL_RC_OK;
2677
2678 for (;;)
2679 {
2680 rc = exec_stmts(estate, stmt->body);
2681
2682 LOOP_RC_PROCESSING(stmt->label, break);
2683 }
2684
2685 return rc;
2686}

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 4758 of file pl_exec.c.

4759{
4760 PLpgSQL_var *curvar;
4761 MemoryContext stmt_mcontext = NULL;
4762 char *curname = NULL;
4763 PLpgSQL_expr *query;
4764 Portal portal;
4765 ParamListInfo paramLI;
4766
4767 /* ----------
4768 * Get the cursor variable and if it has an assigned name, check
4769 * that it's not in use currently.
4770 * ----------
4771 */
4772 curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4773 if (!curvar->isnull)
4774 {
4775 MemoryContext oldcontext;
4776
4777 /* We only need stmt_mcontext to hold the cursor name string */
4778 stmt_mcontext = get_stmt_mcontext(estate);
4779 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
4781 MemoryContextSwitchTo(oldcontext);
4782
4784 ereport(ERROR,
4786 errmsg("cursor \"%s\" already in use", curname)));
4787 }
4788
4789 /* ----------
4790 * Process the OPEN according to its type.
4791 * ----------
4792 */
4793 if (stmt->query != NULL)
4794 {
4795 /* ----------
4796 * This is an OPEN refcursor FOR SELECT ...
4797 *
4798 * We just make sure the query is planned. The real work is
4799 * done downstairs.
4800 * ----------
4801 */
4802 query = stmt->query;
4803 if (query->plan == NULL)
4804 exec_prepare_plan(estate, query, stmt->cursor_options);
4805 }
4806 else if (stmt->dynquery != NULL)
4807 {
4808 /* ----------
4809 * This is an OPEN refcursor FOR EXECUTE ...
4810 * ----------
4811 */
4812 portal = exec_dynquery_with_params(estate,
4813 stmt->dynquery,
4814 stmt->params,
4815 curname,
4816 stmt->cursor_options);
4817
4818 /*
4819 * If cursor variable was NULL, store the generated portal name in it,
4820 * after verifying it's okay to assign to.
4821 *
4822 * Note: exec_dynquery_with_params already reset the stmt_mcontext, so
4823 * curname is a dangling pointer here; but testing it for nullness is
4824 * OK.
4825 */
4826 if (curname == NULL)
4827 {
4828 exec_check_assignable(estate, stmt->curvar);
4829 assign_text_var(estate, curvar, portal->name);
4830 }
4831
4832 return PLPGSQL_RC_OK;
4833 }
4834 else
4835 {
4836 /* ----------
4837 * This is an OPEN cursor
4838 *
4839 * Note: parser should already have checked that statement supplies
4840 * args iff cursor needs them, but we check again to be safe.
4841 * ----------
4842 */
4843 if (stmt->argquery != NULL)
4844 {
4845 /* ----------
4846 * OPEN CURSOR with args. We fake a SELECT ... INTO ...
4847 * statement to evaluate the args and put 'em into the
4848 * internal row.
4849 * ----------
4850 */
4852
4853 if (curvar->cursor_explicit_argrow < 0)
4854 ereport(ERROR,
4856 errmsg("arguments given for cursor without arguments")));
4857
4858 memset(&set_args, 0, sizeof(set_args));
4859 set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
4860 set_args.lineno = stmt->lineno;
4861 set_args.sqlstmt = stmt->argquery;
4862 set_args.into = true;
4863 /* XXX historically this has not been STRICT */
4864 set_args.target = (PLpgSQL_variable *)
4865 (estate->datums[curvar->cursor_explicit_argrow]);
4866
4867 if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
4868 elog(ERROR, "open cursor failed during argument processing");
4869 }
4870 else
4871 {
4872 if (curvar->cursor_explicit_argrow >= 0)
4873 ereport(ERROR,
4875 errmsg("arguments required for cursor")));
4876 }
4877
4878 query = curvar->cursor_explicit_expr;
4879 if (query->plan == NULL)
4880 exec_prepare_plan(estate, query, curvar->cursor_options);
4881 }
4882
4883 /*
4884 * Set up ParamListInfo for this query
4885 */
4886 paramLI = setup_param_list(estate, query);
4887
4888 /*
4889 * Open the cursor (the paramlist will get copied into the portal)
4890 */
4892 paramLI,
4893 estate->readonly_func);
4894 if (portal == NULL)
4895 elog(ERROR, "could not open cursor: %s",
4897
4898 /*
4899 * If cursor variable was NULL, store the generated portal name in it,
4900 * after verifying it's okay to assign to.
4901 */
4902 if (curname == NULL)
4903 {
4904 exec_check_assignable(estate, stmt->curvar);
4905 assign_text_var(estate, curvar, portal->name);
4906 }
4907
4908 /* If we had any transient data, clean it up */
4909 exec_eval_cleanup(estate);
4910 if (stmt_mcontext)
4911 MemoryContextReset(stmt_mcontext);
4912
4913 return PLPGSQL_RC_OK;
4914}

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 2211 of file pl_exec.c.

2212{
2213 PLpgSQL_expr *expr = stmt->expr;
2214
2215 (void) exec_run_select(estate, expr, 0, NULL);
2216 exec_set_found(estate, (estate->eval_processed != 0));
2217 exec_eval_cleanup(estate);
2218
2219 return PLPGSQL_RC_OK;
2220}

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 3758 of file pl_exec.c.

3759{
3760 int err_code = 0;
3761 char *condname = NULL;
3762 char *err_message = NULL;
3763 char *err_detail = NULL;
3764 char *err_hint = NULL;
3765 char *err_column = NULL;
3766 char *err_constraint = NULL;
3767 char *err_datatype = NULL;
3768 char *err_table = NULL;
3769 char *err_schema = NULL;
3770 MemoryContext stmt_mcontext;
3771 ListCell *lc;
3772
3773 /* RAISE with no parameters: re-throw current exception */
3774 if (stmt->condname == NULL && stmt->message == NULL &&
3775 stmt->options == NIL)
3776 {
3777 if (estate->cur_error != NULL)
3778 ReThrowError(estate->cur_error);
3779 /* oops, we're not inside a handler */
3780 ereport(ERROR,
3782 errmsg("RAISE without parameters cannot be used outside an exception handler")));
3783 }
3784
3785 /* We'll need to accumulate the various strings in stmt_mcontext */
3786 stmt_mcontext = get_stmt_mcontext(estate);
3787
3788 if (stmt->condname)
3789 {
3791 condname = MemoryContextStrdup(stmt_mcontext, stmt->condname);
3792 }
3793
3794 if (stmt->message)
3795 {
3798 char *cp;
3799 MemoryContext oldcontext;
3800
3801 /* build string in stmt_mcontext */
3802 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3804 MemoryContextSwitchTo(oldcontext);
3805
3806 current_param = list_head(stmt->params);
3807
3808 for (cp = stmt->message; *cp; cp++)
3809 {
3810 /*
3811 * Occurrences of a single % are replaced by the next parameter's
3812 * external representation. Double %'s are converted to one %.
3813 */
3814 if (cp[0] == '%')
3815 {
3817 int32 paramtypmod;
3819 bool paramisnull;
3820 char *extval;
3821
3822 if (cp[1] == '%')
3823 {
3824 appendStringInfoChar(&ds, '%');
3825 cp++;
3826 continue;
3827 }
3828
3829 /* should have been checked at compile time */
3830 if (current_param == NULL)
3831 elog(ERROR, "unexpected RAISE parameter list length");
3832
3833 paramvalue = exec_eval_expr(estate,
3835 &paramisnull,
3836 &paramtypeid,
3837 &paramtypmod);
3838
3839 if (paramisnull)
3840 extval = "<NULL>";
3841 else
3843 paramvalue,
3844 paramtypeid);
3847 exec_eval_cleanup(estate);
3848 }
3849 else
3851 }
3852
3853 /* should have been checked at compile time */
3854 if (current_param != NULL)
3855 elog(ERROR, "unexpected RAISE parameter list length");
3856
3857 err_message = ds.data;
3858 }
3859
3860 foreach(lc, stmt->options)
3861 {
3864 bool optionisnull;
3867 char *extval;
3868
3869 optionvalue = exec_eval_expr(estate, opt->expr,
3870 &optionisnull,
3871 &optiontypeid,
3872 &optiontypmod);
3873 if (optionisnull)
3874 ereport(ERROR,
3876 errmsg("RAISE statement option cannot be null")));
3877
3879
3880 switch (opt->opt_type)
3881 {
3883 if (err_code)
3884 ereport(ERROR,
3886 errmsg("RAISE option already specified: %s",
3887 "ERRCODE")));
3889 condname = MemoryContextStrdup(stmt_mcontext, extval);
3890 break;
3893 break;
3896 break;
3899 break;
3902 break;
3905 break;
3908 break;
3911 break;
3914 break;
3915 default:
3916 elog(ERROR, "unrecognized raise option: %d", opt->opt_type);
3917 }
3918
3919 exec_eval_cleanup(estate);
3920 }
3921
3922 /* Default code if nothing specified */
3923 if (err_code == 0 && stmt->elog_level >= ERROR)
3925
3926 /* Default error message if nothing specified */
3927 if (err_message == NULL)
3928 {
3929 if (condname)
3930 {
3931 err_message = condname;
3932 condname = NULL;
3933 }
3934 else
3935 err_message = MemoryContextStrdup(stmt_mcontext,
3937 }
3938
3939 /*
3940 * Throw the error (may or may not come back)
3941 */
3942 ereport(stmt->elog_level,
3943 (err_code ? errcode(err_code) : 0,
3945 (err_detail != NULL) ? errdetail_internal("%s", err_detail) : 0,
3946 (err_hint != NULL) ? errhint("%s", err_hint) : 0,
3947 (err_column != NULL) ?
3949 (err_constraint != NULL) ?
3951 (err_datatype != NULL) ?
3953 (err_table != NULL) ?
3955 (err_schema != NULL) ?
3957
3958 /* Clean up transient strings */
3959 MemoryContextReset(stmt_mcontext);
3960
3961 return PLPGSQL_RC_OK;
3962}

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 3228 of file pl_exec.c.

3229{
3230 /*
3231 * If processing a set-returning PL/pgSQL function, the final RETURN
3232 * indicates that the function is finished producing tuples. The rest of
3233 * the work will be done at the top level.
3234 */
3235 if (estate->retisset)
3236 return PLPGSQL_RC_RETURN;
3237
3238 /* initialize for null result */
3239 estate->retval = (Datum) 0;
3240 estate->retisnull = true;
3241 estate->rettype = InvalidOid;
3242
3243 /*
3244 * Special case path when the RETURN expression is a simple variable
3245 * reference; in particular, this path is always taken in functions with
3246 * one or more OUT parameters.
3247 *
3248 * This special case is especially efficient for returning variables that
3249 * have R/W expanded values: we can put the R/W pointer directly into
3250 * estate->retval, leading to transferring the value to the caller's
3251 * context cheaply. If we went through exec_eval_expr we'd end up with a
3252 * R/O pointer. It's okay to skip MakeExpandedObjectReadOnly here since
3253 * we know we won't need the variable's value within the function anymore.
3254 */
3255 if (stmt->retvarno >= 0)
3256 {
3257 PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
3258
3259 switch (retvar->dtype)
3260 {
3262 /* fulfill promise if needed, then handle like regular var */
3264
3266
3267 case PLPGSQL_DTYPE_VAR:
3268 {
3269 PLpgSQL_var *var = (PLpgSQL_var *) retvar;
3270
3271 estate->retval = var->value;
3272 estate->retisnull = var->isnull;
3273 estate->rettype = var->datatype->typoid;
3274
3275 /*
3276 * A PLpgSQL_var could not be of composite type, so
3277 * conversion must fail if retistuple. We throw a custom
3278 * error mainly for consistency with historical behavior.
3279 * For the same reason, we don't throw error if the result
3280 * is NULL. (Note that plpgsql_exec_trigger assumes that
3281 * any non-null result has been verified to be composite.)
3282 */
3283 if (estate->retistuple && !estate->retisnull)
3284 ereport(ERROR,
3286 errmsg("cannot return non-composite value from function returning composite type")));
3287 }
3288 break;
3289
3290 case PLPGSQL_DTYPE_ROW:
3291 case PLPGSQL_DTYPE_REC:
3292 {
3293 /* exec_eval_datum can handle these cases */
3295
3296 exec_eval_datum(estate,
3297 retvar,
3298 &estate->rettype,
3299 &rettypmod,
3300 &estate->retval,
3301 &estate->retisnull);
3302 }
3303 break;
3304
3305 default:
3306 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
3307 }
3308
3309 return PLPGSQL_RC_RETURN;
3310 }
3311
3312 if (stmt->expr != NULL)
3313 {
3315
3316 estate->retval = exec_eval_expr(estate, stmt->expr,
3317 &(estate->retisnull),
3318 &(estate->rettype),
3319 &rettypmod);
3320
3321 /*
3322 * As in the DTYPE_VAR case above, throw a custom error if a non-null,
3323 * non-composite value is returned in a function returning tuple.
3324 */
3325 if (estate->retistuple && !estate->retisnull &&
3326 !type_is_rowtype(estate->rettype))
3327 ereport(ERROR,
3329 errmsg("cannot return non-composite value from function returning composite type")));
3330
3331 return PLPGSQL_RC_RETURN;
3332 }
3333
3334 /*
3335 * Special hack for function returning VOID: instead of NULL, return a
3336 * non-null VOID value. This is of dubious importance but is kept for
3337 * backwards compatibility. We don't do it for procedures, though.
3338 */
3339 if (estate->fn_rettype == VOIDOID &&
3340 estate->func->fn_prokind != PROKIND_PROCEDURE)
3341 {
3342 estate->retval = (Datum) 0;
3343 estate->retisnull = false;
3344 estate->rettype = VOIDOID;
3345 }
3346
3347 return PLPGSQL_RC_RETURN;
3348}

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 3357 of file pl_exec.c.

3359{
3360 TupleDesc tupdesc;
3361 int natts;
3362 HeapTuple tuple;
3363 MemoryContext oldcontext;
3364
3365 if (!estate->retisset)
3366 ereport(ERROR,
3368 errmsg("cannot use RETURN NEXT in a non-SETOF function")));
3369
3370 if (estate->tuple_store == NULL)
3371 exec_init_tuple_store(estate);
3372
3373 /* tuple_store_desc will be filled by exec_init_tuple_store */
3374 tupdesc = estate->tuple_store_desc;
3375 natts = tupdesc->natts;
3376
3377 /*
3378 * Special case path when the RETURN NEXT expression is a simple variable
3379 * reference; in particular, this path is always taken in functions with
3380 * one or more OUT parameters.
3381 *
3382 * Unlike exec_stmt_return, there's no special win here for R/W expanded
3383 * values, since they'll have to get flattened to go into the tuplestore.
3384 * Indeed, we'd better make them R/O to avoid any risk of the casting step
3385 * changing them in-place.
3386 */
3387 if (stmt->retvarno >= 0)
3388 {
3389 PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
3390
3391 switch (retvar->dtype)
3392 {
3394 /* fulfill promise if needed, then handle like regular var */
3396
3398
3399 case PLPGSQL_DTYPE_VAR:
3400 {
3401 PLpgSQL_var *var = (PLpgSQL_var *) retvar;
3402 Datum retval = var->value;
3403 bool isNull = var->isnull;
3404 Form_pg_attribute attr;
3405
3406 if (natts != 1)
3407 ereport(ERROR,
3409 errmsg("wrong result type supplied in RETURN NEXT")));
3410
3411 /* let's be very paranoid about the cast step */
3412 retval = MakeExpandedObjectReadOnly(retval,
3413 isNull,
3414 var->datatype->typlen);
3415
3416 /* coerce type if needed */
3417 attr = TupleDescAttr(tupdesc, 0);
3418 retval = exec_cast_value(estate,
3419 retval,
3420 &isNull,
3421 var->datatype->typoid,
3422 var->datatype->atttypmod,
3423 attr->atttypid,
3424 attr->atttypmod);
3425
3426 tuplestore_putvalues(estate->tuple_store, tupdesc,
3427 &retval, &isNull);
3428 }
3429 break;
3430
3431 case PLPGSQL_DTYPE_REC:
3432 {
3433 PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
3435 TupleConversionMap *tupmap;
3436
3437 /* If rec is null, try to convert it to a row of nulls */
3438 if (rec->erh == NULL)
3440 if (ExpandedRecordIsEmpty(rec->erh))
3442
3443 /* Use eval_mcontext for tuple conversion work */
3444 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3447 tupdesc,
3448 gettext_noop("wrong record type supplied in RETURN NEXT"));
3449 tuple = expanded_record_get_tuple(rec->erh);
3450 if (tupmap)
3451 tuple = execute_attr_map_tuple(tuple, tupmap);
3452 tuplestore_puttuple(estate->tuple_store, tuple);
3453 MemoryContextSwitchTo(oldcontext);
3454 }
3455 break;
3456
3457 case PLPGSQL_DTYPE_ROW:
3458 {
3459 PLpgSQL_row *row = (PLpgSQL_row *) retvar;
3460
3461 /* We get here if there are multiple OUT parameters */
3462
3463 /* Use eval_mcontext for tuple conversion work */
3464 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3465 tuple = make_tuple_from_row(estate, row, tupdesc);
3466 if (tuple == NULL) /* should not happen */
3467 ereport(ERROR,
3469 errmsg("wrong record type supplied in RETURN NEXT")));
3470 tuplestore_puttuple(estate->tuple_store, tuple);
3471 MemoryContextSwitchTo(oldcontext);
3472 }
3473 break;
3474
3475 default:
3476 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
3477 break;
3478 }
3479 }
3480 else if (stmt->expr)
3481 {
3482 Datum retval;
3483 bool isNull;
3484 Oid rettype;
3486
3487 retval = exec_eval_expr(estate,
3488 stmt->expr,
3489 &isNull,
3490 &rettype,
3491 &rettypmod);
3492
3493 if (estate->retistuple)
3494 {
3495 /* Expression should be of RECORD or composite type */
3496 if (!isNull)
3497 {
3500 TupleConversionMap *tupmap;
3501
3502 if (!type_is_rowtype(rettype))
3503 ereport(ERROR,
3505 errmsg("cannot return non-composite value from function returning composite type")));
3506
3507 /* Use eval_mcontext for tuple conversion work */
3508 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
3510 tuple = &tmptup;
3511 tupmap = convert_tuples_by_position(retvaldesc, tupdesc,
3512 gettext_noop("returned record type does not match expected record type"));
3513 if (tupmap)
3514 tuple = execute_attr_map_tuple(tuple, tupmap);
3515 tuplestore_puttuple(estate->tuple_store, tuple);
3517 MemoryContextSwitchTo(oldcontext);
3518 }
3519 else
3520 {
3521 /* Composite NULL --- store a row of nulls */
3523 bool *nullflags;
3524
3525 nulldatums = (Datum *)
3526 eval_mcontext_alloc0(estate, natts * sizeof(Datum));
3527 nullflags = (bool *)
3528 eval_mcontext_alloc(estate, natts * sizeof(bool));
3529 memset(nullflags, true, natts * sizeof(bool));
3530 tuplestore_putvalues(estate->tuple_store, tupdesc,
3532 }
3533 }
3534 else
3535 {
3536 Form_pg_attribute attr;
3537
3538 /* Simple scalar result */
3539 if (natts != 1)
3540 ereport(ERROR,
3542 errmsg("wrong result type supplied in RETURN NEXT")));
3543
3544 /* coerce type if needed */
3545 attr = TupleDescAttr(tupdesc, 0);
3546 retval = exec_cast_value(estate,
3547 retval,
3548 &isNull,
3549 rettype,
3550 rettypmod,
3551 attr->atttypid,
3552 attr->atttypmod);
3553
3554 tuplestore_putvalues(estate->tuple_store, tupdesc,
3555 &retval, &isNull);
3556 }
3557 }
3558 else
3559 {
3560 ereport(ERROR,
3562 errmsg("RETURN NEXT must have a parameter")));
3563 }
3564
3565 exec_eval_cleanup(estate);
3566
3567 return PLPGSQL_RC_OK;
3568}

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 3577 of file pl_exec.c.

3579{
3580 int64 tcount;
3582 int rc;
3583 uint64 processed;
3584 MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
3585 MemoryContext oldcontext;
3586
3587 if (!estate->retisset)
3588 ereport(ERROR,
3590 errmsg("cannot use RETURN QUERY in a non-SETOF function")));
3591
3592 if (estate->tuple_store == NULL)
3593 exec_init_tuple_store(estate);
3594 /* There might be some tuples in the tuplestore already */
3595 tcount = tuplestore_tuple_count(estate->tuple_store);
3596
3597 /*
3598 * Set up DestReceiver to transfer results directly to tuplestore,
3599 * converting rowtype if necessary. DestReceiver lives in mcontext.
3600 */
3601 oldcontext = MemoryContextSwitchTo(stmt_mcontext);
3604 estate->tuple_store,
3605 estate->tuple_store_cxt,
3606 false,
3607 estate->tuple_store_desc,
3608 gettext_noop("structure of query does not match function result type"));
3609 MemoryContextSwitchTo(oldcontext);
3610
3611 if (stmt->query != NULL)
3612 {
3613 /* static query */
3614 PLpgSQL_expr *expr = stmt->query;
3615 ParamListInfo paramLI;
3617
3618 /*
3619 * On the first call for this expression generate the plan.
3620 */
3621 if (expr->plan == NULL)
3623
3624 /*
3625 * Set up ParamListInfo to pass to executor
3626 */
3627 paramLI = setup_param_list(estate, expr);
3628
3629 /*
3630 * Execute the query
3631 */
3632 memset(&options, 0, sizeof(options));
3633 options.params = paramLI;
3634 options.read_only = estate->readonly_func;
3635 options.must_return_tuples = true;
3636 options.dest = treceiver;
3637
3639 if (rc < 0)
3640 elog(ERROR, "SPI_execute_plan_extended failed executing query \"%s\": %s",
3641 expr->query, SPI_result_code_string(rc));
3642 }
3643 else
3644 {
3645 /* RETURN QUERY EXECUTE */
3646 Datum query;
3647 bool isnull;
3648 Oid restype;
3650 char *querystr;
3652
3653 /*
3654 * Evaluate the string expression after the EXECUTE keyword. Its
3655 * result is the querystring we have to execute.
3656 */
3657 Assert(stmt->dynquery != NULL);
3658 query = exec_eval_expr(estate, stmt->dynquery,
3659 &isnull, &restype, &restypmod);
3660 if (isnull)
3661 ereport(ERROR,
3663 errmsg("query string argument of EXECUTE is null")));
3664
3665 /* Get the C-String representation */
3666 querystr = convert_value_to_string(estate, query, restype);
3667
3668 /* copy it into the stmt_mcontext before we clean up */
3669 querystr = MemoryContextStrdup(stmt_mcontext, querystr);
3670
3671 exec_eval_cleanup(estate);
3672
3673 /* Execute query, passing params if necessary */
3674 memset(&options, 0, sizeof(options));
3675 options.params = exec_eval_using_params(estate,
3676 stmt->params);
3677 options.read_only = estate->readonly_func;
3678 options.must_return_tuples = true;
3679 options.dest = treceiver;
3680
3682 if (rc < 0)
3683 elog(ERROR, "SPI_execute_extended failed executing query \"%s\": %s",
3685 }
3686
3687 /* Clean up */
3688 treceiver->rDestroy(treceiver);
3689 exec_eval_cleanup(estate);
3690 MemoryContextReset(stmt_mcontext);
3691
3692 /* Count how many tuples we got */
3693 processed = tuplestore_tuple_count(estate->tuple_store) - tcount;
3694
3695 estate->eval_processed = processed;
3696 exec_set_found(estate, processed != 0);
3697
3698 return PLPGSQL_RC_OK;
3699}

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 5081 of file pl_exec.c.

5082{
5083 if (stmt->chain)
5085 else
5086 SPI_rollback();
5087
5088 /*
5089 * We need to build new simple-expression infrastructure, since the old
5090 * data structures are gone.
5091 */
5092 estate->simple_eval_estate = NULL;
5093 estate->simple_eval_resowner = NULL;
5095
5096 return PLPGSQL_RC_OK;
5097}

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 2696 of file pl_exec.c.

2697{
2698 int rc = PLPGSQL_RC_OK;
2699
2700 for (;;)
2701 {
2702 bool value;
2703 bool isnull;
2704
2705 value = exec_eval_boolean(estate, stmt->cond, &isnull);
2706 exec_eval_cleanup(estate);
2707
2708 if (isnull || !value)
2709 break;
2710
2711 rc = exec_stmts(estate, stmt->body);
2712
2713 LOOP_RC_PROCESSING(stmt->label, break);
2714 }
2715
2716 return rc;
2717}

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 2027 of file pl_exec.c.

2028{
2029 PLpgSQL_stmt *save_estmt = estate->err_stmt;
2030 ListCell *s;
2031
2032 if (stmts == NIL)
2033 {
2034 /*
2035 * Ensure we do a CHECK_FOR_INTERRUPTS() even though there is no
2036 * statement. This prevents hangup in a tight loop if, for instance,
2037 * there is a LOOP construct with an empty body.
2038 */
2040 return PLPGSQL_RC_OK;
2041 }
2042
2043 foreach(s, stmts)
2044 {
2046 int rc;
2047
2048 estate->err_stmt = stmt;
2049
2050 /* Let the plugin know that we are about to execute this statement */
2051 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
2052 ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
2053
2055
2056 switch (stmt->cmd_type)
2057 {
2058 case PLPGSQL_STMT_BLOCK:
2059 rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
2060 break;
2061
2063 rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
2064 break;
2065
2068 break;
2069
2070 case PLPGSQL_STMT_CALL:
2071 rc = exec_stmt_call(estate, (PLpgSQL_stmt_call *) stmt);
2072 break;
2073
2076 break;
2077
2078 case PLPGSQL_STMT_IF:
2079 rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
2080 break;
2081
2082 case PLPGSQL_STMT_CASE:
2083 rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
2084 break;
2085
2086 case PLPGSQL_STMT_LOOP:
2087 rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
2088 break;
2089
2090 case PLPGSQL_STMT_WHILE:
2091 rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
2092 break;
2093
2094 case PLPGSQL_STMT_FORI:
2095 rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
2096 break;
2097
2098 case PLPGSQL_STMT_FORS:
2099 rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
2100 break;
2101
2102 case PLPGSQL_STMT_FORC:
2103 rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
2104 break;
2105
2108 break;
2109
2110 case PLPGSQL_STMT_EXIT:
2111 rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
2112 break;
2113
2115 rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
2116 break;
2117
2120 break;
2121
2124 break;
2125
2126 case PLPGSQL_STMT_RAISE:
2127 rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
2128 break;
2129
2131 rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
2132 break;
2133
2136 break;
2137
2140 break;
2141
2144 break;
2145
2146 case PLPGSQL_STMT_OPEN:
2147 rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
2148 break;
2149
2150 case PLPGSQL_STMT_FETCH:
2151 rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
2152 break;
2153
2154 case PLPGSQL_STMT_CLOSE:
2155 rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
2156 break;
2157
2159 rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit *) stmt);
2160 break;
2161
2164 break;
2165
2166 default:
2167 /* point err_stmt to parent, since this one seems corrupt */
2168 estate->err_stmt = save_estmt;
2169 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
2170 rc = -1; /* keep compiler quiet */
2171 }
2172
2173 /* Let the plugin know that we have finished executing this statement */
2174 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
2175 ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
2176
2177 if (rc != PLPGSQL_RC_OK)
2178 {
2179 estate->err_stmt = save_estmt;
2180 return rc;
2181 }
2182 } /* end of loop over statements */
2183
2184 estate->err_stmt = save_estmt;
2185 return PLPGSQL_RC_OK;
2186}

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 1665 of file pl_exec.c.

1666{
1667 int rc;
1668
1669 estate->err_stmt = (PLpgSQL_stmt *) block;
1670
1671 /* Let the plugin know that we are about to execute this statement */
1672 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
1673 ((*plpgsql_plugin_ptr)->stmt_beg) (estate, (PLpgSQL_stmt *) block);
1674
1676
1677 rc = exec_stmt_block(estate, block);
1678
1679 /* Let the plugin know that we have finished executing this statement */
1680 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
1681 ((*plpgsql_plugin_ptr)->stmt_end) (estate, (PLpgSQL_stmt *) block);
1682
1683 estate->err_stmt = NULL;
1684
1685 return rc;
1686}

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 9122 of file pl_exec.c.

9124{
9125 int paramno;
9126 int dno;
9128 MemoryContext oldcontext;
9129
9130 if (!expr->paramnos)
9131 return NULL;
9132
9133 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
9134
9136 paramno = 0;
9137 dno = -1;
9138 while ((dno = bms_next_member(expr->paramnos, dno)) >= 0)
9139 {
9142 bool paramisnull;
9143 int32 paramtypmod;
9144 PLpgSQL_var *curvar;
9145
9146 curvar = (PLpgSQL_var *) estate->datums[dno];
9147
9148 exec_eval_datum(estate, (PLpgSQL_datum *) curvar,
9149 &paramtypeid, &paramtypmod,
9151
9152 appendStringInfo(&paramstr, "%s%s = ",
9153 paramno > 0 ? ", " : "",
9154 curvar->refname);
9155
9156 if (paramisnull)
9158 else
9161 paramdatum,
9162 paramtypeid),
9163 -1);
9164
9165 paramno++;
9166 }
9167
9168 MemoryContextSwitchTo(oldcontext);
9169
9170 return paramstr.data;
9171}

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 9179 of file pl_exec.c.

9181{
9182 int paramno;
9184 MemoryContext oldcontext;
9185
9186 if (!paramLI)
9187 return NULL;
9188
9189 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
9190
9192 for (paramno = 0; paramno < paramLI->numParams; paramno++)
9193 {
9194 ParamExternData *prm = &paramLI->params[paramno];
9195
9196 /*
9197 * Note: for now, this is only used on ParamListInfos produced by
9198 * exec_eval_using_params(), so we don't worry about invoking the
9199 * paramFetch hook or skipping unused parameters.
9200 */
9201 appendStringInfo(&paramstr, "%s$%d = ",
9202 paramno > 0 ? ", " : "",
9203 paramno + 1);
9204
9205 if (prm->isnull)
9207 else
9210 prm->value,
9211 prm->ptype),
9212 -1);
9213 }
9214
9215 MemoryContextSwitchTo(oldcontext);
9216
9217 return paramstr.data;
9218}

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 8043 of file pl_exec.c.

8046{
8050 bool found;
8052 MemoryContext oldcontext;
8053
8054 /* Look for existing entry */
8055 cast_key.srctype = srctype;
8056 cast_key.dsttype = dsttype;
8057 cast_key.srctypmod = srctypmod;
8058 cast_key.dsttypmod = dsttypmod;
8060 &cast_key,
8061 HASH_ENTER, &found);
8062 if (!found) /* initialize if new entry */
8063 {
8064 /* We need a second lookup to see if a cast_expr_hash entry exists */
8066 &cast_key,
8067 HASH_ENTER,
8068 &found);
8069 if (!found) /* initialize if new expr entry */
8070 expr_entry->cast_cexpr = NULL;
8071
8072 cast_entry->cast_centry = expr_entry;
8073 cast_entry->cast_exprstate = NULL;
8074 cast_entry->cast_in_use = false;
8076 }
8077 else
8078 {
8079 /* Use always-valid link to avoid a second hash lookup */
8080 expr_entry = cast_entry->cast_centry;
8081 }
8082
8083 if (expr_entry->cast_cexpr == NULL ||
8084 !expr_entry->cast_cexpr->is_valid)
8085 {
8086 /*
8087 * We've not looked up this coercion before, or we have but the cached
8088 * expression has been invalidated.
8089 */
8090 Node *cast_expr;
8091 CachedExpression *cast_cexpr;
8093
8094 /*
8095 * Drop old cached expression if there is one.
8096 */
8097 if (expr_entry->cast_cexpr)
8098 {
8099 FreeCachedExpression(expr_entry->cast_cexpr);
8100 expr_entry->cast_cexpr = NULL;
8101 }
8102
8103 /*
8104 * Since we could easily fail (no such coercion), construct a
8105 * temporary coercion expression tree in the short-lived
8106 * eval_mcontext, then if successful save it as a CachedExpression.
8107 */
8108 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
8109
8110 /*
8111 * We use a CaseTestExpr as the base of the coercion tree, since it's
8112 * very cheap to insert the source value for that.
8113 */
8115 placeholder->typeId = srctype;
8116 placeholder->typeMod = srctypmod;
8117 placeholder->collation = get_typcollation(srctype);
8118
8119 /*
8120 * Apply coercion. We use the special coercion context
8121 * COERCION_PLPGSQL to match plpgsql's historical behavior, namely
8122 * that any cast not available at ASSIGNMENT level will be implemented
8123 * as an I/O coercion. (It's somewhat dubious that we prefer I/O
8124 * coercion over cast pathways that exist at EXPLICIT level. Changing
8125 * that would cause assorted minor behavioral differences though, and
8126 * a user who wants the explicit-cast behavior can always write an
8127 * explicit cast.)
8128 *
8129 * If source type is UNKNOWN, coerce_to_target_type will fail (it only
8130 * expects to see that for Const input nodes), so don't call it; we'll
8131 * apply CoerceViaIO instead. Likewise, it doesn't currently work for
8132 * coercing RECORD to some other type, so skip for that too.
8133 */
8134 if (srctype == UNKNOWNOID || srctype == RECORDOID)
8135 cast_expr = NULL;
8136 else
8137 cast_expr = coerce_to_target_type(NULL,
8138 (Node *) placeholder, srctype,
8139 dsttype, dsttypmod,
8142 -1);
8143
8144 /*
8145 * If there's no cast path according to the parser, fall back to using
8146 * an I/O coercion; this is semantically dubious but matches plpgsql's
8147 * historical behavior. We would need something of the sort for
8148 * UNKNOWN literals in any case. (This is probably now only reachable
8149 * in the case where srctype is UNKNOWN/RECORD.)
8150 */
8151 if (cast_expr == NULL)
8152 {
8153 CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
8154
8155 iocoerce->arg = (Expr *) placeholder;
8156 iocoerce->resulttype = dsttype;
8157 iocoerce->resultcollid = InvalidOid;
8158 iocoerce->coerceformat = COERCE_IMPLICIT_CAST;
8159 iocoerce->location = -1;
8160 cast_expr = (Node *) iocoerce;
8161 if (dsttypmod != -1)
8162 cast_expr = coerce_to_target_type(NULL,
8163 cast_expr, dsttype,
8164 dsttype, dsttypmod,
8167 -1);
8168 }
8169
8170 /* Note: we don't bother labeling the expression tree with collation */
8171
8172 /* Plan the expression and build a CachedExpression */
8173 cast_cexpr = GetCachedExpression(cast_expr);
8174 cast_expr = cast_cexpr->expr;
8175
8176 /* Detect whether we have a no-op (RelabelType) coercion */
8177 if (IsA(cast_expr, RelabelType) &&
8178 ((RelabelType *) cast_expr)->arg == (Expr *) placeholder)
8179 cast_expr = NULL;
8180
8181 /* Now we can fill in the expression hashtable entry. */
8182 expr_entry->cast_cexpr = cast_cexpr;
8183 expr_entry->cast_expr = (Expr *) cast_expr;
8184
8185 /* Be sure to reset the exprstate hashtable entry, too. */
8186 cast_entry->cast_exprstate = NULL;
8187 cast_entry->cast_in_use = false;
8189
8190 MemoryContextSwitchTo(oldcontext);
8191 }
8192
8193 /* Done if we have determined that this is a no-op cast. */
8194 if (expr_entry->cast_expr == NULL)
8195 return NULL;
8196
8197 /*
8198 * Prepare the expression for execution, if it's not been done already in
8199 * the current transaction; also, if it's marked busy in the current
8200 * transaction, abandon that expression tree and build a new one, so as to
8201 * avoid potential problems with recursive cast expressions and failed
8202 * executions. (We will leak some memory intra-transaction if that
8203 * happens a lot, but we don't expect it to.) It's okay to update the
8204 * hash table with the new tree because all plpgsql functions within a
8205 * given transaction share the same simple_eval_estate. (Well, regular
8206 * functions do; DO blocks have private simple_eval_estates, and private
8207 * cast hash tables to go with them.)
8208 */
8210 if (cast_entry->cast_lxid != curlxid || cast_entry->cast_in_use)
8211 {
8213 cast_entry->cast_exprstate = ExecInitExpr(expr_entry->cast_expr, NULL);
8214 cast_entry->cast_in_use = false;
8215 cast_entry->cast_lxid = curlxid;
8216 MemoryContextSwitchTo(oldcontext);
8217 }
8218
8219 return cast_entry;
8220}

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 7911 of file pl_exec.c.

7912{
7913 Assert(rec->erh == NULL); /* else caller error */
7914
7915 /* If declared type is RECORD, we can't instantiate */
7916 if (rec->rectypeid == RECORDOID)
7917 ereport(ERROR,
7919 errmsg("record \"%s\" is not assigned yet", rec->refname),
7920 errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
7921
7922 /* Make sure rec->rectypeid is up-to-date before using it */
7924
7925 /* OK, do it */
7927 estate->datum_context);
7928}

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 2320 of file pl_exec.c.

2321{
2322 CachedPlan *cplan;
2323 PlannedStmt *pstmt;
2324 CallStmt *stmt;
2325 FuncExpr *funcexpr;
2327 Oid *argtypes;
2328 char **argnames;
2329 char *argmodes;
2330 int numargs;
2331 MemoryContext oldcontext;
2332 PLpgSQL_row *row;
2333 int nfields;
2334 int i;
2335
2336 /* Use eval_mcontext for any cruft accumulated here */
2337 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
2338
2339 /*
2340 * Get the parsed CallStmt, and look up the called procedure. We use
2341 * SPI_plan_get_cached_plan to cover the edge case where expr->plan is
2342 * already stale and needs to be updated.
2343 */
2344 cplan = SPI_plan_get_cached_plan(expr->plan);
2345 if (cplan == NULL || list_length(cplan->stmt_list) != 1)
2346 elog(ERROR, "query for CALL statement is not a CallStmt");
2347 pstmt = linitial_node(PlannedStmt, cplan->stmt_list);
2348 stmt = (CallStmt *) pstmt->utilityStmt;
2349 if (stmt == NULL || !IsA(stmt, CallStmt))
2350 elog(ERROR, "query for CALL statement is not a CallStmt");
2351
2352 funcexpr = stmt->funcexpr;
2353
2355 ObjectIdGetDatum(funcexpr->funcid));
2357 elog(ERROR, "cache lookup failed for function %u",
2358 funcexpr->funcid);
2359
2360 /*
2361 * Get the argument names and modes, so that we can deliver on-point error
2362 * messages when something is wrong.
2363 */
2364 numargs = get_func_arg_info(func_tuple, &argtypes, &argnames, &argmodes);
2365
2367
2368 /*
2369 * Begin constructing row Datum; keep it in fn_cxt so it's adequately
2370 * long-lived.
2371 */
2373
2375 row->dtype = PLPGSQL_DTYPE_ROW;
2376 row->refname = "(unnamed row)";
2377 row->lineno = -1;
2378 row->varnos = palloc_array(int, numargs);
2379
2381
2382 /*
2383 * Examine procedure's argument list. Each output arg position should be
2384 * an unadorned plpgsql variable (Datum), which we can insert into the row
2385 * Datum.
2386 */
2387 nfields = 0;
2388 for (i = 0; i < numargs; i++)
2389 {
2390 if (argmodes &&
2393 {
2394 Node *n = list_nth(stmt->outargs, nfields);
2395
2396 if (IsA(n, Param))
2397 {
2398 Param *param = (Param *) n;
2399 int dno;
2400
2401 /* paramid is offset by 1 (see make_datum_param()) */
2402 dno = param->paramid - 1;
2403 /* must check assignability now, because grammar can't */
2404 exec_check_assignable(estate, dno);
2405 row->varnos[nfields++] = dno;
2406 }
2407 else
2408 {
2409 /* report error using parameter name, if available */
2410 if (argnames && argnames[i] && argnames[i][0])
2411 ereport(ERROR,
2413 errmsg("procedure parameter \"%s\" is an output parameter but corresponding argument is not writable",
2414 argnames[i])));
2415 else
2416 ereport(ERROR,
2418 errmsg("procedure parameter %d is an output parameter but corresponding argument is not writable",
2419 i + 1)));
2420 }
2421 }
2422 }
2423
2424 Assert(nfields == list_length(stmt->outargs));
2425
2426 row->nfields = nfields;
2427
2429
2430 MemoryContextSwitchTo(oldcontext);
2431
2432 return (PLpgSQL_variable *) row;
2433}

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 7219 of file pl_exec.c.

7223{
7225 MemoryContext mcontext = get_eval_mcontext(estate);
7226
7227 if (rec->rectypeid != RECORDOID)
7228 {
7229 /*
7230 * Make sure rec->rectypeid is up-to-date before using it.
7231 */
7233
7234 /*
7235 * New record must be of desired type, but maybe srcerh has already
7236 * done all the same lookups.
7237 */
7238 if (srcerh && rec->rectypeid == srcerh->er_decltypeid)
7240 mcontext);
7241 else
7243 mcontext);
7244 }
7245 else
7246 {
7247 /*
7248 * We'll adopt the input tupdesc. We can still use
7249 * make_expanded_record_from_exprecord, if srcerh isn't a composite
7250 * domain. (If it is, we effectively adopt its base type.)
7251 */
7254 mcontext);
7255 else
7256 {
7257 if (!srctupdesc)
7260 mcontext);
7261 }
7262 }
7263
7264 return newerh;
7265}

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 7592 of file pl_exec.c.

7595{
7596 int natts = tupdesc->natts;
7597 HeapTuple tuple;
7598 Datum *dvalues;
7599 bool *nulls;
7600 int i;
7601
7602 if (natts != row->nfields)
7603 return NULL;
7604
7605 dvalues = (Datum *) eval_mcontext_alloc0(estate, natts * sizeof(Datum));
7606 nulls = (bool *) eval_mcontext_alloc(estate, natts * sizeof(bool));
7607
7608 for (i = 0; i < natts; i++)
7609 {
7612
7613 if (TupleDescAttr(tupdesc, i)->attisdropped)
7614 {
7615 nulls[i] = true; /* leave the column as null */
7616 continue;
7617 }
7618
7619 exec_eval_datum(estate, estate->datums[row->varnos[i]],
7621 &dvalues[i], &nulls[i]);
7622 if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid)
7623 return NULL;
7624 /* XXX should we insist on typmod match, too? */
7625 }
7626
7627 tuple = heap_form_tuple(tupdesc, dvalues, nulls);
7628
7629 return tuple;
7630}

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 8720 of file pl_exec.c.

8721{
8723
8724 /*
8725 * Create an EState for evaluation of simple expressions, if there's not
8726 * one already in the current transaction. The EState is made a child of
8727 * TopTransactionContext so it will have the right lifespan.
8728 *
8729 * Note that this path is never taken when beginning a DO block; the
8730 * required EState was already made by plpgsql_inline_handler. However,
8731 * if the DO block executes COMMIT or ROLLBACK, then we'll come here and
8732 * make a shared EState to use for the rest of the DO block. That's OK;
8733 * see the comments for shared_simple_eval_estate. (Note also that a DO
8734 * block will continue to use its private cast hash table for the rest of
8735 * the block. That's okay for now, but it might cause problems someday.)
8736 */
8737 if (estate->simple_eval_estate == NULL)
8738 {
8739 MemoryContext oldcontext;
8740
8742 {
8745 MemoryContextSwitchTo(oldcontext);
8746 }
8748 }
8749
8750 /*
8751 * Likewise for the simple-expression resource owner.
8752 */
8753 if (estate->simple_eval_resowner == NULL)
8754 {
8758 "PL/pgSQL simple expressions");
8760 }
8761
8762 /*
8763 * Create a child econtext for the current function.
8764 */
8766
8767 /*
8768 * Make a stack entry so we can clean up the econtext at subxact end.
8769 * Stack entries are kept in TopTransactionContext for simplicity.
8770 */
8771 entry = (SimpleEcontextStackEntry *)
8773 sizeof(SimpleEcontextStackEntry));
8774
8775 entry->stack_econtext = estate->eval_econtext;
8777
8778 entry->next = simple_econtext_stack;
8779 simple_econtext_stack = entry;
8780}

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 4012 of file pl_exec.c.

4017{
4018 HASHCTL ctl;
4019
4020 /* this link will be restored at exit from plpgsql_call_handler */
4021 func->cur_estate = estate;
4022
4023 estate->func = func;
4024 estate->trigdata = NULL;
4025 estate->evtrigdata = NULL;
4026
4027 estate->retval = (Datum) 0;
4028 estate->retisnull = true;
4029 estate->rettype = InvalidOid;
4030
4031 estate->fn_rettype = func->fn_rettype;
4032 estate->retistuple = func->fn_retistuple;
4033 estate->retisset = func->fn_retset;
4034
4035 estate->readonly_func = func->fn_readonly;
4036 estate->atomic = true;
4037
4038 estate->exitlabel = NULL;
4039 estate->cur_error = NULL;
4040
4041 estate->tuple_store = NULL;
4042 estate->tuple_store_desc = NULL;
4043 if (rsi)
4044 {
4047 }
4048 else
4049 {
4050 estate->tuple_store_cxt = NULL;
4051 estate->tuple_store_owner = NULL;
4052 }
4053 estate->rsi = rsi;
4054
4055 estate->found_varno = func->found_varno;
4056 estate->ndatums = func->ndatums;
4057 estate->datums = NULL;
4058 /* the datums array will be filled by copy_plpgsql_datums() */
4060
4061 /* initialize our ParamListInfo with appropriate hook functions */
4062 estate->paramLI = makeParamList(0);
4064 estate->paramLI->paramFetchArg = estate;
4066 estate->paramLI->paramCompileArg = NULL; /* not needed */
4068 estate->paramLI->parserSetupArg = NULL; /* filled during use */
4069 estate->paramLI->numParams = estate->ndatums;
4070
4071 /* Create the session-wide cast-expression hash if we didn't already */
4072 if (cast_expr_hash == NULL)
4073 {
4074 ctl.keysize = sizeof(plpgsql_CastHashKey);
4075 ctl.entrysize = sizeof(plpgsql_CastExprHashEntry);
4076 cast_expr_hash = hash_create("PLpgSQL cast expressions",
4077 16, /* start small and extend */
4078 &ctl,
4080 }
4081
4082 /* set up for use of appropriate simple-expression EState and cast hash */
4083 if (simple_eval_estate)
4084 {
4085 estate->simple_eval_estate = simple_eval_estate;
4086 /* Private cast hash just lives in function's main context */
4087 ctl.keysize = sizeof(plpgsql_CastHashKey);
4088 ctl.entrysize = sizeof(plpgsql_CastHashEntry);
4090 estate->cast_hash = hash_create("PLpgSQL private cast cache",
4091 16, /* start small and extend */
4092 &ctl,
4094 }
4095 else
4096 {
4098 /* Create the session-wide cast-info hash table if we didn't already */
4099 if (shared_cast_hash == NULL)
4100 {
4101 ctl.keysize = sizeof(plpgsql_CastHashKey);
4102 ctl.entrysize = sizeof(plpgsql_CastHashEntry);
4103 shared_cast_hash = hash_create("PLpgSQL cast cache",
4104 16, /* start small and extend */
4105 &ctl,
4107 }
4108 estate->cast_hash = shared_cast_hash;
4109 }
4110 /* likewise for the simple-expression resource owner */
4111 if (simple_eval_resowner)
4112 estate->simple_eval_resowner = simple_eval_resowner;
4113 else
4115
4116 /* if there's a procedure resowner, it'll be filled in later */
4117 estate->procedure_resowner = NULL;
4118
4119 /*
4120 * We start with no stmt_mcontext; one will be created only if needed.
4121 * That context will be a direct child of the function's main execution
4122 * context. Additional stmt_mcontexts might be created as children of it.
4123 */
4124 estate->stmt_mcontext = NULL;
4126
4127 estate->eval_tuptable = NULL;
4128 estate->eval_processed = 0;
4129 estate->eval_econtext = NULL;
4130
4131 estate->err_stmt = NULL;
4132 estate->err_var = NULL;
4133 estate->err_text = NULL;
4134
4135 estate->plugin_info = NULL;
4136
4137 /*
4138 * Create an EState and ExprContext for evaluation of simple expressions.
4139 */
4141
4142 /*
4143 * Let the plugin, if any, see this function before we initialize local
4144 * PL/pgSQL variables. Note that we also give the plugin a few function
4145 * pointers, so it can call back into PL/pgSQL for doing things like
4146 * variable assignments and stack traces.
4147 */
4148 if (*plpgsql_plugin_ptr)
4149 {
4150 (*plpgsql_plugin_ptr)->error_callback = plpgsql_exec_error_callback;
4151 (*plpgsql_plugin_ptr)->assign_expr = exec_assign_expr;
4152 (*plpgsql_plugin_ptr)->assign_value = exec_assign_value;
4153 (*plpgsql_plugin_ptr)->eval_datum = exec_eval_datum;
4154 (*plpgsql_plugin_ptr)->cast_value = exec_cast_value;
4155
4156 if ((*plpgsql_plugin_ptr)->func_setup)
4157 ((*plpgsql_plugin_ptr)->func_setup) (estate, func);
4158 }
4159}

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 1244 of file pl_exec.c.

1245{
1247 int err_lineno;
1248
1249 /*
1250 * If err_var is set, report the variable's declaration line number.
1251 * Otherwise, if err_stmt is set, report the err_stmt's line number. When
1252 * err_stmt is not set, we're in function entry/exit, or some such place
1253 * not attached to a specific line number.
1254 */
1255 if (estate->err_var != NULL)
1256 err_lineno = estate->err_var->lineno;
1257 else if (estate->err_stmt != NULL)
1258 err_lineno = estate->err_stmt->lineno;
1259 else
1260 err_lineno = 0;
1261
1262 if (estate->err_text != NULL)
1263 {
1264 /*
1265 * We don't expend the cycles to run gettext() on err_text unless we
1266 * actually need it. Therefore, places that set up err_text should
1267 * use gettext_noop() to ensure the strings get recorded in the
1268 * message dictionary.
1269 */
1270 if (err_lineno > 0)
1271 {
1272 /*
1273 * translator: last %s is a phrase such as "during statement block
1274 * local variable initialization"
1275 */
1276 errcontext("PL/pgSQL function %s line %d %s",
1277 estate->func->fn_signature,
1278 err_lineno,
1279 _(estate->err_text));
1280 }
1281 else
1282 {
1283 /*
1284 * translator: last %s is a phrase such as "while storing call
1285 * arguments into local variables"
1286 */
1287 errcontext("PL/pgSQL function %s %s",
1288 estate->func->fn_signature,
1289 _(estate->err_text));
1290 }
1291 }
1292 else if (estate->err_stmt != NULL && err_lineno > 0)
1293 {
1294 /* translator: last %s is a plpgsql statement type name */
1295 errcontext("PL/pgSQL function %s line %d at %s",
1296 estate->func->fn_signature,
1297 err_lineno,
1299 }
1300 else
1301 errcontext("PL/pgSQL function %s",
1302 estate->func->fn_signature);
1303}

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 1176 of file pl_exec.c.

1177{
1178 PLpgSQL_execstate estate;
1180 int rc;
1181
1182 /*
1183 * Setup the execution state
1184 */
1185 plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
1186 estate.evtrigdata = trigdata;
1187
1188 /*
1189 * Setup error traceback support for ereport()
1190 */
1192 plerrcontext.arg = &estate;
1195
1196 /*
1197 * Make local execution copies of all the datums
1198 */
1199 estate.err_text = gettext_noop("during initialization of execution state");
1200 copy_plpgsql_datums(&estate, func);
1201
1202 /*
1203 * Let the instrumentation plugin peek at this function
1204 */
1205 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1206 ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1207
1208 /*
1209 * Now call the toplevel block of statements
1210 */
1211 estate.err_text = NULL;
1212 rc = exec_toplevel_block(&estate, func->action);
1213 if (rc != PLPGSQL_RC_RETURN)
1214 {
1215 estate.err_text = NULL;
1216 ereport(ERROR,
1218 errmsg("control reached end of trigger procedure without RETURN")));
1219 }
1220
1221 estate.err_text = gettext_noop("during function exit");
1222
1223 /*
1224 * Let the instrumentation plugin peek at this function
1225 */
1226 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1227 ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1228
1229 /* Clean up any leftover temporary memory */
1230 plpgsql_destroy_econtext(&estate);
1231 exec_eval_cleanup(&estate);
1232 /* stmt_mcontext will be destroyed when function's main context is */
1233
1234 /*
1235 * Pop the error context stack
1236 */
1238}

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 494 of file pl_exec.c.

499{
500 PLpgSQL_execstate estate;
502 int i;
503 int rc;
504
505 /*
506 * Setup the execution state
507 */
508 plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo,
509 simple_eval_estate, simple_eval_resowner);
510 estate.procedure_resowner = procedure_resowner;
511 estate.atomic = atomic;
512
513 /*
514 * Setup error traceback support for ereport()
515 */
517 plerrcontext.arg = &estate;
520
521 /*
522 * Make local execution copies of all the datums
523 */
524 estate.err_text = gettext_noop("during initialization of execution state");
525 copy_plpgsql_datums(&estate, func);
526
527 /*
528 * Store the actual call argument values into the appropriate variables
529 */
530 estate.err_text = gettext_noop("while storing call arguments into local variables");
531 for (i = 0; i < func->fn_nargs; i++)
532 {
533 int n = func->fn_argvarnos[i];
534
535 switch (estate.datums[n]->dtype)
536 {
538 {
539 PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
540
541 assign_simple_var(&estate, var,
542 fcinfo->args[i].value,
543 fcinfo->args[i].isnull,
544 false);
545
546 /*
547 * If it's a varlena type, check to see if we received a
548 * R/W expanded-object pointer. If so, we can commandeer
549 * the object rather than having to copy it. If passed a
550 * R/O expanded pointer, just keep it as the value of the
551 * variable for the moment. (We can change it to R/W if
552 * the variable gets modified, but that may very well
553 * never happen.)
554 *
555 * Also, force any flat array value to be stored in
556 * expanded form in our local variable, in hopes of
557 * improving efficiency of uses of the variable. (This is
558 * a hack, really: why only arrays? Need more thought
559 * about which cases are likely to win. See also
560 * typisarray-specific heuristic in exec_assign_value.)
561 */
562 if (!var->isnull && var->datatype->typlen == -1)
563 {
565 {
566 /* take ownership of R/W object */
567 assign_simple_var(&estate, var,
568 TransferExpandedObject(var->value,
569 estate.datum_context),
570 false,
571 true);
572 }
574 {
575 /* R/O pointer, keep it as-is until assigned to */
576 }
577 else if (var->datatype->typisarray)
578 {
579 /* flat array, so force to expanded form */
580 assign_simple_var(&estate, var,
581 expand_array(var->value,
582 estate.datum_context,
583 NULL),
584 false,
585 true);
586 }
587 }
588 }
589 break;
590
592 {
593 PLpgSQL_rec *rec = (PLpgSQL_rec *) estate.datums[n];
594
595 if (!fcinfo->args[i].isnull)
596 {
597 /* Assign row value from composite datum */
599 (PLpgSQL_variable *) rec,
600 fcinfo->args[i].value);
601 }
602 else
603 {
604 /* If arg is null, set variable to null */
605 exec_move_row(&estate, (PLpgSQL_variable *) rec,
606 NULL, NULL);
607 }
608 /* clean up after exec_move_row() */
609 exec_eval_cleanup(&estate);
610 }
611 break;
612
613 default:
614 /* Anything else should not be an argument variable */
615 elog(ERROR, "unrecognized dtype: %d", func->datums[i]->dtype);
616 }
617 }
618
619 estate.err_text = gettext_noop("during function entry");
620
621 /*
622 * Set the magic variable FOUND to false
623 */
624 exec_set_found(&estate, false);
625
626 /*
627 * Let the instrumentation plugin peek at this function
628 */
629 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
630 ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
631
632 /*
633 * Now call the toplevel block of statements
634 */
635 estate.err_text = NULL;
636 rc = exec_toplevel_block(&estate, func->action);
637 if (rc != PLPGSQL_RC_RETURN)
638 {
639 estate.err_text = NULL;
642 errmsg("control reached end of function without RETURN")));
643 }
644
645 /*
646 * We got a return value - process it
647 */
648 estate.err_text = gettext_noop("while casting return value to function's return type");
649
650 fcinfo->isnull = estate.retisnull;
651
652 if (estate.retisset)
653 {
654 ReturnSetInfo *rsi = estate.rsi;
655
656 /* Check caller can handle a set result */
657 if (!rsi || !IsA(rsi, ReturnSetInfo))
660 errmsg("set-valued function called in context that cannot accept a set")));
661
662 if (!(rsi->allowedModes & SFRM_Materialize))
665 errmsg("materialize mode required, but it is not allowed in this context")));
666
668
669 /* If we produced any tuples, send back the result */
670 if (estate.tuple_store)
671 {
673
674 rsi->setResult = estate.tuple_store;
678 }
679 estate.retval = (Datum) 0;
680 fcinfo->isnull = true;
681 }
682 else if (!estate.retisnull)
683 {
684 /*
685 * Cast result value to function's declared result type, and copy it
686 * out to the upper executor memory context. We must treat tuple
687 * results specially in order to deal with cases like rowtypes
688 * involving dropped columns.
689 */
690 if (estate.retistuple)
691 {
692 /* Don't need coercion if rowtype is known to match */
693 if (func->fn_rettype == estate.rettype &&
694 func->fn_rettype != RECORDOID)
695 {
696 /*
697 * Copy the tuple result into upper executor memory context.
698 * However, if we have a R/W expanded datum, we can just
699 * transfer its ownership out to the upper context.
700 */
701 estate.retval = SPI_datumTransfer(estate.retval,
702 false,
703 -1);
704 }
705 else
706 {
707 /*
708 * Need to look up the expected result type. XXX would be
709 * better to cache the tupdesc instead of repeating
710 * get_call_result_type(), but the only easy place to save it
711 * is in the PLpgSQL_function struct, and that's too
712 * long-lived: composite types could change during the
713 * existence of a PLpgSQL_function.
714 */
716 TupleDesc tupdesc;
717
718 switch (get_call_result_type(fcinfo, &resultTypeId, &tupdesc))
719 {
721 /* got the expected result rowtype, now coerce it */
722 coerce_function_result_tuple(&estate, tupdesc);
723 break;
725 /* got the expected result rowtype, now coerce it */
726 coerce_function_result_tuple(&estate, tupdesc);
727 /* and check domain constraints */
728 /* XXX allowing caching here would be good, too */
729 domain_check(estate.retval, false, resultTypeId,
730 NULL, NULL);
731 break;
732 case TYPEFUNC_RECORD:
733
734 /*
735 * Failed to determine actual type of RECORD. We
736 * could raise an error here, but what this means in
737 * practice is that the caller is expecting any old
738 * generic rowtype, so we don't really need to be
739 * restrictive. Pass back the generated result as-is.
740 */
741 estate.retval = SPI_datumTransfer(estate.retval,
742 false,
743 -1);
744 break;
745 default:
746 /* shouldn't get here if retistuple is true ... */
747 elog(ERROR, "return type must be a row type");
748 break;
749 }
750 }
751 }
752 else
753 {
754 /* Scalar case: use exec_cast_value */
755 estate.retval = exec_cast_value(&estate,
756 estate.retval,
757 &fcinfo->isnull,
758 estate.rettype,
759 -1,
760 func->fn_rettype,
761 -1);
762
763 /*
764 * If the function's return type isn't by value, copy the value
765 * into upper executor memory context. However, if we have a R/W
766 * expanded datum, we can just transfer its ownership out to the
767 * upper executor context.
768 */
769 if (!fcinfo->isnull && !func->fn_retbyval)
770 estate.retval = SPI_datumTransfer(estate.retval,
771 false,
772 func->fn_rettyplen);
773 }
774 }
775 else
776 {
777 /*
778 * We're returning a NULL, which normally requires no conversion work
779 * regardless of datatypes. But, if we are casting it to a domain
780 * return type, we'd better check that the domain's constraints pass.
781 */
782 if (func->fn_retisdomain)
783 estate.retval = exec_cast_value(&estate,
784 estate.retval,
785 &fcinfo->isnull,
786 estate.rettype,
787 -1,
788 func->fn_rettype,
789 -1);
790 }
791
792 estate.err_text = gettext_noop("during function exit");
793
794 /*
795 * Let the instrumentation plugin peek at this function
796 */
797 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
798 ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
799
800 /* Clean up any leftover temporary memory */
802 exec_eval_cleanup(&estate);
803 /* stmt_mcontext will be destroyed when function's main context is */
804
805 /*
806 * Pop the error context stack
807 */
809
810 /*
811 * Return the function's result
812 */
813 return estate.retval;
814}

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 5540 of file pl_exec.c.

5542{
5543 Oid typeid;
5544
5545 switch (datum->dtype)
5546 {
5547 case PLPGSQL_DTYPE_VAR:
5549 {
5550 PLpgSQL_var *var = (PLpgSQL_var *) datum;
5551
5552 typeid = var->datatype->typoid;
5553 break;
5554 }
5555
5556 case PLPGSQL_DTYPE_REC:
5557 {
5558 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5559
5560 if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5561 {
5562 /* Report variable's declared type */
5563 typeid = rec->rectypeid;
5564 }
5565 else
5566 {
5567 /* Report record's actual type if declared RECORD */
5568 typeid = rec->erh->er_typeid;
5569 }
5570 break;
5571 }
5572
5574 {
5576 PLpgSQL_rec *rec;
5577
5578 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5579
5580 /*
5581 * If record variable is NULL, instantiate it if it has a
5582 * named composite type, else complain. (This won't change
5583 * the logical state of the record: it's still NULL.)
5584 */
5585 if (rec->erh == NULL)
5587
5588 /*
5589 * Look up the field's properties if we have not already, or
5590 * if the tuple descriptor ID changed since last time.
5591 */
5592 if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5593 {
5595 recfield->fieldname,
5596 &recfield->finfo))
5597 ereport(ERROR,
5599 errmsg("record \"%s\" has no field \"%s\"",
5600 rec->refname, recfield->fieldname)));
5601 recfield->rectupledescid = rec->erh->er_tupdesc_id;
5602 }
5603
5604 typeid = recfield->finfo.ftypeid;
5605 break;
5606 }
5607
5608 default:
5609 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5610 typeid = InvalidOid; /* keep compiler quiet */
5611 break;
5612 }
5613
5614 return typeid;
5615}

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 5625 of file pl_exec.c.

5628{
5629 switch (datum->dtype)
5630 {
5631 case PLPGSQL_DTYPE_VAR:
5633 {
5634 PLpgSQL_var *var = (PLpgSQL_var *) datum;
5635
5636 *typeId = var->datatype->typoid;
5637 *typMod = var->datatype->atttypmod;
5638 *collation = var->datatype->collation;
5639 break;
5640 }
5641
5642 case PLPGSQL_DTYPE_REC:
5643 {
5644 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5645
5646 if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5647 {
5648 /* Report variable's declared type */
5649 *typeId = rec->rectypeid;
5650 *typMod = -1;
5651 }
5652 else
5653 {
5654 /* Report record's actual type if declared RECORD */
5655 *typeId = rec->erh->er_typeid;
5656 /* do NOT return the mutable typmod of a RECORD variable */
5657 *typMod = -1;
5658 }
5659 /* composite types are never collatable */
5660 *collation = InvalidOid;
5661 break;
5662 }
5663
5665 {
5667 PLpgSQL_rec *rec;
5668
5669 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5670
5671 /*
5672 * If record variable is NULL, instantiate it if it has a
5673 * named composite type, else complain. (This won't change
5674 * the logical state of the record: it's still NULL.)
5675 */
5676 if (rec->erh == NULL)
5678
5679 /*
5680 * Look up the field's properties if we have not already, or
5681 * if the tuple descriptor ID changed since last time.
5682 */
5683 if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5684 {
5686 recfield->fieldname,
5687 &recfield->finfo))
5688 ereport(ERROR,
5690 errmsg("record \"%s\" has no field \"%s\"",
5691 rec->refname, recfield->fieldname)));
5692 recfield->rectupledescid = rec->erh->er_tupdesc_id;
5693 }
5694
5695 *typeId = recfield->finfo.ftypeid;
5696 *typMod = recfield->finfo.ftypmod;
5697 *collation = recfield->finfo.fcollation;
5698 break;
5699 }
5700
5701 default:
5702 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5703 *typeId = InvalidOid; /* keep compiler quiet */
5704 *typMod = -1;
5705 *collation = InvalidOid;
5706 break;
5707 }
5708}

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 936 of file pl_exec.c.

938{
939 PLpgSQL_execstate estate;
941 int rc;
942 TupleDesc tupdesc;
944 *rec_old;
946
947 /*
948 * Setup the execution state
949 */
950 plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
951 estate.trigdata = trigdata;
952
953 /*
954 * Setup error traceback support for ereport()
955 */
957 plerrcontext.arg = &estate;
960
961 /*
962 * Make local execution copies of all the datums
963 */
964 estate.err_text = gettext_noop("during initialization of execution state");
965 copy_plpgsql_datums(&estate, func);
966
967 /*
968 * Put the OLD and NEW tuples into record variables
969 *
970 * We set up expanded records for both variables even though only one may
971 * have a value. This allows record references to succeed in functions
972 * that are used for multiple trigger types. For example, we might have a
973 * test like "if (TG_OP = 'INSERT' and NEW.foo = 'xyz')", which should
974 * work regardless of the current trigger type. If a value is actually
975 * fetched from an unsupplied tuple, it will read as NULL.
976 */
977 tupdesc = RelationGetDescr(trigdata->tg_relation);
978
979 rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
980 rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
981
983 estate.datum_context);
985 estate.datum_context);
986
987 if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
988 {
989 /*
990 * Per-statement triggers don't use OLD/NEW variables
991 */
992 }
993 else if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
994 {
996 false, false);
997 }
998 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
999 {
1001 false, false);
1003 false, false);
1004
1005 /*
1006 * In BEFORE trigger, stored generated columns are not computed yet,
1007 * so make them null in the NEW row. (Only needed in UPDATE branch;
1008 * in the INSERT case, they are already null, but in UPDATE, the field
1009 * still contains the old value.) Alternatively, we could construct a
1010 * whole new row structure without the generated columns, but this way
1011 * seems more efficient and potentially less confusing.
1012 */
1013 if (tupdesc->constr && tupdesc->constr->has_generated_stored &&
1014 TRIGGER_FIRED_BEFORE(trigdata->tg_event))
1015 {
1016 for (int i = 0; i < tupdesc->natts; i++)
1017 if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED)
1019 i + 1,
1020 (Datum) 0,
1021 true, /* isnull */
1022 false, false);
1023 }
1024 }
1025 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
1026 {
1028 false, false);
1029 }
1030 else
1031 elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
1032
1033 /* Make transition tables visible to this SPI connection */
1034 rc = SPI_register_trigger_data(trigdata);
1035 Assert(rc >= 0);
1036
1037 estate.err_text = gettext_noop("during function entry");
1038
1039 /*
1040 * Set the magic variable FOUND to false
1041 */
1042 exec_set_found(&estate, false);
1043
1044 /*
1045 * Let the instrumentation plugin peek at this function
1046 */
1047 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1048 ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1049
1050 /*
1051 * Now call the toplevel block of statements
1052 */
1053 estate.err_text = NULL;
1054 rc = exec_toplevel_block(&estate, func->action);
1055 if (rc != PLPGSQL_RC_RETURN)
1056 {
1057 estate.err_text = NULL;
1058 ereport(ERROR,
1060 errmsg("control reached end of trigger procedure without RETURN")));
1061 }
1062
1063 estate.err_text = gettext_noop("during function exit");
1064
1065 if (estate.retisset)
1066 ereport(ERROR,
1068 errmsg("trigger procedure cannot return a set")));
1069
1070 /*
1071 * Check that the returned tuple structure has the same attributes, the
1072 * relation that fired the trigger has. A per-statement trigger always
1073 * needs to return NULL, so we ignore any return value the function itself
1074 * produces (XXX: is this a good idea?)
1075 *
1076 * XXX This way it is possible, that the trigger returns a tuple where
1077 * attributes don't have the correct atttypmod's length. It's up to the
1078 * trigger's programmer to ensure that this doesn't happen. Jan
1079 */
1080 if (estate.retisnull || !TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
1081 rettup = NULL;
1082 else
1083 {
1085 TupleConversionMap *tupmap;
1086
1087 /* We assume exec_stmt_return verified that result is composite */
1089
1090 /* We can special-case expanded records for speed */
1092 {
1094
1095 Assert(erh->er_magic == ER_MAGIC);
1096
1097 /* Extract HeapTuple and TupleDesc */
1099 Assert(rettup);
1101
1102 if (retdesc != RelationGetDescr(trigdata->tg_relation))
1103 {
1104 /* check rowtype compatibility */
1106 RelationGetDescr(trigdata->tg_relation),
1107 gettext_noop("returned row structure does not match the structure of the triggering table"));
1108 /* it might need conversion */
1109 if (tupmap)
1111 /* no need to free map, we're about to return anyway */
1112 }
1113
1114 /*
1115 * Copy tuple to upper executor memory. But if user just did
1116 * "return new" or "return old" without changing anything, there's
1117 * no need to copy; we can return the original tuple (which will
1118 * save a few cycles in trigger.c as well as here).
1119 */
1120 if (rettup != trigdata->tg_newtuple &&
1121 rettup != trigdata->tg_trigtuple)
1123 }
1124 else
1125 {
1126 /* Convert composite datum to a HeapTuple and TupleDesc */
1128
1130 rettup = &tmptup;
1131
1132 /* check rowtype compatibility */
1134 RelationGetDescr(trigdata->tg_relation),
1135 gettext_noop("returned row structure does not match the structure of the triggering table"));
1136 /* it might need conversion */
1137 if (tupmap)
1139
1141 /* no need to free map, we're about to return anyway */
1142
1143 /* Copy tuple to upper executor memory */
1145 }
1146 }
1147
1148 /*
1149 * Let the instrumentation plugin peek at this function
1150 */
1151 if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1152 ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1153
1154 /* Clean up any leftover temporary memory */
1155 plpgsql_destroy_econtext(&estate);
1156 exec_eval_cleanup(&estate);
1157 /* stmt_mcontext will be destroyed when function's main context is */
1158
1159 /*
1160 * Pop the error context stack
1161 */
1163
1164 /*
1165 * Return the trigger's result
1166 */
1167 return rettup;
1168}

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_execsql_error_callback()

static void plpgsql_execsql_error_callback ( void arg)
static

Definition at line 1313 of file pl_exec.c.

1314{
1315 PLpgSQL_expr *expr = (PLpgSQL_expr *) arg;
1316 const char *query = expr->query;
1318
1319 /*
1320 * If there is a syntax error position, convert to internal syntax error;
1321 * otherwise treat the query as an item of context stack
1322 */
1324 if (syntaxerrposition > 0)
1325 {
1326 errposition(0);
1328 internalerrquery(query);
1329 }
1330 else
1331 {
1332 errcontext("SQL statement \"%s\"", query);
1333 }
1334}

References arg, errcontext, errposition(), fb(), geterrposition(), internalerrposition(), internalerrquery(), and PLpgSQL_expr::query.

Referenced by exec_stmt_execsql().

◆ plpgsql_fulfill_promise()

static void plpgsql_fulfill_promise ( PLpgSQL_execstate estate,
PLpgSQL_var var 
)
static

Definition at line 1415 of file pl_exec.c.

1417{
1418 MemoryContext oldcontext;
1419
1420 if (var->promise == PLPGSQL_PROMISE_NONE)
1421 return; /* nothing to do */
1422
1423 /*
1424 * This will typically be invoked in a short-lived context such as the
1425 * mcontext. We must create variable values in the estate's datum
1426 * context. This quick-and-dirty solution risks leaking some additional
1427 * cruft there, but since any one promise is honored at most once per
1428 * function call, it's probably not worth being more careful.
1429 */
1430 oldcontext = MemoryContextSwitchTo(estate->datum_context);
1431
1432 switch (var->promise)
1433 {
1435 if (estate->trigdata == NULL)
1436 elog(ERROR, "trigger promise is not in a trigger function");
1437 assign_simple_var(estate, var,
1440 false, true);
1441 break;
1442
1444 if (estate->trigdata == NULL)
1445 elog(ERROR, "trigger promise is not in a trigger function");
1447 assign_text_var(estate, var, "BEFORE");
1448 else if (TRIGGER_FIRED_AFTER(estate->trigdata->tg_event))
1449 assign_text_var(estate, var, "AFTER");
1450 else if (TRIGGER_FIRED_INSTEAD(estate->trigdata->tg_event))
1451 assign_text_var(estate, var, "INSTEAD OF");
1452 else
1453 elog(ERROR, "unrecognized trigger execution time: not BEFORE, AFTER, or INSTEAD OF");
1454 break;
1455
1457 if (estate->trigdata == NULL)
1458 elog(ERROR, "trigger promise is not in a trigger function");
1460 assign_text_var(estate, var, "ROW");
1462 assign_text_var(estate, var, "STATEMENT");
1463 else
1464 elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
1465 break;
1466
1468 if (estate->trigdata == NULL)
1469 elog(ERROR, "trigger promise is not in a trigger function");
1471 assign_text_var(estate, var, "INSERT");
1472 else if (TRIGGER_FIRED_BY_UPDATE(estate->trigdata->tg_event))
1473 assign_text_var(estate, var, "UPDATE");
1474 else if (TRIGGER_FIRED_BY_DELETE(estate->trigdata->tg_event))
1475 assign_text_var(estate, var, "DELETE");
1476 else if (TRIGGER_FIRED_BY_TRUNCATE(estate->trigdata->tg_event))
1477 assign_text_var(estate, var, "TRUNCATE");
1478 else
1479 elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, UPDATE, or TRUNCATE");
1480 break;
1481
1483 if (estate->trigdata == NULL)
1484 elog(ERROR, "trigger promise is not in a trigger function");
1485 assign_simple_var(estate, var,
1487 false, false);
1488 break;
1489
1491 if (estate->trigdata == NULL)
1492 elog(ERROR, "trigger promise is not in a trigger function");
1493 assign_simple_var(estate, var,
1496 false, true);
1497 break;
1498
1500 if (estate->trigdata == NULL)
1501 elog(ERROR, "trigger promise is not in a trigger function");
1502 assign_simple_var(estate, var,
1505 false, true);
1506 break;
1507
1509 if (estate->trigdata == NULL)
1510 elog(ERROR, "trigger promise is not in a trigger function");
1511 assign_simple_var(estate, var,
1513 false, false);
1514 break;
1515
1517 if (estate->trigdata == NULL)
1518 elog(ERROR, "trigger promise is not in a trigger function");
1519 if (estate->trigdata->tg_trigger->tgnargs > 0)
1520 {
1521 /*
1522 * For historical reasons, tg_argv[] subscripts start at zero
1523 * not one. So we can't use construct_array().
1524 */
1525 int nelems = estate->trigdata->tg_trigger->tgnargs;
1526 Datum *elems;
1527 int dims[1];
1528 int lbs[1];
1529 int i;
1530
1531 elems = palloc_array(Datum, nelems);
1532 for (i = 0; i < nelems; i++)
1533 elems[i] = CStringGetTextDatum(estate->trigdata->tg_trigger->tgargs[i]);
1534 dims[0] = nelems;
1535 lbs[0] = 0;
1536
1537 assign_simple_var(estate, var,
1539 1, dims, lbs,
1540 TEXTOID,
1541 -1, false, TYPALIGN_INT)),
1542 false, true);
1543 }
1544 else
1545 {
1546 assign_simple_var(estate, var, (Datum) 0, true, false);
1547 }
1548 break;
1549
1551 if (estate->evtrigdata == NULL)
1552 elog(ERROR, "event trigger promise is not in an event trigger function");
1553 assign_text_var(estate, var, estate->evtrigdata->event);
1554 break;
1555
1557 if (estate->evtrigdata == NULL)
1558 elog(ERROR, "event trigger promise is not in an event trigger function");
1559 assign_text_var(estate, var, GetCommandTagName(estate->evtrigdata->tag));
1560 break;
1561
1562 default:
1563 elog(ERROR, "unrecognized promise type: %d", var->promise);
1564 }
1565
1566 MemoryContextSwitchTo(oldcontext);
1567}

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 6526 of file pl_exec.c.

6529{
6530 PLpgSQL_execstate *estate;
6531 PLpgSQL_expr *expr;
6532 int dno;
6533 PLpgSQL_datum *datum;
6535
6536 /* fetch back the hook data */
6537 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6538 expr = (PLpgSQL_expr *) params->parserSetupArg;
6539
6540 /* paramid's are 1-based, but dnos are 0-based */
6541 dno = param->paramid - 1;
6542 Assert(dno >= 0 && dno < estate->ndatums);
6543
6544 /* now we can access the target datum */
6545 datum = estate->datums[dno];
6546
6548 scratch.resvalue = resv;
6549 scratch.resnull = resnull;
6550
6551 /*
6552 * Select appropriate eval function.
6553 *
6554 * First, if this Param references the same varlena-type DTYPE_VAR datum
6555 * that is the target of the assignment containing this simple expression,
6556 * then it's possible we will be able to optimize handling of R/W expanded
6557 * datums. We don't want to do the work needed to determine that unless
6558 * we actually see a R/W expanded datum at runtime, so install a checking
6559 * function that will figure that out when needed.
6560 *
6561 * Otherwise, it seems worth special-casing DTYPE_VAR and DTYPE_RECFIELD
6562 * for performance. Also, we can determine in advance whether
6563 * MakeExpandedObjectReadOnly() will be required. Currently, only
6564 * VAR/PROMISE and REC datums could contain read/write expanded objects.
6565 */
6566 if (datum->dtype == PLPGSQL_DTYPE_VAR)
6567 {
6568 bool isvarlena = (((PLpgSQL_var *) datum)->datatype->typlen == -1);
6569
6570 if (isvarlena && dno == expr->target_param && expr->expr_simple_expr)
6571 scratch.d.cparam.paramfunc = plpgsql_param_eval_var_check;
6572 else if (isvarlena)
6573 scratch.d.cparam.paramfunc = plpgsql_param_eval_var_ro;
6574 else
6575 scratch.d.cparam.paramfunc = plpgsql_param_eval_var;
6576 }
6577 else if (datum->dtype == PLPGSQL_DTYPE_RECFIELD)
6578 scratch.d.cparam.paramfunc = plpgsql_param_eval_recfield;
6579 else if (datum->dtype == PLPGSQL_DTYPE_PROMISE)
6580 {
6581 if (((PLpgSQL_var *) datum)->datatype->typlen == -1)
6582 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro;
6583 else
6584 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic;
6585 }
6586 else if (datum->dtype == PLPGSQL_DTYPE_REC)
6587 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro;
6588 else
6589 scratch.d.cparam.paramfunc = plpgsql_param_eval_generic;
6590
6591 /*
6592 * Note: it's tempting to use paramarg to store the estate pointer and
6593 * thereby save an indirection or two in the eval functions. But that
6594 * doesn't work because the compiled expression might be used with
6595 * different estates for the same PL/pgSQL function. Instead, store
6596 * pointers to the PLpgSQL_expr as well as this specific Param, to support
6597 * plpgsql_param_eval_var_check().
6598 */
6599 scratch.d.cparam.paramarg = expr;
6600 scratch.d.cparam.paramarg2 = param;
6601 scratch.d.cparam.paramid = param->paramid;
6602 scratch.d.cparam.paramtype = param->paramtype;
6604}
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 6914 of file pl_exec.c.

6916{
6917 ParamListInfo params;
6918 PLpgSQL_execstate *estate;
6919 int dno = op->d.cparam.paramid - 1;
6920 PLpgSQL_datum *datum;
6921 Oid datumtype;
6923
6924 /* fetch back the hook data */
6925 params = econtext->ecxt_param_list_info;
6926 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6927 Assert(dno >= 0 && dno < estate->ndatums);
6928
6929 /* now we can access the target datum */
6930 datum = estate->datums[dno];
6931
6932 /* fetch datum's value */
6933 exec_eval_datum(estate, datum,
6935 op->resvalue, op->resnull);
6936
6937 /* safety check -- needed for, eg, record fields */
6938 if (unlikely(datumtype != op->d.cparam.paramtype))
6939 ereport(ERROR,
6941 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6942 op->d.cparam.paramid,
6945}
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 6954 of file pl_exec.c.

6956{
6957 ParamListInfo params;
6958 PLpgSQL_execstate *estate;
6959 int dno = op->d.cparam.paramid - 1;
6960 PLpgSQL_datum *datum;
6961 Oid datumtype;
6963
6964 /* fetch back the hook data */
6965 params = econtext->ecxt_param_list_info;
6966 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6967 Assert(dno >= 0 && dno < estate->ndatums);
6968
6969 /* now we can access the target datum */
6970 datum = estate->datums[dno];
6971
6972 /* fetch datum's value */
6973 exec_eval_datum(estate, datum,
6975 op->resvalue, op->resnull);
6976
6977 /* safety check -- needed for, eg, record fields */
6978 if (unlikely(datumtype != op->d.cparam.paramtype))
6979 ereport(ERROR,
6981 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6982 op->d.cparam.paramid,
6985
6986 /* force the value to read-only */
6988 *op->resnull,
6989 -1);
6990}

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 6842 of file pl_exec.c.

6844{
6845 ParamListInfo params;
6846 PLpgSQL_execstate *estate;
6847 int dno = op->d.cparam.paramid - 1;
6849 PLpgSQL_rec *rec;
6851
6852 /* fetch back the hook data */
6853 params = econtext->ecxt_param_list_info;
6854 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6855 Assert(dno >= 0 && dno < estate->ndatums);
6856
6857 /* now we can access the target datum */
6858 recfield = (PLpgSQL_recfield *) estate->datums[dno];
6860
6861 /* inline the relevant part of exec_eval_datum */
6862 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
6863 erh = rec->erh;
6864
6865 /*
6866 * If record variable is NULL, instantiate it if it has a named composite
6867 * type, else complain. (This won't change the logical state of the
6868 * record: it's still NULL.)
6869 */
6870 if (erh == NULL)
6871 {
6873 erh = rec->erh;
6874 }
6875
6876 /*
6877 * Look up the field's properties if we have not already, or if the tuple
6878 * descriptor ID changed since last time.
6879 */
6880 if (unlikely(recfield->rectupledescid != erh->er_tupdesc_id))
6881 {
6883 recfield->fieldname,
6884 &recfield->finfo))
6885 ereport(ERROR,
6887 errmsg("record \"%s\" has no field \"%s\"",
6888 rec->refname, recfield->fieldname)));
6889 recfield->rectupledescid = erh->er_tupdesc_id;
6890 }
6891
6892 /* OK to fetch the field value. */
6894 recfield->finfo.fnumber,
6895 op->resnull);
6896
6897 /* safety check -- needed for, eg, record fields */
6898 if (unlikely(recfield->finfo.ftypeid != op->d.cparam.paramtype))
6899 ereport(ERROR,
6901 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
6902 op->d.cparam.paramid,
6903 format_type_be(recfield->finfo.ftypeid),
6905}

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 6773 of file pl_exec.c.

6775{
6776 ParamListInfo params;
6777 PLpgSQL_execstate *estate;
6778 int dno = op->d.cparam.paramid - 1;
6779 PLpgSQL_var *var;
6780
6781 /* fetch back the hook data */
6782 params = econtext->ecxt_param_list_info;
6783 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6784 Assert(dno >= 0 && dno < estate->ndatums);
6785
6786 /* now we can access the target datum */
6787 var = (PLpgSQL_var *) estate->datums[dno];
6788 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6789
6790 /* inlined version of exec_eval_datum() */
6791 *op->resvalue = var->value;
6792 *op->resnull = var->isnull;
6793
6794 /* safety check -- an assertion should be sufficient */
6795 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6796}

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 6620 of file pl_exec.c.

6622{
6623 ParamListInfo params;
6624 PLpgSQL_execstate *estate;
6625 int dno = op->d.cparam.paramid - 1;
6626 PLpgSQL_var *var;
6627
6628 /* fetch back the hook data */
6629 params = econtext->ecxt_param_list_info;
6630 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6631 Assert(dno >= 0 && dno < estate->ndatums);
6632
6633 /* now we can access the target datum */
6634 var = (PLpgSQL_var *) estate->datums[dno];
6635 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6636
6637 /*
6638 * If the variable's current value is a R/W expanded object, it's time to
6639 * decide whether/how to optimize the assignment.
6640 */
6641 if (!var->isnull &&
6643 {
6644 PLpgSQL_expr *expr = (PLpgSQL_expr *) op->d.cparam.paramarg;
6645 Param *param = (Param *) op->d.cparam.paramarg2;
6646
6647 /*
6648 * We might have already figured this out while evaluating some other
6649 * Param referencing the same variable, so check expr_rwopt first.
6650 */
6651 if (expr->expr_rwopt == PLPGSQL_RWOPT_UNKNOWN)
6653
6654 /*
6655 * Update the callback pointer to match what we decided to do, so that
6656 * this function will not be called again. Then pass off this
6657 * execution to the newly-selected function.
6658 */
6659 switch (expr->expr_rwopt)
6660 {
6662 Assert(false);
6663 break;
6664 case PLPGSQL_RWOPT_NOPE:
6665 /* Force the value to read-only in all future executions */
6667 plpgsql_param_eval_var_ro(state, op, econtext);
6668 break;
6670 /* There can be only one matching Param in this case */
6671 Assert(param == expr->expr_rw_param);
6672 /* When the value is read/write, transfer to exec context */
6675 break;
6677 if (param == expr->expr_rw_param)
6678 {
6679 /* When the value is read/write, deliver it as-is */
6681 plpgsql_param_eval_var(state, op, econtext);
6682 }
6683 else
6684 {
6685 /* Not the optimizable reference, so force to read-only */
6687 plpgsql_param_eval_var_ro(state, op, econtext);
6688 }
6689 break;
6690 }
6691 return;
6692 }
6693
6694 /*
6695 * Otherwise, continue to postpone that decision, and execute an inlined
6696 * version of exec_eval_datum(). Although this value could potentially
6697 * need MakeExpandedObjectReadOnly, we know it doesn't right now.
6698 */
6699 *op->resvalue = var->value;
6700 *op->resnull = var->isnull;
6701
6702 /* safety check -- an assertion should be sufficient */
6703 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6704}
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 6805 of file pl_exec.c.

6807{
6808 ParamListInfo params;
6809 PLpgSQL_execstate *estate;
6810 int dno = op->d.cparam.paramid - 1;
6811 PLpgSQL_var *var;
6812
6813 /* fetch back the hook data */
6814 params = econtext->ecxt_param_list_info;
6815 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6816 Assert(dno >= 0 && dno < estate->ndatums);
6817
6818 /* now we can access the target datum */
6819 var = (PLpgSQL_var *) estate->datums[dno];
6820 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6821
6822 /*
6823 * Inlined version of exec_eval_datum() ... and while we're at it, force
6824 * expanded datums to read-only.
6825 */
6826 *op->resvalue = MakeExpandedObjectReadOnly(var->value,
6827 var->isnull,
6828 -1);
6829 *op->resnull = var->isnull;
6830
6831 /* safety check -- an assertion should be sufficient */
6832 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6833}

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 6717 of file pl_exec.c.

6719{
6720 ParamListInfo params;
6721 PLpgSQL_execstate *estate;
6722 int dno = op->d.cparam.paramid - 1;
6723 PLpgSQL_var *var;
6724
6725 /* fetch back the hook data */
6726 params = econtext->ecxt_param_list_info;
6727 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6728 Assert(dno >= 0 && dno < estate->ndatums);
6729
6730 /* now we can access the target datum */
6731 var = (PLpgSQL_var *) estate->datums[dno];
6732 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6733
6734 /*
6735 * If the variable's current value is a R/W expanded object, transfer its
6736 * ownership into the expression execution context, then drop our own
6737 * reference to the value by setting the variable to NULL. That'll be
6738 * overwritten (perhaps with this same object) when control comes back
6739 * from the expression.
6740 */
6741 if (!var->isnull &&
6743 {
6744 *op->resvalue = TransferExpandedObject(var->value,
6745 get_eval_mcontext(estate));
6746 *op->resnull = false;
6747
6748 var->value = (Datum) 0;
6749 var->isnull = true;
6750 var->freeval = false;
6751 }
6752 else
6753 {
6754 /*
6755 * Otherwise we can pass the variable's value directly; we now know
6756 * that MakeExpandedObjectReadOnly isn't needed.
6757 */
6758 *op->resvalue = var->value;
6759 *op->resnull = var->isnull;
6760 }
6761
6762 /* safety check -- an assertion should be sufficient */
6763 Assert(var->datatype->typoid == op->d.cparam.paramtype);
6764}

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 6399 of file pl_exec.c.

6402{
6403 int dno;
6404 PLpgSQL_execstate *estate;
6405 PLpgSQL_expr *expr;
6406 PLpgSQL_datum *datum;
6407 bool ok = true;
6409
6410 /* paramid's are 1-based, but dnos are 0-based */
6411 dno = paramid - 1;
6412 Assert(dno >= 0 && dno < params->numParams);
6413
6414 /* fetch back the hook data */
6415 estate = (PLpgSQL_execstate *) params->paramFetchArg;
6416 expr = (PLpgSQL_expr *) params->parserSetupArg;
6417 Assert(params->numParams == estate->ndatums);
6418
6419 /* now we can access the target datum */
6420 datum = estate->datums[dno];
6421
6422 /*
6423 * Since copyParamList() or SerializeParamList() will try to materialize
6424 * every single parameter slot, it's important to return a dummy param
6425 * when asked for a datum that's not supposed to be used by this SQL
6426 * expression. Otherwise we risk failures in exec_eval_datum(), or
6427 * copying a lot more data than necessary.
6428 */
6429 if (!bms_is_member(dno, expr->paramnos))
6430 ok = false;
6431
6432 /*
6433 * If the access is speculative, we prefer to return no data rather than
6434 * to fail in exec_eval_datum(). Check the likely failure cases.
6435 */
6436 else if (speculative)
6437 {
6438 switch (datum->dtype)
6439 {
6440 case PLPGSQL_DTYPE_VAR:
6442 /* always safe */
6443 break;
6444
6445 case PLPGSQL_DTYPE_ROW:
6446 /* should be safe in all interesting cases */
6447 break;
6448
6449 case PLPGSQL_DTYPE_REC:
6450 /* always safe (might return NULL, that's fine) */
6451 break;
6452
6454 {
6456 PLpgSQL_rec *rec;
6457
6458 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
6459
6460 /*
6461 * If record variable is NULL, don't risk anything.
6462 */
6463 if (rec->erh == NULL)
6464 ok = false;
6465
6466 /*
6467 * Look up the field's properties if we have not already,
6468 * or if the tuple descriptor ID changed since last time.
6469 */
6470 else if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
6471 {
6473 recfield->fieldname,
6474 &recfield->finfo))
6475 recfield->rectupledescid = rec->erh->er_tupdesc_id;
6476 else
6477 ok = false;
6478 }
6479 break;
6480 }
6481
6482 default:
6483 ok = false;
6484 break;
6485 }
6486 }
6487
6488 /* Return "no such parameter" if not ok */
6489 if (!ok)
6490 {
6491 prm->value = (Datum) 0;
6492 prm->isnull = true;
6493 prm->pflags = 0;
6494 prm->ptype = InvalidOid;
6495 return prm;
6496 }
6497
6498 /* OK, evaluate the value and store into the return struct */
6499 exec_eval_datum(estate, datum,
6500 &prm->ptype, &prmtypmod,
6501 &prm->value, &prm->isnull);
6502 /* We can always mark params as "const" for executor's purposes */
6503 prm->pflags = PARAM_FLAG_CONST;
6504
6505 /*
6506 * If it's a read/write expanded datum, convert reference to read-only.
6507 * (There's little point in trying to optimize read/write parameters,
6508 * given the cases in which this function is used.)
6509 */
6510 if (datum->dtype == PLPGSQL_DTYPE_VAR)
6511 prm->value = MakeExpandedObjectReadOnly(prm->value,
6512 prm->isnull,
6513 ((PLpgSQL_var *) datum)->datatype->typlen);
6514 else if (datum->dtype == PLPGSQL_DTYPE_REC)
6515 prm->value = MakeExpandedObjectReadOnly(prm->value,
6516 prm->isnull,
6517 -1);
6518
6519 return prm;
6520}

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 8811 of file pl_exec.c.

8812{
8813 /*
8814 * If we are doing a clean transaction shutdown, free the EState and tell
8815 * the resowner to release whatever plancache references it has, so that
8816 * all remaining resources will be released correctly. (We don't need to
8817 * actually delete the resowner here; deletion of the
8818 * TopTransactionResourceOwner will take care of that.)
8819 *
8820 * In an abort, we expect the regular abort recovery procedures to release
8821 * everything of interest, so just clear our pointers.
8822 */
8823 if (event == XACT_EVENT_COMMIT ||
8824 event == XACT_EVENT_PARALLEL_COMMIT ||
8825 event == XACT_EVENT_PREPARE)
8826 {
8828
8835 }
8836 else if (event == XACT_EVENT_ABORT ||
8838 {
8842 }
8843}

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 1613 of file pl_exec.c.

1614{
1615 /* We need only pop the stack */
1616 estate->stmt_mcontext = estate->stmt_mcontext_parent;
1618}

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 1594 of file pl_exec.c.

1595{
1596 /* Should have done get_stmt_mcontext() first */
1597 Assert(estate->stmt_mcontext != NULL);
1598 /* Assert we've not messed up the stack linkage */
1600 /* Push it down to become the parent of any nested stmt mcontext */
1601 estate->stmt_mcontext_parent = estate->stmt_mcontext;
1602 /* And make it not available for use directly */
1603 estate->stmt_mcontext = NULL;
1604}

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 7139 of file pl_exec.c.

7140{
7141 PLpgSQL_type *typ = rec->datatype;
7142 TypeCacheEntry *typentry;
7143
7144 if (rec->rectypeid == RECORDOID)
7145 return; /* it's RECORD, so nothing to do */
7146 Assert(typ != NULL);
7147 if (typ->tcache &&
7148 typ->tcache->tupDesc_identifier == typ->tupdesc_id)
7149 {
7150 /*
7151 * Although *typ is known up-to-date, it's possible that rectypeid
7152 * isn't, because *rec is cloned during each function startup from a
7153 * copy that we don't have a good way to update. Hence, forcibly fix
7154 * rectypeid before returning.
7155 */
7156 rec->rectypeid = typ->typoid;
7157 return;
7158 }
7159
7160 /*
7161 * typcache entry has suffered invalidation, so re-look-up the type name
7162 * if possible, and then recheck the type OID. If we don't have a
7163 * TypeName, then we just have to soldier on with the OID we've got.
7164 */
7165 if (typ->origtypname != NULL)
7166 {
7167 /* this bit should match parse_datatype() in pl_gram.y */
7168 typenameTypeIdAndMod(NULL, typ->origtypname,
7169 &typ->typoid,
7170 &typ->atttypmod);
7171 }
7172
7173 /* this bit should match build_datatype() in pl_comp.c */
7174 typentry = lookup_type_cache(typ->typoid,
7177 if (typentry->typtype == TYPTYPE_DOMAIN)
7178 typentry = lookup_type_cache(typentry->domainBaseType,
7180 if (typentry->tupDesc == NULL)
7181 {
7182 /*
7183 * If we get here, user tried to replace a composite type with a
7184 * non-composite one. We're not gonna support that.
7185 */
7186 ereport(ERROR,
7188 errmsg("type %s is not composite",
7189 format_type_be(typ->typoid))));
7190 }
7191
7192 /*
7193 * Update tcache and tupdesc_id. Since we don't support changing to a
7194 * non-composite type, none of the rest of *typ needs to change.
7195 */
7196 typ->tcache = typentry;
7197 typ->tupdesc_id = typentry->tupDesc_identifier;
7198
7199 /*
7200 * Update *rec, too. (We'll deal with subsidiary RECFIELDs as needed.)
7201 */
7202 rec->rectypeid = typ->typoid;
7203}

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 6351 of file pl_exec.c.

6352{
6353 ParamListInfo paramLI;
6354
6355 /*
6356 * We must have created the SPIPlan already (hence, query text has been
6357 * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
6358 */
6359 Assert(expr->plan != NULL);
6360
6361 /*
6362 * We only need a ParamListInfo if the expression has parameters.
6363 */
6364 if (!bms_is_empty(expr->paramnos))
6365 {
6366 /* Use the common ParamListInfo */
6367 paramLI = estate->paramLI;
6368
6369 /*
6370 * Set up link to active expr where the hook functions can find it.
6371 * Callers must save and restore parserSetupArg if there is any chance
6372 * that they are interrupting an active use of parameters.
6373 */
6374 paramLI->parserSetupArg = expr;
6375 }
6376 else
6377 {
6378 /*
6379 * Expression requires no parameters. Be sure we represent this case
6380 * as a NULL ParamListInfo, so that plancache.c knows there is no
6381 * point in a custom plan.
6382 */
6383 paramLI = NULL;
6384 }
6385 return paramLI;
6386}

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