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 bool exec_simple_check_node (Node *node)
 
static void exec_simple_check_plan (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
static void exec_simple_recheck_plan (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:1064

Definition at line 3120 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 7140 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().

7142 {
7143  ParamExternData *prm;
7144 
7145  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
7146  /* Free the old value if needed */
7147  if (var->freeval)
7148  {
7150  var->isnull,
7151  var->datatype->typlen))
7153  else
7154  pfree(DatumGetPointer(var->value));
7155  }
7156  /* Assign new value to datum */
7157  var->value = newvalue;
7158  var->isnull = isnull;
7159  var->freeval = freeable;
7160  /* And update the image in the common parameter list */
7161  prm = &estate->paramLI->params[var->dno];
7162  prm->value = MakeExpandedObjectReadOnly(newvalue,
7163  isnull,
7164  var->datatype->typlen);
7165  prm->isnull = isnull;
7166  /* these might be set already, but let's be sure */
7167  prm->pflags = PARAM_FLAG_CONST;
7168  prm->ptype = var->datatype->typoid;
7169 }
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:950
ParamListInfo paramLI
Definition: plpgsql.h:910
#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:675
#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 7175 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().

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

Definition at line 6972 of file pl_exec.c.

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

Referenced by exec_check_rw_parameter().

6973 {
6974  if (node == NULL)
6975  return false;
6976  if (IsA(node, Param))
6977  {
6978  Param *param = (Param *) node;
6979 
6980  if (param->paramkind == PARAM_EXTERN &&
6981  param->paramid == *target_dno + 1)
6982  return true;
6983  return false;
6984  }
6986  (void *) target_dno);
6987 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
ParamKind paramkind
Definition: primnodes.h:244
static bool contains_target_param(Node *node, int *target_dno)
Definition: pl_exec.c:6972
#define NULL
Definition: c.h:229
int paramid
Definition: primnodes.h:245
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1855
static char * convert_value_to_string ( PLpgSQL_execstate estate,
Datum  value,
Oid  valtype 
)
static

Definition at line 6222 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().

6223 {
6224  char *result;
6225  MemoryContext oldcontext;
6226  Oid typoutput;
6227  bool typIsVarlena;
6228 
6229  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6230  getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
6231  result = OidOutputFunctionCall(typoutput, value);
6232  MemoryContextSwitchTo(oldcontext);
6233 
6234  return result;
6235 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2600
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1618
unsigned int Oid
Definition: postgres_ext.h:31
static struct @114 value
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:2056
static PLpgSQL_datum * copy_plpgsql_datum ( PLpgSQL_datum datum)
static

Definition at line 1028 of file pl_exec.c.

References Assert, PLpgSQL_datum::dtype, elog, ERROR, NULL, 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().

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

Definition at line 1140 of file pl_exec.c.

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

Referenced by exec_stmt_block().

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

Definition at line 4390 of file pl_exec.c.

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

Referenced by exec_stmt_getdiag().

4392 {
4393  text *value;
4394  MemoryContext oldcontext;
4395 
4396  /* Use eval_mcontext for short-lived text value */
4397  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4398  if (str != NULL)
4399  value = cstring_to_text(str);
4400  else
4401  value = cstring_to_text("");
4402  MemoryContextSwitchTo(oldcontext);
4403 
4404  exec_assign_value(estate, target, PointerGetDatum(value), false,
4405  TEXTOID, -1);
4406 }
#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 @114 value
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define NULL
Definition: c.h:229
Definition: c.h:439
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4418
static void exec_assign_expr ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
PLpgSQL_expr expr 
)
static

Definition at line 4353 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(), NULL, PLpgSQL_expr::plan, PLPGSQL_DTYPE_VAR, and value.

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

4355 {
4356  Datum value;
4357  bool isnull;
4358  Oid valtype;
4359  int32 valtypmod;
4360 
4361  /*
4362  * If first time through, create a plan for this expression, and then see
4363  * if we can pass the target variable as a read-write parameter to the
4364  * expression. (This is a bit messy, but it seems cleaner than modifying
4365  * the API of exec_eval_expr for the purpose.)
4366  */
4367  if (expr->plan == NULL)
4368  {
4369  exec_prepare_plan(estate, expr, 0);
4370  if (target->dtype == PLPGSQL_DTYPE_VAR)
4371  exec_check_rw_parameter(expr, target->dno);
4372  }
4373 
4374  value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
4375  exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
4376  exec_eval_cleanup(estate);
4377 }
static void exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno)
Definition: pl_exec.c:6895
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3532
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:256
static struct @114 value
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5164
uintptr_t Datum
Definition: postgres.h:372
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3553
#define NULL
Definition: c.h:229
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4418
static void exec_assign_value ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
Datum  value,
bool  isNull,
Oid  valtype,
int32  valtypmod 
)
static

Definition at line 4418 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(), tupleDesc::attrs, 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, NULL, 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, 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().

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

6255 {
6256  /*
6257  * If the type of the given value isn't what's requested, convert it.
6258  */
6259  if (valtype != reqtype ||
6260  (valtypmod != reqtypmod && reqtypmod != -1))
6261  {
6262  plpgsql_CastHashEntry *cast_entry;
6263 
6264  cast_entry = get_cast_hashentry(estate,
6265  valtype, valtypmod,
6266  reqtype, reqtypmod);
6267  if (cast_entry)
6268  {
6269  ExprContext *econtext = estate->eval_econtext;
6270  MemoryContext oldcontext;
6271 
6272  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6273 
6274  econtext->caseValue_datum = value;
6275  econtext->caseValue_isNull = *isnull;
6276 
6277  cast_entry->cast_in_use = true;
6278 
6279  value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
6280  isnull);
6281 
6282  cast_entry->cast_in_use = false;
6283 
6284  MemoryContextSwitchTo(oldcontext);
6285  }
6286  }
6287 
6288  return value;
6289 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static struct @114 value
static plpgsql_CastHashEntry * get_cast_hashentry(PLpgSQL_execstate *estate, Oid srctype, int32 srctypmod, Oid dsttype, int32 dsttypmod)
Definition: pl_exec.c:6302
Datum caseValue_datum
Definition: execnodes.h:216
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:266
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
ExprContext * eval_econtext
Definition: plpgsql.h:928
bool caseValue_isNull
Definition: execnodes.h:217
ExprState * cast_exprstate
Definition: pl_exec.c:149
static void exec_check_rw_parameter ( PLpgSQL_expr expr,
int  target_dno 
)
static

Definition at line 6895 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, NULL, OpExpr::opfuncid, PLpgSQL_expr::paramnos, and PLpgSQL_expr::rwparam.

Referenced by exec_assign_expr(), and exec_eval_simple_expr().

6896 {
6897  Oid funcid;
6898  List *fargs;
6899  ListCell *lc;
6900 
6901  /* Assume unsafe */
6902  expr->rwparam = -1;
6903 
6904  /*
6905  * If the expression isn't simple, there's no point in trying to optimize
6906  * (because the exec_run_select code path will flatten any expanded result
6907  * anyway). Even without that, this seems like a good safety restriction.
6908  */
6909  if (expr->expr_simple_expr == NULL)
6910  return;
6911 
6912  /*
6913  * If target variable isn't referenced by expression, no need to look
6914  * further.
6915  */
6916  if (!bms_is_member(target_dno, expr->paramnos))
6917  return;
6918 
6919  /*
6920  * Top level of expression must be a simple FuncExpr or OpExpr.
6921  */
6922  if (IsA(expr->expr_simple_expr, FuncExpr))
6923  {
6924  FuncExpr *fexpr = (FuncExpr *) expr->expr_simple_expr;
6925 
6926  funcid = fexpr->funcid;
6927  fargs = fexpr->args;
6928  }
6929  else if (IsA(expr->expr_simple_expr, OpExpr))
6930  {
6931  OpExpr *opexpr = (OpExpr *) expr->expr_simple_expr;
6932 
6933  funcid = opexpr->opfuncid;
6934  fargs = opexpr->args;
6935  }
6936  else
6937  return;
6938 
6939  /*
6940  * The top-level function must be one that we trust to be "safe".
6941  * Currently we hard-wire the list, but it would be very desirable to
6942  * allow extensions to mark their functions as safe ...
6943  */
6944  if (!(funcid == F_ARRAY_APPEND ||
6945  funcid == F_ARRAY_PREPEND))
6946  return;
6947 
6948  /*
6949  * The target variable (in the form of a Param) must only appear as a
6950  * direct argument of the top-level function.
6951  */
6952  foreach(lc, fargs)
6953  {
6954  Node *arg = (Node *) lfirst(lc);
6955 
6956  /* A Param is OK, whether it's the target variable or not */
6957  if (arg && IsA(arg, Param))
6958  continue;
6959  /* Otherwise, argument expression must not reference target */
6960  if (contains_target_param(arg, &target_dno))
6961  return;
6962  }
6963 
6964  /* OK, we can pass target as a read-write parameter */
6965  expr->rwparam = target_dno;
6966 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
List * args
Definition: primnodes.h:456
Definition: nodes.h:504
unsigned int Oid
Definition: postgres_ext.h:31
Bitmapset * paramnos
Definition: plpgsql.h:225
Oid funcid
Definition: primnodes.h:448
static bool contains_target_param(Node *node, int *target_dno)
Definition: pl_exec.c:6972
Expr * expr_simple_expr
Definition: plpgsql.h:235
int rwparam
Definition: plpgsql.h:226
Oid opfuncid
Definition: primnodes.h:496
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
void * arg
List * args
Definition: primnodes.h:501
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
static Portal exec_dynquery_with_params ( PLpgSQL_execstate estate,
PLpgSQL_expr dynquery,
List params,
const char *  portalname,
int  cursorOptions 
)
static

Definition at line 7266 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, NULL, 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().

7271 {
7272  Portal portal;
7273  Datum query;
7274  bool isnull;
7275  Oid restype;
7276  int32 restypmod;
7277  char *querystr;
7278  MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
7279 
7280  /*
7281  * Evaluate the string expression after the EXECUTE keyword. Its result is
7282  * the querystring we have to execute.
7283  */
7284  query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod);
7285  if (isnull)
7286  ereport(ERROR,
7287  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
7288  errmsg("query string argument of EXECUTE is null")));
7289 
7290  /* Get the C-String representation */
7291  querystr = convert_value_to_string(estate, query, restype);
7292 
7293  /* copy it into the stmt_mcontext before we clean up */
7294  querystr = MemoryContextStrdup(stmt_mcontext, querystr);
7295 
7296  exec_eval_cleanup(estate);
7297 
7298  /*
7299  * Open an implicit cursor for the query. We use
7300  * SPI_cursor_open_with_args even when there are no params, because this
7301  * avoids making and freeing one copy of the plan.
7302  */
7303  if (params)
7304  {
7305  PreparedParamsData *ppd;
7306 
7307  ppd = exec_eval_using_params(estate, params);
7308  portal = SPI_cursor_open_with_args(portalname,
7309  querystr,
7310  ppd->nargs, ppd->types,
7311  ppd->values, ppd->nulls,
7312  estate->readonly_func,
7313  cursorOptions);
7314  }
7315  else
7316  {
7317  portal = SPI_cursor_open_with_args(portalname,
7318  querystr,
7319  0, NULL,
7320  NULL, NULL,
7321  estate->readonly_func,
7322  cursorOptions);
7323  }
7324 
7325  if (portal == NULL)
7326  elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
7327  querystr, SPI_result_code_string(SPI_result));
7328 
7329  /* Release transient data */
7330  MemoryContextReset(stmt_mcontext);
7331 
7332  return portal;
7333 }
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:3532
Datum * values
Definition: pl_exec.c:51
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
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:5164
static PreparedParamsData * exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
Definition: pl_exec.c:7187
const char * SPI_result_code_string(int code)
Definition: spi.c:1509
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1089
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
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:1055
bool readonly_func
Definition: plpgsql.h:892
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1064
static char * convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
Definition: pl_exec.c:6222
#define elog
Definition: elog.h:219
static bool exec_eval_boolean ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull 
)
static

Definition at line 5141 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().

5144 {
5145  Datum exprdatum;
5146  Oid exprtypeid;
5147  int32 exprtypmod;
5148 
5149  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5150  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5151  exprtypeid, exprtypmod,
5152  BOOLOID, -1);
5153  return DatumGetBool(exprdatum);
5154 }
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6251
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5164
#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 3532 of file pl_exec.c.

References PLpgSQL_execstate::eval_econtext, PLpgSQL_execstate::eval_tuptable, NULL, 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().

3533 {
3534  /* Clear result of a full SPI_execute */
3535  if (estate->eval_tuptable != NULL)
3537  estate->eval_tuptable = NULL;
3538 
3539  /*
3540  * Clear result of exec_eval_simple_expr (but keep the econtext). This
3541  * also clears any short-lived allocations done via get_eval_mcontext.
3542  */
3543  if (estate->eval_econtext != NULL)
3545 }
SPITupleTable * eval_tuptable
Definition: plpgsql.h:925
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:969
#define NULL
Definition: c.h:229
ExprContext * eval_econtext
Definition: plpgsql.h:928
#define ResetExprContext(econtext)
Definition: executor.h:450
static void exec_eval_datum ( PLpgSQL_execstate estate,
PLpgSQL_datum datum,
Oid typeid,
int32 typetypmod,
Datum value,
bool isnull 
)
static

Definition at line 4826 of file pl_exec.c.

References Assert, tupleDesc::attrs, 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(), NULL, 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, 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().

4832 {
4833  MemoryContext oldcontext;
4834 
4835  switch (datum->dtype)
4836  {
4837  case PLPGSQL_DTYPE_VAR:
4838  {
4839  PLpgSQL_var *var = (PLpgSQL_var *) datum;
4840 
4841  *typeid = var->datatype->typoid;
4842  *typetypmod = var->datatype->atttypmod;
4843  *value = var->value;
4844  *isnull = var->isnull;
4845  break;
4846  }
4847 
4848  case PLPGSQL_DTYPE_ROW:
4849  {
4850  PLpgSQL_row *row = (PLpgSQL_row *) datum;
4851  HeapTuple tup;
4852 
4853  if (!row->rowtupdesc) /* should not happen */
4854  elog(ERROR, "row variable has no tupdesc");
4855  /* Make sure we have a valid type/typmod setting */
4856  BlessTupleDesc(row->rowtupdesc);
4857  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4858  tup = make_tuple_from_row(estate, row, row->rowtupdesc);
4859  if (tup == NULL) /* should not happen */
4860  elog(ERROR, "row not compatible with its own tupdesc");
4861  *typeid = row->rowtupdesc->tdtypeid;
4862  *typetypmod = row->rowtupdesc->tdtypmod;
4863  *value = HeapTupleGetDatum(tup);
4864  *isnull = false;
4865  MemoryContextSwitchTo(oldcontext);
4866  break;
4867  }
4868 
4869  case PLPGSQL_DTYPE_REC:
4870  {
4871  PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
4872 
4873  if (!HeapTupleIsValid(rec->tup))
4874  ereport(ERROR,
4875  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4876  errmsg("record \"%s\" is not assigned yet",
4877  rec->refname),
4878  errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4879  Assert(rec->tupdesc != NULL);
4880  /* Make sure we have a valid type/typmod setting */
4881  BlessTupleDesc(rec->tupdesc);
4882 
4883  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4884  *typeid = rec->tupdesc->tdtypeid;
4885  *typetypmod = rec->tupdesc->tdtypmod;
4886  *value = heap_copy_tuple_as_datum(rec->tup, rec->tupdesc);
4887  *isnull = false;
4888  MemoryContextSwitchTo(oldcontext);
4889  break;
4890  }
4891 
4893  {
4894  PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
4895  PLpgSQL_rec *rec;
4896  int fno;
4897 
4898  rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
4899  if (!HeapTupleIsValid(rec->tup))
4900  ereport(ERROR,
4901  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4902  errmsg("record \"%s\" is not assigned yet",
4903  rec->refname),
4904  errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4905  fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
4906  if (fno == SPI_ERROR_NOATTRIBUTE)
4907  ereport(ERROR,
4908  (errcode(ERRCODE_UNDEFINED_COLUMN),
4909  errmsg("record \"%s\" has no field \"%s\"",
4910  rec->refname, recfield->fieldname)));
4911  *typeid = SPI_gettypeid(rec->tupdesc, fno);
4912  if (fno > 0)
4913  *typetypmod = rec->tupdesc->attrs[fno - 1]->atttypmod;
4914  else
4915  *typetypmod = -1;
4916  *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
4917  break;
4918  }
4919 
4920  default:
4921  elog(ERROR, "unrecognized dtype: %d", datum->dtype);
4922  }
4923 }
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:760
TupleDesc tupdesc
Definition: plpgsql.h:308
Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)
Definition: spi.c:891
static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate, PLpgSQL_row *row, TupleDesc tupdesc)
Definition: pl_exec.c:6081
Oid tdtypeid
Definition: tupdesc.h:77
PLpgSQL_type * datatype
Definition: plpgsql.h:261
Form_pg_attribute * attrs
Definition: tupdesc.h:74
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:78
PLpgSQL_datum ** datums
Definition: plpgsql.h:907
static struct @114 value
#define ERROR
Definition: elog.h:43
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
Definition: spi.c:835
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:656
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
Datum value
Definition: plpgsql.h:269
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#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 5164 of file pl_exec.c.

References tupleDesc::attrs, 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, NULL, PLpgSQL_expr::plan, PLpgSQL_expr::query, result, SPI_getbinval(), SPI_OK_SELECT, SPITupleTable::tupdesc, 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().

5169 {
5170  Datum result = 0;
5171  int rc;
5172 
5173  /*
5174  * If first time through, create a plan for this expression.
5175  */
5176  if (expr->plan == NULL)
5178 
5179  /*
5180  * If this is a simple expression, bypass SPI and use the executor
5181  * directly
5182  */
5183  if (exec_eval_simple_expr(estate, expr,
5184  &result, isNull, rettype, rettypmod))
5185  return result;
5186 
5187  /*
5188  * Else do it the hard way via exec_run_select
5189  */
5190  rc = exec_run_select(estate, expr, 2, NULL);
5191  if (rc != SPI_OK_SELECT)
5192  ereport(ERROR,
5193  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5194  errmsg("query \"%s\" did not return data", expr->query)));
5195 
5196  /*
5197  * Check that the expression returns exactly one column...
5198  */
5199  if (estate->eval_tuptable->tupdesc->natts != 1)
5200  ereport(ERROR,
5201  (errcode(ERRCODE_SYNTAX_ERROR),
5202  errmsg_plural("query \"%s\" returned %d column",
5203  "query \"%s\" returned %d columns",
5204  estate->eval_tuptable->tupdesc->natts,
5205  expr->query,
5206  estate->eval_tuptable->tupdesc->natts)));
5207 
5208  /*
5209  * ... and get the column's datatype.
5210  */
5211  *rettype = estate->eval_tuptable->tupdesc->attrs[0]->atttypid;
5212  *rettypmod = estate->eval_tuptable->tupdesc->attrs[0]->atttypmod;
5213 
5214  /*
5215  * If there are no rows selected, the result is a NULL of that type.
5216  */
5217  if (estate->eval_processed == 0)
5218  {
5219  *isNull = true;
5220  return (Datum) 0;
5221  }
5222 
5223  /*
5224  * Check that the expression returned no more than one row.
5225  */
5226  if (estate->eval_processed != 1)
5227  ereport(ERROR,
5228  (errcode(ERRCODE_CARDINALITY_VIOLATION),
5229  errmsg("query \"%s\" returned more than one row",
5230  expr->query)));
5231 
5232  /*
5233  * Return the single result Datum.
5234  */
5235  return SPI_getbinval(estate->eval_tuptable->vals[0],
5236  estate->eval_tuptable->tupdesc, 1, isNull);
5237 }
char * query
Definition: plpgsql.h:223
SPITupleTable * eval_tuptable
Definition: plpgsql.h:925
uint64 eval_processed
Definition: plpgsql.h:926
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
Form_pg_attribute * attrs
Definition: tupdesc.h:74
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1618
HeapTuple * vals
Definition: spi.h:27
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:835
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
TupleDesc tupdesc
Definition: spi.h:26
#define SPI_OK_SELECT
Definition: spi.h:51
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3553
static int exec_run_select(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
Definition: pl_exec.c:5245
#define NULL
Definition: c.h:229
static bool exec_eval_simple_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, Datum *result, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5500
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2579
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 5118 of file pl_exec.c.

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

Referenced by exec_assign_value(), and exec_stmt_fetch().

5121 {
5122  Datum exprdatum;
5123  Oid exprtypeid;
5124  int32 exprtypmod;
5125 
5126  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5127  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5128  exprtypeid, exprtypmod,
5129  INT4OID, -1);
5130  return DatumGetInt32(exprdatum);
5131 }
#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:256
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6251
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5164
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 5500 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_simple_recheck_plan(), 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, NULL, 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().

5506 {
5507  ExprContext *econtext = estate->eval_econtext;
5508  LocalTransactionId curlxid = MyProc->lxid;
5509  CachedPlan *cplan;
5510  ParamListInfo paramLI;
5511  void *save_setup_arg;
5512  MemoryContext oldcontext;
5513 
5514  /*
5515  * Forget it if expression wasn't simple before.
5516  */
5517  if (expr->expr_simple_expr == NULL)
5518  return false;
5519 
5520  /*
5521  * If expression is in use in current xact, don't touch it.
5522  */
5523  if (expr->expr_simple_in_use && expr->expr_simple_lxid == curlxid)
5524  return false;
5525 
5526  /*
5527  * Revalidate cached plan, so that we will notice if it became stale. (We
5528  * need to hold a refcount while using the plan, anyway.) If replanning
5529  * is needed, do that work in the eval_mcontext.
5530  */
5531  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5532  cplan = SPI_plan_get_cached_plan(expr->plan);
5533  MemoryContextSwitchTo(oldcontext);
5534 
5535  /*
5536  * We can't get a failure here, because the number of CachedPlanSources in
5537  * the SPI plan can't change from what exec_simple_check_plan saw; it's a
5538  * property of the raw parsetree generated from the query text.
5539  */
5540  Assert(cplan != NULL);
5541 
5542  if (cplan->generation != expr->expr_simple_generation)
5543  {
5544  /* It got replanned ... is it still simple? */
5545  exec_simple_recheck_plan(expr, cplan);
5546  /* better recheck r/w safety, as well */
5547  if (expr->rwparam >= 0)
5548  exec_check_rw_parameter(expr, expr->rwparam);
5549  if (expr->expr_simple_expr == NULL)
5550  {
5551  /* Oops, release refcount and fail */
5552  ReleaseCachedPlan(cplan, true);
5553  return false;
5554  }
5555  }
5556 
5557  /*
5558  * Pass back previously-determined result type.
5559  */
5560  *rettype = expr->expr_simple_type;
5561  *rettypmod = expr->expr_simple_typmod;
5562 
5563  /*
5564  * Prepare the expression for execution, if it's not been done already in
5565  * the current transaction. (This will be forced to happen if we called
5566  * exec_simple_recheck_plan above.)
5567  */
5568  if (expr->expr_simple_lxid != curlxid)
5569  {
5570  oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
5572  expr->expr_simple_in_use = false;
5573  expr->expr_simple_lxid = curlxid;
5574  MemoryContextSwitchTo(oldcontext);
5575  }
5576 
5577  /*
5578  * We have to do some of the things SPI_execute_plan would do, in
5579  * particular advance the snapshot if we are in a non-read-only function.
5580  * Without this, stable functions within the expression would fail to see
5581  * updates made so far by our own function.
5582  */
5583  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
5584  if (!estate->readonly_func)
5585  {
5588  }
5589 
5590  /*
5591  * Set up ParamListInfo to pass to executor. We need an unshared list if
5592  * it's going to include any R/W expanded-object pointer. For safety,
5593  * save and restore estate->paramLI->parserSetupArg around our use of the
5594  * param list.
5595  */
5596  save_setup_arg = estate->paramLI->parserSetupArg;
5597 
5598  if (expr->rwparam >= 0)
5599  paramLI = setup_unshared_param_list(estate, expr);
5600  else
5601  paramLI = setup_param_list(estate, expr);
5602 
5603  econtext->ecxt_param_list_info = paramLI;
5604 
5605  /*
5606  * Mark expression as busy for the duration of the ExecEvalExpr call.
5607  */
5608  expr->expr_simple_in_use = true;
5609 
5610  /*
5611  * Finally we can call the executor to evaluate the expression
5612  */
5614  econtext,
5615  isNull);
5616 
5617  /* Assorted cleanup */
5618  expr->expr_simple_in_use = false;
5619 
5620  econtext->ecxt_param_list_info = NULL;
5621 
5622  estate->paramLI->parserSetupArg = save_setup_arg;
5623 
5624  if (!estate->readonly_func)
5626 
5627  MemoryContextSwitchTo(oldcontext);
5628 
5629  /*
5630  * Now we can release our refcount on the cached plan.
5631  */
5632  ReleaseCachedPlan(cplan, true);
5633 
5634  /*
5635  * That's it.
5636  */
5637  return true;
5638 }
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:6895
PGPROC * MyProc
Definition: proc.c:67
static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5772
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1618
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
SPIPlanPtr plan
Definition: plpgsql.h:224
CachedPlan * SPI_plan_get_cached_plan(SPIPlanPtr plan)
Definition: spi.c:1594
MemoryContext es_query_cxt
Definition: execnodes.h:435
ParamListInfo paramLI
Definition: plpgsql.h:910
EState * simple_eval_estate
Definition: plpgsql.h:914
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
static void exec_simple_recheck_plan(PLpgSQL_expr *expr, CachedPlan *cplan)
Definition: pl_exec.c:6816
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:266
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1252
Expr * expr_simple_expr
Definition: plpgsql.h:235
uint32 LocalTransactionId
Definition: c.h:399
static ParamListInfo setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5675
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:922
LocalTransactionId expr_simple_lxid
Definition: plpgsql.h:248
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
ExprContext * eval_econtext
Definition: plpgsql.h:928
bool readonly_func
Definition: plpgsql.h:892
int generation
Definition: plancache.h:140
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:206
Oid expr_simple_type
Definition: plpgsql.h:237
LocalTransactionId lxid
Definition: proc.h:105
static PreparedParamsData * exec_eval_using_params ( PLpgSQL_execstate estate,
List params 
)
static

Definition at line 7187 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().

7188 {
7189  PreparedParamsData *ppd;
7190  MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
7191  int nargs;
7192  int i;
7193  ListCell *lc;
7194 
7195  ppd = (PreparedParamsData *)
7196  MemoryContextAlloc(stmt_mcontext, sizeof(PreparedParamsData));
7197  nargs = list_length(params);
7198 
7199  ppd->nargs = nargs;
7200  ppd->types = (Oid *)
7201  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Oid));
7202  ppd->values = (Datum *)
7203  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Datum));
7204  ppd->nulls = (char *)
7205  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(char));
7206 
7207  i = 0;
7208  foreach(lc, params)
7209  {
7210  PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
7211  bool isnull;
7212  int32 ppdtypmod;
7213  MemoryContext oldcontext;
7214 
7215  ppd->values[i] = exec_eval_expr(estate, param,
7216  &isnull,
7217  &ppd->types[i],
7218  &ppdtypmod);
7219  ppd->nulls[i] = isnull ? 'n' : ' ';
7220 
7221  oldcontext = MemoryContextSwitchTo(stmt_mcontext);
7222 
7223  if (ppd->types[i] == UNKNOWNOID)
7224  {
7225  /*
7226  * Treat 'unknown' parameters as text, since that's what most
7227  * people would expect. SPI_execute_with_args can coerce unknown
7228  * constants in a more intelligent way, but not unknown Params.
7229  * This code also takes care of copying into the right context.
7230  * Note we assume 'unknown' has the representation of C-string.
7231  */
7232  ppd->types[i] = TEXTOID;
7233  if (!isnull)
7235  }
7236  /* pass-by-ref non null values must be copied into stmt_mcontext */
7237  else if (!isnull)
7238  {
7239  int16 typLen;
7240  bool typByVal;
7241 
7242  get_typlenbyval(ppd->types[i], &typLen, &typByVal);
7243  if (!typByVal)
7244  ppd->values[i] = datumCopy(ppd->values[i], typByVal, typLen);
7245  }
7246 
7247  MemoryContextSwitchTo(oldcontext);
7248 
7249  exec_eval_cleanup(estate);
7250 
7251  i++;
7252  }
7253 
7254  return ppd;
7255 }
signed short int16
Definition: c.h:255
#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:3532
Datum * values
Definition: pl_exec.c:51
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
#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:5164
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1089
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:1969
#define UNKNOWNOID
Definition: pg_type.h:427
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
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 5315 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, NULL, 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().

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

Definition at line 3083 of file pl_exec.c.

References ReturnSetInfo::allowedModes, CurrentResourceOwner, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, IsA, MemoryContextSwitchTo(), NULL, 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().

3084 {
3085  ReturnSetInfo *rsi = estate->rsi;
3086  MemoryContext oldcxt;
3087  ResourceOwner oldowner;
3088 
3089  /*
3090  * Check caller can handle a set result in the way we want
3091  */
3092  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
3093  (rsi->allowedModes & SFRM_Materialize) == 0 ||
3094  rsi->expectedDesc == NULL)
3095  ereport(ERROR,
3096  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3097  errmsg("set-valued function called in context that cannot accept a set")));
3098 
3099  /*
3100  * Switch to the right memory context and resource owner for storing the
3101  * tuplestore for return set. If we're within a subtransaction opened for
3102  * an exception-block, for example, we must still create the tuplestore in
3103  * the resource owner that was active when this function was entered, and
3104  * not in the subtransaction resource owner.
3105  */
3106  oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
3107  oldowner = CurrentResourceOwner;
3109 
3110  estate->tuple_store =
3112  false, work_mem);
3113 
3114  CurrentResourceOwner = oldowner;
3115  MemoryContextSwitchTo(oldcxt);
3116 
3117  estate->rettupdesc = rsi->expectedDesc;
3118 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
ResourceOwner tuple_store_owner
Definition: plpgsql.h:901
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:266
TupleDesc rettupdesc
Definition: plpgsql.h:894
#define ERROR
Definition: elog.h:43
MemoryContext tuple_store_cxt
Definition: plpgsql.h:900
ReturnSetInfo * rsi
Definition: plpgsql.h:902
#define ereport(elevel, rest)
Definition: elog.h:122
Tuplestorestate * tuple_store
Definition: plpgsql.h:899
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:316
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:267
#define NULL
Definition: c.h:229
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 5932 of file pl_exec.c.

References tupleDesc::attrs, 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, NULL, SPI_getbinval(), HeapTupleData::t_data, PLpgSQL_rec::tup, PLpgSQL_rec::tupdesc, 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().

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

Definition at line 6177 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().

6181 {
6183  Oid tupType;
6184  int32 tupTypmod;
6185  TupleDesc tupdesc;
6186  HeapTupleData tmptup;
6187 
6188  /* Extract rowtype info and find a tupdesc */
6189  tupType = HeapTupleHeaderGetTypeId(td);
6190  tupTypmod = HeapTupleHeaderGetTypMod(td);
6191  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
6192 
6193  /* Build a temporary HeapTuple control structure */
6194  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
6195  ItemPointerSetInvalid(&(tmptup.t_self));
6196  tmptup.t_tableOid = InvalidOid;
6197  tmptup.t_data = td;
6198 
6199  /* Do the move */
6200  exec_move_row(estate, rec, row, &tmptup, tupdesc);
6201 
6202  /* Release tupdesc usage count */
6203  ReleaseTupleDesc(tupdesc);
6204 }
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1257
unsigned int Oid
Definition: postgres_ext.h:31
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
signed int int32
Definition: c.h:256
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:455
static struct @114 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:5932
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:445
#define InvalidOid
Definition: postgres_ext.h:36
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:131
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:107
#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 3553 of file pl_exec.c.

References elog, ereport, errcode(), errhint(), errmsg(), ERROR, exec_simple_check_plan(), PLpgSQL_expr::func, PLpgSQL_execstate::func, NULL, 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().

3555 {
3556  SPIPlanPtr plan;
3557 
3558  /*
3559  * The grammar can't conveniently set expr->func while building the parse
3560  * tree, so make sure it's set before parser hooks need it.
3561  */
3562  expr->func = estate->func;
3563 
3564  /*
3565  * Generate and save the plan
3566  */
3567  plan = SPI_prepare_params(expr->query,
3569  (void *) expr,
3570  cursorOptions);
3571  if (plan == NULL)
3572  {
3573  /* Some SPI errors deserve specific error messages */
3574  switch (SPI_result)
3575  {
3576  case SPI_ERROR_COPY:
3577  ereport(ERROR,
3578  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3579  errmsg("cannot COPY to/from client in PL/pgSQL")));
3580  case SPI_ERROR_TRANSACTION:
3581  ereport(ERROR,
3582  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3583  errmsg("cannot begin/end transactions in PL/pgSQL"),
3584  errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
3585  default:
3586  elog(ERROR, "SPI_prepare_params failed for \"%s\": %s",
3588  }
3589  }
3590  SPI_keepplan(plan);
3591  expr->plan = plan;
3592 
3593  /* Check to see if it's a simple expression */
3594  exec_simple_check_plan(estate, expr);
3595 
3596  /*
3597  * Mark expression as not using a read-write param. exec_assign_value has
3598  * to take steps to override this if appropriate; that seems cleaner than
3599  * adding parameters to all other callers.
3600  */
3601  expr->rwparam = -1;
3602 }
int errhint(const char *fmt,...)
Definition: elog.c:987
char * query
Definition: plpgsql.h:223
#define SPI_ERROR_COPY
Definition: spi.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_function * func
Definition: plpgsql.h:882
static void exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:6716
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:1509
void plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
Definition: pl_comp.c:1018
int SPI_keepplan(SPIPlanPtr plan)
Definition: spi.c:559
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:42
int rwparam
Definition: plpgsql.h:226
struct PLpgSQL_function * func
Definition: plpgsql.h:229
#define NULL
Definition: c.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:522
static int exec_run_select ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
long  maxtuples,
Portal portalP 
)
static

Definition at line 5245 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(), NULL, 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().

5247 {
5248  ParamListInfo paramLI;
5249  int rc;
5250 
5251  /*
5252  * On the first call for this expression generate the plan.
5253  *
5254  * If we don't need to return a portal, then we're just going to execute
5255  * the query once, which means it's OK to use a parallel plan, even if the
5256  * number of rows being fetched is limited. If we do need to return a
5257  * portal, the caller might do cursor operations, which parallel query
5258  * can't support.
5259  */
5260  if (expr->plan == NULL)
5261  exec_prepare_plan(estate, expr,
5262  portalP == NULL ? CURSOR_OPT_PARALLEL_OK : 0);
5263 
5264  /*
5265  * If a portal was requested, put the query into the portal
5266  */
5267  if (portalP != NULL)
5268  {
5269  /*
5270  * Set up short-lived ParamListInfo
5271  */
5272  paramLI = setup_unshared_param_list(estate, expr);
5273 
5274  *portalP = SPI_cursor_open_with_paramlist(NULL, expr->plan,
5275  paramLI,
5276  estate->readonly_func);
5277  if (*portalP == NULL)
5278  elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
5280  exec_eval_cleanup(estate);
5281  return SPI_OK_CURSOR;
5282  }
5283 
5284  /*
5285  * Set up ParamListInfo to pass to executor
5286  */
5287  paramLI = setup_param_list(estate, expr);
5288 
5289  /*
5290  * Execute the query
5291  */
5292  rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
5293  estate->readonly_func, maxtuples);
5294  if (rc != SPI_OK_SELECT)
5295  ereport(ERROR,
5296  (errcode(ERRCODE_SYNTAX_ERROR),
5297  errmsg("query \"%s\" is not a SELECT", expr->query)));
5298 
5299  /* Save query results for eventual cleanup */
5300  Assert(estate->eval_tuptable == NULL);
5301  estate->eval_tuptable = SPI_tuptable;
5302  estate->eval_processed = SPI_processed;
5303  estate->eval_lastoid = SPI_lastoid;
5304 
5305  return rc;
5306 }
char * query
Definition: plpgsql.h:223
SPITupleTable * eval_tuptable
Definition: plpgsql.h:925
uint64 eval_processed
Definition: plpgsql.h:926
static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5772
Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only)
Definition: spi.c:1107
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:3532
#define SPI_OK_CURSOR
Definition: spi.h:56
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:372
const char * SPI_result_code_string(int code)
Definition: spi.c:1509
static ParamListInfo setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5675
#define ereport(elevel, rest)
Definition: elog.h:122
Oid SPI_lastoid
Definition: spi.c:40
#define SPI_OK_SELECT
Definition: spi.h:51
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3553
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool readonly_func
Definition: plpgsql.h:892
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2579
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
static void exec_set_found ( PLpgSQL_execstate estate,
bool  state 
)
static

Definition at line 6994 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().

6995 {
6996  PLpgSQL_var *var;
6997 
6998  var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
6999  assign_simple_var(estate, var, BoolGetDatum(state), false, false);
7000 }
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:7140
PLpgSQL_datum ** datums
Definition: plpgsql.h:907
#define BoolGetDatum(X)
Definition: postgres.h:408
Definition: regguts.h:298
static bool exec_simple_check_node ( Node node)
static

Definition at line 6457 of file pl_exec.c.

References arg, FieldStore::arg, CaseExpr::arg, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, CaseExpr::args, RowExpr::args, CoalesceExpr::args, MinMaxExpr::args, XmlExpr::args, CaseExpr::defresult, ArrayExpr::elements, CaseWhen::expr, FALSE, FuncExpr::funcretset, RowCompareExpr::largs, lfirst, XmlExpr::named_args, FieldStore::newvals, nodeTag, NULL, OpExpr::opretset, RowCompareExpr::rargs, ArrayRef::refassgnexpr, ArrayRef::refexpr, ArrayRef::reflowerindexpr, ArrayRef::refupperindexpr, CaseWhen::result, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CaseWhen, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_Const, T_ConvertRowtypeExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_List, T_MinMaxExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SQLValueFunction, T_XmlExpr, and TRUE.

Referenced by exec_simple_recheck_plan().

6458 {
6459  if (node == NULL)
6460  return TRUE;
6461 
6462  switch (nodeTag(node))
6463  {
6464  case T_Const:
6465  return TRUE;
6466 
6467  case T_Param:
6468  return TRUE;
6469 
6470  case T_ArrayRef:
6471  {
6472  ArrayRef *expr = (ArrayRef *) node;
6473 
6475  return FALSE;
6477  return FALSE;
6478  if (!exec_simple_check_node((Node *) expr->refexpr))
6479  return FALSE;
6480  if (!exec_simple_check_node((Node *) expr->refassgnexpr))
6481  return FALSE;
6482 
6483  return TRUE;
6484  }
6485 
6486  case T_FuncExpr:
6487  {
6488  FuncExpr *expr = (FuncExpr *) node;
6489 
6490  if (expr->funcretset)
6491  return FALSE;
6492  if (!exec_simple_check_node((Node *) expr->args))
6493  return FALSE;
6494 
6495  return TRUE;
6496  }
6497 
6498  case T_OpExpr:
6499  {
6500  OpExpr *expr = (OpExpr *) node;
6501 
6502  if (expr->opretset)
6503  return FALSE;
6504  if (!exec_simple_check_node((Node *) expr->args))
6505  return FALSE;
6506 
6507  return TRUE;
6508  }
6509 
6510  case T_DistinctExpr:
6511  {
6512  DistinctExpr *expr = (DistinctExpr *) node;
6513 
6514  if (expr->opretset)
6515  return FALSE;
6516  if (!exec_simple_check_node((Node *) expr->args))
6517  return FALSE;
6518 
6519  return TRUE;
6520  }
6521 
6522  case T_NullIfExpr:
6523  {
6524  NullIfExpr *expr = (NullIfExpr *) node;
6525 
6526  if (expr->opretset)
6527  return FALSE;
6528  if (!exec_simple_check_node((Node *) expr->args))
6529  return FALSE;
6530 
6531  return TRUE;
6532  }
6533 
6534  case T_ScalarArrayOpExpr:
6535  {
6536  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
6537 
6538  if (!exec_simple_check_node((Node *) expr->args))
6539  return FALSE;
6540 
6541  return TRUE;
6542  }
6543 
6544  case T_BoolExpr:
6545  {
6546  BoolExpr *expr = (BoolExpr *) node;
6547 
6548  if (!exec_simple_check_node((Node *) expr->args))
6549  return FALSE;
6550 
6551  return TRUE;
6552  }
6553 
6554  case T_FieldSelect:
6555  return exec_simple_check_node((Node *) ((FieldSelect *) node)->arg);
6556 
6557  case T_FieldStore:
6558  {
6559  FieldStore *expr = (FieldStore *) node;
6560 
6561  if (!exec_simple_check_node((Node *) expr->arg))
6562  return FALSE;
6563  if (!exec_simple_check_node((Node *) expr->newvals))
6564  return FALSE;
6565 
6566  return TRUE;
6567  }
6568 
6569  case T_RelabelType:
6570  return exec_simple_check_node((Node *) ((RelabelType *) node)->arg);
6571 
6572  case T_CoerceViaIO:
6573  return exec_simple_check_node((Node *) ((CoerceViaIO *) node)->arg);
6574 
6575  case T_ArrayCoerceExpr:
6576  return exec_simple_check_node((Node *) ((ArrayCoerceExpr *) node)->arg);
6577 
6578  case T_ConvertRowtypeExpr:
6579  return exec_simple_check_node((Node *) ((ConvertRowtypeExpr *) node)->arg);
6580 
6581  case T_CaseExpr:
6582  {
6583  CaseExpr *expr = (CaseExpr *) node;
6584 
6585  if (!exec_simple_check_node((Node *) expr->arg))
6586  return FALSE;
6587  if (!exec_simple_check_node((Node *) expr->args))
6588  return FALSE;
6589  if (!exec_simple_check_node((Node *) expr->defresult))
6590  return FALSE;
6591 
6592  return TRUE;
6593  }
6594 
6595  case T_CaseWhen:
6596  {
6597  CaseWhen *when = (CaseWhen *) node;
6598 
6599  if (!exec_simple_check_node((Node *) when->expr))
6600  return FALSE;
6601  if (!exec_simple_check_node((Node *) when->result))
6602  return FALSE;
6603 
6604  return TRUE;
6605  }
6606 
6607  case T_CaseTestExpr:
6608  return TRUE;
6609 
6610  case T_ArrayExpr:
6611  {
6612  ArrayExpr *expr = (ArrayExpr *) node;
6613 
6614  if (!exec_simple_check_node((Node *) expr->elements))
6615  return FALSE;
6616 
6617  return TRUE;
6618  }
6619 
6620  case T_RowExpr:
6621  {
6622  RowExpr *expr = (RowExpr *) node;
6623 
6624  if (!exec_simple_check_node((Node *) expr->args))
6625  return FALSE;
6626 
6627  return TRUE;
6628  }
6629 
6630  case T_RowCompareExpr:
6631  {
6632  RowCompareExpr *expr = (RowCompareExpr *) node;
6633 
6634  if (!exec_simple_check_node((Node *) expr->largs))
6635  return FALSE;
6636  if (!exec_simple_check_node((Node *) expr->rargs))
6637  return FALSE;
6638 
6639  return TRUE;
6640  }
6641 
6642  case T_CoalesceExpr:
6643  {
6644  CoalesceExpr *expr = (CoalesceExpr *) node;
6645 
6646  if (!exec_simple_check_node((Node *) expr->args))
6647  return FALSE;
6648 
6649  return TRUE;
6650  }
6651 
6652  case T_MinMaxExpr:
6653  {
6654  MinMaxExpr *expr = (MinMaxExpr *) node;
6655 
6656  if (!exec_simple_check_node((Node *) expr->args))
6657  return FALSE;
6658 
6659  return TRUE;
6660  }
6661 
6662  case T_SQLValueFunction:
6663  return TRUE;
6664 
6665  case T_XmlExpr:
6666  {
6667  XmlExpr *expr = (XmlExpr *) node;
6668 
6669  if (!exec_simple_check_node((Node *) expr->named_args))
6670  return FALSE;
6671  if (!exec_simple_check_node((Node *) expr->args))
6672  return FALSE;
6673 
6674  return TRUE;
6675  }
6676 
6677  case T_NullTest:
6678  return exec_simple_check_node((Node *) ((NullTest *) node)->arg);
6679 
6680  case T_BooleanTest:
6681  return exec_simple_check_node((Node *) ((BooleanTest *) node)->arg);
6682 
6683  case T_CoerceToDomain:
6684  return exec_simple_check_node((Node *) ((CoerceToDomain *) node)->arg);
6685 
6686  case T_CoerceToDomainValue:
6687  return TRUE;
6688 
6689  case T_List:
6690  {
6691  List *expr = (List *) node;
6692  ListCell *l;
6693 
6694  foreach(l, expr)
6695  {
6696  if (!exec_simple_check_node(lfirst(l)))
6697  return FALSE;
6698  }
6699 
6700  return TRUE;
6701  }
6702 
6703  default:
6704  return FALSE;
6705  }
6706 }
Expr * refassgnexpr
Definition: primnodes.h:409
List * args
Definition: primnodes.h:1065
List * args
Definition: primnodes.h:984
Expr * arg
Definition: primnodes.h:766
List * args
Definition: primnodes.h:456
Definition: nodes.h:504
bool funcretset
Definition: primnodes.h:450
#define FALSE
Definition: c.h:221
List * args
Definition: primnodes.h:1045
List * refupperindexpr
Definition: primnodes.h:403
List * reflowerindexpr
Definition: primnodes.h:405
List * elements
Definition: primnodes.h:953
Definition: type.h:83
Definition: nodes.h:286
List * newvals
Definition: primnodes.h:767
Definition: nodes.h:145
List * args
Definition: primnodes.h:907
static bool exec_simple_check_node(Node *node)
Definition: pl_exec.c:6457
List * named_args
Definition: primnodes.h:1142
List * args
Definition: primnodes.h:1144
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: primnodes.h:562
#define nodeTag(nodeptr)
Definition: nodes.h:509
void * arg
#define TRUE
Definition: c.h:217
Expr * arg
Definition: primnodes.h:906
Expr * result
Definition: primnodes.h:919
List * args
Definition: primnodes.h:501
Expr * defresult
Definition: primnodes.h:908
Expr * expr
Definition: primnodes.h:918
Definition: pg_list.h:45
Expr * refexpr
Definition: primnodes.h:407
bool opretset
Definition: primnodes.h:498
Definition: nodes.h:146
static void exec_simple_check_plan ( PLpgSQL_execstate estate,
PLpgSQL_expr expr 
)
static

Definition at line 6716 of file pl_exec.c.

References Assert, CMD_SELECT, Query::commandType, Query::cteList, Query::distinctClause, exec_simple_recheck_plan(), PLpgSQL_expr::expr_simple_expr, PLpgSQL_expr::expr_simple_generation, get_eval_mcontext, Query::groupClause, Query::hasAggs, Query::hasForUpdate, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, IsA, Query::jointree, Query::limitCount, Query::limitOffset, linitial, list_length(), MemoryContextSwitchTo(), NIL, NULL, 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().

6717 {
6718  List *plansources;
6719  CachedPlanSource *plansource;
6720  Query *query;
6721  CachedPlan *cplan;
6722  MemoryContext oldcontext;
6723 
6724  /*
6725  * Initialize to "not simple", and remember the plan generation number we
6726  * last checked. (If we don't get as far as obtaining a plan to check, we
6727  * just leave expr_simple_generation set to 0.)
6728  */
6729  expr->expr_simple_expr = NULL;
6730  expr->expr_simple_generation = 0;
6731 
6732  /*
6733  * We can only test queries that resulted in exactly one CachedPlanSource
6734  */
6735  plansources = SPI_plan_get_plan_sources(expr->plan);
6736  if (list_length(plansources) != 1)
6737  return;
6738  plansource = (CachedPlanSource *) linitial(plansources);
6739 
6740  /*
6741  * Do some checking on the analyzed-and-rewritten form of the query. These
6742  * checks are basically redundant with the tests in
6743  * exec_simple_recheck_plan, but the point is to avoid building a plan if
6744  * possible. Since this function is only called immediately after
6745  * creating the CachedPlanSource, we need not worry about the query being
6746  * stale.
6747  */
6748 
6749  /*
6750  * 1. There must be one single querytree.
6751  */
6752  if (list_length(plansource->query_list) != 1)
6753  return;
6754  query = (Query *) linitial(plansource->query_list);
6755 
6756  /*
6757  * 2. It must be a plain SELECT query without any input tables
6758  */
6759  if (!IsA(query, Query))
6760  return;
6761  if (query->commandType != CMD_SELECT)
6762  return;
6763  if (query->rtable != NIL)
6764  return;
6765 
6766  /*
6767  * 3. Can't have any subplans, aggregates, qual clauses either
6768  */
6769  if (query->hasAggs ||
6770  query->hasWindowFuncs ||
6771  query->hasTargetSRFs ||
6772  query->hasSubLinks ||
6773  query->hasForUpdate ||
6774  query->cteList ||
6775  query->jointree->quals ||
6776  query->groupClause ||
6777  query->havingQual ||
6778  query->windowClause ||
6779  query->distinctClause ||
6780  query->sortClause ||
6781  query->limitOffset ||
6782  query->limitCount ||
6783  query->setOperations)
6784  return;
6785 
6786  /*
6787  * 4. The query must have a single attribute as result
6788  */
6789  if (list_length(query->targetList) != 1)
6790  return;
6791 
6792  /*
6793  * OK, it seems worth constructing a plan for more careful checking.
6794  *
6795  * Get the generic plan for the query. If replanning is needed, do that
6796  * work in the eval_mcontext.
6797  */
6798  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6799  cplan = SPI_plan_get_cached_plan(expr->plan);
6800  MemoryContextSwitchTo(oldcontext);
6801 
6802  /* Can't fail, because we checked for a single CachedPlanSource above */
6803  Assert(cplan != NULL);
6804 
6805  /* Share the remaining work with recheck code path */
6806  exec_simple_recheck_plan(expr, cplan);
6807 
6808  /* Release our plan refcount */
6809  ReleaseCachedPlan(cplan, true);
6810 }
int expr_simple_generation
Definition: plpgsql.h:236
Node * limitOffset
Definition: parsenodes.h:149
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
List * sortClause
Definition: parsenodes.h:147
FromExpr * jointree
Definition: parsenodes.h:129
bool hasAggs
Definition: parsenodes.h:116
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Node * quals
Definition: primnodes.h:1456
SPIPlanPtr plan
Definition: plpgsql.h:224
List * windowClause
Definition: parsenodes.h:143
List * targetList
Definition: parsenodes.h:131
CachedPlan * SPI_plan_get_cached_plan(SPIPlanPtr plan)
Definition: spi.c:1594
#define linitial(l)
Definition: pg_list.h:110
List * rtable
Definition: parsenodes.h:128
List * distinctClause
Definition: parsenodes.h:145
Node * limitCount
Definition: parsenodes.h:150
static void exec_simple_recheck_plan(PLpgSQL_expr *expr, CachedPlan *cplan)
Definition: pl_exec.c:6816
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1252
Expr * expr_simple_expr
Definition: plpgsql.h:235
#define get_eval_mcontext(estate)
Definition: pl_exec.c:114
CmdType commandType
Definition: parsenodes.h:103
bool hasTargetSRFs
Definition: parsenodes.h:118
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool hasWindowFuncs
Definition: parsenodes.h:117
static int list_length(const List *l)
Definition: pg_list.h:89
List * cteList
Definition: parsenodes.h:126
Node * setOperations
Definition: parsenodes.h:154
List * groupClause
Definition: parsenodes.h:137
bool hasSubLinks
Definition: parsenodes.h:119
bool hasForUpdate
Definition: parsenodes.h:123
List * SPI_plan_get_plan_sources(SPIPlanPtr plan)
Definition: spi.c:1578
List * query_list
Definition: plancache.h:94
Node * havingQual
Definition: parsenodes.h:141
Definition: pg_list.h:45
static void exec_simple_recheck_plan ( PLpgSQL_expr expr,
CachedPlan cplan 
)
static

Definition at line 6816 of file pl_exec.c.

References castNode, CMD_SELECT, PlannedStmt::commandType, exec_simple_check_node(), TargetEntry::expr, 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, list_length(), NULL, PlannedStmt::planTree, Plan::qual, Plan::righttree, CachedPlan::stmt_list, and Plan::targetlist.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

6817 {
6818  PlannedStmt *stmt;
6819  Plan *plan;
6820  TargetEntry *tle;
6821 
6822  /*
6823  * Initialize to "not simple", and remember the plan generation number we
6824  * last checked.
6825  */
6826  expr->expr_simple_expr = NULL;
6827  expr->expr_simple_generation = cplan->generation;
6828 
6829  /*
6830  * 1. There must be one single plantree
6831  */
6832  if (list_length(cplan->stmt_list) != 1)
6833  return;
6834  stmt = castNode(PlannedStmt, linitial(cplan->stmt_list));
6835 
6836  /*
6837  * 2. It must be a RESULT plan --> no scan's required
6838  */
6839  if (stmt->commandType != CMD_SELECT)
6840  return;
6841  plan = stmt->planTree;
6842  if (!IsA(plan, Result))
6843  return;
6844 
6845  /*
6846  * 3. Can't have any subplan or qual clause, either
6847  */
6848  if (plan->lefttree != NULL ||
6849  plan->righttree != NULL ||
6850  plan->initPlan != NULL ||
6851  plan->qual != NULL ||
6852  ((Result *) plan)->resconstantqual != NULL)
6853  return;
6854 
6855  /*
6856  * 4. The plan must have a single attribute as result
6857  */
6858  if (list_length(plan->targetlist) != 1)
6859  return;
6860 
6861  tle = (TargetEntry *) linitial(plan->targetlist);
6862 
6863  /*
6864  * 5. Check that all the nodes in the expression are non-scary.
6865  */
6866  if (!exec_simple_check_node((Node *) tle->expr))
6867  return;
6868 
6869  /*
6870  * Yes - this is a simple expression. Mark it as such, and initialize
6871  * state to "not valid in current transaction".
6872  */
6873  expr->expr_simple_expr = tle->expr;
6874  expr->expr_simple_state = NULL;
6875  expr->expr_simple_in_use = false;
6877  /* Also stash away the expression result type */
6878  expr->expr_simple_type = exprType((Node *) tle->expr);
6879  expr->expr_simple_typmod = exprTypmod((Node *) tle->expr);
6880 }
int expr_simple_generation
Definition: plpgsql.h:236
List * qual
Definition: plannodes.h:133
#define IsA(nodeptr, _type_)
Definition: nodes.h:555
#define castNode(_type_, nodeptr)
Definition: nodes.h:573
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:273
Definition: nodes.h:504
struct Plan * planTree
Definition: plannodes.h:61
struct Plan * righttree
Definition: plannodes.h:135
#define linitial(l)
Definition: pg_list.h:110
Expr * expr_simple_expr
Definition: plpgsql.h:235
ExprState * expr_simple_state
Definition: plpgsql.h:246
CmdType commandType
Definition: plannodes.h:45
static bool exec_simple_check_node(Node *node)
Definition: pl_exec.c:6457
LocalTransactionId expr_simple_lxid
Definition: plpgsql.h:248
#define NULL
Definition: c.h:229
Expr * expr
Definition: primnodes.h:1352
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int generation
Definition: plancache.h:140
static int list_length(const List *l)
Definition: pg_list.h:89
struct Plan * lefttree
Definition: plannodes.h:134
List * targetlist
Definition: plannodes.h:132
int32 expr_simple_typmod
Definition: plpgsql.h:238
List * initPlan
Definition: plannodes.h:136
#define InvalidLocalTransactionId
Definition: lock.h:70
List * stmt_list
Definition: plancache.h:132
bool expr_simple_in_use
Definition: plpgsql.h:247
Oid expr_simple_type
Definition: plpgsql.h:237
static int exec_stmt ( PLpgSQL_execstate estate,
PLpgSQL_stmt stmt 
)
static

Definition at line 1534 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().

1535 {
1536  PLpgSQL_stmt *save_estmt;
1537  int rc = -1;
1538 
1539  save_estmt = estate->err_stmt;
1540  estate->err_stmt = stmt;
1541 
1542  /* Let the plugin know that we are about to execute this statement */
1543  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
1544  ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
1545 
1547 
1548  switch (stmt->cmd_type)
1549  {
1550  case PLPGSQL_STMT_BLOCK:
1551  rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
1552  break;
1553 
1554  case PLPGSQL_STMT_ASSIGN:
1555  rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
1556  break;
1557 
1558  case PLPGSQL_STMT_PERFORM:
1559  rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
1560  break;
1561 
1562  case PLPGSQL_STMT_GETDIAG:
1563  rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
1564  break;
1565 
1566  case PLPGSQL_STMT_IF:
1567  rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
1568  break;
1569 
1570  case PLPGSQL_STMT_CASE:
1571  rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
1572  break;
1573 
1574  case PLPGSQL_STMT_LOOP:
1575  rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
1576  break;
1577 
1578  case PLPGSQL_STMT_WHILE:
1579  rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
1580  break;
1581 
1582  case PLPGSQL_STMT_FORI:
1583  rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
1584  break;
1585 
1586  case PLPGSQL_STMT_FORS:
1587  rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
1588  break;
1589 
1590  case PLPGSQL_STMT_FORC:
1591  rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
1592  break;
1593 
1595  rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
1596  break;
1597 
1598  case PLPGSQL_STMT_EXIT:
1599  rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
1600  break;
1601 
1602  case PLPGSQL_STMT_RETURN:
1603  rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
1604  break;
1605 
1607  rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
1608  break;
1609 
1611  rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
1612  break;
1613 
1614  case PLPGSQL_STMT_RAISE:
1615  rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
1616  break;
1617 
1618  case PLPGSQL_STMT_ASSERT:
1619  rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
1620  break;
1621 
1622  case PLPGSQL_STMT_EXECSQL:
1623  rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
1624  break;
1625 
1627  rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
1628  break;
1629 
1630  case PLPGSQL_STMT_DYNFORS:
1631  rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
1632  break;
1633 
1634  case PLPGSQL_STMT_OPEN:
1635  rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
1636  break;
1637 
1638  case PLPGSQL_STMT_FETCH:
1639  rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
1640  break;
1641 
1642  case PLPGSQL_STMT_CLOSE:
1643  rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
1644  break;
1645 
1646  default:
1647  estate->err_stmt = save_estmt;
1648  elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);
1649  }
1650 
1651  /* Let the plugin know that we have finished executing this statement */
1652  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
1653  ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
1654 
1655  estate->err_stmt = save_estmt;
1656 
1657  return rc;
1658 }
static int exec_stmt_execsql(PLpgSQL_execstate *estate, PLpgSQL_stmt_execsql *stmt)
Definition: pl_exec.c:3613
static int exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
Definition: pl_exec.c:1846
PLpgSQL_stmt * err_stmt
Definition: plpgsql.h:931
static int exec_stmt_return_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_return_query *stmt)
Definition: pl_exec.c:3006
static int exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
Definition: pl_exec.c:2397
static int exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
Definition: pl_exec.c:4053
static int exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
Definition: pl_exec.c:4026
static int exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
Definition: pl_exec.c:1932
static int exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
Definition: pl_exec.c:2232
static int exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
Definition: pl_exec.c:1667
#define ERROR
Definition: elog.h:43
static int exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
Definition: pl_exec.c:3346
static int exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
Definition: pl_exec.c:3135
static int exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
Definition: pl_exec.c:2046
void(* stmt_beg)(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
Definition: plpgsql.h:973
static int exec_stmt_dynexecute(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynexecute *stmt)
Definition: pl_exec.c:3831
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:1700
void(* stmt_end)(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
Definition: plpgsql.h:974
static int exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
Definition: pl_exec.c:2597
static int exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
Definition: pl_exec.c:2634
static int exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
Definition: pl_exec.c:1983
static int exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
Definition: pl_exec.c:4209
static int exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
Definition: pl_exec.c:1174
static int exec_stmt_return_next(PLpgSQL_execstate *estate, PLpgSQL_stmt_return_next *stmt)
Definition: pl_exec.c:2800
static int exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
Definition: pl_exec.c:4310
static int exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
Definition: pl_exec.c:1816
static int exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
Definition: pl_exec.c:1683
PLpgSQL_stmt_type cmd_type
Definition: plpgsql.h:366
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define elog
Definition: elog.h:219
static int exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
Definition: pl_exec.c:2261
static int exec_stmt_assert ( PLpgSQL_execstate estate,
PLpgSQL_stmt_assert stmt 
)
static

Definition at line 3346 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, NULL, plpgsql_check_asserts, PLPGSQL_RC_OK, val, and value.

Referenced by exec_stmt().

3347 {
3348  bool value;
3349  bool isnull;
3350 
3351  /* do nothing when asserts are not enabled */
3352  if (!plpgsql_check_asserts)
3353  return PLPGSQL_RC_OK;
3354 
3355  value = exec_eval_boolean(estate, stmt->cond, &isnull);
3356  exec_eval_cleanup(estate);
3357 
3358  if (isnull || !value)
3359  {
3360  char *message = NULL;
3361 
3362  if (stmt->message != NULL)
3363  {
3364  Datum val;
3365  Oid typeid;
3366  int32 typmod;
3367 
3368  val = exec_eval_expr(estate, stmt->message,
3369  &isnull, &typeid, &typmod);
3370  if (!isnull)
3371  message = convert_value_to_string(estate, val, typeid);
3372  /* we mustn't do exec_eval_cleanup here */
3373  }
3374 
3375  ereport(ERROR,
3376  (errcode(ERRCODE_ASSERT_FAILURE),
3377  message ? errmsg_internal("%s", message) :
3378  errmsg("assertion failed")));
3379  }
3380 
3381  return PLPGSQL_RC_OK;
3382 }
int errcode(int sqlerrcode)
Definition: elog.c:575
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3532
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
static struct @114 value
#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:5164
PLpgSQL_expr * message
Definition: plpgsql.h:737
static bool exec_eval_boolean(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
Definition: pl_exec.c:5141
#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
#define NULL
Definition: c.h:229
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:6222
PLpgSQL_expr * cond
Definition: plpgsql.h:736
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 1667 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().

1668 {
1669  Assert(stmt->varno >= 0);
1670 
1671  exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
1672 
1673  return PLPGSQL_RC_OK;
1674 }
PLpgSQL_datum ** datums
Definition: plpgsql.h:907
static void exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target, PLpgSQL_expr *expr)
Definition: pl_exec.c:4353
#define Assert(condition)
Definition: c.h:675
PLpgSQL_expr * expr
Definition: plpgsql.h:422
static int exec_stmt_block ( PLpgSQL_execstate estate,
PLpgSQL_stmt_block block 
)
static

Definition at line 1174 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, NULL, 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().

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

Definition at line 1846 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, NULL, 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().

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

Definition at line 4310 of file pl_exec.c.

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

Referenced by exec_stmt().

4311 {
4312  PLpgSQL_var *curvar;
4313  Portal portal;
4314  char *curname;
4315  MemoryContext oldcontext;
4316 
4317  /* ----------
4318  * Get the portal of the cursor by name
4319  * ----------
4320  */
4321  curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4322  if (curvar->isnull)
4323  ereport(ERROR,
4324  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4325  errmsg("cursor variable \"%s\" is null", curvar->refname)));
4326 
4327  /* Use eval_mcontext for short-lived string */
4328  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4329  curname = TextDatumGetCString(curvar->value);
4330  MemoryContextSwitchTo(oldcontext);
4331 
4332  portal = SPI_cursor_find(curname);
4333  if (portal == NULL)
4334  ereport(ERROR,
4335  (errcode(ERRCODE_UNDEFINED_CURSOR),
4336  errmsg("cursor \"%s\" does not exist", curname)));
4337 
4338  /* ----------
4339  * And close it.
4340  * ----------
4341  */
4342  SPI_cursor_close(portal);
4343 
4344  return PLPGSQL_RC_OK;
4345 }
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:907
Portal SPI_cursor_find(const char *name)
Definition: spi.c:1331
#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
#define NULL
Definition: c.h:229
void SPI_cursor_close(Portal portal)
Definition: spi.c:1399
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 3831 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, NULL, 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().

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