PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pl_exec.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "access/transam.h"
#include "access/tupconvert.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/planner.h"
#include "parser/parse_coerce.h"
#include "parser/scansup.h"
#include "storage/proc.h"
#include "tcop/tcopprot.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/typcache.h"
#include "plpgsql.h"
Include dependency graph for pl_exec.c:

Go to the source code of this file.

Data Structures

struct  PreparedParamsData
 
struct  SimpleEcontextStackEntry
 
struct  plpgsql_CastHashKey
 
struct  plpgsql_CastHashEntry
 

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 SET_RAISE_OPTION_TEXT(opt, name)
 

Typedefs

typedef struct
SimpleEcontextStackEntry 
SimpleEcontextStackEntry
 

Functions

static void plpgsql_exec_error_callback (void *arg)
 
static PLpgSQL_datumcopy_plpgsql_datum (PLpgSQL_datum *datum)
 
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_stmt_block (PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 
static int exec_stmts (PLpgSQL_execstate *estate, List *stmts)
 
static int exec_stmt (PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
 
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_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 void plpgsql_estate_setup (PLpgSQL_execstate *estate, PLpgSQL_function *func, ReturnSetInfo *rsi, EState *simple_eval_estate)
 
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 void exec_save_simple_expr (PLpgSQL_expr *expr, CachedPlan *cplan)
 
static void exec_check_rw_parameter (PLpgSQL_expr *expr, int target_dno)
 
static bool contains_target_param (Node *node, int *target_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 ParamListInfo setup_unshared_param_list (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
static void plpgsql_param_fetch (ParamListInfo params, int paramid)
 
static void exec_move_row (PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
 
static HeapTuple make_tuple_from_row (PLpgSQL_execstate *estate, PLpgSQL_row *row, TupleDesc tupdesc)
 
static HeapTuple get_tuple_from_datum (Datum value)
 
static TupleDesc get_tupdesc_from_datum (Datum value)
 
static void exec_move_row_from_datum (PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, Datum value)
 
static char * convert_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 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 PreparedParamsDataexec_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 char * format_expr_params (PLpgSQL_execstate *estate, const PLpgSQL_expr *expr)
 
static char * format_preparedparamsdata (PLpgSQL_execstate *estate, const PreparedParamsData *ppd)
 
Datum plpgsql_exec_function (PLpgSQL_function *func, FunctionCallInfo fcinfo, EState *simple_eval_estate)
 
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 MemoryContext shared_cast_context = NULL
 
static HTABshared_cast_hash = NULL
 

Macro Definition Documentation

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

Definition at line 116 of file pl_exec.c.

Referenced by exec_move_row(), exec_stmt_return_next(), and make_tuple_from_row().

#define eval_mcontext_alloc0 (   estate,
  sz 
)    MemoryContextAllocZero(get_eval_mcontext(estate), sz)
#define SET_RAISE_OPTION_TEXT (   opt,
  name 
)
Value:
do { \
if (opt) \
(errcode(ERRCODE_SYNTAX_ERROR), \
errmsg("RAISE option already specified: %s", \
name))); \
opt = MemoryContextStrdup(stmt_mcontext, extval); \
} while (0)
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063

Definition at line 3126 of file pl_exec.c.

Referenced by exec_stmt_raise().

Typedef Documentation

Function Documentation

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

Definition at line 6902 of file pl_exec.c.

References Assert, PLpgSQL_var::datatype, DatumGetPointer, DatumIsReadWriteExpandedObject, DeleteExpandedObject(), PLpgSQL_var::dno, PLpgSQL_var::dtype, PLpgSQL_var::freeval, ParamExternData::isnull, PLpgSQL_var::isnull, MakeExpandedObjectReadOnly, PARAM_FLAG_CONST, PLpgSQL_execstate::paramLI, ParamListInfoData::params, ParamExternData::pflags, pfree(), PLPGSQL_DTYPE_VAR, ParamExternData::ptype, PLpgSQL_type::typlen, PLpgSQL_type::typoid, ParamExternData::value, and PLpgSQL_var::value.

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_exec_trigger().

6904 {
6905  ParamExternData *prm;
6906 
6907  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
6908  /* Free the old value if needed */
6909  if (var->freeval)
6910  {
6912  var->isnull,
6913  var->datatype->typlen))
6915  else
6916  pfree(DatumGetPointer(var->value));
6917  }
6918  /* Assign new value to datum */
6919  var->value = newvalue;
6920  var->isnull = isnull;
6921  var->freeval = freeable;
6922  /* And update the image in the common parameter list */
6923  prm = &estate->paramLI->params[var->dno];
6924  prm->value = MakeExpandedObjectReadOnly(newvalue,
6925  isnull,
6926  var->datatype->typlen);
6927  prm->isnull = isnull;
6928  /* these might be set already, but let's be sure */
6929  prm->pflags = PARAM_FLAG_CONST;
6930  prm->ptype = var->datatype->typoid;
6931 }
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:76
Datum value
Definition: params.h:56
PLpgSQL_datum_type dtype
Definition: plpgsql.h:256
PLpgSQL_type * datatype
Definition: plpgsql.h:261
void pfree(void *pointer)
Definition: mcxt.c:949
ParamListInfo paramLI
Definition: plpgsql.h:911
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
bool freeval
Definition: plpgsql.h:271
Datum value
Definition: plpgsql.h:269
void DeleteExpandedObject(Datum d)
#define Assert(condition)
Definition: c.h:664
#define DatumIsReadWriteExpandedObject(d, isnull, typlen)
uint16 pflags
Definition: params.h:58
#define DatumGetPointer(X)
Definition: postgres.h:555
int16 typlen
Definition: plpgsql.h:181
bool isnull
Definition: params.h:57
#define PARAM_FLAG_CONST
Definition: params.h:52
bool isnull
Definition: plpgsql.h:270
Oid typoid
Definition: plpgsql.h:179
static void assign_text_var ( PLpgSQL_execstate estate,
PLpgSQL_var var,
const char *  str 
)
static

Definition at line 6937 of file pl_exec.c.

References assign_simple_var(), and CStringGetTextDatum.

Referenced by exec_stmt_block(), exec_stmt_forc(), exec_stmt_open(), plpgsql_exec_event_trigger(), and plpgsql_exec_trigger().

6938 {
6939  assign_simple_var(estate, var, CStringGetTextDatum(str), false, true);
6940 }
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:6902
#define CStringGetTextDatum(s)
Definition: builtins.h:91
static bool contains_target_param ( Node node,
int *  target_dno 
)
static

Definition at line 6734 of file pl_exec.c.

References expression_tree_walker(), IsA, PARAM_EXTERN, Param::paramid, and Param::paramkind.

Referenced by exec_check_rw_parameter().

6735 {
6736  if (node == NULL)
6737  return false;
6738  if (IsA(node, Param))
6739  {
6740  Param *param = (Param *) node;
6741 
6742  if (param->paramkind == PARAM_EXTERN &&
6743  param->paramid == *target_dno + 1)
6744  return true;
6745  return false;
6746  }
6748  (void *) target_dno);
6749 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
ParamKind paramkind
Definition: primnodes.h:244
static bool contains_target_param(Node *node, int *target_dno)
Definition: pl_exec.c:6734
int paramid
Definition: primnodes.h:245
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
static char * convert_value_to_string ( PLpgSQL_execstate estate,
Datum  value,
Oid  valtype 
)
static

Definition at line 6236 of file pl_exec.c.

References get_eval_mcontext, getTypeOutputInfo(), MemoryContextSwitchTo(), OidOutputFunctionCall(), and result.

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

6237 {
6238  char *result;
6239  MemoryContext oldcontext;
6240  Oid typoutput;
6241  bool typIsVarlena;
6242 
6243  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6244  getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
6245  result = OidOutputFunctionCall(typoutput, value);
6246  MemoryContextSwitchTo(oldcontext);
6247 
6248  return result;
6249 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2632
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1633
unsigned int Oid
Definition: postgres_ext.h:31
static struct @121 value
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1747
static PLpgSQL_datum * copy_plpgsql_datum ( PLpgSQL_datum datum)
static

Definition at line 1031 of file pl_exec.c.

References Assert, PLpgSQL_datum::dtype, elog, ERROR, palloc(), PLPGSQL_DTYPE_ARRAYELEM, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, and result.

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

1032 {
1034 
1035  switch (datum->dtype)
1036  {
1037  case PLPGSQL_DTYPE_VAR:
1038  {
1039  PLpgSQL_var *new = palloc(sizeof(PLpgSQL_var));
1040 
1041  memcpy(new, datum, sizeof(PLpgSQL_var));
1042  /* should be preset to null/non-freeable */
1043  Assert(new->isnull);
1044  Assert(!new->freeval);
1045 
1046  result = (PLpgSQL_datum *) new;
1047  }
1048  break;
1049 
1050  case PLPGSQL_DTYPE_REC:
1051  {
1052  PLpgSQL_rec *new = palloc(sizeof(PLpgSQL_rec));
1053 
1054  memcpy(new, datum, sizeof(PLpgSQL_rec));
1055  /* should be preset to null/non-freeable */
1056  Assert(new->tup == NULL);
1057  Assert(new->tupdesc == NULL);
1058  Assert(!new->freetup);
1059  Assert(!new->freetupdesc);
1060 
1061  result = (PLpgSQL_datum *) new;
1062  }
1063  break;
1064 
1065  case PLPGSQL_DTYPE_ROW:
1068 
1069  /*
1070  * These datum records are read-only at runtime, so no need to
1071  * copy them (well, ARRAYELEM contains some cached type data, but
1072  * we'd just as soon centralize the caching anyway)
1073  */
1074  result = datum;
1075  break;
1076 
1077  default:
1078  elog(ERROR, "unrecognized dtype: %d", datum->dtype);
1079  result = NULL; /* keep compiler quiet */
1080  break;
1081  }
1082 
1083  return result;
1084 }
return result
Definition: formatting.c:1633
PLpgSQL_datum_type dtype
Definition: plpgsql.h:198
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:664
void * palloc(Size size)
Definition: mcxt.c:848
#define elog
Definition: elog.h:219
static bool exception_matches_conditions ( ErrorData edata,
PLpgSQL_condition cond 
)
static

Definition at line 1143 of file pl_exec.c.

References ERRCODE_IS_CATEGORY, ERRCODE_TO_CATEGORY, PLpgSQL_condition::next, ErrorData::sqlerrcode, and PLpgSQL_condition::sqlerrstate.

Referenced by exec_stmt_block().

1144 {
1145  for (; cond != NULL; cond = cond->next)
1146  {
1147  int sqlerrstate = cond->sqlerrstate;
1148 
1149  /*
1150  * OTHERS matches everything *except* query-canceled and
1151  * assert-failure. If you're foolish enough, you can match those
1152  * explicitly.
1153  */
1154  if (sqlerrstate == 0)
1155  {
1156  if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED &&
1157  edata->sqlerrcode != ERRCODE_ASSERT_FAILURE)
1158  return true;
1159  }
1160  /* Exact match? */
1161  else if (edata->sqlerrcode == sqlerrstate)
1162  return true;
1163  /* Category match? */
1164  else if (ERRCODE_IS_CATEGORY(sqlerrstate) &&
1165  ERRCODE_TO_CATEGORY(edata->sqlerrcode) == sqlerrstate)
1166  return true;
1167  }
1168  return false;
1169 }
#define ERRCODE_IS_CATEGORY(ec)
Definition: elog.h:68
int sqlerrcode
Definition: elog.h:342
struct PLpgSQL_condition * next
Definition: plpgsql.h:378
#define ERRCODE_TO_CATEGORY(ec)
Definition: elog.h:67
static void exec_assign_c_string ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
const char *  str 
)
static

Definition at line 4396 of file pl_exec.c.

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

Referenced by exec_stmt_getdiag().

4398 {
4399  text *value;
4400  MemoryContext oldcontext;
4401 
4402  /* Use eval_mcontext for short-lived text value */
4403  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4404  if (str != NULL)
4405  value = cstring_to_text(str);
4406  else
4407  value = cstring_to_text("");
4408  MemoryContextSwitchTo(oldcontext);
4409 
4410  exec_assign_value(estate, target, PointerGetDatum(value), false,
4411  TEXTOID, -1);
4412 }
#define TEXTOID
Definition: pg_type.h:324
#define PointerGetDatum(X)
Definition: postgres.h:562
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static struct @121 value
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
text * cstring_to_text(const char *s)
Definition: varlena.c:149
Definition: c.h:433
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4424
static void exec_assign_expr ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
PLpgSQL_expr expr 
)
static

Definition at line 4359 of file pl_exec.c.

References PLpgSQL_datum::dno, PLpgSQL_datum::dtype, exec_assign_value(), exec_check_rw_parameter(), exec_eval_cleanup(), exec_eval_expr(), exec_prepare_plan(), PLpgSQL_expr::plan, PLPGSQL_DTYPE_VAR, and value.

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

4361 {
4362  Datum value;
4363  bool isnull;
4364  Oid valtype;
4365  int32 valtypmod;
4366 
4367  /*
4368  * If first time through, create a plan for this expression, and then see
4369  * if we can pass the target variable as a read-write parameter to the
4370  * expression. (This is a bit messy, but it seems cleaner than modifying
4371  * the API of exec_eval_expr for the purpose.)
4372  */
4373  if (expr->plan == NULL)
4374  {
4375  exec_prepare_plan(estate, expr, 0);
4376  if (target->dtype == PLPGSQL_DTYPE_VAR)
4377  exec_check_rw_parameter(expr, target->dno);
4378  }
4379 
4380  value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
4381  exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
4382  exec_eval_cleanup(estate);
4383 }
static void exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno)
Definition: pl_exec.c:6657
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
unsigned int Oid
Definition: postgres_ext.h:31
PLpgSQL_datum_type dtype
Definition: plpgsql.h:198
SPIPlanPtr plan
Definition: plpgsql.h:224
signed int int32
Definition: c.h:246
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
static struct @121 value
uintptr_t Datum
Definition: postgres.h:372
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3559
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4424
static void exec_assign_value ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
Datum  value,
bool  isNull,
Oid  valtype,
int32  valtypmod 
)
static

Definition at line 4424 of file pl_exec.c.

References array_set_element(), PLpgSQL_arrayelem::arrayparentno, PLpgSQL_arrayelem::arraytyplen, PLpgSQL_arrayelem::arraytypmod, PLpgSQL_arrayelem::arraytypoid, Assert, assign_simple_var(), PLpgSQL_type::atttypmod, construct_empty_array(), CurrentMemoryContext, PLpgSQL_var::datatype, DatumGetPointer, PLpgSQL_execstate::datums, datumTransfer(), PLpgSQL_datum::dtype, PLpgSQL_arrayelem::elemtypalign, PLpgSQL_arrayelem::elemtypbyval, PLpgSQL_arrayelem::elemtyplen, PLpgSQL_arrayelem::elemtypoid, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, PLpgSQL_execstate::eval_tuptable, exec_cast_value(), exec_eval_datum(), exec_eval_integer(), exec_move_row(), exec_move_row_from_datum(), expand_array(), PLpgSQL_recfield::fieldname, PLpgSQL_rec::freetup, get_element_type(), get_eval_mcontext, get_typlen(), get_typlenbyvalalign(), getBaseTypeAndTypmod(), heap_freetuple(), heap_modify_tuple_by_cols(), HeapTupleIsValid, i, PLpgSQL_var::isnull, MAXDIM, MemoryContextSwitchTo(), PLpgSQL_var::notnull, OidIsValid, PLpgSQL_arrayelem::parenttypmod, PLpgSQL_arrayelem::parenttypoid, PLPGSQL_DTYPE_ARRAYELEM, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, PointerGetDatum, PLpgSQL_recfield::recparentno, PLpgSQL_var::refname, PLpgSQL_rec::refname, SPI_fnumber(), SPI_freetuptable(), PLpgSQL_arrayelem::subscript, PLpgSQL_rec::tup, PLpgSQL_rec::tupdesc, TupleDescAttr, PLpgSQL_type::typbyval, type_is_rowtype(), PLpgSQL_type::typisarray, PLpgSQL_type::typlen, PLpgSQL_type::typoid, PLpgSQL_var::value, values, and VARATT_IS_EXTERNAL_EXPANDED_RW.

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

4428 {
4429  switch (target->dtype)
4430  {
4431  case PLPGSQL_DTYPE_VAR:
4432  {
4433  /*
4434  * Target is a variable
4435  */
4436  PLpgSQL_var *var = (PLpgSQL_var *) target;
4437  Datum newvalue;
4438 
4439  newvalue = exec_cast_value(estate,
4440  value,
4441  &isNull,
4442  valtype,
4443  valtypmod,
4444  var->datatype->typoid,
4445  var->datatype->atttypmod);
4446 
4447  if (isNull && var->notnull)
4448  ereport(ERROR,
4449  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4450  errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
4451  var->refname)));
4452 
4453  /*
4454  * If type is by-reference, copy the new value (which is
4455  * probably in the eval_mcontext) into the procedure's main
4456  * memory context. But if it's a read/write reference to an
4457  * expanded object, no physical copy needs to happen; at most
4458  * we need to reparent the object's memory context.
4459  *
4460  * If it's an array, we force the value to be stored in R/W
4461  * expanded form. This wins if the function later does, say,
4462  * a lot of array subscripting operations on the variable, and
4463  * otherwise might lose. We might need to use a different
4464  * heuristic, but it's too soon to tell. Also, are there
4465  * cases where it'd be useful to force non-array values into
4466  * expanded form?
4467  */
4468  if (!var->datatype->typbyval && !isNull)
4469  {
4470  if (var->datatype->typisarray &&
4472  {
4473  /* array and not already R/W, so apply expand_array */
4474  newvalue = expand_array(newvalue,
4476  NULL);
4477  }
4478  else
4479  {
4480  /* else transfer value if R/W, else just datumCopy */
4481  newvalue = datumTransfer(newvalue,
4482  false,
4483  var->datatype->typlen);
4484  }
4485  }
4486 
4487  /*
4488  * Now free the old value, if any, and assign the new one. But
4489  * skip the assignment if old and new values are the same.
4490  * Note that for expanded objects, this test is necessary and
4491  * cannot reliably be made any earlier; we have to be looking
4492  * at the object's standard R/W pointer to be sure pointer
4493  * equality is meaningful.
4494  */
4495  if (var->value != newvalue || var->isnull || isNull)
4496  assign_simple_var(estate, var, newvalue, isNull,
4497  (!var->datatype->typbyval && !isNull));
4498  break;
4499  }
4500 
4501  case PLPGSQL_DTYPE_ROW:
4502  {
4503  /*
4504  * Target is a row variable
4505  */
4506  PLpgSQL_row *row = (PLpgSQL_row *) target;
4507 
4508  if (isNull)
4509  {
4510  /* If source is null, just assign nulls to the row */
4511  exec_move_row(estate, NULL, row, NULL, NULL);
4512  }
4513  else
4514  {
4515  /* Source must be of RECORD or composite type */
4516  if (!type_is_rowtype(valtype))
4517  ereport(ERROR,
4518  (errcode(ERRCODE_DATATYPE_MISMATCH),
4519  errmsg("cannot assign non-composite value to a row variable")));
4520  exec_move_row_from_datum(estate, NULL, row, value);
4521  }
4522  break;
4523  }
4524 
4525  case PLPGSQL_DTYPE_REC:
4526  {
4527  /*
4528  * Target is a record variable
4529  */
4530  PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
4531 
4532  if (isNull)
4533  {
4534  /* If source is null, just assign nulls to the record */
4535  exec_move_row(estate, rec, NULL, NULL, NULL);
4536  }
4537  else
4538  {
4539  /* Source must be of RECORD or composite type */
4540  if (!type_is_rowtype(valtype))
4541  ereport(ERROR,
4542  (errcode(ERRCODE_DATATYPE_MISMATCH),
4543  errmsg("cannot assign non-composite value to a record variable")));
4544  exec_move_row_from_datum(estate, rec, NULL, value);
4545  }
4546  break;
4547  }
4548 
4550  {
4551  /*
4552  * Target is a field of a record
4553  */
4554  PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) target;
4555  PLpgSQL_rec *rec;
4556  int fno;
4557  HeapTuple newtup;
4558  int colnums[1];
4559  Datum values[1];
4560  bool nulls[1];
4561  Oid atttype;
4562  int32 atttypmod;
4563 
4564  rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
4565 
4566  /*
4567  * Check that there is already a tuple in the record. We need
4568  * that because records don't have any predefined field
4569  * structure.
4570  */
4571  if (!HeapTupleIsValid(rec->tup))
4572  ereport(ERROR,
4573  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4574  errmsg("record \"%s\" is not assigned yet",
4575  rec->refname),
4576  errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4577 
4578  /*
4579  * Get the number of the record field to change. Disallow
4580  * system columns because the code below won't cope.
4581  */
4582  fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
4583  if (fno <= 0)
4584  ereport(ERROR,
4585  (errcode(ERRCODE_UNDEFINED_COLUMN),
4586  errmsg("record \"%s\" has no field \"%s\"",
4587  rec->refname, recfield->fieldname)));
4588  colnums[0] = fno;
4589 
4590  /*
4591  * Now insert the new value, being careful to cast it to the
4592  * right type.
4593  */
4594  atttype = TupleDescAttr(rec->tupdesc, fno - 1)->atttypid;
4595  atttypmod = TupleDescAttr(rec->tupdesc, fno - 1)->atttypmod;
4596  values[0] = exec_cast_value(estate,
4597  value,
4598  &isNull,
4599  valtype,
4600  valtypmod,
4601  atttype,
4602  atttypmod);
4603  nulls[0] = isNull;
4604 
4605  newtup = heap_modify_tuple_by_cols(rec->tup, rec->tupdesc,
4606  1, colnums, values, nulls);
4607 
4608  if (rec->freetup)
4609  heap_freetuple(rec->tup);
4610 
4611  rec->tup = newtup;
4612  rec->freetup = true;
4613 
4614  break;
4615  }
4616 
4618  {
4619  /*
4620  * Target is an element of an array
4621  */
4622  PLpgSQL_arrayelem *arrayelem;
4623  int nsubscripts;
4624  int i;
4625  PLpgSQL_expr *subscripts[MAXDIM];
4626  int subscriptvals[MAXDIM];
4627  Datum oldarraydatum,
4628  newarraydatum,
4629  coerced_value;
4630  bool oldarrayisnull;
4631  Oid parenttypoid;
4632  int32 parenttypmod;
4633  SPITupleTable *save_eval_tuptable;
4634  MemoryContext oldcontext;
4635 
4636  /*
4637  * We need to do subscript evaluation, which might require
4638  * evaluating general expressions; and the caller might have
4639  * done that too in order to prepare the input Datum. We have
4640  * to save and restore the caller's SPI_execute result, if
4641  * any.
4642  */
4643  save_eval_tuptable = estate->eval_tuptable;
4644  estate->eval_tuptable = NULL;
4645 
4646  /*
4647  * To handle constructs like x[1][2] := something, we have to
4648  * be prepared to deal with a chain of arrayelem datums. Chase
4649  * back to find the base array datum, and save the subscript
4650  * expressions as we go. (We are scanning right to left here,
4651  * but want to evaluate the subscripts left-to-right to
4652  * minimize surprises.) Note that arrayelem is left pointing
4653  * to the leftmost arrayelem datum, where we will cache the
4654  * array element type data.
4655  */
4656  nsubscripts = 0;
4657  do
4658  {
4659  arrayelem = (PLpgSQL_arrayelem *) target;
4660  if (nsubscripts >= MAXDIM)
4661  ereport(ERROR,
4662  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
4663  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
4664  nsubscripts + 1, MAXDIM)));
4665  subscripts[nsubscripts++] = arrayelem->subscript;
4666  target = estate->datums[arrayelem->arrayparentno];
4667  } while (target->dtype == PLPGSQL_DTYPE_ARRAYELEM);
4668 
4669  /* Fetch current value of array datum */
4670  exec_eval_datum(estate, target,
4671  &parenttypoid, &parenttypmod,
4672  &oldarraydatum, &oldarrayisnull);
4673 
4674  /* Update cached type data if necessary */
4675  if (arrayelem->parenttypoid != parenttypoid ||
4676  arrayelem->parenttypmod != parenttypmod)
4677  {
4678  Oid arraytypoid;
4679  int32 arraytypmod = parenttypmod;
4680  int16 arraytyplen;
4681  Oid elemtypoid;
4682  int16 elemtyplen;
4683  bool elemtypbyval;
4684  char elemtypalign;
4685 
4686  /* If target is domain over array, reduce to base type */
4687  arraytypoid = getBaseTypeAndTypmod(parenttypoid,
4688  &arraytypmod);
4689 
4690  /* ... and identify the element type */
4691  elemtypoid = get_element_type(arraytypoid);
4692  if (!OidIsValid(elemtypoid))
4693  ereport(ERROR,
4694  (errcode(ERRCODE_DATATYPE_MISMATCH),
4695  errmsg("subscripted object is not an array")));
4696 
4697  /* Collect needed data about the types */
4698  arraytyplen = get_typlen(arraytypoid);
4699 
4700  get_typlenbyvalalign(elemtypoid,
4701  &elemtyplen,
4702  &elemtypbyval,
4703  &elemtypalign);
4704 
4705  /* Now safe to update the cached data */
4706  arrayelem->parenttypoid = parenttypoid;
4707  arrayelem->parenttypmod = parenttypmod;
4708  arrayelem->arraytypoid = arraytypoid;
4709  arrayelem->arraytypmod = arraytypmod;
4710  arrayelem->arraytyplen = arraytyplen;
4711  arrayelem->elemtypoid = elemtypoid;
4712  arrayelem->elemtyplen = elemtyplen;
4713  arrayelem->elemtypbyval = elemtypbyval;
4714  arrayelem->elemtypalign = elemtypalign;
4715  }
4716 
4717  /*
4718  * Evaluate the subscripts, switch into left-to-right order.
4719  * Like the expression built by ExecInitArrayRef(), complain
4720  * if any subscript is null.
4721  */
4722  for (i = 0; i < nsubscripts; i++)
4723  {
4724  bool subisnull;
4725 
4726  subscriptvals[i] =
4727  exec_eval_integer(estate,
4728  subscripts[nsubscripts - 1 - i],
4729  &subisnull);
4730  if (subisnull)
4731  ereport(ERROR,
4732  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4733  errmsg("array subscript in assignment must not be null")));
4734 
4735  /*
4736  * Clean up in case the subscript expression wasn't
4737  * simple. We can't do exec_eval_cleanup, but we can do
4738  * this much (which is safe because the integer subscript
4739  * value is surely pass-by-value), and we must do it in
4740  * case the next subscript expression isn't simple either.
4741  */
4742  if (estate->eval_tuptable != NULL)
4744  estate->eval_tuptable = NULL;
4745  }
4746 
4747  /* Now we can restore caller's SPI_execute result if any. */
4748  Assert(estate->eval_tuptable == NULL);
4749  estate->eval_tuptable = save_eval_tuptable;
4750 
4751  /* Coerce source value to match array element type. */
4752  coerced_value = exec_cast_value(estate,
4753  value,
4754  &isNull,
4755  valtype,
4756  valtypmod,
4757  arrayelem->elemtypoid,
4758  arrayelem->arraytypmod);
4759 
4760  /*
4761  * If the original array is null, cons up an empty array so
4762  * that the assignment can proceed; we'll end with a
4763  * one-element array containing just the assigned-to
4764  * subscript. This only works for varlena arrays, though; for
4765  * fixed-length array types we skip the assignment. We can't
4766  * support assignment of a null entry into a fixed-length
4767  * array, either, so that's a no-op too. This is all ugly but
4768  * corresponds to the current behavior of execExpr*.c.
4769  */
4770  if (arrayelem->arraytyplen > 0 && /* fixed-length array? */
4771  (oldarrayisnull || isNull))
4772  return;
4773 
4774  /* empty array, if any, and newarraydatum are short-lived */
4775  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4776 
4777  if (oldarrayisnull)
4778  oldarraydatum = PointerGetDatum(construct_empty_array(arrayelem->elemtypoid));
4779 
4780  /*
4781  * Build the modified array value.
4782  */
4783  newarraydatum = array_set_element(oldarraydatum,
4784  nsubscripts,
4785  subscriptvals,
4786  coerced_value,
4787  isNull,
4788  arrayelem->arraytyplen,
4789  arrayelem->elemtyplen,
4790  arrayelem->elemtypbyval,
4791  arrayelem->elemtypalign);
4792 
4793  MemoryContextSwitchTo(oldcontext);
4794 
4795  /*
4796  * Assign the new array to the base variable. It's never NULL
4797  * at this point. Note that if the target is a domain,
4798  * coercing the base array type back up to the domain will
4799  * happen within exec_assign_value.
4800  */
4801  exec_assign_value(estate, target,
4802  newarraydatum,
4803  false,
4804  arrayelem->arraytypoid,
4805  arrayelem->arraytypmod);
4806  break;
4807  }
4808 
4809  default:
4810  elog(ERROR, "unrecognized dtype: %d", target->dtype);
4811  }
4812 }
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:761
signed short int16
Definition: c.h:245
int16 elemtyplen
Definition: plpgsql.h:341
TupleDesc tupdesc
Definition: plpgsql.h:308
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2288
int notnull
Definition: plpgsql.h:263
SPITupleTable * eval_tuptable
Definition: plpgsql.h:926
char * refname
Definition: plpgsql.h:258
static void exec_eval_datum(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeid, int32 *typetypmod, Datum *value, bool *isnull)
Definition: pl_exec.c:4832
static void exec_move_row_from_datum(PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, Datum value)
Definition: pl_exec.c:6191
#define MAXDIM
Definition: c.h:413
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2484
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
#define PointerGetDatum(X)
Definition: postgres.h:562
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
PLpgSQL_type * datatype
Definition: plpgsql.h:261
bool freetup
Definition: plpgsql.h:309
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:6902
Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2187
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3425
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
PLpgSQL_datum_type dtype
Definition: plpgsql.h:198
#define OidIsValid(objectId)
Definition: c.h:532
char * refname
Definition: plpgsql.h:304
signed int int32
Definition: c.h:246
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
int32 arraytypmod
Definition: plpgsql.h:338
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6265
#define ERROR
Definition: elog.h:43
static struct @121 value
int errdetail(const char *fmt,...)
Definition: elog.c:873
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2404
static void exec_move_row(PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
Definition: pl_exec.c:5945
#define ereport(elevel, rest)
Definition: elog.h:122
bool typbyval
Definition: plpgsql.h:182
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:972
bool typisarray
Definition: plpgsql.h:186
uintptr_t Datum
Definition: postgres.h:372
static int exec_eval_integer(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
Definition: pl_exec.c:5136
int32 parenttypmod
Definition: plpgsql.h:336
Datum value
Definition: plpgsql.h:269
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:190
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:664
int16 arraytyplen
Definition: plpgsql.h:339
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, int *replCols, Datum *replValues, bool *replIsnull)
Definition: heaptuple.c:865
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int16 get_typlen(Oid typid)
Definition: lsyscache.c:1947
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 atttypmod
Definition: plpgsql.h:187
HeapTuple tup
Definition: plpgsql.h:307
int i
PLpgSQL_expr * subscript
Definition: plpgsql.h:331
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: postgres.h:321
#define elog
Definition: elog.h:219
int16 typlen
Definition: plpgsql.h:181
char * fieldname
Definition: plpgsql.h:320
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4424
bool isnull
Definition: plpgsql.h:270
Oid typoid
Definition: plpgsql.h:179
static Datum exec_cast_value ( PLpgSQL_execstate estate,
Datum  value,
bool isnull,
Oid  valtype,
int32  valtypmod,
Oid  reqtype,
int32  reqtypmod 
)
static

Definition at line 6265 of file pl_exec.c.

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

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

6269 {
6270  /*
6271  * If the type of the given value isn't what's requested, convert it.
6272  */
6273  if (valtype != reqtype ||
6274  (valtypmod != reqtypmod && reqtypmod != -1))
6275  {
6276  plpgsql_CastHashEntry *cast_entry;
6277 
6278  cast_entry = get_cast_hashentry(estate,
6279  valtype, valtypmod,
6280  reqtype, reqtypmod);
6281  if (cast_entry)
6282  {
6283  ExprContext *econtext = estate->eval_econtext;
6284  MemoryContext oldcontext;
6285 
6286  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6287 
6288  econtext->caseValue_datum = value;
6289  econtext->caseValue_isNull = *isnull;
6290 
6291  cast_entry->cast_in_use = true;
6292 
6293  value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
6294  isnull);
6295 
6296  cast_entry->cast_in_use = false;
6297 
6298  MemoryContextSwitchTo(oldcontext);
6299  }
6300  }
6301 
6302  return value;
6303 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static plpgsql_CastHashEntry * get_cast_hashentry(PLpgSQL_execstate *estate, Oid srctype, int32 srctypmod, Oid dsttype, int32 dsttypmod)
Definition: pl_exec.c:6316
Datum caseValue_datum
Definition: execnodes.h:217
static struct @121 value
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:286
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
ExprContext * eval_econtext
Definition: plpgsql.h:929
bool caseValue_isNull
Definition: execnodes.h:218
ExprState * cast_exprstate
Definition: pl_exec.c:149
static void exec_check_rw_parameter ( PLpgSQL_expr expr,
int  target_dno 
)
static

Definition at line 6657 of file pl_exec.c.

References arg, FuncExpr::args, OpExpr::args, bms_is_member(), contains_target_param(), PLpgSQL_expr::expr_simple_expr, FuncExpr::funcid, IsA, lfirst, OpExpr::opfuncid, PLpgSQL_expr::paramnos, and PLpgSQL_expr::rwparam.

Referenced by exec_assign_expr(), and exec_eval_simple_expr().

6658 {
6659  Oid funcid;
6660  List *fargs;
6661  ListCell *lc;
6662 
6663  /* Assume unsafe */
6664  expr->rwparam = -1;
6665 
6666  /*
6667  * If the expression isn't simple, there's no point in trying to optimize
6668  * (because the exec_run_select code path will flatten any expanded result
6669  * anyway). Even without that, this seems like a good safety restriction.
6670  */
6671  if (expr->expr_simple_expr == NULL)
6672  return;
6673 
6674  /*
6675  * If target variable isn't referenced by expression, no need to look
6676  * further.
6677  */
6678  if (!bms_is_member(target_dno, expr->paramnos))
6679  return;
6680 
6681  /*
6682  * Top level of expression must be a simple FuncExpr or OpExpr.
6683  */
6684  if (IsA(expr->expr_simple_expr, FuncExpr))
6685  {
6686  FuncExpr *fexpr = (FuncExpr *) expr->expr_simple_expr;
6687 
6688  funcid = fexpr->funcid;
6689  fargs = fexpr->args;
6690  }
6691  else if (IsA(expr->expr_simple_expr, OpExpr))
6692  {
6693  OpExpr *opexpr = (OpExpr *) expr->expr_simple_expr;
6694 
6695  funcid = opexpr->opfuncid;
6696  fargs = opexpr->args;
6697  }
6698  else
6699  return;
6700 
6701  /*
6702  * The top-level function must be one that we trust to be "safe".
6703  * Currently we hard-wire the list, but it would be very desirable to
6704  * allow extensions to mark their functions as safe ...
6705  */
6706  if (!(funcid == F_ARRAY_APPEND ||
6707  funcid == F_ARRAY_PREPEND))
6708  return;
6709 
6710  /*
6711  * The target variable (in the form of a Param) must only appear as a
6712  * direct argument of the top-level function.
6713  */
6714  foreach(lc, fargs)
6715  {
6716  Node *arg = (Node *) lfirst(lc);
6717 
6718  /* A Param is OK, whether it's the target variable or not */
6719  if (arg && IsA(arg, Param))
6720  continue;
6721  /* Otherwise, argument expression must not reference target */
6722  if (contains_target_param(arg, &target_dno))
6723  return;
6724  }
6725 
6726  /* OK, we can pass target as a read-write parameter */
6727  expr->rwparam = target_dno;
6728 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * args
Definition: primnodes.h:457
Definition: nodes.h:509
unsigned int Oid
Definition: postgres_ext.h:31
Bitmapset * paramnos
Definition: plpgsql.h:225
Oid funcid
Definition: primnodes.h:449
static bool contains_target_param(Node *node, int *target_dno)
Definition: pl_exec.c:6734
Expr * expr_simple_expr
Definition: plpgsql.h:235
int rwparam
Definition: plpgsql.h:226
Oid opfuncid
Definition: primnodes.h:497
#define lfirst(lc)
Definition: pg_list.h:106
void * arg
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
static Portal exec_dynquery_with_params ( PLpgSQL_execstate estate,
PLpgSQL_expr dynquery,
List params,
const char *  portalname,
int  cursorOptions 
)
static

Definition at line 7028 of file pl_exec.c.

References convert_value_to_string(), elog, ereport, errcode(), errmsg(), ERROR, exec_eval_cleanup(), exec_eval_expr(), exec_eval_using_params(), get_stmt_mcontext(), MemoryContextReset(), MemoryContextStrdup(), PreparedParamsData::nargs, PreparedParamsData::nulls, PLpgSQL_execstate::readonly_func, SPI_cursor_open_with_args(), SPI_result, SPI_result_code_string(), PreparedParamsData::types, and PreparedParamsData::values.

Referenced by exec_stmt_dynfors(), exec_stmt_open(), and exec_stmt_return_query().

7033 {
7034  Portal portal;
7035  Datum query;
7036  bool isnull;
7037  Oid restype;
7038  int32 restypmod;
7039  char *querystr;
7040  MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
7041 
7042  /*
7043  * Evaluate the string expression after the EXECUTE keyword. Its result is
7044  * the querystring we have to execute.
7045  */
7046  query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod);
7047  if (isnull)
7048  ereport(ERROR,
7049  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
7050  errmsg("query string argument of EXECUTE is null")));
7051 
7052  /* Get the C-String representation */
7053  querystr = convert_value_to_string(estate, query, restype);
7054 
7055  /* copy it into the stmt_mcontext before we clean up */
7056  querystr = MemoryContextStrdup(stmt_mcontext, querystr);
7057 
7058  exec_eval_cleanup(estate);
7059 
7060  /*
7061  * Open an implicit cursor for the query. We use
7062  * SPI_cursor_open_with_args even when there are no params, because this
7063  * avoids making and freeing one copy of the plan.
7064  */
7065  if (params)
7066  {
7067  PreparedParamsData *ppd;
7068 
7069  ppd = exec_eval_using_params(estate, params);
7070  portal = SPI_cursor_open_with_args(portalname,
7071  querystr,
7072  ppd->nargs, ppd->types,
7073  ppd->values, ppd->nulls,
7074  estate->readonly_func,
7075  cursorOptions);
7076  }
7077  else
7078  {
7079  portal = SPI_cursor_open_with_args(portalname,
7080  querystr,
7081  0, NULL,
7082  NULL, NULL,
7083  estate->readonly_func,
7084  cursorOptions);
7085  }
7086 
7087  if (portal == NULL)
7088  elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
7089  querystr, SPI_result_code_string(SPI_result));
7090 
7091  /* Release transient data */
7092  MemoryContextReset(stmt_mcontext);
7093 
7094  return portal;
7095 }
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
Datum * values
Definition: pl_exec.c:51
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
int SPI_result
Definition: spi.c:42
#define ERROR
Definition: elog.h:43
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
static PreparedParamsData * exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
Definition: pl_exec.c:6949
const char * SPI_result_code_string(int code)
Definition: spi.c:1515
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1092
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
Portal SPI_cursor_open_with_args(const char *name, const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, int cursorOptions)
Definition: spi.c:1058
bool readonly_func
Definition: plpgsql.h:893
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
static char * convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
Definition: pl_exec.c:6236
#define elog
Definition: elog.h:219
static bool exec_eval_boolean ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull 
)
static

Definition at line 5159 of file pl_exec.c.

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

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

5162 {
5163  Datum exprdatum;
5164  Oid exprtypeid;
5165  int32 exprtypmod;
5166 
5167  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5168  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5169  exprtypeid, exprtypmod,
5170  BOOLOID, -1);
5171  return DatumGetBool(exprdatum);
5172 }
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6265
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
#define DatumGetBool(X)
Definition: postgres.h:399
uintptr_t Datum
Definition: postgres.h:372
#define BOOLOID
Definition: pg_type.h:288
static void exec_eval_cleanup ( PLpgSQL_execstate estate)
static

Definition at line 3538 of file pl_exec.c.

References PLpgSQL_execstate::eval_econtext, PLpgSQL_execstate::eval_tuptable, ResetExprContext, and SPI_freetuptable().

Referenced by exec_assign_expr(), exec_dynquery_with_params(), exec_eval_using_params(), exec_for_query(), exec_run_select(), exec_stmt_assert(), exec_stmt_block(), exec_stmt_case(), exec_stmt_dynexecute(), exec_stmt_execsql(), exec_stmt_exit(), exec_stmt_fetch(), exec_stmt_forc(), exec_stmt_foreach_a(), exec_stmt_fori(), exec_stmt_getdiag(), exec_stmt_if(), exec_stmt_open(), exec_stmt_perform(), exec_stmt_raise(), exec_stmt_return_next(), exec_stmt_return_query(), exec_stmt_while(), plpgsql_exec_event_trigger(), plpgsql_exec_function(), and plpgsql_exec_trigger().

3539 {
3540  /* Clear result of a full SPI_execute */
3541  if (estate->eval_tuptable != NULL)
3543  estate->eval_tuptable = NULL;
3544 
3545  /*
3546  * Clear result of exec_eval_simple_expr (but keep the econtext). This
3547  * also clears any short-lived allocations done via get_eval_mcontext.
3548  */
3549  if (estate->eval_econtext != NULL)
3551 }
SPITupleTable * eval_tuptable
Definition: plpgsql.h:926
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:972
ExprContext * eval_econtext
Definition: plpgsql.h:929
#define ResetExprContext(econtext)
Definition: executor.h:470
static void exec_eval_datum ( PLpgSQL_execstate estate,
PLpgSQL_datum datum,
Oid typeid,
int32 typetypmod,
Datum value,
bool isnull 
)
static

Definition at line 4832 of file pl_exec.c.

References Assert, PLpgSQL_type::atttypmod, BlessTupleDesc(), PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, PLpgSQL_recfield::fieldname, get_eval_mcontext, heap_copy_tuple_as_datum(), HeapTupleGetDatum, HeapTupleIsValid, PLpgSQL_var::isnull, make_tuple_from_row(), MemoryContextSwitchTo(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, PLpgSQL_recfield::recparentno, PLpgSQL_rec::refname, PLpgSQL_row::rowtupdesc, SPI_ERROR_NOATTRIBUTE, SPI_fnumber(), SPI_getbinval(), SPI_gettypeid(), tupleDesc::tdtypeid, tupleDesc::tdtypmod, PLpgSQL_rec::tup, PLpgSQL_rec::tupdesc, TupleDescAttr, PLpgSQL_type::typoid, and PLpgSQL_var::value.

Referenced by exec_assign_value(), exec_stmt_return(), format_expr_params(), make_tuple_from_row(), and plpgsql_param_fetch().

4838 {
4839  MemoryContext oldcontext;
4840 
4841  switch (datum->dtype)
4842  {
4843  case PLPGSQL_DTYPE_VAR:
4844  {
4845  PLpgSQL_var *var = (PLpgSQL_var *) datum;
4846 
4847  *typeid = var->datatype->typoid;
4848  *typetypmod = var->datatype->atttypmod;
4849  *value = var->value;
4850  *isnull = var->isnull;
4851  break;
4852  }
4853 
4854  case PLPGSQL_DTYPE_ROW:
4855  {
4856  PLpgSQL_row *row = (PLpgSQL_row *) datum;
4857  HeapTuple tup;
4858 
4859  if (!row->rowtupdesc) /* should not happen */
4860  elog(ERROR, "row variable has no tupdesc");
4861  /* Make sure we have a valid type/typmod setting */
4862  BlessTupleDesc(row->rowtupdesc);
4863  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4864  tup = make_tuple_from_row(estate, row, row->rowtupdesc);
4865  if (tup == NULL) /* should not happen */
4866  elog(ERROR, "row not compatible with its own tupdesc");
4867  *typeid = row->rowtupdesc->tdtypeid;
4868  *typetypmod = row->rowtupdesc->tdtypmod;
4869  *value = HeapTupleGetDatum(tup);
4870  *isnull = false;
4871  MemoryContextSwitchTo(oldcontext);
4872  break;
4873  }
4874 
4875  case PLPGSQL_DTYPE_REC:
4876  {
4877  PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
4878 
4879  if (!HeapTupleIsValid(rec->tup))
4880  ereport(ERROR,
4881  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4882  errmsg("record \"%s\" is not assigned yet",
4883  rec->refname),
4884  errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4885  Assert(rec->tupdesc != NULL);
4886  /* Make sure we have a valid type/typmod setting */
4887  BlessTupleDesc(rec->tupdesc);
4888 
4889  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4890  *typeid = rec->tupdesc->tdtypeid;
4891  *typetypmod = rec->tupdesc->tdtypmod;
4892  *value = heap_copy_tuple_as_datum(rec->tup, rec->tupdesc);
4893  *isnull = false;
4894  MemoryContextSwitchTo(oldcontext);
4895  break;
4896  }
4897 
4899  {
4900  PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
4901  PLpgSQL_rec *rec;
4902  int fno;
4903 
4904  rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
4905  if (!HeapTupleIsValid(rec->tup))
4906  ereport(ERROR,
4907  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4908  errmsg("record \"%s\" is not assigned yet",
4909  rec->refname),
4910  errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4911  fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
4912  if (fno == SPI_ERROR_NOATTRIBUTE)
4913  ereport(ERROR,
4914  (errcode(ERRCODE_UNDEFINED_COLUMN),
4915  errmsg("record \"%s\" has no field \"%s\"",
4916  rec->refname, recfield->fieldname)));
4917  *typeid = SPI_gettypeid(rec->tupdesc, fno);
4918  if (fno > 0)
4919  {
4920  Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1);
4921 
4922  *typetypmod = attr->atttypmod;
4923  }
4924  else
4925  *typetypmod = -1;
4926  *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
4927  break;
4928  }
4929 
4930  default:
4931  elog(ERROR, "unrecognized dtype: %d", datum->dtype);
4932  }
4933 }
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:761
TupleDesc tupdesc
Definition: plpgsql.h:308
Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)
Definition: spi.c:894
static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate, PLpgSQL_row *row, TupleDesc tupdesc)
Definition: pl_exec.c:6095
Oid tdtypeid
Definition: tupdesc.h:74
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
PLpgSQL_type * datatype
Definition: plpgsql.h:261
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_datum_type dtype
Definition: plpgsql.h:198
char * refname
Definition: plpgsql.h:304
int32 tdtypmod
Definition: tupdesc.h:75
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
#define ERROR
Definition: elog.h:43
static struct @121 value
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
Definition: spi.c:838
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
int errdetail(const char *fmt,...)
Definition: elog.c:873
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:659
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
Datum value
Definition: plpgsql.h:269
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:664
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 atttypmod
Definition: plpgsql.h:187
HeapTuple tup
Definition: plpgsql.h:307
TupleDesc rowtupdesc
Definition: plpgsql.h:285
#define elog
Definition: elog.h:219
char * fieldname
Definition: plpgsql.h:320
bool isnull
Definition: plpgsql.h:270
Oid typoid
Definition: plpgsql.h:179
static Datum exec_eval_expr ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull,
Oid rettype,
int32 rettypmod 
)
static

Definition at line 5182 of file pl_exec.c.

References CURSOR_OPT_PARALLEL_OK, ereport, errcode(), errmsg(), errmsg_plural(), ERROR, PLpgSQL_execstate::eval_processed, PLpgSQL_execstate::eval_tuptable, exec_eval_simple_expr(), exec_prepare_plan(), exec_run_select(), tupleDesc::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_foreach_a(), exec_stmt_fori(), exec_stmt_raise(), exec_stmt_return(), and exec_stmt_return_next().

5187 {
5188  Datum result = 0;
5189  int rc;
5190  Form_pg_attribute attr;
5191 
5192  /*
5193  * If first time through, create a plan for this expression.
5194  */
5195  if (expr->plan == NULL)
5197 
5198  /*
5199  * If this is a simple expression, bypass SPI and use the executor
5200  * directly
5201  */
5202  if (exec_eval_simple_expr(estate, expr,
5203  &result, isNull, rettype, rettypmod))
5204  return result;
5205 
5206  /*
5207  * Else do it the hard way via exec_run_select
5208  */
5209  rc = exec_run_select(estate, expr, 2, NULL);
5210  if (rc != SPI_OK_SELECT)
5211  ereport(ERROR,
5212  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5213  errmsg("query \"%s\" did not return data", expr->query)));
5214 
5215  /*
5216  * Check that the expression returns exactly one column...
5217  */
5218  if (estate->eval_tuptable->tupdesc->natts != 1)
5219  ereport(ERROR,
5220  (errcode(ERRCODE_SYNTAX_ERROR),
5221  errmsg_plural("query \"%s\" returned %d column",
5222  "query \"%s\" returned %d columns",
5223  estate->eval_tuptable->tupdesc->natts,
5224  expr->query,
5225  estate->eval_tuptable->tupdesc->natts)));
5226 
5227  /*
5228  * ... and get the column's datatype.
5229  */
5230  attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0);
5231  *rettype = attr->atttypid;
5232  *rettypmod = attr->atttypmod;
5233 
5234  /*
5235  * If there are no rows selected, the result is a NULL of that type.
5236  */
5237  if (estate->eval_processed == 0)
5238  {
5239  *isNull = true;
5240  return (Datum) 0;
5241  }
5242 
5243  /*
5244  * Check that the expression returned no more than one row.
5245  */
5246  if (estate->eval_processed != 1)
5247  ereport(ERROR,
5248  (errcode(ERRCODE_CARDINALITY_VIOLATION),
5249  errmsg("query \"%s\" returned more than one row",
5250  expr->query)));
5251 
5252  /*
5253  * Return the single result Datum.
5254  */
5255  return SPI_getbinval(estate->eval_tuptable->vals[0],
5256  estate->eval_tuptable->tupdesc, 1, isNull);
5257 }
char * query
Definition: plpgsql.h:223
SPITupleTable * eval_tuptable
Definition: plpgsql.h:926
uint64 eval_processed
Definition: plpgsql.h:927
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1633
HeapTuple * vals
Definition: spi.h:28
int natts
Definition: tupdesc.h:73
SPIPlanPtr plan
Definition: plpgsql.h:224
#define ERROR
Definition: elog.h:43
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
Definition: spi.c:838
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
TupleDesc tupdesc
Definition: spi.h:27
#define SPI_OK_SELECT
Definition: spi.h:54
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3559
static int exec_run_select(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
Definition: pl_exec.c:5265
static bool exec_eval_simple_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, Datum *result, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5519
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2639
int errmsg(const char *fmt,...)
Definition: elog.c:797
static int exec_eval_integer ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull 
)
static

Definition at line 5136 of file pl_exec.c.

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

Referenced by exec_assign_value(), and exec_stmt_fetch().

5139 {
5140  Datum exprdatum;
5141  Oid exprtypeid;
5142  int32 exprtypmod;
5143 
5144  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5145  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5146  exprtypeid, exprtypmod,
5147  INT4OID, -1);
5148  return DatumGetInt32(exprdatum);
5149 }
#define DatumGetInt32(X)
Definition: postgres.h:478
#define INT4OID
Definition: pg_type.h:316
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6265
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
uintptr_t Datum
Definition: postgres.h:372
static bool exec_eval_simple_expr ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
Datum result,
bool isNull,
Oid rettype,
int32 rettypmod 
)
static

Definition at line 5519 of file pl_exec.c.

References Assert, CommandCounterIncrement(), ExprContext::ecxt_param_list_info, EState::es_query_cxt, PLpgSQL_execstate::eval_econtext, exec_check_rw_parameter(), exec_save_simple_expr(), ExecEvalExpr(), ExecInitExpr(), PLpgSQL_expr::expr_simple_expr, PLpgSQL_expr::expr_simple_generation, PLpgSQL_expr::expr_simple_in_use, PLpgSQL_expr::expr_simple_lxid, PLpgSQL_expr::expr_simple_state, PLpgSQL_expr::expr_simple_type, PLpgSQL_expr::expr_simple_typmod, CachedPlan::generation, get_eval_mcontext, GetTransactionSnapshot(), PGPROC::lxid, MemoryContextSwitchTo(), MyProc, PLpgSQL_execstate::paramLI, ParamListInfoData::parserSetupArg, PLpgSQL_expr::plan, PopActiveSnapshot(), PushActiveSnapshot(), PLpgSQL_execstate::readonly_func, ReleaseCachedPlan(), PLpgSQL_expr::rwparam, setup_param_list(), setup_unshared_param_list(), PLpgSQL_execstate::simple_eval_estate, and SPI_plan_get_cached_plan().

Referenced by exec_eval_expr().

5525 {
5526  ExprContext *econtext = estate->eval_econtext;
5527  LocalTransactionId curlxid = MyProc->lxid;
5528  CachedPlan *cplan;
5529  ParamListInfo paramLI;
5530  void *save_setup_arg;
5531  MemoryContext oldcontext;
5532 
5533  /*
5534  * Forget it if expression wasn't simple before.
5535  */
5536  if (expr->expr_simple_expr == NULL)
5537  return false;
5538 
5539  /*
5540  * If expression is in use in current xact, don't touch it.
5541  */
5542  if (expr->expr_simple_in_use && expr->expr_simple_lxid == curlxid)
5543  return false;
5544 
5545  /*
5546  * Revalidate cached plan, so that we will notice if it became stale. (We
5547  * need to hold a refcount while using the plan, anyway.) If replanning
5548  * is needed, do that work in the eval_mcontext.
5549  */
5550  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5551  cplan = SPI_plan_get_cached_plan(expr->plan);
5552  MemoryContextSwitchTo(oldcontext);
5553 
5554  /*
5555  * We can't get a failure here, because the number of CachedPlanSources in
5556  * the SPI plan can't change from what exec_simple_check_plan saw; it's a
5557  * property of the raw parsetree generated from the query text.
5558  */
5559  Assert(cplan != NULL);
5560 
5561  /* If it got replanned, update our copy of the simple expression */
5562  if (cplan->generation != expr->expr_simple_generation)
5563  {
5564  exec_save_simple_expr(expr, cplan);
5565  /* better recheck r/w safety, as it could change due to inlining */
5566  if (expr->rwparam >= 0)
5567  exec_check_rw_parameter(expr, expr->rwparam);
5568  }
5569 
5570  /*
5571  * Pass back previously-determined result type.
5572  */
5573  *rettype = expr->expr_simple_type;
5574  *rettypmod = expr->expr_simple_typmod;
5575 
5576  /*
5577  * Prepare the expression for execution, if it's not been done already in
5578  * the current transaction. (This will be forced to happen if we called
5579  * exec_save_simple_expr above.)
5580  */
5581  if (expr->expr_simple_lxid != curlxid)
5582  {
5583  oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
5584  expr->expr_simple_state = ExecInitExpr(expr->expr_simple_expr, NULL);
5585  expr->expr_simple_in_use = false;
5586  expr->expr_simple_lxid = curlxid;
5587  MemoryContextSwitchTo(oldcontext);
5588  }
5589 
5590  /*
5591  * We have to do some of the things SPI_execute_plan would do, in
5592  * particular advance the snapshot if we are in a non-read-only function.
5593  * Without this, stable functions within the expression would fail to see
5594  * updates made so far by our own function.
5595  */
5596  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5597  if (!estate->readonly_func)
5598  {
5601  }
5602 
5603  /*
5604  * Set up ParamListInfo to pass to executor. We need an unshared list if
5605  * it's going to include any R/W expanded-object pointer. For safety,
5606  * save and restore estate->paramLI->parserSetupArg around our use of the
5607  * param list.
5608  */
5609  save_setup_arg = estate->paramLI->parserSetupArg;
5610 
5611  if (expr->rwparam >= 0)
5612  paramLI = setup_unshared_param_list(estate, expr);
5613  else
5614  paramLI = setup_param_list(estate, expr);
5615 
5616  econtext->ecxt_param_list_info = paramLI;
5617 
5618  /*
5619  * Mark expression as busy for the duration of the ExecEvalExpr call.
5620  */
5621  expr->expr_simple_in_use = true;
5622 
5623  /*
5624  * Finally we can call the executor to evaluate the expression
5625  */
5627  econtext,
5628  isNull);
5629 
5630  /* Assorted cleanup */
5631  expr->expr_simple_in_use = false;
5632 
5633  econtext->ecxt_param_list_info = NULL;
5634 
5635  estate->paramLI->parserSetupArg = save_setup_arg;
5636 
5637  if (!estate->readonly_func)
5639 
5640  MemoryContextSwitchTo(oldcontext);
5641 
5642  /*
5643  * Now we can release our refcount on the cached plan.
5644  */
5645  ReleaseCachedPlan(cplan, true);
5646 
5647  /*
5648  * That's it.
5649  */
5650  return true;
5651 }
int expr_simple_generation
Definition: plpgsql.h:236
void * parserSetupArg
Definition: params.h:73
static void exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno)
Definition: pl_exec.c:6657
PGPROC * MyProc
Definition: proc.c:67
static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5785
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1633
void PopActiveSnapshot(void)
Definition: snapmgr.c:812
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:304
static void exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
Definition: pl_exec.c:6570
SPIPlanPtr plan
Definition: plpgsql.h:224
CachedPlan * SPI_plan_get_cached_plan(SPIPlanPtr plan)
Definition: spi.c:1608
MemoryContext es_query_cxt
Definition: execnodes.h:471
ParamListInfo paramLI
Definition: plpgsql.h:911
EState * simple_eval_estate
Definition: plpgsql.h:915
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:733
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:286
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1256
Expr * expr_simple_expr
Definition: plpgsql.h:235
uint32 LocalTransactionId
Definition: c.h:393
static ParamListInfo setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5688
int rwparam
Definition: plpgsql.h:226
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
ExprState * expr_simple_state
Definition: plpgsql.h:246
void CommandCounterIncrement(void)
Definition: xact.c:923
LocalTransactionId expr_simple_lxid
Definition: plpgsql.h:248
#define Assert(condition)
Definition: c.h:664
ExprContext * eval_econtext
Definition: plpgsql.h:929
bool readonly_func
Definition: plpgsql.h:893
int generation
Definition: plancache.h:141
int32 expr_simple_typmod
Definition: plpgsql.h:238
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:113
bool expr_simple_in_use
Definition: plpgsql.h:247
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:207
Oid expr_simple_type
Definition: plpgsql.h:237
LocalTransactionId lxid
Definition: proc.h:106
static PreparedParamsData * exec_eval_using_params ( PLpgSQL_execstate estate,
List params 
)
static

Definition at line 6949 of file pl_exec.c.

References CStringGetTextDatum, datumCopy(), DatumGetCString, exec_eval_cleanup(), exec_eval_expr(), get_stmt_mcontext(), get_typlenbyval(), i, lfirst, list_length(), MemoryContextAlloc(), MemoryContextSwitchTo(), PreparedParamsData::nargs, PreparedParamsData::nulls, TEXTOID, PreparedParamsData::types, UNKNOWNOID, and PreparedParamsData::values.

Referenced by exec_dynquery_with_params(), and exec_stmt_dynexecute().

6950 {
6951  PreparedParamsData *ppd;
6952  MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
6953  int nargs;
6954  int i;
6955  ListCell *lc;
6956 
6957  ppd = (PreparedParamsData *)
6958  MemoryContextAlloc(stmt_mcontext, sizeof(PreparedParamsData));
6959  nargs = list_length(params);
6960 
6961  ppd->nargs = nargs;
6962  ppd->types = (Oid *)
6963  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Oid));
6964  ppd->values = (Datum *)
6965  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Datum));
6966  ppd->nulls = (char *)
6967  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(char));
6968 
6969  i = 0;
6970  foreach(lc, params)
6971  {
6972  PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
6973  bool isnull;
6974  int32 ppdtypmod;
6975  MemoryContext oldcontext;
6976 
6977  ppd->values[i] = exec_eval_expr(estate, param,
6978  &isnull,
6979  &ppd->types[i],
6980  &ppdtypmod);
6981  ppd->nulls[i] = isnull ? 'n' : ' ';
6982 
6983  oldcontext = MemoryContextSwitchTo(stmt_mcontext);
6984 
6985  if (ppd->types[i] == UNKNOWNOID)
6986  {
6987  /*
6988  * Treat 'unknown' parameters as text, since that's what most
6989  * people would expect. SPI_execute_with_args can coerce unknown
6990  * constants in a more intelligent way, but not unknown Params.
6991  * This code also takes care of copying into the right context.
6992  * Note we assume 'unknown' has the representation of C-string.
6993  */
6994  ppd->types[i] = TEXTOID;
6995  if (!isnull)
6997  }
6998  /* pass-by-ref non null values must be copied into stmt_mcontext */
6999  else if (!isnull)
7000  {
7001  int16 typLen;
7002  bool typByVal;
7003 
7004  get_typlenbyval(ppd->types[i], &typLen, &typByVal);
7005  if (!typByVal)
7006  ppd->values[i] = datumCopy(ppd->values[i], typByVal, typLen);
7007  }
7008 
7009  MemoryContextSwitchTo(oldcontext);
7010 
7011  exec_eval_cleanup(estate);
7012 
7013  i++;
7014  }
7015 
7016  return ppd;
7017 }
signed short int16
Definition: c.h:245
#define TEXTOID
Definition: pg_type.h:324
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
Datum * values
Definition: pl_exec.c:51
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
#define DatumGetCString(X)
Definition: postgres.h:572
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1092
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:372
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2001
#define UNKNOWNOID
Definition: pg_type.h:431
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:91
static int exec_for_query ( PLpgSQL_execstate estate,
PLpgSQL_stmt_forq stmt,
Portal  portal,
bool  prefetch_ok 
)
static

Definition at line 5335 of file pl_exec.c.

References PLpgSQL_stmt_forq::body, PLpgSQL_execstate::datums, PLpgSQL_row::dno, PLpgSQL_rec::dno, elog, ERROR, exec_eval_cleanup(), exec_move_row(), exec_set_found(), exec_stmts(), PLpgSQL_execstate::exitlabel, i, PLpgSQL_stmt_forq::label, PinPortal(), PLPGSQL_RC_CONTINUE, PLPGSQL_RC_EXIT, PLPGSQL_RC_OK, PLpgSQL_stmt_forq::rec, PLpgSQL_stmt_forq::row, SPI_cursor_fetch(), SPI_freetuptable(), SPI_processed, SPI_tuptable, SPITupleTable::tupdesc, UnpinPortal(), and SPITupleTable::vals.

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

5337 {
5338  PLpgSQL_rec *rec = NULL;
5339  PLpgSQL_row *row = NULL;
5340  SPITupleTable *tuptab;
5341  bool found = false;
5342  int rc = PLPGSQL_RC_OK;
5343  uint64 n;
5344 
5345  /*
5346  * Determine if we assign to a record or a row
5347  */
5348  if (stmt->rec != NULL)
5349  rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
5350  else if (stmt->row != NULL)
5351  row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
5352  else
5353  elog(ERROR, "unsupported target");
5354 
5355  /*
5356  * Make sure the portal doesn't get closed by the user statements we
5357  * execute.
5358  */
5359  PinPortal(portal);
5360 
5361  /*
5362  * Fetch the initial tuple(s). If prefetching is allowed then we grab a
5363  * few more rows to avoid multiple trips through executor startup
5364  * overhead.
5365  */
5366  SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1);
5367  tuptab = SPI_tuptable;
5368  n = SPI_processed;
5369 
5370  /*
5371  * If the query didn't return any rows, set the target to NULL and fall
5372  * through with found = false.
5373  */
5374  if (n == 0)
5375  {
5376  exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
5377  exec_eval_cleanup(estate);
5378  }
5379  else
5380  found = true; /* processed at least one tuple */
5381 
5382  /*
5383  * Now do the loop
5384  */
5385  while (n > 0)
5386  {
5387  uint64 i;
5388 
5389  for (i = 0; i < n; i++)
5390  {
5391  /*
5392  * Assign the tuple to the target
5393  */
5394  exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);
5395  exec_eval_cleanup(estate);
5396 
5397  /*
5398  * Execute the statements
5399  */
5400  rc = exec_stmts(estate, stmt->body);
5401 
5402  if (rc != PLPGSQL_RC_OK)
5403  {
5404  if (rc == PLPGSQL_RC_EXIT)
5405  {
5406  if (estate->exitlabel == NULL)
5407  {
5408  /* unlabelled exit, so exit the current loop */
5409  rc = PLPGSQL_RC_OK;
5410  }
5411  else if (stmt->label != NULL &&
5412  strcmp(stmt->label, estate->exitlabel) == 0)
5413  {
5414  /* label matches this loop, so exit loop */
5415  estate->exitlabel = NULL;
5416  rc = PLPGSQL_RC_OK;
5417  }
5418 
5419  /*
5420  * otherwise, we processed a labelled exit that does not
5421  * match the current statement's label, if any; return
5422  * RC_EXIT so that the EXIT continues to recurse upward.
5423  */
5424  }
5425  else if (rc == PLPGSQL_RC_CONTINUE)
5426  {
5427  if (estate->exitlabel == NULL)
5428  {
5429  /* unlabelled continue, so re-run the current loop */
5430  rc = PLPGSQL_RC_OK;
5431  continue;
5432  }
5433  else if (stmt->label != NULL &&
5434  strcmp(stmt->label, estate->exitlabel) == 0)
5435  {
5436  /* label matches this loop, so re-run loop */
5437  estate->exitlabel = NULL;
5438  rc = PLPGSQL_RC_OK;
5439  continue;
5440  }
5441 
5442  /*
5443  * otherwise, we process a labelled continue that does not
5444  * match the current statement's label, if any; return
5445  * RC_CONTINUE so that the CONTINUE will propagate up the
5446  * stack.
5447  */
5448  }
5449 
5450  /*
5451  * We're aborting the loop. Need a goto to get out of two
5452  * levels of loop...
5453  */
5454  goto loop_exit;
5455  }
5456  }
5457 
5458  SPI_freetuptable(tuptab);
5459 
5460  /*
5461  * Fetch more tuples. If prefetching is allowed, grab 50 at a time.
5462  */
5463  SPI_cursor_fetch(portal, true, prefetch_ok ? 50 : 1);
5464  tuptab = SPI_tuptable;
5465  n = SPI_processed;
5466  }
5467 
5468 loop_exit:
5469 
5470  /*
5471  * Release last group of tuples (if any)
5472  */
5473  SPI_freetuptable(tuptab);
5474 
5475  UnpinPortal(portal);
5476 
5477  /*
5478  * Set the FOUND variable to indicate the result of executing the loop
5479  * (namely, whether we looped one or more times). This must be set last so
5480  * that it does not interfere with the value of the FOUND variable inside
5481  * the loop processing itself.
5482  */
5483  exec_set_found(estate, found);
5484 
5485  return rc;
5486 }
void UnpinPortal(Portal portal)
Definition: portalmem.c:373
PLpgSQL_rec * rec
Definition: plpgsql.h:552
SPITupleTable * SPI_tuptable
Definition: spi.c:41
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
HeapTuple * vals
Definition: spi.h:28
uint64 SPI_processed
Definition: spi.c:39
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
#define ERROR
Definition: elog.h:43
void PinPortal(Portal portal)
Definition: portalmem.c:364
static void exec_move_row(PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
Definition: pl_exec.c:5945
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:972
TupleDesc tupdesc
Definition: spi.h:27
static void exec_set_found(PLpgSQL_execstate *estate, bool state)
Definition: pl_exec.c:6756
int i
PLpgSQL_row * row
Definition: plpgsql.h:553
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Definition: spi.c:1349
#define elog
Definition: elog.h:219
char * exitlabel
Definition: plpgsql.h:896
static int exec_stmts(PLpgSQL_execstate *estate, List *stmts)
Definition: pl_exec.c:1503
static void exec_init_tuple_store ( PLpgSQL_execstate estate)
static

Definition at line 3089 of file pl_exec.c.

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

Referenced by exec_stmt_return_next(), and exec_stmt_return_query().

3090 {
3091  ReturnSetInfo *rsi = estate->rsi;
3092  MemoryContext oldcxt;
3093  ResourceOwner oldowner;
3094 
3095  /*
3096  * Check caller can handle a set result in the way we want
3097  */
3098  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
3099  (rsi->allowedModes & SFRM_Materialize) == 0 ||
3100  rsi->expectedDesc == NULL)
3101  ereport(ERROR,
3102  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3103  errmsg("set-valued function called in context that cannot accept a set")));
3104 
3105  /*
3106  * Switch to the right memory context and resource owner for storing the
3107  * tuplestore for return set. If we're within a subtransaction opened for
3108  * an exception-block, for example, we must still create the tuplestore in
3109  * the resource owner that was active when this function was entered, and
3110  * not in the subtransaction resource owner.
3111  */
3112  oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
3113  oldowner = CurrentResourceOwner;
3115 
3116  estate->tuple_store =
3118  false, work_mem);
3119 
3120  CurrentResourceOwner = oldowner;
3121  MemoryContextSwitchTo(oldcxt);
3122 
3123  estate->rettupdesc = rsi->expectedDesc;
3124 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
ResourceOwner tuple_store_owner
Definition: plpgsql.h:902
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
TupleDesc expectedDesc
Definition: execnodes.h:267
TupleDesc rettupdesc
Definition: plpgsql.h:895
#define ERROR
Definition: elog.h:43
MemoryContext tuple_store_cxt
Definition: plpgsql.h:901
ReturnSetInfo * rsi
Definition: plpgsql.h:903
#define ereport(elevel, rest)
Definition: elog.h:122
Tuplestorestate * tuple_store
Definition: plpgsql.h:900
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
int work_mem
Definition: globals.c:113
int allowedModes
Definition: execnodes.h:268
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void exec_move_row ( PLpgSQL_execstate estate,
PLpgSQL_rec rec,
PLpgSQL_row row,
HeapTuple  tup,
TupleDesc  tupdesc 
)
static

Definition at line 5945 of file pl_exec.c.

References CreateTupleDescCopy(), PLpgSQL_execstate::datums, elog, ERROR, eval_mcontext_alloc, exec_assign_value(), PLpgSQL_rec::freetup, PLpgSQL_rec::freetupdesc, FreeTupleDesc(), heap_copytuple(), heap_form_tuple(), heap_freetuple(), HeapTupleHeaderGetNatts, HeapTupleIsValid, tupleDesc::natts, PLpgSQL_row::nfields, SPI_getbinval(), HeapTupleData::t_data, PLpgSQL_rec::tup, PLpgSQL_rec::tupdesc, TupleDescAttr, UNKNOWNOID, value, and PLpgSQL_row::varnos.

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

5949 {
5950  /*
5951  * Record is simple - just copy the tuple and its descriptor into the
5952  * record variable
5953  */
5954  if (rec != NULL)
5955  {
5956  /*
5957  * Copy input first, just in case it is pointing at variable's value
5958  */
5959  if (HeapTupleIsValid(tup))
5960  tup = heap_copytuple(tup);
5961  else if (tupdesc)
5962  {
5963  /* If we have a tupdesc but no data, form an all-nulls tuple */
5964  bool *nulls;
5965 
5966  nulls = (bool *)
5967  eval_mcontext_alloc(estate, tupdesc->natts * sizeof(bool));
5968  memset(nulls, true, tupdesc->natts * sizeof(bool));
5969 
5970  tup = heap_form_tuple(tupdesc, NULL, nulls);
5971  }
5972 
5973  if (tupdesc)
5974  tupdesc = CreateTupleDescCopy(tupdesc);
5975 
5976  /* Free the old value ... */
5977  if (rec->freetup)
5978  {
5979  heap_freetuple(rec->tup);
5980  rec->freetup = false;
5981  }
5982  if (rec->freetupdesc)
5983  {
5984  FreeTupleDesc(rec->tupdesc);
5985  rec->freetupdesc = false;
5986  }
5987 
5988  /* ... and install the new */
5989  if (HeapTupleIsValid(tup))
5990  {
5991  rec->tup = tup;
5992  rec->freetup = true;
5993  }
5994  else
5995  rec->tup = NULL;
5996 
5997  if (tupdesc)
5998  {
5999  rec->tupdesc = tupdesc;
6000  rec->freetupdesc = true;
6001  }
6002  else
6003  rec->tupdesc = NULL;
6004 
6005  return;
6006  }
6007 
6008  /*
6009  * Row is a bit more complicated in that we assign the individual
6010  * attributes of the tuple to the variables the row points to.
6011  *
6012  * NOTE: this code used to demand row->nfields ==
6013  * HeapTupleHeaderGetNatts(tup->t_data), but that's wrong. The tuple
6014  * might have more fields than we expected if it's from an
6015  * inheritance-child table of the current table, or it might have fewer if
6016  * the table has had columns added by ALTER TABLE. Ignore extra columns
6017  * and assume NULL for missing columns, the same as heap_getattr would do.
6018  * We also have to skip over dropped columns in either the source or
6019  * destination.
6020  *
6021  * If we have no tuple data at all, we'll assign NULL to all columns of
6022  * the row variable.
6023  */
6024  if (row != NULL)
6025  {
6026  int td_natts = tupdesc ? tupdesc->natts : 0;
6027  int t_natts;
6028  int fnum;
6029  int anum;
6030 
6031  if (HeapTupleIsValid(tup))
6032  t_natts = HeapTupleHeaderGetNatts(tup->t_data);
6033  else
6034  t_natts = 0;
6035 
6036  anum = 0;
6037  for (fnum = 0; fnum < row->nfields; fnum++)
6038  {
6039  PLpgSQL_var *var;
6040  Datum value;
6041  bool isnull;
6042  Oid valtype;
6043  int32 valtypmod;
6044 
6045  if (row->varnos[fnum] < 0)
6046  continue; /* skip dropped column in row struct */
6047 
6048  var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
6049 
6050  while (anum < td_natts &&
6051  TupleDescAttr(tupdesc, anum)->attisdropped)
6052  anum++; /* skip dropped column in tuple */
6053 
6054  if (anum < td_natts)
6055  {
6056  if (anum < t_natts)
6057  value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
6058  else
6059  {
6060  value = (Datum) 0;
6061  isnull = true;
6062  }
6063  valtype = TupleDescAttr(tupdesc, anum)->atttypid;
6064  valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
6065  anum++;
6066  }
6067  else
6068  {
6069  value = (Datum) 0;
6070  isnull = true;
6071  valtype = UNKNOWNOID;
6072  valtypmod = -1;
6073  }
6074 
6075  exec_assign_value(estate, (PLpgSQL_datum *) var,
6076  value, isnull, valtype, valtypmod);
6077  }
6078 
6079  return;
6080  }
6081 
6082  elog(ERROR, "unsupported target");
6083 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
TupleDesc tupdesc
Definition: plpgsql.h:308
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
bool freetup
Definition: plpgsql.h:309
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:73
signed int int32
Definition: c.h:246
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
HeapTupleHeader t_data
Definition: htup.h:67
#define ERROR
Definition: elog.h:43
#define HeapTupleHeaderGetNatts(tup)
Definition: htup_details.h:532
#define eval_mcontext_alloc(estate, sz)
Definition: pl_exec.c:116
static struct @121 value
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
Definition: spi.c:838
int * varnos
Definition: plpgsql.h:294
uintptr_t Datum
Definition: postgres.h:372
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
int nfields
Definition: plpgsql.h:292
bool freetupdesc
Definition: plpgsql.h:310
#define UNKNOWNOID
Definition: pg_type.h:431
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:251
HeapTuple tup
Definition: plpgsql.h:307
#define elog
Definition: elog.h:219
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4424
static void exec_move_row_from_datum ( PLpgSQL_execstate estate,
PLpgSQL_rec rec,
PLpgSQL_row row,
Datum  value 
)
static

Definition at line 6191 of file pl_exec.c.

References DatumGetHeapTupleHeader, exec_move_row(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, InvalidOid, ItemPointerSetInvalid, lookup_rowtype_tupdesc(), ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

Referenced by exec_assign_value(), and plpgsql_exec_function().

6195 {
6197  Oid tupType;
6198  int32 tupTypmod;
6199  TupleDesc tupdesc;
6200  HeapTupleData tmptup;
6201 
6202  /* Extract rowtype info and find a tupdesc */
6203  tupType = HeapTupleHeaderGetTypeId(td);
6204  tupTypmod = HeapTupleHeaderGetTypMod(td);
6205  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
6206 
6207  /* Build a temporary HeapTuple control structure */
6208  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
6209  ItemPointerSetInvalid(&(tmptup.t_self));
6210  tmptup.t_tableOid = InvalidOid;
6211  tmptup.t_data = td;
6212 
6213  /* Do the move */
6214  exec_move_row(estate, rec, row, &tmptup, tupdesc);
6215 
6216  /* Release tupdesc usage count */
6217  ReleaseTupleDesc(tupdesc);
6218 }
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1486
unsigned int Oid
Definition: postgres_ext.h:31
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
signed int int32
Definition: c.h:246
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:455
static struct @121 value
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
Oid t_tableOid
Definition: htup.h:66
static void exec_move_row(PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
Definition: pl_exec.c:5945
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:445
#define InvalidOid
Definition: postgres_ext.h:36
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:115
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:439
static void exec_prepare_plan ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
int  cursorOptions 
)
static

Definition at line 3559 of file pl_exec.c.

References elog, ereport, errcode(), errhint(), errmsg(), ERROR, exec_simple_check_plan(), PLpgSQL_expr::func, PLpgSQL_execstate::func, PLpgSQL_expr::plan, plpgsql_parser_setup(), PLpgSQL_expr::query, PLpgSQL_expr::rwparam, SPI_ERROR_COPY, SPI_ERROR_TRANSACTION, SPI_keepplan(), SPI_prepare_params(), SPI_result, and SPI_result_code_string().

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

3561 {
3562  SPIPlanPtr plan;
3563 
3564  /*
3565  * The grammar can't conveniently set expr->func while building the parse
3566  * tree, so make sure it's set before parser hooks need it.
3567  */
3568  expr->func = estate->func;
3569 
3570  /*
3571  * Generate and save the plan
3572  */
3573  plan = SPI_prepare_params(expr->query,
3575  (void *) expr,
3576  cursorOptions);
3577  if (plan == NULL)
3578  {
3579  /* Some SPI errors deserve specific error messages */
3580  switch (SPI_result)
3581  {
3582  case SPI_ERROR_COPY:
3583  ereport(ERROR,
3584  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3585  errmsg("cannot COPY to/from client in PL/pgSQL")));
3586  case SPI_ERROR_TRANSACTION:
3587  ereport(ERROR,
3588  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3589  errmsg("cannot begin/end transactions in PL/pgSQL"),
3590  errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
3591  default:
3592  elog(ERROR, "SPI_prepare_params failed for \"%s\": %s",
3594  }
3595  }
3596  SPI_keepplan(plan);
3597  expr->plan = plan;
3598 
3599  /* Check to see if it's a simple expression */
3600  exec_simple_check_plan(estate, expr);
3601 
3602  /*
3603  * Mark expression as not using a read-write param. exec_assign_value has
3604  * to take steps to override this if appropriate; that seems cleaner than
3605  * adding parameters to all other callers.
3606  */
3607  expr->rwparam = -1;
3608 }
int errhint(const char *fmt,...)
Definition: elog.c:987
char * query
Definition: plpgsql.h:223
#define SPI_ERROR_COPY
Definition: spi.h:37
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_function * func
Definition: plpgsql.h:883
static void exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:6471
SPIPlanPtr plan
Definition: plpgsql.h:224
int SPI_result
Definition: spi.c:42
#define ERROR
Definition: elog.h:43
const char * SPI_result_code_string(int code)
Definition: spi.c:1515
void plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
Definition: pl_comp.c:1023
int SPI_keepplan(SPIPlanPtr plan)
Definition: spi.c:560
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:66
#define ereport(elevel, rest)
Definition: elog.h:122
#define SPI_ERROR_TRANSACTION
Definition: spi.h:43
int rwparam
Definition: plpgsql.h:226
struct PLpgSQL_function * func
Definition: plpgsql.h:229
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions)
Definition: spi.c:523
static int exec_run_select ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
long  maxtuples,
Portal portalP 
)
static

Definition at line 5265 of file pl_exec.c.

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

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

5267 {
5268  ParamListInfo paramLI;
5269  int rc;
5270 
5271  /*
5272  * On the first call for this expression generate the plan.
5273  *
5274  * If we don't need to return a portal, then we're just going to execute
5275  * the query once, which means it's OK to use a parallel plan, even if the
5276  * number of rows being fetched is limited. If we do need to return a
5277  * portal, the caller might do cursor operations, which parallel query
5278  * can't support.
5279  */
5280  if (expr->plan == NULL)
5281  exec_prepare_plan(estate, expr,
5282  portalP == NULL ? CURSOR_OPT_PARALLEL_OK : 0);
5283 
5284  /*
5285  * If a portal was requested, put the query into the portal
5286  */
5287  if (portalP != NULL)
5288  {
5289  /*
5290  * Set up short-lived ParamListInfo
5291  */
5292  paramLI = setup_unshared_param_list(estate, expr);
5293 
5294  *portalP = SPI_cursor_open_with_paramlist(NULL, expr->plan,
5295  paramLI,
5296  estate->readonly_func);
5297  if (*portalP == NULL)
5298  elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
5300  exec_eval_cleanup(estate);
5301  return SPI_OK_CURSOR;
5302  }
5303 
5304  /*
5305  * Set up ParamListInfo to pass to executor
5306  */
5307  paramLI = setup_param_list(estate, expr);
5308 
5309  /*
5310  * Execute the query
5311  */
5312  rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
5313  estate->readonly_func, maxtuples);
5314  if (rc != SPI_OK_SELECT)
5315  ereport(ERROR,
5316  (errcode(ERRCODE_SYNTAX_ERROR),
5317  errmsg("query \"%s\" is not a SELECT", expr->query)));
5318 
5319  /* Save query results for eventual cleanup */
5320  Assert(estate->eval_tuptable == NULL);
5321  estate->eval_tuptable = SPI_tuptable;
5322  estate->eval_processed = SPI_processed;
5323  estate->eval_lastoid = SPI_lastoid;
5324 
5325  return rc;
5326 }
char * query
Definition: plpgsql.h:223
SPITupleTable * eval_tuptable
Definition: plpgsql.h:926
uint64 eval_processed
Definition: plpgsql.h:927
static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5785
Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only)
Definition: spi.c:1110
SPITupleTable * SPI_tuptable
Definition: spi.c:41
int errcode(int sqlerrcode)
Definition: elog.c:575
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
#define SPI_OK_CURSOR
Definition: spi.h:59
uint64 SPI_processed
Definition: spi.c:39
SPIPlanPtr plan
Definition: plpgsql.h:224
int SPI_result
Definition: spi.c:42
#define ERROR
Definition: elog.h:43
int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount)
Definition: spi.c:373
const char * SPI_result_code_string(int code)
Definition: spi.c:1515
static ParamListInfo setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5688
#define ereport(elevel, rest)
Definition: elog.h:122
Oid SPI_lastoid
Definition: spi.c:40
#define SPI_OK_SELECT
Definition: spi.h:54
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3559
#define Assert(condition)
Definition: c.h:664
bool readonly_func
Definition: plpgsql.h:893
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2639
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
static void exec_save_simple_expr ( PLpgSQL_expr expr,
CachedPlan cplan 
)
static

Definition at line 6570 of file pl_exec.c.

References Assert, castNode, CMD_SELECT, PlannedStmt::commandType, elog, ERROR, PLpgSQL_expr::expr_simple_expr, PLpgSQL_expr::expr_simple_generation, PLpgSQL_expr::expr_simple_in_use, PLpgSQL_expr::expr_simple_lxid, PLpgSQL_expr::expr_simple_state, PLpgSQL_expr::expr_simple_type, PLpgSQL_expr::expr_simple_typmod, exprType(), exprTypmod(), CachedPlan::generation, Plan::initPlan, InvalidLocalTransactionId, IsA, Plan::lefttree, linitial, linitial_node, list_length(), nodeTag, OUTER_VAR, PlannedStmt::planTree, Plan::qual, Plan::righttree, CachedPlan::stmt_list, and Plan::targetlist.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

6571 {
6572  PlannedStmt *stmt;
6573  Plan *plan;
6574  Expr *tle_expr;
6575 
6576  /*
6577  * Given the checks that exec_simple_check_plan did, none of the Asserts
6578  * here should ever fail.
6579  */
6580 
6581  /* Extract the single PlannedStmt */
6582  Assert(list_length(cplan->stmt_list) == 1);
6583  stmt = linitial_node(PlannedStmt, cplan->stmt_list);
6584  Assert(stmt->commandType == CMD_SELECT);
6585 
6586  /*
6587  * Ordinarily, the plan node should be a simple Result. However, if
6588  * force_parallel_mode is on, the planner might've stuck a Gather node
6589  * atop that. The simplest way to deal with this is to look through the
6590  * Gather node. The Gather node's tlist would normally contain a Var
6591  * referencing the child node's output ... but setrefs.c might also have
6592  * copied a Const as-is.
6593  */
6594  plan = stmt->planTree;
6595  for (;;)
6596  {
6597  /* Extract the single tlist expression */
6598  Assert(list_length(plan->targetlist) == 1);
6599  tle_expr = castNode(TargetEntry, linitial(plan->targetlist))->expr;
6600 
6601  if (IsA(plan, Result))
6602  {
6603  Assert(plan->lefttree == NULL &&
6604  plan->righttree == NULL &&
6605  plan->initPlan == NULL &&
6606  plan->qual == NULL &&
6607  ((Result *) plan)->resconstantqual == NULL);
6608  break;
6609  }
6610  else if (IsA(plan, Gather))
6611  {
6612  Assert(plan->lefttree != NULL &&
6613  plan->righttree == NULL &&
6614  plan->initPlan == NULL &&
6615  plan->qual == NULL);
6616  /* If setrefs.c copied up a Const, no need to look further */
6617  if (IsA(tle_expr, Const))
6618  break;
6619  /* Otherwise, it better be an outer Var */
6620  Assert(IsA(tle_expr, Var));
6621  Assert(((Var *) tle_expr)->varno == OUTER_VAR);
6622  /* Descend to the child node */
6623  plan = plan->lefttree;
6624  }
6625  else
6626  elog(ERROR, "unexpected plan node type: %d",
6627  (int) nodeTag(plan));
6628  }
6629 
6630  /*
6631  * Save the simple expression, and initialize state to "not valid in
6632  * current transaction".
6633  */
6634  expr->expr_simple_expr = tle_expr;
6635  expr->expr_simple_generation = cplan->generation;
6636  expr->expr_simple_state = NULL;
6637  expr->expr_simple_in_use = false;
6639  /* Also stash away the expression result type */
6640  expr->expr_simple_type = exprType((Node *) tle_expr);
6641  expr->expr_simple_typmod = exprTypmod((Node *) tle_expr);
6642 }
int expr_simple_generation
Definition: plpgsql.h:236
List * qual
Definition: plannodes.h:145
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Definition: nodes.h:509
Definition: primnodes.h:163
#define linitial_node(type, l)
Definition: pg_list.h:114
struct Plan * planTree
Definition: plannodes.h:61
struct Plan * righttree
Definition: plannodes.h:147
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
Expr * expr_simple_expr
Definition: plpgsql.h:235
ExprState * expr_simple_state
Definition: plpgsql.h:246
CmdType commandType
Definition: plannodes.h:45
LocalTransactionId expr_simple_lxid
Definition: plpgsql.h:248
#define Assert(condition)
Definition: c.h:664
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int generation
Definition: plancache.h:141
static int list_length(const List *l)
Definition: pg_list.h:89
struct Plan * lefttree
Definition: plannodes.h:146
#define nodeTag(nodeptr)
Definition: nodes.h:514
List * targetlist
Definition: plannodes.h:144
int32 expr_simple_typmod
Definition: plpgsql.h:238
List * initPlan
Definition: plannodes.h:148
#define InvalidLocalTransactionId
Definition: lock.h:69
List * stmt_list
Definition: plancache.h:133
bool expr_simple_in_use
Definition: plpgsql.h:247
#define elog
Definition: elog.h:219
#define OUTER_VAR
Definition: primnodes.h:154
Oid expr_simple_type
Definition: plpgsql.h:237
static void exec_set_found ( PLpgSQL_execstate estate,
bool  state 
)
static

Definition at line 6756 of file pl_exec.c.

References assign_simple_var(), BoolGetDatum, PLpgSQL_execstate::datums, and PLpgSQL_execstate::found_varno.

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

6757 {
6758  PLpgSQL_var *var;
6759 
6760  var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
6761  assign_simple_var(estate, var, BoolGetDatum(state), false, false);
6762 }
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:6902
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
#define BoolGetDatum(X)
Definition: postgres.h:408
Definition: regguts.h:298
static void exec_simple_check_plan ( PLpgSQL_execstate estate,
PLpgSQL_expr expr 
)
static

Definition at line 6471 of file pl_exec.c.

References Assert, CMD_SELECT, Query::commandType, Query::cteList, Query::distinctClause, exec_save_simple_expr(), PLpgSQL_expr::expr_simple_expr, FromExpr::fromlist, get_eval_mcontext, Query::groupClause, Query::groupingSets, Query::hasAggs, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, IsA, Query::jointree, Query::limitCount, Query::limitOffset, linitial, list_length(), MemoryContextSwitchTo(), NIL, PLpgSQL_expr::plan, FromExpr::quals, CachedPlanSource::query_list, ReleaseCachedPlan(), Query::rtable, Query::setOperations, Query::sortClause, SPI_plan_get_cached_plan(), SPI_plan_get_plan_sources(), Query::targetList, and Query::windowClause.

Referenced by exec_prepare_plan().

6472 {
6473  List *plansources;
6474  CachedPlanSource *plansource;
6475  Query *query;
6476  CachedPlan *cplan;
6477  MemoryContext oldcontext;
6478 
6479  /*
6480  * Initialize to "not simple".
6481  */
6482  expr->expr_simple_expr = NULL;
6483 
6484  /*
6485  * Check the analyzed-and-rewritten form of the query to see if we will be
6486  * able to treat it as a simple expression. Since this function is only
6487  * called immediately after creating the CachedPlanSource, we need not
6488  * worry about the query being stale.
6489  */
6490 
6491  /*
6492  * We can only test queries that resulted in exactly one CachedPlanSource
6493  */
6494  plansources = SPI_plan_get_plan_sources(expr->plan);
6495  if (list_length(plansources) != 1)
6496  return;
6497  plansource = (CachedPlanSource *) linitial(plansources);
6498 
6499  /*
6500  * 1. There must be one single querytree.
6501  */
6502  if (list_length(plansource->query_list) != 1)
6503  return;
6504  query = (Query *) linitial(plansource->query_list);
6505 
6506  /*
6507  * 2. It must be a plain SELECT query without any input tables
6508  */
6509  if (!IsA(query, Query))
6510  return;
6511  if (query->commandType != CMD_SELECT)
6512  return;
6513  if (query->rtable != NIL)
6514  return;
6515 
6516  /*
6517  * 3. Can't have any subplans, aggregates, qual clauses either. (These
6518  * tests should generally match what inline_function() checks before
6519  * inlining a SQL function; otherwise, inlining could change our
6520  * conclusion about whether an expression is simple, which we don't want.)
6521  */
6522  if (query->hasAggs ||
6523  query->hasWindowFuncs ||
6524  query->hasTargetSRFs ||
6525  query->hasSubLinks ||
6526  query->cteList ||
6527  query->jointree->fromlist ||
6528  query->jointree->quals ||
6529  query->groupClause ||
6530  query->groupingSets ||
6531  query->havingQual ||
6532  query->windowClause ||
6533  query->distinctClause ||
6534  query->sortClause ||
6535  query->limitOffset ||
6536  query->limitCount ||
6537  query->setOperations)
6538  return;
6539 
6540  /*
6541  * 4. The query must have a single attribute as result
6542  */
6543  if (list_length(query->targetList) != 1)
6544  return;
6545 
6546  /*
6547  * OK, we can treat it as a simple plan.
6548  *
6549  * Get the generic plan for the query. If replanning is needed, do that
6550  * work in the eval_mcontext.
6551  */
6552  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6553  cplan = SPI_plan_get_cached_plan(expr->plan);
6554  MemoryContextSwitchTo(oldcontext);
6555 
6556  /* Can't fail, because we checked for a single CachedPlanSource above */
6557  Assert(cplan != NULL);
6558 
6559  /* Share the remaining work with replan code path */
6560  exec_save_simple_expr(expr, cplan);
6561 
6562  /* Release our plan refcount */
6563  ReleaseCachedPlan(cplan, true);
6564 }
Node * limitOffset
Definition: parsenodes.h:158
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * sortClause
Definition: parsenodes.h:156
FromExpr * jointree
Definition: parsenodes.h:136
bool hasAggs
Definition: parsenodes.h:123
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * groupingSets
Definition: parsenodes.h:148
List * fromlist
Definition: primnodes.h:1471
Node * quals
Definition: primnodes.h:1472
static void exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
Definition: pl_exec.c:6570
SPIPlanPtr plan
Definition: plpgsql.h:224
List * windowClause
Definition: parsenodes.h:152
List * targetList
Definition: parsenodes.h:138
CachedPlan * SPI_plan_get_cached_plan(SPIPlanPtr plan)
Definition: spi.c:1608
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
List * distinctClause
Definition: parsenodes.h:154
Node * limitCount
Definition: parsenodes.h:159
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1256
Expr * expr_simple_expr
Definition: plpgsql.h:235
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define Assert(condition)
Definition: c.h:664
bool hasWindowFuncs
Definition: parsenodes.h:124
static int list_length(const List *l)
Definition: pg_list.h:89
List * cteList
Definition: parsenodes.h:133
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
bool hasSubLinks
Definition: parsenodes.h:126
List * SPI_plan_get_plan_sources(SPIPlanPtr plan)
Definition: spi.c:1592
List * query_list
Definition: plancache.h:95
Node * havingQual
Definition: parsenodes.h:150
Definition: pg_list.h:45
static int exec_stmt ( PLpgSQL_execstate estate,
PLpgSQL_stmt stmt 
)
static

Definition at line 1537 of file pl_exec.c.

References CHECK_FOR_INTERRUPTS, PLpgSQL_stmt::cmd_type, elog, PLpgSQL_execstate::err_stmt, ERROR, exec_stmt_assert(), exec_stmt_assign(), exec_stmt_block(), exec_stmt_case(), exec_stmt_close(), 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_while(), plpgsql_plugin_ptr, PLPGSQL_STMT_ASSERT, PLPGSQL_STMT_ASSIGN, PLPGSQL_STMT_BLOCK, PLPGSQL_STMT_CASE, PLPGSQL_STMT_CLOSE, 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_WHILE, PLpgSQL_plugin::stmt_beg, and PLpgSQL_plugin::stmt_end.

Referenced by exec_stmts().

1538 {
1539  PLpgSQL_stmt *save_estmt;
1540  int rc = -1;
1541 
1542  save_estmt = estate->err_stmt;
1543  estate->err_stmt = stmt;
1544 
1545  /* Let the plugin know that we are about to execute this statement */
1546  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
1547  ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
1548 
1550 
1551  switch (stmt->cmd_type)
1552  {
1553  case PLPGSQL_STMT_BLOCK:
1554  rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
1555  break;
1556 
1557  case PLPGSQL_STMT_ASSIGN:
1558  rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
1559  break;
1560 
1561  case PLPGSQL_STMT_PERFORM:
1562  rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
1563  break;
1564 
1565  case PLPGSQL_STMT_GETDIAG:
1566  rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
1567  break;
1568 
1569  case PLPGSQL_STMT_IF:
1570  rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
1571  break;
1572 
1573  case PLPGSQL_STMT_CASE:
1574  rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
1575  break;
1576 
1577  case PLPGSQL_STMT_LOOP:
1578  rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
1579  break;
1580 
1581  case PLPGSQL_STMT_WHILE:
1582  rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
1583  break;
1584 
1585  case PLPGSQL_STMT_FORI:
1586  rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
1587  break;
1588 
1589  case PLPGSQL_STMT_FORS:
1590  rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
1591  break;
1592 
1593  case PLPGSQL_STMT_FORC:
1594  rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
1595  break;
1596 
1598  rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
1599  break;
1600 
1601  case PLPGSQL_STMT_EXIT:
1602  rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
1603  break;
1604 
1605  case PLPGSQL_STMT_RETURN:
1606  rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
1607  break;
1608 
1610  rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
1611  break;
1612 
1614  rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
1615  break;
1616 
1617  case PLPGSQL_STMT_RAISE:
1618  rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
1619  break;
1620 
1621  case PLPGSQL_STMT_ASSERT:
1622  rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
1623  break;
1624 
1625  case PLPGSQL_STMT_EXECSQL:
1626  rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
1627  break;
1628 
1630  rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
1631  break;
1632 
1633  case PLPGSQL_STMT_DYNFORS:
1634  rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
1635  break;
1636 
1637  case PLPGSQL_STMT_OPEN:
1638  rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
1639  break;
1640 
1641  case PLPGSQL_STMT_FETCH:
1642  rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
1643  break;
1644 
1645  case PLPGSQL_STMT_CLOSE:
1646  rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
1647  break;
1648 
1649  default:
1650  estate->err_stmt = save_estmt;
1651  elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);
1652  }
1653 
1654  /* Let the plugin know that we have finished executing this statement */
1655  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
1656  ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
1657 
1658  estate->err_stmt = save_estmt;
1659 
1660  return rc;
1661 }
static int exec_stmt_execsql(PLpgSQL_execstate *estate, PLpgSQL_stmt_execsql *stmt)
Definition: pl_exec.c:3619
static int exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
Definition: pl_exec.c:1849
PLpgSQL_stmt * err_stmt
Definition: plpgsql.h:932
static int exec_stmt_return_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_return_query *stmt)
Definition: pl_exec.c:3012
static int exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
Definition: pl_exec.c:2400
static int exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
Definition: pl_exec.c:4059
static int exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
Definition: pl_exec.c:4032
static int exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
Definition: pl_exec.c:1935
static int exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
Definition: pl_exec.c:2235
static int exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
Definition: pl_exec.c:1670
#define ERROR
Definition: elog.h:43
static int exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
Definition: pl_exec.c:3352
static int exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
Definition: pl_exec.c:3141
static int exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
Definition: pl_exec.c:2049
void(* stmt_beg)(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
Definition: plpgsql.h:974
static int exec_stmt_dynexecute(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynexecute *stmt)
Definition: pl_exec.c:3837
PLpgSQL_plugin ** plpgsql_plugin_ptr
Definition: pl_handler.c:58
static int exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
Definition: pl_exec.c:1703
void(* stmt_end)(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
Definition: plpgsql.h:975
static int exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
Definition: pl_exec.c:2600
static int exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
Definition: pl_exec.c:2637
static int exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
Definition: pl_exec.c:1986
static int exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
Definition: pl_exec.c:4215
static int exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
Definition: pl_exec.c:1177
static int exec_stmt_return_next(PLpgSQL_execstate *estate, PLpgSQL_stmt_return_next *stmt)
Definition: pl_exec.c:2803
static int exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
Definition: pl_exec.c:4316
static int exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
Definition: pl_exec.c:1819
static int exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
Definition: pl_exec.c:1686
PLpgSQL_stmt_type cmd_type
Definition: plpgsql.h:367
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
static int exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
Definition: pl_exec.c:2264
static int exec_stmt_assert ( PLpgSQL_execstate estate,
PLpgSQL_stmt_assert stmt 
)
static

Definition at line 3352 of file pl_exec.c.

References PLpgSQL_stmt_assert::cond, convert_value_to_string(), ereport, errcode(), errmsg(), errmsg_internal(), ERROR, exec_eval_boolean(), exec_eval_cleanup(), exec_eval_expr(), PLpgSQL_stmt_assert::message, plpgsql_check_asserts, PLPGSQL_RC_OK, val, and value.

Referenced by exec_stmt().

3353 {
3354  bool value;
3355  bool isnull;
3356 
3357  /* do nothing when asserts are not enabled */
3358  if (!plpgsql_check_asserts)
3359  return PLPGSQL_RC_OK;
3360 
3361  value = exec_eval_boolean(estate, stmt->cond, &isnull);
3362  exec_eval_cleanup(estate);
3363 
3364  if (isnull || !value)
3365  {
3366  char *message = NULL;
3367 
3368  if (stmt->message != NULL)
3369  {
3370  Datum val;
3371  Oid typeid;
3372  int32 typmod;
3373 
3374  val = exec_eval_expr(estate, stmt->message,
3375  &isnull, &typeid, &typmod);
3376  if (!isnull)
3377  message = convert_value_to_string(estate, val, typeid);
3378  /* we mustn't do exec_eval_cleanup here */
3379  }
3380 
3381  ereport(ERROR,
3382  (errcode(ERRCODE_ASSERT_FAILURE),
3383  message ? errmsg_internal("%s", message) :
3384  errmsg("assertion failed")));
3385  }
3386 
3387  return PLPGSQL_RC_OK;
3388 }
int errcode(int sqlerrcode)
Definition: elog.c:575
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
#define ERROR
Definition: elog.h:43
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
PLpgSQL_expr * message
Definition: plpgsql.h:738
static struct @121 value
static bool exec_eval_boolean(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
Definition: pl_exec.c:5159
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
int errmsg(const char *fmt,...)
Definition: elog.c:797
static char * convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
Definition: pl_exec.c:6236
PLpgSQL_expr * cond
Definition: plpgsql.h:737
bool plpgsql_check_asserts
Definition: pl_handler.c:50
long val
Definition: informix.c:689
static int exec_stmt_assign ( PLpgSQL_execstate estate,
PLpgSQL_stmt_assign stmt 
)
static

Definition at line 1670 of file pl_exec.c.

References Assert, PLpgSQL_execstate::datums, exec_assign_expr(), PLpgSQL_stmt_assign::expr, PLPGSQL_RC_OK, and PLpgSQL_stmt_assign::varno.

Referenced by exec_stmt().

1671 {
1672  Assert(stmt->varno >= 0);
1673 
1674  exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
1675 
1676  return PLPGSQL_RC_OK;
1677 }
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
static void exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target, PLpgSQL_expr *expr)
Definition: pl_exec.c:4359
#define Assert(condition)
Definition: c.h:664
PLpgSQL_expr * expr
Definition: plpgsql.h:423
static int exec_stmt_block ( PLpgSQL_execstate estate,
PLpgSQL_stmt_block block 
)
static

Definition at line 1177 of file pl_exec.c.

References PLpgSQL_exception::action, Assert, assign_simple_var(), assign_text_var(), BeginInternalSubTransaction(), PLpgSQL_stmt_block::body, PLpgSQL_exception::conditions, CopyErrorData(), PLpgSQL_execstate::cur_error, CurrentMemoryContext, CurrentResourceOwner, PLpgSQL_var::datatype, PLpgSQL_execstate::datums, datumTransfer(), PLpgSQL_var::default_val, PLpgSQL_datum::dtype, elog, ereport, PLpgSQL_execstate::err_text, errcode(), errmsg(), 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_stmts(), PLpgSQL_execstate::exitlabel, FlushErrorState(), PLpgSQL_rec::freetup, PLpgSQL_rec::freetupdesc, FreeTupleDesc(), get_stmt_mcontext(), get_typlenbyval(), gettext_noop, heap_freetuple(), i, PLpgSQL_stmt_block::initvarnos, PLpgSQL_stmt_block::label, lfirst, MemoryContextDeleteChildren(), MemoryContextReset(), MemoryContextSwitchTo(), ErrorData::message, PLpgSQL_stmt_block::n_initvars, PLpgSQL_var::notnull, PG_CATCH, PG_END_TRY, PG_TRY, plpgsql_create_econtext(), PLPGSQL_DTYPE_ARRAYELEM, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_VAR, PLPGSQL_RC_CONTINUE, PLPGSQL_RC_EXIT, PLPGSQL_RC_OK, PLPGSQL_RC_RETURN, pop_stmt_mcontext(), PLpgSQL_var::refname, ReleaseCurrentSubTransaction(), ReThrowError(), PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::rettupdesc, PLpgSQL_execstate::rettype, PLpgSQL_execstate::retval, RollbackAndReleaseCurrentSubTransaction(), ErrorData::sqlerrcode, PLpgSQL_exception_block::sqlerrm_varno, PLpgSQL_exception_block::sqlstate_varno, PLpgSQL_execstate::stmt_mcontext, PLpgSQL_execstate::stmt_mcontext_parent, PLpgSQL_rec::tup, PLpgSQL_rec::tupdesc, PLpgSQL_type::typtype, TYPTYPE_DOMAIN, UNKNOWNOID, and unpack_sql_state().

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

1178 {
1179  volatile int rc = -1;
1180  int i;
1181  int n;
1182 
1183  /*
1184  * First initialize all variables declared in this block
1185  */
1186  estate->err_text = gettext_noop("during statement block local variable initialization");
1187 
1188  for (i = 0; i < block->n_initvars; i++)
1189  {
1190  n = block->initvarnos[i];
1191 
1192  switch (estate->datums[n]->dtype)
1193  {
1194  case PLPGSQL_DTYPE_VAR:
1195  {
1196  PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]);
1197 
1198  /*
1199  * Free any old value, in case re-entering block, and
1200  * initialize to NULL
1201  */
1202  assign_simple_var(estate, var, (Datum) 0, true, false);
1203 
1204  if (var->default_val == NULL)
1205  {
1206  /*
1207  * If needed, give the datatype a chance to reject
1208  * NULLs, by assigning a NULL to the variable. We
1209  * claim the value is of type UNKNOWN, not the var's
1210  * datatype, else coercion will be skipped. (Do this
1211  * before the notnull check to be consistent with
1212  * exec_assign_value.)
1213  */
1214  if (var->datatype->typtype == TYPTYPE_DOMAIN)
1215  exec_assign_value(estate,
1216  (PLpgSQL_datum *) var,
1217  (Datum) 0,
1218  true,
1219  UNKNOWNOID,
1220  -1);
1221 
1222  if (var->notnull)
1223  ereport(ERROR,
1224  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1225  errmsg("variable \"%s\" declared NOT NULL cannot default to NULL",
1226  var->refname)));
1227  }
1228  else
1229  {
1230  exec_assign_expr(estate, (PLpgSQL_datum *) var,
1231  var->default_val);
1232  }
1233  }
1234  break;
1235 
1236  case PLPGSQL_DTYPE_REC:
1237  {
1238  PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[n]);
1239 
1240  if (rec->freetup)
1241  {
1242  heap_freetuple(rec->tup);
1243  rec->freetup = false;
1244  }
1245  if (rec->freetupdesc)
1246  {
1247  FreeTupleDesc(rec->tupdesc);
1248  rec->freetupdesc = false;
1249  }
1250  rec->tup = NULL;
1251  rec->tupdesc = NULL;
1252  }
1253  break;
1254 
1257  break;
1258 
1259  default:
1260  elog(ERROR, "unrecognized dtype: %d",
1261  estate->datums[n]->dtype);
1262  }
1263  }
1264 
1265  if (block->exceptions)
1266  {
1267  /*
1268  * Execute the statements in the block's body inside a sub-transaction
1269  */
1270  MemoryContext oldcontext = CurrentMemoryContext;
1272  ExprContext *old_eval_econtext = estate->eval_econtext;
1273  ErrorData *save_cur_error = estate->cur_error;
1274  MemoryContext stmt_mcontext;
1275 
1276  estate->err_text = gettext_noop("during statement block entry");
1277 
1278  /*
1279  * We will need a stmt_mcontext to hold the error data if an error
1280  * occurs. It seems best to force it to exist before entering the
1281  * subtransaction, so that we reduce the risk of out-of-memory during
1282  * error recovery, and because this greatly simplifies restoring the
1283  * stmt_mcontext stack to the correct state after an error. We can
1284  * ameliorate the cost of this by allowing the called statements to
1285  * use this mcontext too; so we don't push it down here.
1286  */
1287  stmt_mcontext = get_stmt_mcontext(estate);
1288 
1290  /* Want to run statements inside function's memory context */
1291  MemoryContextSwitchTo(oldcontext);
1292 
1293  PG_TRY();
1294  {
1295  /*
1296  * We need to run the block's statements with a new eval_econtext
1297  * that belongs to the current subtransaction; if we try to use
1298  * the outer econtext then ExprContext shutdown callbacks will be
1299  * called at the wrong times.
1300  */
1301  plpgsql_create_econtext(estate);
1302 
1303  estate->err_text = NULL;
1304 
1305  /* Run the block's statements */
1306  rc = exec_stmts(estate, block->body);
1307 
1308  estate->err_text = gettext_noop("during statement block exit");
1309 
1310  /*
1311  * If the block ended with RETURN, we may need to copy the return
1312  * value out of the subtransaction eval_context. This is
1313  * currently only needed for scalar result types --- rowtype
1314  * values will always exist in the function's main memory context,
1315  * cf. exec_stmt_return(). We can avoid a physical copy if the
1316  * value happens to be a R/W expanded object.
1317  */
1318  if (rc == PLPGSQL_RC_RETURN &&
1319  !estate->retisset &&
1320  !estate->retisnull &&
1321  estate->rettupdesc == NULL)
1322  {
1323  int16 resTypLen;
1324  bool resTypByVal;
1325 
1326  get_typlenbyval(estate->rettype, &resTypLen, &resTypByVal);
1327  estate->retval = datumTransfer(estate->retval,
1328  resTypByVal, resTypLen);
1329  }
1330 
1331  /* Commit the inner transaction, return to outer xact context */
1333  MemoryContextSwitchTo(oldcontext);
1334  CurrentResourceOwner = oldowner;
1335 
1336  /* Assert that the stmt_mcontext stack is unchanged */
1337  Assert(stmt_mcontext == estate->stmt_mcontext);
1338 
1339  /*
1340  * Revert to outer eval_econtext. (The inner one was
1341  * automatically cleaned up during subxact exit.)
1342  */
1343  estate->eval_econtext = old_eval_econtext;
1344  }
1345  PG_CATCH();
1346  {
1347  ErrorData *edata;
1348  ListCell *e;
1349 
1350  estate->err_text = gettext_noop("during exception cleanup");
1351 
1352  /* Save error info in our stmt_mcontext */
1353  MemoryContextSwitchTo(stmt_mcontext);
1354  edata = CopyErrorData();
1355  FlushErrorState();
1356 
1357  /* Abort the inner transaction */
1359  MemoryContextSwitchTo(oldcontext);
1360  CurrentResourceOwner = oldowner;
1361 
1362  /*
1363  * Set up the stmt_mcontext stack as though we had restored our
1364  * previous state and then done push_stmt_mcontext(). The push is
1365  * needed so that statements in the exception handler won't
1366  * clobber the error data that's in our stmt_mcontext.
1367  */
1368  estate->stmt_mcontext_parent = stmt_mcontext;
1369  estate->stmt_mcontext = NULL;
1370 
1371  /*
1372  * Now we can delete any nested stmt_mcontexts that might have
1373  * been created as children of ours. (Note: we do not immediately
1374  * release any statement-lifespan data that might have been left
1375  * behind in stmt_mcontext itself. We could attempt that by doing
1376  * a MemoryContextReset on it before collecting the error data
1377  * above, but it seems too risky to do any significant amount of
1378  * work before collecting the error.)
1379  */
1380  MemoryContextDeleteChildren(stmt_mcontext);
1381 
1382  /* Revert to outer eval_econtext */
1383  estate->eval_econtext = old_eval_econtext;
1384 
1385  /*
1386  * Must clean up the econtext too. However, any tuple table made
1387  * in the subxact will have been thrown away by SPI during subxact
1388  * abort, so we don't need to (and mustn't try to) free the
1389  * eval_tuptable.
1390  */
1391  estate->eval_tuptable = NULL;
1392  exec_eval_cleanup(estate);
1393 
1394  /* Look for a matching exception handler */
1395  foreach(e, block->exceptions->exc_list)
1396  {
1397  PLpgSQL_exception *exception = (PLpgSQL_exception *) lfirst(e);
1398 
1399  if (exception_matches_conditions(edata, exception->conditions))
1400  {
1401  /*
1402  * Initialize the magic SQLSTATE and SQLERRM variables for
1403  * the exception block; this also frees values from any
1404  * prior use of the same exception. We needn't do this
1405  * until we have found a matching exception.
1406  */
1407  PLpgSQL_var *state_var;
1408  PLpgSQL_var *errm_var;
1409 
1410  state_var = (PLpgSQL_var *)
1411  estate->datums[block->exceptions->sqlstate_varno];
1412  errm_var = (PLpgSQL_var *)
1413  estate->datums[block->exceptions->sqlerrm_varno];
1414 
1415  assign_text_var(estate, state_var,
1416  unpack_sql_state(edata->sqlerrcode));
1417  assign_text_var(estate, errm_var, edata->message);
1418 
1419  /*
1420  * Also set up cur_error so the error data is accessible
1421  * inside the handler.
1422  */
1423  estate->cur_error = edata;
1424 
1425  estate->err_text = NULL;
1426 
1427  rc = exec_stmts(estate, exception->action);
1428 
1429  break;
1430  }
1431  }
1432 
1433  /*
1434  * Restore previous state of cur_error, whether or not we executed
1435  * a handler. This is needed in case an error got thrown from
1436  * some inner block's exception handler.
1437  */
1438  estate->cur_error = save_cur_error;
1439 
1440  /* If no match found, re-throw the error */
1441  if (e == NULL)
1442  ReThrowError(edata);
1443 
1444  /* Restore stmt_mcontext stack and release the error data */
1445  pop_stmt_mcontext(estate);
1446  MemoryContextReset(stmt_mcontext);
1447  }
1448  PG_END_TRY();
1449 
1450  Assert(save_cur_error == estate->cur_error);
1451  }
1452  else
1453  {
1454  /*
1455  * Just execute the statements in the block's body
1456  */
1457  estate->err_text = NULL;
1458 
1459  rc = exec_stmts(estate, block->body);
1460  }
1461 
1462  estate->err_text = NULL;
1463 
1464  /*
1465  * Handle the return code.
1466  */
1467  switch (rc)
1468  {
1469  case PLPGSQL_RC_OK:
1470  case PLPGSQL_RC_RETURN:
1471  case PLPGSQL_RC_CONTINUE:
1472  return rc;
1473 
1474  case PLPGSQL_RC_EXIT:
1475 
1476  /*
1477  * This is intentionally different from the handling of RC_EXIT
1478  * for loops: to match a block, we require a match by label.
1479  */
1480  if (estate->exitlabel == NULL)
1481  return PLPGSQL_RC_EXIT;
1482  if (block->label == NULL)
1483  return PLPGSQL_RC_EXIT;
1484  if (strcmp(block->label, estate->exitlabel) != 0)
1485  return PLPGSQL_RC_EXIT;
1486  estate->exitlabel = NULL;
1487  return PLPGSQL_RC_OK;
1488 
1489  default:
1490  elog(ERROR, "unrecognized rc: %d", rc);
1491  }
1492 
1493  return PLPGSQL_RC_OK;
1494 }
signed short int16
Definition: c.h:245
TupleDesc tupdesc
Definition: plpgsql.h:308
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
int notnull
Definition: plpgsql.h:263
SPITupleTable * eval_tuptable
Definition: plpgsql.h:926
char * refname
Definition: plpgsql.h:258
int sqlerrcode
Definition: elog.h:342
ErrorData * CopyErrorData(void)
Definition: elog.c:1497
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ReleaseCurrentSubTransaction(void)
Definition: xact.c:4250
char * unpack_sql_state(int sql_state)
Definition: elog.c:2844
PLpgSQL_type * datatype
Definition: plpgsql.h:261
bool freetup
Definition: plpgsql.h:309
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define gettext_noop(x)
Definition: c.h:139
int errcode(int sqlerrcode)
Definition: elog.c:575
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:6902
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
PLpgSQL_datum_type dtype
Definition: plpgsql.h:198
void FlushErrorState(void)
Definition: elog.c:1587
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
static void exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target, PLpgSQL_expr *expr)
Definition: pl_exec.c:4359
TupleDesc rettupdesc
Definition: plpgsql.h:895
#define ERROR
Definition: elog.h:43
PLpgSQL_expr * default_val
Definition: plpgsql.h:264
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4284
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1092
#define ereport(elevel, rest)
Definition: elog.h:122
static bool exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond)
Definition: pl_exec.c:1143
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:236
ErrorData * cur_error
Definition: plpgsql.h:898
MemoryContext stmt_mcontext_parent
Definition: plpgsql.h:923
uintptr_t Datum
Definition: postgres.h:372
const char * err_text
Definition: plpgsql.h:933
PLpgSQL_condition * conditions
Definition: plpgsql.h:397
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:190
#define PG_CATCH()
Definition: elog.h:293
static void assign_text_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, const char *str)
Definition: pl_exec.c:6937
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
PLpgSQL_exception_block * exceptions
Definition: plpgsql.h:412
ExprContext * eval_econtext
Definition: plpgsql.h:929
void BeginInternalSubTransaction(char *name)
Definition: xact.c:4179
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2001
bool freetupdesc
Definition: plpgsql.h:310
#define UNKNOWNOID
Definition: pg_type.h:431
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:251
char typtype
Definition: plpgsql.h:183
e
Definition: preproc-init.c:82
int errmsg(const char *fmt,...)
Definition: elog.c:797
HeapTuple tup
Definition: plpgsql.h:307
int i
static void plpgsql_create_econtext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:6772
MemoryContext stmt_mcontext
Definition: plpgsql.h:922
static void pop_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1130
#define elog
Definition: elog.h:219
char * exitlabel
Definition: plpgsql.h:896
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
void ReThrowError(ErrorData *edata)
Definition: elog.c:1670
char * message
Definition: elog.h:343
static int exec_stmts(PLpgSQL_execstate *estate, List *stmts)
Definition: pl_exec.c:1503
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4424
static int exec_stmt_case ( PLpgSQL_execstate estate,
PLpgSQL_stmt_case stmt 
)
static

Definition at line 1849 of file pl_exec.c.

References assign_simple_var(), PLpgSQL_type::atttypmod, PLpgSQL_stmt_case::case_when_list, PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_stmt_case::else_stmts, ereport, errcode(), errhint(), errmsg(), ERROR, exec_assign_value(), exec_eval_boolean(), exec_eval_cleanup(), exec_eval_expr(), exec_stmts(), PLpgSQL_case_when::expr, PLpgSQL_function::fn_input_collation, PLpgSQL_execstate::func, PLpgSQL_stmt_case::have_else, lfirst, plpgsql_build_datatype(), PLpgSQL_case_when::stmts, PLpgSQL_stmt_case::t_expr, PLpgSQL_stmt_case::t_varno, PLpgSQL_type::typoid, and value.

Referenced by exec_stmt().

1850 {
1851  PLpgSQL_var *t_var = NULL;
1852  bool isnull;
1853  ListCell *l;
1854 
1855  if (stmt->t_expr != NULL)
1856  {
1857  /* simple case */
1858  Datum t_val;
1859  Oid t_typoid;
1860  int32 t_typmod;
1861 
1862  t_val = exec_eval_expr(estate, stmt->t_expr,
1863  &isnull, &t_typoid, &t_typmod);
1864 
1865  t_var = (PLpgSQL_var *) estate->datums[stmt->t_varno];
1866 
1867  /*
1868  * When expected datatype is different from real, change it. Note that
1869  * what we're modifying here is an execution copy of the datum, so
1870  * this doesn't affect the originally stored function parse tree. (In
1871  * theory, if the expression datatype keeps changing during execution,
1872  * this could cause a function-lifespan memory leak. Doesn't seem
1873  * worth worrying about though.)
1874  */
1875  if (t_var->datatype->typoid != t_typoid ||
1876  t_var->datatype->atttypmod != t_typmod)
1877  t_var->datatype = plpgsql_build_datatype(t_typoid,
1878  t_typmod,
1879  estate->func->fn_input_collation);
1880 
1881  /* now we can assign to the variable */
1882  exec_assign_value(estate,
1883  (PLpgSQL_datum *) t_var,
1884  t_val,
1885  isnull,
1886  t_typoid,
1887  t_typmod);
1888 
1889  exec_eval_cleanup(estate);
1890  }
1891 
1892  /* Now search for a successful WHEN clause */
1893  foreach(l, stmt->case_when_list)
1894  {
1896  bool value;
1897 
1898  value = exec_eval_boolean(estate, cwt->expr, &isnull);
1899  exec_eval_cleanup(estate);
1900  if (!isnull && value)
1901  {
1902  /* Found it */
1903 
1904  /* We can now discard any value we had for the temp variable */
1905  if (t_var != NULL)
1906  assign_simple_var(estate, t_var, (Datum) 0, true, false);
1907 
1908  /* Evaluate the statement(s), and we're done */
1909  return exec_stmts(estate, cwt->stmts);
1910  }
1911  }
1912 
1913  /* We can now discard any value we had for the temp variable */
1914  if (t_var != NULL)
1915  assign_simple_var(estate, t_var, (Datum) 0, true, false);
1916 
1917  /* SQL2003 mandates this error if there was no ELSE clause */
1918  if (!stmt->have_else)
1919  ereport(ERROR,
1920  (errcode(ERRCODE_CASE_NOT_FOUND),
1921  errmsg("case not found"),
1922  errhint("CASE statement is missing ELSE part.")));
1923 
1924  /* Evaluate the ELSE statements, and we're done */
1925  return exec_stmts(estate, stmt->else_stmts);
1926 }
int errhint(const char *fmt,...)
Definition: elog.c:987
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2132
PLpgSQL_type * datatype
Definition: plpgsql.h:261
int errcode(int sqlerrcode)
Definition: elog.c:575
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:6902
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
PLpgSQL_function * func
Definition: plpgsql.h:883
unsigned int Oid
Definition: postgres_ext.h:31
List * else_stmts
Definition: plpgsql.h:490
signed int int32
Definition: c.h:246
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
#define ERROR
Definition: elog.h:43
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
static struct @121 value
static bool exec_eval_boolean(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
Definition: pl_exec.c:5159
PLpgSQL_expr * expr
Definition: plpgsql.h:499
#define ereport(elevel, rest)
Definition: elog.h:122
List * case_when_list
Definition: plpgsql.h:488
Oid fn_input_collation
Definition: plpgsql.h:825
uintptr_t Datum
Definition: postgres.h:372
#define lfirst(lc)
Definition: pg_list.h:106
PLpgSQL_expr * t_expr
Definition: plpgsql.h:486
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 atttypmod
Definition: plpgsql.h:187
static int exec_stmts(PLpgSQL_execstate *estate, List *stmts)
Definition: pl_exec.c:1503
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4424
Oid typoid
Definition: plpgsql.h:179
static int exec_stmt_close ( PLpgSQL_execstate estate,
PLpgSQL_stmt_close stmt 
)
static

Definition at line 4316 of file pl_exec.c.

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

Referenced by exec_stmt().

4317 {
4318  PLpgSQL_var *curvar;
4319  Portal portal;
4320  char *curname;
4321  MemoryContext oldcontext;
4322 
4323  /* ----------
4324  * Get the portal of the cursor by name
4325  * ----------
4326  */
4327  curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4328  if (curvar->isnull)
4329  ereport(ERROR,
4330  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4331  errmsg("cursor variable \"%s\" is null", curvar->refname)));
4332 
4333  /* Use eval_mcontext for short-lived string */
4334  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4335  curname = TextDatumGetCString(curvar->value);
4336  MemoryContextSwitchTo(oldcontext);
4337 
4338  portal = SPI_cursor_find(curname);
4339  if (portal == NULL)
4340  ereport(ERROR,
4341  (errcode(ERRCODE_UNDEFINED_CURSOR),
4342  errmsg("cursor \"%s\" does not exist", curname)));
4343 
4344  /* ----------
4345  * And close it.
4346  * ----------
4347  */
4348  SPI_cursor_close(portal);
4349 
4350  return PLPGSQL_RC_OK;
4351 }
char * refname
Definition: plpgsql.h:258
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
Portal SPI_cursor_find(const char *name)
Definition: spi.c:1337
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
#define TextDatumGetCString(d)
Definition: builtins.h:92
Datum value
Definition: plpgsql.h:269
void SPI_cursor_close(Portal portal)
Definition: spi.c:1405
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool isnull
Definition: plpgsql.h:270
static int exec_stmt_dynexecute ( PLpgSQL_execstate estate,
PLpgSQL_stmt_dynexecute stmt 
)
static

Definition at line 3837 of file pl_exec.c.

References convert_value_to_string(), PLpgSQL_execstate::datums, PLpgSQL_row::dno, PLpgSQL_rec::dno, elog, ereport, errcode(), errdetail(), errdetail_internal(), errhint(), errmsg(), ERROR, PLpgSQL_execstate::eval_lastoid, PLpgSQL_execstate::eval_processed, exec_eval_cleanup(), exec_eval_expr(), exec_eval_using_params(), exec_move_row(), format_preparedparamsdata(), PLpgSQL_execstate::func, get_stmt_mcontext(), PLpgSQL_stmt_dynexecute::into, MemoryContextReset(), MemoryContextStrdup(), PreparedParamsData::nargs, PreparedParamsData::nulls, PLpgSQL_stmt_dynexecute::params, PLPGSQL_RC_OK, PLpgSQL_function::print_strict_params, PLpgSQL_stmt_dynexecute::query, PLpgSQL_execstate::readonly_func, PLpgSQL_stmt_dynexecute::rec, PLpgSQL_stmt_dynexecute::row, SPI_ERROR_COPY, SPI_ERROR_TRANSACTION, SPI_execute(), SPI_execute_with_args(), SPI_freetuptable(), SPI_lastoid, SPI_OK_DELETE, SPI_OK_DELETE_RETURNING, SPI_OK_INSERT, SPI_OK_INSERT_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, PLpgSQL_stmt_dynexecute::strict, SPITupleTable::tupdesc, PreparedParamsData::types, SPITupleTable::vals, and PreparedParamsData::values.

Referenced by exec_stmt().

3839 {
3840  Datum query;
3841  bool isnull;
3842  Oid restype;
3843  int32 restypmod;
3844  char *querystr;
3845  int exec_res;
3846  PreparedParamsData *ppd = NULL;
3847  MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
3848 
3849  /*
3850  * First we evaluate the string expression after the EXECUTE keyword. Its
3851  * result is the querystring we have to execute.
3852  */
3853  query = exec_eval_expr(estate, stmt->query, &isnull, &restype, &restypmod);
3854  if (isnull)
3855  ereport(ERROR,
3856  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3857  errmsg("query string argument of EXECUTE is null")));
3858 
3859  /* Get the C-String representation */
3860  querystr = convert_value_to_string(estate, query, restype);
3861 
3862  /* copy it into the stmt_mcontext before we clean up */
3863  querystr = MemoryContextStrdup(stmt_mcontext, querystr);
3864 
3865  exec_eval_cleanup(estate);
3866 
3867  /*
3868  * Execute the query without preparing a saved plan.
3869  */
3870  if (stmt->params)
3871  {
3872  ppd = exec_eval_using_params(estate, stmt->params);
3873  exec_res = SPI_execute_with_args(querystr,
3874  ppd->nargs, ppd->types,
3875  ppd->values, ppd->nulls,
3876  estate->readonly_func, 0);
3877  }
3878  else
3879  exec_res = SPI_execute(querystr, estate->readonly_func, 0);
3880 
3881  switch (exec_res)
3882  {
3883  case SPI_OK_SELECT:
3884  case SPI_OK_INSERT:
3885  case SPI_OK_UPDATE:
3886  case SPI_OK_DELETE:
3890  case SPI_OK_UTILITY:
3891  case SPI_OK_REWRITTEN:
3892  break;
3893 
3894  case 0:
3895 
3896  /*
3897  * Also allow a zero return, which implies the querystring
3898  * contained no commands.
3899  */
3900  break;
3901 
3902  case SPI_OK_SELINTO:
3903 
3904  /*
3905  * We want to disallow SELECT INTO for now, because its behavior
3906  * is not consistent with SELECT INTO in a normal plpgsql context.
3907  * (We need to reimplement EXECUTE to parse the string as a
3908  * plpgsql command, not just feed it to SPI_execute.) This is not
3909  * a functional limitation because CREATE TABLE AS is allowed.
3910  */
3911  ereport(ERROR,
3912  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3913  errmsg("EXECUTE of SELECT ... INTO is not implemented"),
3914  errhint("You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.")));
3915  break;
3916 
3917  /* Some SPI errors deserve specific error messages */
3918  case SPI_ERROR_COPY:
3919  ereport(ERROR,
3920  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3921  errmsg("cannot COPY to/from client in PL/pgSQL")));
3922  case SPI_ERROR_TRANSACTION:
3923  ereport(ERROR,
3924  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3925  errmsg("cannot begin/end transactions in PL/pgSQL"),
3926  errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
3927 
3928  default:
3929  elog(ERROR, "SPI_execute failed executing query \"%s\": %s",
3930  querystr, SPI_result_code_string(exec_res));
3931  break;
3932  }
3933 
3934  /* Save result info for GET DIAGNOSTICS */
3935  estate->eval_processed = SPI_processed;
3936  estate->eval_lastoid = SPI_lastoid;
3937 
3938  /* Process INTO if present */
3939  if (stmt->into)
3940  {
3941  SPITupleTable *tuptab = SPI_tuptable;
3942  uint64 n = SPI_processed;
3943  PLpgSQL_rec *rec = NULL;
3944  PLpgSQL_row *row = NULL;
3945 
3946  /* If the statement did not return a tuple table, complain */
3947  if (tuptab == NULL)
3948  ereport(ERROR,
3949  (errcode(ERRCODE_SYNTAX_ERROR),
3950  errmsg("INTO used with a command that cannot return data")));
3951 
3952  /* Determine if we assign to a record or a row */
3953  if (stmt->rec != NULL)
3954  rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
3955  else if (stmt->row != NULL)
3956  row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
3957  else
3958  elog(ERROR, "unsupported target");
3959 
3960  /*
3961  * If SELECT ... INTO specified STRICT, and the query didn't find
3962  * exactly one row, throw an error. If STRICT was not specified, then
3963  * allow the query to find any number of rows.
3964  */
3965  if (n == 0)
3966  {
3967  if (stmt->strict)
3968  {
3969  char *errdetail;
3970 
3971  if (estate->func->print_strict_params)
3972  errdetail = format_preparedparamsdata(estate, ppd);
3973  else
3974  errdetail = NULL;
3975 
3976  ereport(ERROR,
3977  (errcode(ERRCODE_NO_DATA_FOUND),
3978  errmsg("query returned no rows"),
3979  errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3980  }
3981  /* set the target to NULL(s) */
3982  exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
3983  }
3984  else
3985  {
3986  if (n > 1 && stmt->strict)
3987  {
3988  char *errdetail;
3989 
3990  if (estate->func->print_strict_params)
3991  errdetail = format_preparedparamsdata(estate, ppd);
3992  else
3993  errdetail = NULL;
3994 
3995  ereport(ERROR,
3996  (errcode(ERRCODE_TOO_MANY_ROWS),
3997  errmsg("query returned more than one row"),
3998  errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3999  }
4000 
4001  /* Put the first result row into the target */
4002  exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
4003  }
4004  /* clean up after exec_move_row() */
4005  exec_eval_cleanup(estate);
4006  }
4007  else
4008  {
4009  /*
4010  * It might be a good idea to raise an error if the query returned
4011  * tuples that are being ignored, but historically we have not done
4012  * that.
4013  */
4014  }
4015 
4016  /* Release any result from SPI_execute, as well as transient data */
4018  MemoryContextReset(stmt_mcontext);
4019 
4020  return PLPGSQL_RC_OK;
4021 }
PLpgSQL_expr * query
Definition: plpgsql.h:764
bool print_strict_params
Definition: plpgsql.h:859
int errhint(const char *fmt,...)
Definition: elog.c:987
uint64 eval_processed
Definition: plpgsql.h:927
static char * format_preparedparamsdata(PLpgSQL_execstate *estate, const PreparedParamsData *ppd)
Definition: pl_exec.c:7168
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:61
#define SPI_OK_DELETE
Definition: spi.h:57
#define SPI_ERROR_COPY
Definition: spi.h:37
PLpgSQL_row * row
Definition: plpgsql.h:768
SPITupleTable * SPI_tuptable
Definition: spi.c:41
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
PLpgSQL_function * func
Definition: plpgsql.h:883
Datum * values
Definition: pl_exec.c:51
unsigned int Oid
Definition: postgres_ext.h:31
HeapTuple * vals
Definition: spi.h:28
uint64 SPI_processed
Definition: spi.c:39
signed int int32
Definition: c.h:246
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
#define ERROR
Definition: elog.h:43
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5182
int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:441
static PreparedParamsData * exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
Definition: pl_exec.c:6949
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:60
const char * SPI_result_code_string(int code)
Definition: spi.c:1515
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define SPI_OK_UTILITY
Definition: spi.h:53
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:62
#define SPI_OK_REWRITTEN
Definition: spi.h:63
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1092
static void exec_move_row(PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
Definition: pl_exec.c:5945
#define ereport(elevel, rest)
Definition: elog.h:122
#define SPI_ERROR_TRANSACTION
Definition: spi.h:43
#define SPI_OK_SELINTO
Definition: spi.h:55
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:972
uintptr_t Datum
Definition: postgres.h:372
Oid SPI_lastoid
Definition: spi.c:40
TupleDesc tupdesc
Definition: spi.h:27
#define SPI_OK_SELECT
Definition: spi.h:54
bool readonly_func
Definition: plpgsql.h:893
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SPI_OK_UPDATE
Definition: spi.h:58
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
PLpgSQL_rec * rec
Definition: plpgsql.h:767
static char * convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
Definition: pl_exec.c:6236
#define SPI_OK_INSERT
Definition: spi.h:56
#define elog
Definition: elog.h:219
int SPI_execute(const char *src, bool read_only, long tcount)
Definition: spi.c:304
static int exec_stmt_dynfors ( PLpgSQL_execstate estate,
PLpgSQL_stmt_dynfors stmt 
)
static

Definition at line 4032 of file pl_exec.c.

References exec_dynquery_with_params(), exec_for_query(), PLpgSQL_stmt_dynfors::params, PLpgSQL_stmt_dynfors::query, and SPI_cursor_close().

Referenced by exec_stmt().

4033 {
4034  Portal portal;
4035  int rc;
4036 
4037  portal = exec_dynquery_with_params(estate, stmt->query, stmt->params,
4038  NULL, 0);
4039 
4040  /*
4041  * Execute the loop
4042  */
4043  rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
4044 
4045  /*
4046  * Close the implicit cursor
4047  */
4048  SPI_cursor_close(portal);
4049 
4050  return rc;
4051 }
static int exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, Portal portal, bool prefetch_ok)
Definition: pl_exec.c:5335
PLpgSQL_expr * query
Definition: plpgsql.h:600
void SPI_cursor_close(Portal portal)
Definition: spi.c:1405
static Portal exec_dynquery_with_params(PLpgSQL_execstate *estate, PLpgSQL_expr *dynquery, List *params, const char *portalname, int cursorOptions)
Definition: pl_exec.c:7028
static int exec_stmt_execsql ( PLpgSQL_execstate estate,
PLpgSQL_stmt_execsql stmt 
)
static

Definition at line 3619 of file pl_exec.c.

References Assert, Query::canSetTag, CMD_DELETE, CMD_INSERT, CMD_UPDATE, Query::commandType, CURSOR_OPT_PARALLEL_OK, PLpgSQL_execstate::datums, PLpgSQL_row::dno, PLpgSQL_rec::dno, elog, ereport, errcode(), errdetail(), errdetail_internal(), errhint(), errmsg(), ERROR, PLpgSQL_execstate::eval_lastoid, PLpgSQL_execstate::eval_processed, exec_eval_cleanup(), exec_move_row(), exec_prepare_plan(), exec_set_found(), format_expr_params(), PLpgSQL_execstate::func, PLpgSQL_stmt_execsql::into, lfirst, lfirst_node, PLpgSQL_stmt_execsql::mod_stmt, PLpgSQL_expr::plan, PLPGSQL_RC_OK, PLpgSQL_function::print_strict_params, PLpgSQL_expr::query, CachedPlanSource::query_list, PLpgSQL_execstate::readonly_func, PLpgSQL_stmt_execsql::rec, PLpgSQL_stmt_execsql::row, setup_param_list(), SPI_ERROR_COPY, SPI_ERROR_TRANSACTION, SPI_execute_plan_with_paramlist(), SPI_freetuptable(), SPI_lastoid, SPI_OK_DELETE, SPI_OK_DELETE_RETURNING, SPI_OK_INSERT, SPI_OK_INSERT_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, PLpgSQL_stmt_execsql::sqlstmt, PLpgSQL_stmt_execsql::strict, SPITupleTable::tupdesc, and SPITupleTable::vals.

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

3621 {
3622  ParamListInfo paramLI;
3623  long tcount;
3624  int rc;
3625  PLpgSQL_expr *expr = stmt->sqlstmt;
3626 
3627  /*
3628  * On the first call for this statement generate the plan, and detect
3629  * whether the statement is INSERT/UPDATE/DELETE
3630  */
3631  if (expr->plan == NULL)
3632  {
3633  ListCell *l;
3634 
3636  stmt->mod_stmt = false;
3637  foreach(l, SPI_plan_get_plan_sources(expr->plan))
3638  {
3639  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l);
3640  ListCell *l2;
3641 
3642  foreach(l2, plansource->query_list)
3643  {
3644  Query *q = lfirst_node(Query, l2);
3645 
3646  if (q->canSetTag)
3647  {
3648  if (q->commandType == CMD_INSERT ||
3649  q->commandType == CMD_UPDATE ||
3650  q->commandType == CMD_DELETE)
3651  stmt->mod_stmt = true;
3652  }
3653  }
3654  }
3655  }
3656 
3657  /*
3658  * Set up ParamListInfo to pass to executor
3659  */
3660  paramLI = setup_param_list(estate, expr);
3661 
3662  /*
3663  * If we have INTO, then we only need one row back ... but if we have INTO
3664  * STRICT, ask for two rows, so that we can verify the statement returns
3665  * only one. INSERT/UPDATE/DELETE are always treated strictly. Without
3666  * INTO, just run the statement to completion (tcount = 0).
3667  *
3668  * We could just ask for two rows always when using INTO, but there are
3669  * some cases where demanding the extra row costs significant time, eg by
3670  * forcing completion of a sequential scan. So don't do it unless we need
3671  * to enforce strictness.
3672  */
3673  if (stmt->into)
3674  {
3675  if (stmt->strict || stmt->mod_stmt)
3676  tcount = 2;
3677  else
3678  tcount = 1;
3679  }
3680  else
3681  tcount = 0;
3682 
3683  /*
3684  * Execute the plan
3685  */
3686  rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
3687  estate->readonly_func, tcount);
3688 
3689  /*
3690  * Check for error, and set FOUND if appropriate (for historical reasons
3691  * we set FOUND only for certain query types). Also Assert that we
3692  * identified the statement type the same as SPI did.
3693  */
3694  switch (rc)
3695  {
3696  case SPI_OK_SELECT:
3697  Assert(!stmt->mod_stmt);
3698  exec_set_found(estate, (SPI_processed != 0));
3699  break;
3700 
3701  case SPI_OK_INSERT:
3702  case SPI_OK_UPDATE:
3703  case SPI_OK_DELETE:
3707  Assert(stmt->mod_stmt);
3708  exec_set_found(estate, (SPI_processed != 0));
3709  break;
3710 
3711  case SPI_OK_SELINTO:
3712  case SPI_OK_UTILITY:
3713  Assert(!stmt->mod_stmt);
3714  break;
3715 
3716  case SPI_OK_REWRITTEN:
3717  Assert(!stmt->mod_stmt);
3718 
3719  /*
3720  * The command was rewritten into another kind of command. It's
3721  * not clear what FOUND would mean in that case (and SPI doesn't
3722  * return the row count either), so just set it to false.
3723  */
3724  exec_set_found(estate, false);
3725  break;
3726 
3727  /* Some SPI errors deserve specific error messages */
3728  case SPI_ERROR_COPY:
3729  ereport(ERROR,
3730  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3731  errmsg("cannot COPY to/from client in PL/pgSQL")));
3732  case SPI_ERROR_TRANSACTION:
3733  ereport(ERROR,
3734  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3735  errmsg("cannot begin/end transactions in PL/pgSQL"),
3736  errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
3737 
3738  default:
3739  elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s",
3740  expr->query, SPI_result_code_string(rc));
3741  }
3742 
3743  /* All variants should save result info for GET DIAGNOSTICS */
3744  estate->eval_processed = SPI_processed;
3745  estate->eval_lastoid = SPI_lastoid;
3746 
3747  /* Process INTO if present */
3748  if (stmt->into)
3749  {
3750  SPITupleTable *tuptab = SPI_tuptable;
3751  uint64 n = SPI_processed;
3752  PLpgSQL_rec *rec = NULL;
3753  PLpgSQL_row *row = NULL;
3754 
3755  /* If the statement did not return a tuple table, complain */
3756  if (tuptab == NULL)
3757  ereport(ERROR,
3758  (errcode(ERRCODE_SYNTAX_ERROR),
3759  errmsg("INTO used with a command that cannot return data")));
3760 
3761  /* Determine if we assign to a record or a row */
3762  if (stmt->rec != NULL)
3763  rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
3764  else if (stmt->row != NULL)
3765  row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
3766  else
3767  elog(ERROR, "unsupported target");
3768 
3769  /*
3770  * If SELECT ... INTO specified STRICT, and the query didn't find
3771  * exactly one row, throw an error. If STRICT was not specified, then
3772  * allow the query to find any number of rows.
3773  */
3774  if (n == 0)
3775  {
3776  if (stmt->strict)
3777  {
3778  char *errdetail;
3779 
3780  if (estate->func->print_strict_params)
3781  errdetail = format_expr_params(estate, expr);
3782  else
3783  errdetail = NULL;
3784 
3785  ereport(ERROR,
3786  (errcode(ERRCODE_NO_DATA_FOUND),
3787  errmsg("query returned no rows"),
3788  errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3789  }
3790  /* set the target to NULL(s) */
3791  exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
3792  }
3793  else
3794  {
3795  if (n > 1 && (stmt->strict || stmt->mod_stmt))
3796  {
3797  char *errdetail;
3798 
3799  if (estate->func->print_strict_params)
3800  errdetail = format_expr_params(estate, expr);
3801  else
3802  errdetail = NULL;
3803 
3804  ereport(ERROR,
3805  (errcode(ERRCODE_TOO_MANY_ROWS),
3806  errmsg("query returned more than one row"),
3807  errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
3808  }
3809  /* Put the first result row into the target */
3810  exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
3811  }
3812 
3813  /* Clean up */
3814  exec_eval_cleanup(estate);
3816  }
3817  else
3818  {
3819  /* If the statement returned a tuple table, complain */
3820  if (SPI_tuptable != NULL)
3821  ereport(ERROR,
3822  (errcode(ERRCODE_SYNTAX_ERROR),
3823  errmsg("query has no destination for result data"),
3824  (rc == SPI_OK_SELECT) ? errhint("If you want to discard the results of a SELECT, use PERFORM instead.") : 0));
3825  }
3826 
3827  return PLPGSQL_RC_OK;
3828 }
bool print_strict_params
Definition: plpgsql.h:859
int errhint(const char *fmt,...)
Definition: elog.c:987
char * query
Definition: plpgsql.h:223
uint64 eval_processed
Definition: plpgsql.h:927
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:61
#define SPI_OK_DELETE
Definition: spi.h:57
#define SPI_ERROR_COPY
Definition: spi.h:37
SPITupleTable * SPI_tuptable
Definition: spi.c:41
PLpgSQL_expr * sqlstmt
Definition: plpgsql.h:748
int errcode(int sqlerrcode)
Definition: elog.c:575
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3538
PLpgSQL_function * func
Definition: plpgsql.h:883
HeapTuple * vals
Definition: spi.h:28
uint64 SPI_processed
Definition: spi.c:39
SPIPlanPtr plan
Definition: plpgsql.h:224
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
PLpgSQL_rec * rec
Definition: plpgsql.h:753
#define ERROR
Definition: elog.h:43
int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount)
Definition: spi.c:373
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:60
const char * SPI_result_code_string(int code)
Definition: spi.c:1515
#define lfirst_node(type, lc)
Definition: pg_list.h:109
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define SPI_OK_UTILITY
Definition: spi.h:53
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:62
static char * format_expr_params(PLpgSQL_execstate *estate, const PLpgSQL_expr *expr)
Definition: pl_exec.c:7103
#define SPI_OK_REWRITTEN
Definition: spi.h:63
static ParamListInfo setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5688
static void exec_move_row(PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
Definition: pl_exec.c:5945
#define ereport(elevel, rest)
Definition: elog.h:122
#define SPI_ERROR_TRANSACTION
Definition: spi.h:43
#define SPI_OK_SELINTO
Definition: spi.h:55
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:972
Oid SPI_lastoid
Definition: spi.c:40
TupleDesc tupdesc
Definition: spi.h:27
#define SPI_OK_SELECT
Definition: spi.h:54
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3559
CmdType commandType
Definition: parsenodes.h:110
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
bool canSetTag
Definition: parsenodes.h:116
bool readonly_func
Definition: plpgsql.h:893
static void exec_set_found(PLpgSQL_execstate *estate, bool state)
Definition: pl_exec.c:6756
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2639
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SPI_OK_UPDATE
Definition: spi.h:58
List * SPI_plan_get_plan_sources(SPIPlanPtr plan)
Definition: spi.c:1592
#define SPI_OK_INSERT
Definition: spi.h:56
List * query_list
Definition: plancache.h:95
#define elog
Definition: elog.h:219
PLpgSQL_row * row
Definition: plpgsql.h:754
static int exec_stmt_exit ( PLpgSQL_execstate estate,
PLpgSQL_stmt_exit stmt 
)