PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pl_exec.c File Reference
#include "plpgsql.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 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, bool parallelOK)
 
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 114 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:1152

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

7135 {
7136  ParamExternData *prm;
7137 
7138  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
7139  /* Free the old value if needed */
7140  if (var->freeval)
7141  {
7143  var->isnull,
7144  var->datatype->typlen))
7146  else
7147  pfree(DatumGetPointer(var->value));
7148  }
7149  /* Assign new value to datum */
7150  var->value = newvalue;
7151  var->isnull = isnull;
7152  var->freeval = freeable;
7153  /* And update the image in the common parameter list */
7154  prm = &estate->paramLI->params[var->dno];
7155  prm->value = MakeExpandedObjectReadOnly(newvalue,
7156  isnull,
7157  var->datatype->typlen);
7158  prm->isnull = isnull;
7159  /* these might be set already, but let's be sure */
7160  prm->pflags = PARAM_FLAG_CONST;
7161  prm->ptype = var->datatype->typoid;
7162 }
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:76
Datum value
Definition: params.h:56
PLpgSQL_datum_type dtype
Definition: plpgsql.h:258
PLpgSQL_type * datatype
Definition: plpgsql.h:263
void pfree(void *pointer)
Definition: mcxt.c:992
ParamListInfo paramLI
Definition: plpgsql.h:912
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
bool freeval
Definition: plpgsql.h:273
Datum value
Definition: plpgsql.h:271
void DeleteExpandedObject(Datum d)
#define Assert(condition)
Definition: c.h:671
#define DatumIsReadWriteExpandedObject(d, isnull, typlen)
uint16 pflags
Definition: params.h:58
#define DatumGetPointer(X)
Definition: postgres.h:557
int16 typlen
Definition: plpgsql.h:183
bool isnull
Definition: params.h:57
#define PARAM_FLAG_CONST
Definition: params.h:52
bool isnull
Definition: plpgsql.h:272
Oid typoid
Definition: plpgsql.h:181
static void assign_text_var ( PLpgSQL_execstate estate,
PLpgSQL_var var,
const char *  str 
)
static

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

7169 {
7170  assign_simple_var(estate, var, CStringGetTextDatum(str), false, true);
7171 }
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:7133
#define CStringGetTextDatum(s)
Definition: builtins.h:90
static bool contains_target_param ( Node node,
int *  target_dno 
)
static

Definition at line 6965 of file pl_exec.c.

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

Referenced by exec_check_rw_parameter().

6966 {
6967  if (node == NULL)
6968  return false;
6969  if (IsA(node, Param))
6970  {
6971  Param *param = (Param *) node;
6972 
6973  if (param->paramkind == PARAM_EXTERN &&
6974  param->paramid == *target_dno + 1)
6975  return true;
6976  return false;
6977  }
6979  (void *) target_dno);
6980 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
ParamKind paramkind
Definition: primnodes.h:222
static bool contains_target_param(Node *node, int *target_dno)
Definition: pl_exec.c:6965
#define NULL
Definition: c.h:226
int paramid
Definition: primnodes.h:223
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1852
static char * convert_value_to_string ( PLpgSQL_execstate estate,
Datum  value,
Oid  valtype 
)
static

Definition at line 6215 of file pl_exec.c.

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

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

6216 {
6217  char *result;
6218  MemoryContext oldcontext;
6219  Oid typoutput;
6220  bool typIsVarlena;
6221 
6222  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
6223  getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
6224  result = OidOutputFunctionCall(typoutput, value);
6225  MemoryContextSwitchTo(oldcontext);
6226 
6227  return result;
6228 }
static struct @76 value
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2600
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define get_eval_mcontext(estate)
Definition: pl_exec.c:112
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:2006
static PLpgSQL_datum * copy_plpgsql_datum ( PLpgSQL_datum datum)
static

Definition at line 1027 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, and PLPGSQL_DTYPE_VAR.

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

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

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

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

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

4391 {
4392  text *value;
4393  MemoryContext oldcontext;
4394 
4395  /* Use eval_mcontext for short-lived text value */
4396  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4397  if (str != NULL)
4398  value = cstring_to_text(str);
4399  else
4400  value = cstring_to_text("");
4401  MemoryContextSwitchTo(oldcontext);
4402 
4403  exec_assign_value(estate, target, PointerGetDatum(value), false,
4404  TEXTOID, -1);
4405 }
static struct @76 value
#define TEXTOID
Definition: pg_type.h:324
#define PointerGetDatum(X)
Definition: postgres.h:564
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define get_eval_mcontext(estate)
Definition: pl_exec.c:112
text * cstring_to_text(const char *s)
Definition: varlena.c:151
#define NULL
Definition: c.h:226
Definition: c.h:435
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4417
static void exec_assign_expr ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
PLpgSQL_expr expr 
)
static

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

4354 {
4355  Datum value;
4356  bool isnull;
4357  Oid valtype;
4358  int32 valtypmod;
4359 
4360  /*
4361  * If first time through, create a plan for this expression, and then see
4362  * if we can pass the target variable as a read-write parameter to the
4363  * expression. (This is a bit messy, but it seems cleaner than modifying
4364  * the API of exec_eval_expr for the purpose.)
4365  */
4366  if (expr->plan == NULL)
4367  {
4368  exec_prepare_plan(estate, expr, 0);
4369  if (target->dtype == PLPGSQL_DTYPE_VAR)
4370  exec_check_rw_parameter(expr, target->dno);
4371  }
4372 
4373  value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
4374  exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
4375  exec_eval_cleanup(estate);
4376 }
static struct @76 value
static void exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno)
Definition: pl_exec.c:6888
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3531
unsigned int Oid
Definition: postgres_ext.h:31
PLpgSQL_datum_type dtype
Definition: plpgsql.h:200
SPIPlanPtr plan
Definition: plpgsql.h:226
signed int int32
Definition: c.h:253
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5162
uintptr_t Datum
Definition: postgres.h:374
static void exec_prepare_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
Definition: pl_exec.c:3552
#define NULL
Definition: c.h:226
static void exec_assign_value(PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
Definition: pl_exec.c:4417
static void exec_assign_value ( PLpgSQL_execstate estate,
PLpgSQL_datum target,
Datum  value,
bool  isNull,
Oid  valtype,
int32  valtypmod 
)
static

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

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

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

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

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

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

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

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

5142 {
5143  Datum exprdatum;
5144  Oid exprtypeid;
5145  int32 exprtypmod;
5146 
5147  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5148  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5149  exprtypeid, exprtypmod,
5150  BOOLOID, -1);
5151  return DatumGetBool(exprdatum);
5152 }
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:253
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6244
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5162
#define DatumGetBool(X)
Definition: postgres.h:401
uintptr_t Datum
Definition: postgres.h:374
#define BOOLOID
Definition: pg_type.h:288
static void exec_eval_cleanup ( PLpgSQL_execstate estate)
static

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

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

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

4830 {
4831  MemoryContext oldcontext;
4832 
4833  switch (datum->dtype)
4834  {
4835  case PLPGSQL_DTYPE_VAR:
4836  {
4837  PLpgSQL_var *var = (PLpgSQL_var *) datum;
4838 
4839  *typeid = var->datatype->typoid;
4840  *typetypmod = var->datatype->atttypmod;
4841  *value = var->value;
4842  *isnull = var->isnull;
4843  break;
4844  }
4845 
4846  case PLPGSQL_DTYPE_ROW:
4847  {
4848  PLpgSQL_row *row = (PLpgSQL_row *) datum;
4849  HeapTuple tup;
4850 
4851  if (!row->rowtupdesc) /* should not happen */
4852  elog(ERROR, "row variable has no tupdesc");
4853  /* Make sure we have a valid type/typmod setting */
4854  BlessTupleDesc(row->rowtupdesc);
4855  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4856  tup = make_tuple_from_row(estate, row, row->rowtupdesc);
4857  if (tup == NULL) /* should not happen */
4858  elog(ERROR, "row not compatible with its own tupdesc");
4859  *typeid = row->rowtupdesc->tdtypeid;
4860  *typetypmod = row->rowtupdesc->tdtypmod;
4861  *value = HeapTupleGetDatum(tup);
4862  *isnull = false;
4863  MemoryContextSwitchTo(oldcontext);
4864  break;
4865  }
4866 
4867  case PLPGSQL_DTYPE_REC:
4868  {
4869  PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
4870 
4871  if (!HeapTupleIsValid(rec->tup))
4872  ereport(ERROR,
4873  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4874  errmsg("record \"%s\" is not assigned yet",
4875  rec->refname),
4876  errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4877  Assert(rec->tupdesc != NULL);
4878  /* Make sure we have a valid type/typmod setting */
4879  BlessTupleDesc(rec->tupdesc);
4880 
4881  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4882  *typeid = rec->tupdesc->tdtypeid;
4883  *typetypmod = rec->tupdesc->tdtypmod;
4884  *value = heap_copy_tuple_as_datum(rec->tup, rec->tupdesc);
4885  *isnull = false;
4886  MemoryContextSwitchTo(oldcontext);
4887  break;
4888  }
4889 
4891  {
4892  PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
4893  PLpgSQL_rec *rec;
4894  int fno;
4895 
4896  rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
4897  if (!HeapTupleIsValid(rec->tup))
4898  ereport(ERROR,
4899  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4900  errmsg("record \"%s\" is not assigned yet",
4901  rec->refname),
4902  errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
4903  fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
4904  if (fno == SPI_ERROR_NOATTRIBUTE)
4905  ereport(ERROR,
4906  (errcode(ERRCODE_UNDEFINED_COLUMN),
4907  errmsg("record \"%s\" has no field \"%s\"",
4908  rec->refname, recfield->fieldname)));
4909  *typeid = SPI_gettypeid(rec->tupdesc, fno);
4910  if (fno > 0)
4911  *typetypmod = rec->tupdesc->attrs[fno - 1]->atttypmod;
4912  else
4913  *typetypmod = -1;
4914  *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
4915  break;
4916  }
4917 
4918  default:
4919  elog(ERROR, "unrecognized dtype: %d", datum->dtype);
4920  }
4921 }
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:760
TupleDesc tupdesc
Definition: plpgsql.h:310
static struct @76 value
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:6074
Oid tdtypeid
Definition: tupdesc.h:77
PLpgSQL_type * datatype
Definition: plpgsql.h:263
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:200
char * refname
Definition: plpgsql.h:306
int32 tdtypmod
Definition: tupdesc.h:78
PLpgSQL_datum ** datums
Definition: plpgsql.h:909
#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:112
Datum value
Definition: plpgsql.h:271
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 atttypmod
Definition: plpgsql.h:189
HeapTuple tup
Definition: plpgsql.h:309
TupleDesc rowtupdesc
Definition: plpgsql.h:287
#define elog
Definition: elog.h:219
char * fieldname
Definition: plpgsql.h:322
bool isnull
Definition: plpgsql.h:272
Oid typoid
Definition: plpgsql.h:181
static Datum exec_eval_expr ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
bool isNull,
Oid rettype,
int32 rettypmod 
)
static

Definition at line 5162 of file pl_exec.c.

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

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

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

Referenced by exec_assign_value(), and exec_stmt_fetch().

5119 {
5120  Datum exprdatum;
5121  Oid exprtypeid;
5122  int32 exprtypmod;
5123 
5124  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5125  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5126  exprtypeid, exprtypmod,
5127  INT4OID, -1);
5128  return DatumGetInt32(exprdatum);
5129 }
#define DatumGetInt32(X)
Definition: postgres.h:480
#define INT4OID
Definition: pg_type.h:316
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:253
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6244
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5162
uintptr_t Datum
Definition: postgres.h:374
static bool exec_eval_simple_expr ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
Datum result,
bool isNull,
Oid rettype,
int32 rettypmod 
)
static

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

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

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

7181 {
7182  PreparedParamsData *ppd;
7183  MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
7184  int nargs;
7185  int i;
7186  ListCell *lc;
7187 
7188  ppd = (PreparedParamsData *)
7189  MemoryContextAlloc(stmt_mcontext, sizeof(PreparedParamsData));
7190  nargs = list_length(params);
7191 
7192  ppd->nargs = nargs;
7193  ppd->types = (Oid *)
7194  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Oid));
7195  ppd->values = (Datum *)
7196  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Datum));
7197  ppd->nulls = (char *)
7198  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(char));
7199 
7200  i = 0;
7201  foreach(lc, params)
7202  {
7203  PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
7204  bool isnull;
7205  int32 ppdtypmod;
7206  MemoryContext oldcontext;
7207 
7208  ppd->values[i] = exec_eval_expr(estate, param,
7209  &isnull,
7210  &ppd->types[i],
7211  &ppdtypmod);
7212  ppd->nulls[i] = isnull ? 'n' : ' ';
7213 
7214  oldcontext = MemoryContextSwitchTo(stmt_mcontext);
7215 
7216  if (ppd->types[i] == UNKNOWNOID)
7217  {
7218  /*
7219  * Treat 'unknown' parameters as text, since that's what most
7220  * people would expect. SPI_execute_with_args can coerce unknown
7221  * constants in a more intelligent way, but not unknown Params.
7222  * This code also takes care of copying into the right context.
7223  * Note we assume 'unknown' has the representation of C-string.
7224  */
7225  ppd->types[i] = TEXTOID;
7226  if (!isnull)
7228  }
7229  /* pass-by-ref non null values must be copied into stmt_mcontext */
7230  else if (!isnull)
7231  {
7232  int16 typLen;
7233  bool typByVal;
7234 
7235  get_typlenbyval(ppd->types[i], &typLen, &typByVal);
7236  if (!typByVal)
7237  ppd->values[i] = datumCopy(ppd->values[i], typByVal, typLen);
7238  }
7239 
7240  MemoryContextSwitchTo(oldcontext);
7241 
7242  exec_eval_cleanup(estate);
7243 
7244  i++;
7245  }
7246 
7247  return ppd;
7248 }
signed short int16
Definition: c.h:252
#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:3531
Datum * values
Definition: pl_exec.c:49
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:253
#define DatumGetCString(X)
Definition: postgres.h:574
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5162
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1088
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:374
#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:423
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:90
static int exec_for_query ( PLpgSQL_execstate estate,
PLpgSQL_stmt_forq stmt,
Portal  portal,
bool  prefetch_ok 
)
static

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

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

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

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

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

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

6174 {
6176  Oid tupType;
6177  int32 tupTypmod;
6178  TupleDesc tupdesc;
6179  HeapTupleData tmptup;
6180 
6181  /* Extract rowtype info and find a tupdesc */
6182  tupType = HeapTupleHeaderGetTypeId(td);
6183  tupTypmod = HeapTupleHeaderGetTypMod(td);
6184  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
6185 
6186  /* Build a temporary HeapTuple control structure */
6187  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
6188  ItemPointerSetInvalid(&(tmptup.t_self));
6189  tmptup.t_tableOid = InvalidOid;
6190  tmptup.t_data = td;
6191 
6192  /* Do the move */
6193  exec_move_row(estate, rec, row, &tmptup, tupdesc);
6194 
6195  /* Release tupdesc usage count */
6196  ReleaseTupleDesc(tupdesc);
6197 }
static struct @76 value
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1245
unsigned int Oid
Definition: postgres_ext.h:31
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:254
signed int int32
Definition: c.h:253
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:455
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:5925
#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 3552 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().

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

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

5246 {
5247  ParamListInfo paramLI;
5248  int rc;
5249 
5250  /*
5251  * On the first call for this expression generate the plan
5252  */
5253  if (expr->plan == NULL)
5254  exec_prepare_plan(estate, expr, parallelOK ?
5256 
5257  /*
5258  * If a portal was requested, put the query into the portal
5259  */
5260  if (portalP != NULL)
5261  {
5262  /*
5263  * Set up short-lived ParamListInfo
5264  */
5265  paramLI = setup_unshared_param_list(estate, expr);
5266 
5267  *portalP = SPI_cursor_open_with_paramlist(NULL, expr->plan,
5268  paramLI,
5269  estate->readonly_func);
5270  if (*portalP == NULL)
5271  elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
5273  exec_eval_cleanup(estate);
5274  return SPI_OK_CURSOR;
5275  }
5276 
5277  /*
5278  * Set up ParamListInfo to pass to executor
5279  */
5280  paramLI = setup_param_list(estate, expr);
5281 
5282  /*
5283  * Execute the query
5284  */
5285  rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
5286  estate->readonly_func, maxtuples);
5287  if (rc != SPI_OK_SELECT)
5288  ereport(ERROR,
5289  (errcode(ERRCODE_SYNTAX_ERROR),
5290  errmsg("query \"%s\" is not a SELECT", expr->query)));
5291 
5292  /* Save query results for eventual cleanup */
5293  Assert(estate->eval_tuptable == NULL);
5294  estate->eval_tuptable = SPI_tuptable;
5295  estate->eval_processed = SPI_processed;
5296  estate->eval_lastoid = SPI_lastoid;
5297 
5298  return rc;
5299 }
char * query
Definition: plpgsql.h:225
SPITupleTable * eval_tuptable
Definition: plpgsql.h:927
uint64 eval_processed
Definition: plpgsql.h:928
static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
Definition: pl_exec.c:5765
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:3531
#define SPI_OK_CURSOR
Definition: spi.h:56
uint64 SPI_processed
Definition: spi.c:39
SPIPlanPtr plan
Definition: plpgsql.h:226
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:5668
#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:3552
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool readonly_func
Definition: plpgsql.h:894
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2528
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 6987 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().

6988 {
6989  PLpgSQL_var *var;
6990 
6991  var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
6992  assign_simple_var(estate, var, BoolGetDatum(state), false, false);
6993 }
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:7133
PLpgSQL_datum ** datums
Definition: plpgsql.h:909
#define BoolGetDatum(X)
Definition: postgres.h:410
Definition: regguts.h:298
static bool exec_simple_check_node ( Node node)
static

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

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

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

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

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

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

1534 {
1535  PLpgSQL_stmt *save_estmt;
1536  int rc = -1;
1537 
1538  save_estmt = estate->err_stmt;
1539  estate->err_stmt = stmt;
1540 
1541  /* Let the plugin know that we are about to execute this statement */
1542  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
1543  ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
1544 
1546 
1547  switch (stmt->cmd_type)
1548  {
1549  case PLPGSQL_STMT_BLOCK:
1550  rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
1551  break;
1552 
1553  case PLPGSQL_STMT_ASSIGN:
1554  rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
1555  break;
1556 
1557  case PLPGSQL_STMT_PERFORM:
1558  rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
1559  break;
1560 
1561  case PLPGSQL_STMT_GETDIAG:
1562  rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
1563  break;
1564 
1565  case PLPGSQL_STMT_IF:
1566  rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
1567  break;
1568 
1569  case PLPGSQL_STMT_CASE:
1570  rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
1571  break;
1572 
1573  case PLPGSQL_STMT_LOOP:
1574  rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
1575  break;
1576 
1577  case PLPGSQL_STMT_WHILE:
1578  rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
1579  break;
1580 
1581  case PLPGSQL_STMT_FORI:
1582  rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
1583  break;
1584 
1585  case PLPGSQL_STMT_FORS:
1586  rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
1587  break;
1588 
1589  case PLPGSQL_STMT_FORC:
1590  rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
1591  break;
1592 
1594  rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
1595  break;
1596 
1597  case PLPGSQL_STMT_EXIT:
1598  rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
1599  break;
1600 
1601  case PLPGSQL_STMT_RETURN:
1602  rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
1603  break;
1604 
1606  rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
1607  break;
1608 
1610  rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
1611  break;
1612 
1613  case PLPGSQL_STMT_RAISE:
1614  rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
1615  break;
1616 
1617  case PLPGSQL_STMT_ASSERT:
1618  rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
1619  break;
1620 
1621  case PLPGSQL_STMT_EXECSQL:
1622  rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
1623  break;
1624 
1626  rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
1627  break;
1628 
1629  case PLPGSQL_STMT_DYNFORS:
1630  rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
1631  break;
1632 
1633  case PLPGSQL_STMT_OPEN:
1634  rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
1635  break;
1636 
1637  case PLPGSQL_STMT_FETCH:
1638  rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
1639  break;
1640 
1641  case PLPGSQL_STMT_CLOSE:
1642  rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
1643  break;
1644 
1645  default:
1646  estate->err_stmt = save_estmt;
1647  elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);
1648  }
1649 
1650  /* Let the plugin know that we have finished executing this statement */
1651  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
1652  ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
1653 
1654  estate->err_stmt = save_estmt;
1655 
1656  return rc;
1657 }
static int exec_stmt_execsql(PLpgSQL_execstate *estate, PLpgSQL_stmt_execsql *stmt)
Definition: pl_exec.c:3612
static int exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
Definition: pl_exec.c:1845
PLpgSQL_stmt * err_stmt
Definition: plpgsql.h:933
static int exec_stmt_return_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_return_query *stmt)
Definition: pl_exec.c:3005
static int exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
Definition: pl_exec.c:2396
static int exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
Definition: pl_exec.c:4052
static int exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
Definition: pl_exec.c:4025
static int exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
Definition: pl_exec.c:1931
static int exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
Definition: pl_exec.c:2231
static int exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
Definition: pl_exec.c:1666
#define ERROR
Definition: elog.h:43
static int exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
Definition: pl_exec.c:3345
static int exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
Definition: pl_exec.c:3134
static int exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
Definition: pl_exec.c:2045
void(* stmt_beg)(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
Definition: plpgsql.h:975
static int exec_stmt_dynexecute(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynexecute *stmt)
Definition: pl_exec.c:3830
PLpgSQL_plugin ** plpgsql_plugin_ptr
Definition: pl_handler.c:56
static int exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
Definition: pl_exec.c:1699
void(* stmt_end)(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
Definition: plpgsql.h:976
static int exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
Definition: pl_exec.c:2596
static int exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
Definition: pl_exec.c:2633
static int exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
Definition: pl_exec.c:1982
static int exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
Definition: pl_exec.c:4208
static int exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
Definition: pl_exec.c:1173
static int exec_stmt_return_next(PLpgSQL_execstate *estate, PLpgSQL_stmt_return_next *stmt)
Definition: pl_exec.c:2799
static int exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
Definition: pl_exec.c:4309
static int exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
Definition: pl_exec.c:1815
static int exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
Definition: pl_exec.c:1682
PLpgSQL_stmt_type cmd_type
Definition: plpgsql.h:368
#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:2260
static int exec_stmt_assert ( PLpgSQL_execstate estate,
PLpgSQL_stmt_assert stmt 
)
static

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

3346 {
3347  bool value;
3348  bool isnull;
3349 
3350  /* do nothing when asserts are not enabled */
3351  if (!plpgsql_check_asserts)
3352  return PLPGSQL_RC_OK;
3353 
3354  value = exec_eval_boolean(estate, stmt->cond, &isnull);
3355  exec_eval_cleanup(estate);
3356 
3357  if (isnull || !value)
3358  {
3359  char *message = NULL;
3360 
3361  if (stmt->message != NULL)
3362  {
3363  Datum val;
3364  Oid typeid;
3365  int32 typmod;
3366 
3367  val = exec_eval_expr(estate, stmt->message,
3368  &isnull, &typeid, &typmod);
3369  if (!isnull)
3370  message = convert_value_to_string(estate, val, typeid);
3371  /* we mustn't do exec_eval_cleanup here */
3372  }
3373 
3374  ereport(ERROR,
3375  (errcode(ERRCODE_ASSERT_FAILURE),
3376  message ? errmsg_internal("%s", message) :
3377  errmsg("assertion failed")));
3378  }
3379 
3380  return PLPGSQL_RC_OK;
3381 }
static struct @76 value
int errcode(int sqlerrcode)
Definition: elog.c:575
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3531
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:253
#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:5162
PLpgSQL_expr * message
Definition: plpgsql.h:739
static bool exec_eval_boolean(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
Definition: pl_exec.c:5139
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
#define NULL
Definition: c.h:226
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:6215
PLpgSQL_expr * cond
Definition: plpgsql.h:738
bool plpgsql_check_asserts
Definition: pl_handler.c:48
long val
Definition: informix.c:689
static int exec_stmt_assign ( PLpgSQL_execstate estate,
PLpgSQL_stmt_assign stmt 
)
static

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

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

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

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

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

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

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

4310 {
4311  PLpgSQL_var *curvar;
4312  Portal portal;
4313  char *curname;
4314  MemoryContext oldcontext;
4315 
4316  /* ----------
4317  * Get the portal of the cursor by name
4318  * ----------
4319  */
4320  curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
4321  if (curvar->isnull)
4322  ereport(ERROR,
4323  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4324  errmsg("cursor variable \"%s\" is null", curvar->refname)));
4325 
4326  /* Use eval_mcontext for short-lived string */
4327  oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
4328  curname = TextDatumGetCString(curvar->value);
4329  MemoryContextSwitchTo(oldcontext);
4330 
4331  portal = SPI_cursor_find(curname);
4332  if (portal == NULL)
4333  ereport(ERROR,
4334  (errcode(ERRCODE_UNDEFINED_CURSOR),
4335  errmsg("cursor \"%s\" does not exist", curname)));
4336 
4337  /* ----------
4338  * And close it.
4339  * ----------
4340  */
4341  SPI_cursor_close(portal);
4342 
4343  return PLPGSQL_RC_OK;
4344 }
char * refname
Definition: plpgsql.h:260
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_datum ** datums
Definition: plpgsql.h:909
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:112
#define TextDatumGetCString(d)
Definition: builtins.h:91
Datum value
Definition: plpgsql.h:271
#define NULL
Definition: c.h:226
void SPI_cursor_close(Portal portal)
Definition: spi.c:1399
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool isnull
Definition: plpgsql.h:272
static int exec_stmt_dynexecute ( PLpgSQL_execstate estate,
PLpgSQL_stmt_dynexecute stmt 
)
static

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

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