PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pl_exec.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "access/transam.h"
#include "access/tupconvert.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/planner.h"
#include "parser/parse_coerce.h"
#include "parser/scansup.h"
#include "storage/proc.h"
#include "tcop/tcopprot.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/typcache.h"
#include "plpgsql.h"
Include dependency graph for pl_exec.c:

Go to the source code of this file.

Data Structures

struct  PreparedParamsData
 
struct  SimpleEcontextStackEntry
 
struct  plpgsql_CastHashKey
 
struct  plpgsql_CastHashEntry
 

Macros

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

Typedefs

typedef struct
SimpleEcontextStackEntry 
SimpleEcontextStackEntry
 

Functions

static void plpgsql_exec_error_callback (void *arg)
 
static PLpgSQL_datumcopy_plpgsql_datum (PLpgSQL_datum *datum)
 
static MemoryContext get_stmt_mcontext (PLpgSQL_execstate *estate)
 
static void push_stmt_mcontext (PLpgSQL_execstate *estate)
 
static void pop_stmt_mcontext (PLpgSQL_execstate *estate)
 
static int exec_stmt_block (PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 
static int exec_stmts (PLpgSQL_execstate *estate, List *stmts)
 
static int exec_stmt (PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
 
static int exec_stmt_assign (PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
 
static int exec_stmt_perform (PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
 
static int exec_stmt_getdiag (PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
 
static int exec_stmt_if (PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
 
static int exec_stmt_case (PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
 
static int exec_stmt_loop (PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
 
static int exec_stmt_while (PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
 
static int exec_stmt_fori (PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
 
static int exec_stmt_fors (PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
 
static int exec_stmt_forc (PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
 
static int exec_stmt_foreach_a (PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
 
static int exec_stmt_open (PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
 
static int exec_stmt_fetch (PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
 
static int exec_stmt_close (PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
 
static int exec_stmt_exit (PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
 
static int exec_stmt_return (PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
 
static int exec_stmt_return_next (PLpgSQL_execstate *estate, PLpgSQL_stmt_return_next *stmt)
 
static int exec_stmt_return_query (PLpgSQL_execstate *estate, PLpgSQL_stmt_return_query *stmt)
 
static int exec_stmt_raise (PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 
static int exec_stmt_assert (PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
 
static int exec_stmt_execsql (PLpgSQL_execstate *estate, PLpgSQL_stmt_execsql *stmt)
 
static int exec_stmt_dynexecute (PLpgSQL_execstate *estate, PLpgSQL_stmt_dynexecute *stmt)
 
static int exec_stmt_dynfors (PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
 
static void plpgsql_estate_setup (PLpgSQL_execstate *estate, PLpgSQL_function *func, ReturnSetInfo *rsi, EState *simple_eval_estate)
 
static void exec_eval_cleanup (PLpgSQL_execstate *estate)
 
static void exec_prepare_plan (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, int cursorOptions)
 
static bool exec_simple_check_node (Node *node)
 
static void exec_simple_check_plan (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
static void exec_simple_recheck_plan (PLpgSQL_expr *expr, CachedPlan *cplan)
 
static void exec_check_rw_parameter (PLpgSQL_expr *expr, int target_dno)
 
static bool contains_target_param (Node *node, int *target_dno)
 
static bool exec_eval_simple_expr (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, Datum *result, bool *isNull, Oid *rettype, int32 *rettypmod)
 
static void exec_assign_expr (PLpgSQL_execstate *estate, PLpgSQL_datum *target, PLpgSQL_expr *expr)
 
static void exec_assign_c_string (PLpgSQL_execstate *estate, PLpgSQL_datum *target, const char *str)
 
static void exec_assign_value (PLpgSQL_execstate *estate, PLpgSQL_datum *target, Datum value, bool isNull, Oid valtype, int32 valtypmod)
 
static void exec_eval_datum (PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeid, int32 *typetypmod, Datum *value, bool *isnull)
 
static int exec_eval_integer (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
 
static bool exec_eval_boolean (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull)
 
static Datum exec_eval_expr (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
 
static int exec_run_select (PLpgSQL_execstate *estate, PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
 
static int exec_for_query (PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, Portal portal, bool prefetch_ok)
 
static ParamListInfo setup_param_list (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
static ParamListInfo setup_unshared_param_list (PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 
static void plpgsql_param_fetch (ParamListInfo params, int paramid)
 
static void exec_move_row (PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
 
static HeapTuple make_tuple_from_row (PLpgSQL_execstate *estate, PLpgSQL_row *row, TupleDesc tupdesc)
 
static HeapTuple get_tuple_from_datum (Datum value)
 
static TupleDesc get_tupdesc_from_datum (Datum value)
 
static void exec_move_row_from_datum (PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, Datum value)
 
static char * convert_value_to_string (PLpgSQL_execstate *estate, Datum value, Oid valtype)
 
static Datum exec_cast_value (PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
 
static plpgsql_CastHashEntryget_cast_hashentry (PLpgSQL_execstate *estate, Oid srctype, int32 srctypmod, Oid dsttype, int32 dsttypmod)
 
static void exec_init_tuple_store (PLpgSQL_execstate *estate)
 
static void exec_set_found (PLpgSQL_execstate *estate, bool state)
 
static void plpgsql_create_econtext (PLpgSQL_execstate *estate)
 
static void plpgsql_destroy_econtext (PLpgSQL_execstate *estate)
 
static void assign_simple_var (PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
 
static void assign_text_var (PLpgSQL_execstate *estate, PLpgSQL_var *var, const char *str)
 
static PreparedParamsDataexec_eval_using_params (PLpgSQL_execstate *estate, List *params)
 
static Portal exec_dynquery_with_params (PLpgSQL_execstate *estate, PLpgSQL_expr *dynquery, List *params, const char *portalname, int cursorOptions)
 
static char * format_expr_params (PLpgSQL_execstate *estate, const PLpgSQL_expr *expr)
 
static char * format_preparedparamsdata (PLpgSQL_execstate *estate, const PreparedParamsData *ppd)
 
Datum plpgsql_exec_function (PLpgSQL_function *func, FunctionCallInfo fcinfo, EState *simple_eval_estate)
 
HeapTuple plpgsql_exec_trigger (PLpgSQL_function *func, TriggerData *trigdata)
 
void plpgsql_exec_event_trigger (PLpgSQL_function *func, EventTriggerData *trigdata)
 
static bool exception_matches_conditions (ErrorData *edata, PLpgSQL_condition *cond)
 
Oid plpgsql_exec_get_datum_type (PLpgSQL_execstate *estate, PLpgSQL_datum *datum)
 
void plpgsql_exec_get_datum_type_info (PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeid, int32 *typmod, Oid *collation)
 
void plpgsql_xact_cb (XactEvent event, void *arg)
 
void plpgsql_subxact_cb (SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
 

Variables

static EStateshared_simple_eval_estate = NULL
 
static SimpleEcontextStackEntrysimple_econtext_stack = NULL
 
static MemoryContext shared_cast_context = NULL
 
static HTABshared_cast_hash = NULL
 

Macro Definition Documentation

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

Definition at line 116 of file pl_exec.c.

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

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

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

7146 {
7147  ParamExternData *prm;
7148 
7149  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
7150  /* Free the old value if needed */
7151  if (var->freeval)
7152  {
7154  var->isnull,
7155  var->datatype->typlen))
7157  else
7158  pfree(DatumGetPointer(var->value));
7159  }
7160  /* Assign new value to datum */
7161  var->value = newvalue;
7162  var->isnull = isnull;
7163  var->freeval = freeable;
7164  /* And update the image in the common parameter list */
7165  prm = &estate->paramLI->params[var->dno];
7166  prm->value = MakeExpandedObjectReadOnly(newvalue,
7167  isnull,
7168  var->datatype->typlen);
7169  prm->isnull = isnull;
7170  /* these might be set already, but let's be sure */
7171  prm->pflags = PARAM_FLAG_CONST;
7172  prm->ptype = var->datatype->typoid;
7173 }
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:76
Datum value
Definition: params.h:56
PLpgSQL_datum_type dtype
Definition: plpgsql.h:256
PLpgSQL_type * datatype
Definition: plpgsql.h:261
void pfree(void *pointer)
Definition: mcxt.c:950
ParamListInfo paramLI
Definition: plpgsql.h:911
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
bool freeval
Definition: plpgsql.h:271
Datum value
Definition: plpgsql.h:269
void DeleteExpandedObject(Datum d)
#define Assert(condition)
Definition: c.h:675
#define DatumIsReadWriteExpandedObject(d, isnull, typlen)
uint16 pflags
Definition: params.h:58
#define DatumGetPointer(X)
Definition: postgres.h:555
int16 typlen
Definition: plpgsql.h:181
bool isnull
Definition: params.h:57
#define PARAM_FLAG_CONST
Definition: params.h:52
bool isnull
Definition: plpgsql.h:270
Oid typoid
Definition: plpgsql.h:179
static void assign_text_var ( PLpgSQL_execstate estate,
PLpgSQL_var var,
const char *  str 
)
static

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

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

Definition at line 6976 of file pl_exec.c.

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

Referenced by exec_check_rw_parameter().

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

Definition at line 6226 of file pl_exec.c.

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

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

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

Definition at line 1032 of file pl_exec.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5148 {
5149  Datum exprdatum;
5150  Oid exprtypeid;
5151  int32 exprtypmod;
5152 
5153  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5154  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5155  exprtypeid, exprtypmod,
5156  BOOLOID, -1);
5157  return DatumGetBool(exprdatum);
5158 }
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6255
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5168
#define DatumGetBool(X)
Definition: postgres.h:399
uintptr_t Datum
Definition: postgres.h:372
#define BOOLOID
Definition: pg_type.h:288
static void exec_eval_cleanup ( PLpgSQL_execstate estate)
static

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

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

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

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

Definition at line 5168 of file pl_exec.c.

References tupleDesc::attrs, CURSOR_OPT_PARALLEL_OK, ereport, errcode(), errmsg(), errmsg_plural(), ERROR, PLpgSQL_execstate::eval_processed, PLpgSQL_execstate::eval_tuptable, exec_eval_simple_expr(), exec_prepare_plan(), exec_run_select(), tupleDesc::natts, NULL, PLpgSQL_expr::plan, PLpgSQL_expr::query, result, SPI_getbinval(), SPI_OK_SELECT, SPITupleTable::tupdesc, and SPITupleTable::vals.

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

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

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

Referenced by exec_assign_value(), and exec_stmt_fetch().

5125 {
5126  Datum exprdatum;
5127  Oid exprtypeid;
5128  int32 exprtypmod;
5129 
5130  exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
5131  exprdatum = exec_cast_value(estate, exprdatum, isNull,
5132  exprtypeid, exprtypmod,
5133  INT4OID, -1);
5134  return DatumGetInt32(exprdatum);
5135 }
#define DatumGetInt32(X)
Definition: postgres.h:478
#define INT4OID
Definition: pg_type.h:316
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:6255
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5168
uintptr_t Datum
Definition: postgres.h:372
static bool exec_eval_simple_expr ( PLpgSQL_execstate estate,
PLpgSQL_expr expr,
Datum result,
bool isNull,
Oid rettype,
int32 rettypmod 
)
static

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

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

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

7192 {
7193  PreparedParamsData *ppd;
7194  MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
7195  int nargs;
7196  int i;
7197  ListCell *lc;
7198 
7199  ppd = (PreparedParamsData *)
7200  MemoryContextAlloc(stmt_mcontext, sizeof(PreparedParamsData));
7201  nargs = list_length(params);
7202 
7203  ppd->nargs = nargs;
7204  ppd->types = (Oid *)
7205  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Oid));
7206  ppd->values = (Datum *)
7207  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Datum));
7208  ppd->nulls = (char *)
7209  MemoryContextAlloc(stmt_mcontext, nargs * sizeof(char));
7210 
7211  i = 0;
7212  foreach(lc, params)
7213  {
7214  PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
7215  bool isnull;
7216  int32 ppdtypmod;
7217  MemoryContext oldcontext;
7218 
7219  ppd->values[i] = exec_eval_expr(estate, param,
7220  &isnull,
7221  &ppd->types[i],
7222  &ppdtypmod);
7223  ppd->nulls[i] = isnull ? 'n' : ' ';
7224 
7225  oldcontext = MemoryContextSwitchTo(stmt_mcontext);
7226 
7227  if (ppd->types[i] == UNKNOWNOID)
7228  {
7229  /*
7230  * Treat 'unknown' parameters as text, since that's what most
7231  * people would expect. SPI_execute_with_args can coerce unknown
7232  * constants in a more intelligent way, but not unknown Params.
7233  * This code also takes care of copying into the right context.
7234  * Note we assume 'unknown' has the representation of C-string.
7235  */
7236  ppd->types[i] = TEXTOID;
7237  if (!isnull)
7239  }
7240  /* pass-by-ref non null values must be copied into stmt_mcontext */
7241  else if (!isnull)
7242  {
7243  int16 typLen;
7244  bool typByVal;
7245 
7246  get_typlenbyval(ppd->types[i], &typLen, &typByVal);
7247  if (!typByVal)
7248  ppd->values[i] = datumCopy(ppd->values[i], typByVal, typLen);
7249  }
7250 
7251  MemoryContextSwitchTo(oldcontext);
7252 
7253  exec_eval_cleanup(estate);
7254 
7255  i++;
7256  }
7257 
7258  return ppd;
7259 }
signed short int16
Definition: c.h:255
#define TEXTOID
Definition: pg_type.h:324
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:3536
Datum * values
Definition: pl_exec.c:51
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
#define DatumGetCString(X)
Definition: postgres.h:572
static Datum exec_eval_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, bool *isNull, Oid *rettype, int32 *rettypmod)
Definition: pl_exec.c:5168
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:1093
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:372
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2001
#define UNKNOWNOID
Definition: pg_type.h:431
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:91
static int exec_for_query ( PLpgSQL_execstate estate,
PLpgSQL_stmt_forq stmt,
Portal  portal,
bool  prefetch_ok 
)
static

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

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

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

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

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

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

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

6185 {
6187  Oid tupType;
6188  int32 tupTypmod;
6189  TupleDesc tupdesc;
6190  HeapTupleData tmptup;
6191 
6192  /* Extract rowtype info and find a tupdesc */
6193  tupType = HeapTupleHeaderGetTypeId(td);
6194  tupTypmod = HeapTupleHeaderGetTypMod(td);
6195  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
6196 
6197  /* Build a temporary HeapTuple control structure */
6198  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
6199  ItemPointerSetInvalid(&(tmptup.t_self));
6200  tmptup.t_tableOid = InvalidOid;
6201  tmptup.t_data = td;
6202 
6203  /* Do the move */
6204  exec_move_row(estate, rec, row, &tmptup, tupdesc);
6205 
6206  /* Release tupdesc usage count */
6207  ReleaseTupleDesc(tupdesc);
6208 }
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1257
unsigned int Oid
Definition: postgres_ext.h:31
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
signed int int32
Definition: c.h:256
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:455
static struct @121 value
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
Oid t_tableOid
Definition: htup.h:66
static void exec_move_row(PLpgSQL_execstate *estate, PLpgSQL_rec *rec, PLpgSQL_row *row, HeapTuple tup, TupleDesc tupdesc)
Definition: pl_exec.c:5936
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:445
#define InvalidOid
Definition: postgres_ext.h:36
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h: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 3557 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().

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

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

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

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

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

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

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

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

Definition at line 6820 of file pl_exec.c.

References 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, linitial_node, 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().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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