PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pl_handler.c File Reference
#include "plpgsql.h"
#include "access/htup_details.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
Include dependency graph for pl_handler.c:

Go to the source code of this file.

Functions

static bool plpgsql_extra_checks_check_hook (char **newvalue, void **extra, GucSource source)
 
static void plpgsql_extra_warnings_assign_hook (const char *newvalue, void *extra)
 
static void plpgsql_extra_errors_assign_hook (const char *newvalue, void *extra)
 
void _PG_init (void)
 
 PG_FUNCTION_INFO_V1 (plpgsql_call_handler)
 
Datum plpgsql_call_handler (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (plpgsql_inline_handler)
 
Datum plpgsql_inline_handler (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (plpgsql_validator)
 
Datum plpgsql_validator (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 
static const struct
config_enum_entry 
variable_conflict_options []
 
int plpgsql_variable_conflict = PLPGSQL_RESOLVE_ERROR
 
bool plpgsql_print_strict_params = false
 
bool plpgsql_check_asserts = true
 
char * plpgsql_extra_warnings_string = NULL
 
char * plpgsql_extra_errors_string = NULL
 
int plpgsql_extra_warnings
 
int plpgsql_extra_errors
 
PLpgSQL_plugin ** plpgsql_plugin_ptr = NULL
 

Function Documentation

void _PG_init ( void  )

Definition at line 141 of file pl_handler.c.

References DefineCustomBoolVariable(), DefineCustomEnumVariable(), DefineCustomStringVariable(), EmitWarningsOnPlaceholders(), find_rendezvous_variable(), gettext_noop, GUC_LIST_INPUT, NULL, pg_bindtextdomain(), PGC_SUSET, PGC_USERSET, plpgsql_check_asserts, plpgsql_extra_checks_check_hook(), plpgsql_extra_errors_assign_hook(), plpgsql_extra_errors_string, plpgsql_extra_warnings_assign_hook(), plpgsql_extra_warnings_string, plpgsql_HashTableInit(), plpgsql_print_strict_params, PLPGSQL_RESOLVE_ERROR, plpgsql_subxact_cb(), plpgsql_variable_conflict, plpgsql_xact_cb(), RegisterSubXactCallback(), RegisterXactCallback(), and TEXTDOMAIN.

142 {
143  /* Be sure we do initialization only once (should be redundant now) */
144  static bool inited = false;
145 
146  if (inited)
147  return;
148 
150 
151  DefineCustomEnumVariable("plpgsql.variable_conflict",
152  gettext_noop("Sets handling of conflicts between PL/pgSQL variable names and table column names."),
153  NULL,
157  PGC_SUSET, 0,
158  NULL, NULL, NULL);
159 
160  DefineCustomBoolVariable("plpgsql.print_strict_params",
161  gettext_noop("Print information about parameters in the DETAIL part of the error messages generated on INTO ... STRICT failures."),
162  NULL,
164  false,
165  PGC_USERSET, 0,
166  NULL, NULL, NULL);
167 
168  DefineCustomBoolVariable("plpgsql.check_asserts",
169  gettext_noop("Perform checks given in ASSERT statements."),
170  NULL,
172  true,
173  PGC_USERSET, 0,
174  NULL, NULL, NULL);
175 
176  DefineCustomStringVariable("plpgsql.extra_warnings",
177  gettext_noop("List of programming constructs that should produce a warning."),
178  NULL,
180  "none",
184  NULL);
185 
186  DefineCustomStringVariable("plpgsql.extra_errors",
187  gettext_noop("List of programming constructs that should produce an error."),
188  NULL,
190  "none",
194  NULL);
195 
196  EmitWarningsOnPlaceholders("plpgsql");
197 
201 
202  /* Set up a rendezvous point with optional instrumentation plugin */
204 
205  inited = true;
206 }
#define TEXTDOMAIN
Definition: elog.h:125
char * plpgsql_extra_warnings_string
Definition: pl_handler.c:50
void plpgsql_HashTableInit(void)
Definition: pl_comp.c:2561
#define gettext_noop(x)
Definition: c.h:139
void ** find_rendezvous_variable(const char *varName)
Definition: dfmgr.c:667
void DefineCustomEnumVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, const struct config_enum_entry *options, GucContext context, int flags, GucEnumCheckHook check_hook, GucEnumAssignHook assign_hook, GucShowHook show_hook)
Definition: guc.c:7794
char * plpgsql_extra_errors_string
Definition: pl_handler.c:51
Definition: guc.h:75
void EmitWarningsOnPlaceholders(const char *className)
Definition: guc.c:7822
static const struct config_enum_entry variable_conflict_options[]
Definition: pl_handler.c:37
PLpgSQL_plugin ** plpgsql_plugin_ptr
Definition: pl_handler.c:56
static void plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra)
Definition: pl_handler.c:123
void DefineCustomStringVariable(const char *name, const char *short_desc, const char *long_desc, char **valueAddr, const char *bootValue, GucContext context, int flags, GucStringCheckHook check_hook, GucStringAssignHook assign_hook, GucShowHook show_hook)
Definition: guc.c:7769
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3358
bool plpgsql_print_strict_params
Definition: pl_handler.c:46
int plpgsql_variable_conflict
Definition: pl_handler.c:44
#define NULL
Definition: c.h:226
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3303
static void plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra)
Definition: pl_handler.c:129
void pg_bindtextdomain(const char *domain)
Definition: miscinit.c:1488
void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: pl_exec.c:7107
static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source)
Definition: pl_handler.c:60
bool plpgsql_check_asserts
Definition: pl_handler.c:48
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
Definition: guc.c:7683
#define GUC_LIST_INPUT
Definition: guc.h:204
void plpgsql_xact_cb(XactEvent event, void *arg)
Definition: pl_exec.c:7075
PG_FUNCTION_INFO_V1 ( plpgsql_call_handler  )
PG_FUNCTION_INFO_V1 ( plpgsql_inline_handler  )
PG_FUNCTION_INFO_V1 ( plpgsql_validator  )
Datum plpgsql_call_handler ( PG_FUNCTION_ARGS  )

Definition at line 218 of file pl_handler.c.

References CALLED_AS_EVENT_TRIGGER, CALLED_AS_TRIGGER, PLpgSQL_function::cur_estate, elog, ERROR, NULL, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, plpgsql_compile(), plpgsql_exec_event_trigger(), plpgsql_exec_function(), plpgsql_exec_trigger(), PointerGetDatum, SPI_connect(), SPI_finish(), SPI_OK_CONNECT, SPI_OK_FINISH, SPI_result_code_string(), and PLpgSQL_function::use_count.

219 {
220  PLpgSQL_function *func;
221  PLpgSQL_execstate *save_cur_estate;
222  Datum retval;
223  int rc;
224 
225  /*
226  * Connect to SPI manager
227  */
228  if ((rc = SPI_connect()) != SPI_OK_CONNECT)
229  elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));
230 
231  /* Find or compile the function */
232  func = plpgsql_compile(fcinfo, false);
233 
234  /* Must save and restore prior value of cur_estate */
235  save_cur_estate = func->cur_estate;
236 
237  /* Mark the function as busy, so it can't be deleted from under us */
238  func->use_count++;
239 
240  PG_TRY();
241  {
242  /*
243  * Determine if called as function or trigger and call appropriate
244  * subhandler
245  */
246  if (CALLED_AS_TRIGGER(fcinfo))
248  (TriggerData *) fcinfo->context));
249  else if (CALLED_AS_EVENT_TRIGGER(fcinfo))
250  {
252  (EventTriggerData *) fcinfo->context);
253  retval = (Datum) 0;
254  }
255  else
256  retval = plpgsql_exec_function(func, fcinfo, NULL);
257  }
258  PG_CATCH();
259  {
260  /* Decrement use-count, restore cur_estate, and propagate error */
261  func->use_count--;
262  func->cur_estate = save_cur_estate;
263  PG_RE_THROW();
264  }
265  PG_END_TRY();
266 
267  func->use_count--;
268 
269  func->cur_estate = save_cur_estate;
270 
271  /*
272  * Disconnect from SPI manager
273  */
274  if ((rc = SPI_finish()) != SPI_OK_FINISH)
275  elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
276 
277  return retval;
278 }
#define SPI_OK_CONNECT
Definition: spi.h:47
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:40
void plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
Definition: pl_exec.c:885
int SPI_connect(void)
Definition: spi.c:84
#define PointerGetDatum(X)
Definition: postgres.h:564
int SPI_finish(void)
Definition: spi.c:147
PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
Definition: pl_comp.c:135
#define ERROR
Definition: elog.h:43
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:875
unsigned long use_count
Definition: plpgsql.h:876
const char * SPI_result_code_string(int code)
Definition: spi.c:1509
uintptr_t Datum
Definition: postgres.h:374
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:226
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define SPI_OK_FINISH
Definition: spi.h:48
#define PG_RE_THROW()
Definition: elog.h:314
Datum plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, EState *simple_eval_estate)
Definition: pl_exec.c:329
HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func, TriggerData *trigdata)
Definition: pl_exec.c:615
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
static bool plpgsql_extra_checks_check_hook ( char **  newvalue,
void **  extra,
GucSource  source 
)
static

Definition at line 60 of file pl_handler.c.

References GUC_check_errdetail, lfirst, list_free(), malloc, pfree(), pg_strcasecmp(), PLPGSQL_XCHECK_ALL, PLPGSQL_XCHECK_NONE, PLPGSQL_XCHECK_SHADOWVAR, pstrdup(), and SplitIdentifierString().

Referenced by _PG_init().

61 {
62  char *rawstring;
63  List *elemlist;
64  ListCell *l;
65  int extrachecks = 0;
66  int *myextra;
67 
68  if (pg_strcasecmp(*newvalue, "all") == 0)
69  extrachecks = PLPGSQL_XCHECK_ALL;
70  else if (pg_strcasecmp(*newvalue, "none") == 0)
71  extrachecks = PLPGSQL_XCHECK_NONE;
72  else
73  {
74  /* Need a modifiable copy of string */
75  rawstring = pstrdup(*newvalue);
76 
77  /* Parse string into list of identifiers */
78  if (!SplitIdentifierString(rawstring, ',', &elemlist))
79  {
80  /* syntax error in list */
81  GUC_check_errdetail("List syntax is invalid.");
82  pfree(rawstring);
83  list_free(elemlist);
84  return false;
85  }
86 
87  foreach(l, elemlist)
88  {
89  char *tok = (char *) lfirst(l);
90 
91  if (pg_strcasecmp(tok, "shadowed_variables") == 0)
92  extrachecks |= PLPGSQL_XCHECK_SHADOWVAR;
93  else if (pg_strcasecmp(tok, "all") == 0 || pg_strcasecmp(tok, "none") == 0)
94  {
95  GUC_check_errdetail("Key word \"%s\" cannot be combined with other key words.", tok);
96  pfree(rawstring);
97  list_free(elemlist);
98  return false;
99  }
100  else
101  {
102  GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
103  pfree(rawstring);
104  list_free(elemlist);
105  return false;
106  }
107  }
108 
109  pfree(rawstring);
110  list_free(elemlist);
111  }
112 
113  myextra = (int *) malloc(sizeof(int));
114  if (!myextra)
115  return false;
116  *myextra = extrachecks;
117  *extra = (void *) myextra;
118 
119  return true;
120 }
#define GUC_check_errdetail
Definition: guc.h:407
char * pstrdup(const char *in)
Definition: mcxt.c:1165
#define PLPGSQL_XCHECK_NONE
Definition: plpgsql.h:1027
#define PLPGSQL_XCHECK_SHADOWVAR
Definition: plpgsql.h:1028
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define malloc(a)
Definition: header.h:45
void pfree(void *pointer)
Definition: mcxt.c:992
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3129
#define lfirst(lc)
Definition: pg_list.h:106
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
#define PLPGSQL_XCHECK_ALL
Definition: plpgsql.h:1029
static void plpgsql_extra_errors_assign_hook ( const char *  newvalue,
void *  extra 
)
static

Definition at line 129 of file pl_handler.c.

References plpgsql_extra_errors.

Referenced by _PG_init().

130 {
131  plpgsql_extra_errors = *((int *) extra);
132 }
int plpgsql_extra_errors
Definition: pl_handler.c:53
static void plpgsql_extra_warnings_assign_hook ( const char *  newvalue,
void *  extra 
)
static

Definition at line 123 of file pl_handler.c.

References plpgsql_extra_warnings.

Referenced by _PG_init().

124 {
125  plpgsql_extra_warnings = *((int *) extra);
126 }
int plpgsql_extra_warnings
Definition: pl_handler.c:52
Datum plpgsql_inline_handler ( PG_FUNCTION_ARGS  )

Definition at line 289 of file pl_handler.c.

References Assert, castNode, CreateExecutorState(), CurrentMemoryContext, DatumGetPointer, elog, ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_mcxt, FmgrInfo::fn_oid, FreeExecutorState(), GetCurrentSubTransactionId(), InvalidOid, MemSet, NULL, PG_CATCH, PG_END_TRY, PG_GETARG_DATUM, PG_RE_THROW, PG_TRY, plpgsql_compile_inline(), plpgsql_exec_function(), plpgsql_free_function_memory(), plpgsql_subxact_cb(), InlineCodeBlock::source_text, SPI_connect(), SPI_finish(), SPI_OK_CONNECT, SPI_OK_FINISH, SPI_result_code_string(), SUBXACT_EVENT_ABORT_SUB, and PLpgSQL_function::use_count.

290 {
292  PLpgSQL_function *func;
293  FunctionCallInfoData fake_fcinfo;
294  FmgrInfo flinfo;
295  EState *simple_eval_estate;
296  Datum retval;
297  int rc;
298 
299  /*
300  * Connect to SPI manager
301  */
302  if ((rc = SPI_connect()) != SPI_OK_CONNECT)
303  elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));
304 
305  /* Compile the anonymous code block */
306  func = plpgsql_compile_inline(codeblock->source_text);
307 
308  /* Mark the function as busy, just pro forma */
309  func->use_count++;
310 
311  /*
312  * Set up a fake fcinfo with just enough info to satisfy
313  * plpgsql_exec_function(). In particular note that this sets things up
314  * with no arguments passed.
315  */
316  MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
317  MemSet(&flinfo, 0, sizeof(flinfo));
318  fake_fcinfo.flinfo = &flinfo;
319  flinfo.fn_oid = InvalidOid;
320  flinfo.fn_mcxt = CurrentMemoryContext;
321 
322  /* Create a private EState for simple-expression execution */
323  simple_eval_estate = CreateExecutorState();
324 
325  /* And run the function */
326  PG_TRY();
327  {
328  retval = plpgsql_exec_function(func, &fake_fcinfo, simple_eval_estate);
329  }
330  PG_CATCH();
331  {
332  /*
333  * We need to clean up what would otherwise be long-lived resources
334  * accumulated by the failed DO block, principally cached plans for
335  * statements (which can be flushed with plpgsql_free_function_memory)
336  * and execution trees for simple expressions, which are in the
337  * private EState.
338  *
339  * Before releasing the private EState, we must clean up any
340  * simple_econtext_stack entries pointing into it, which we can do by
341  * invoking the subxact callback. (It will be called again later if
342  * some outer control level does a subtransaction abort, but no harm
343  * is done.) We cheat a bit knowing that plpgsql_subxact_cb does not
344  * pay attention to its parentSubid argument.
345  */
348  0, NULL);
349 
350  /* Clean up the private EState */
351  FreeExecutorState(simple_eval_estate);
352 
353  /* Function should now have no remaining use-counts ... */
354  func->use_count--;
355  Assert(func->use_count == 0);
356 
357  /* ... so we can free subsidiary storage */
359 
360  /* And propagate the error */
361  PG_RE_THROW();
362  }
363  PG_END_TRY();
364 
365  /* Clean up the private EState */
366  FreeExecutorState(simple_eval_estate);
367 
368  /* Function should now have no remaining use-counts ... */
369  func->use_count--;
370  Assert(func->use_count == 0);
371 
372  /* ... so we can free subsidiary storage */
374 
375  /*
376  * Disconnect from SPI manager
377  */
378  if ((rc = SPI_finish()) != SPI_OK_FINISH)
379  elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
380 
381  return retval;
382 }
PLpgSQL_function * plpgsql_compile_inline(char *proc_source)
Definition: pl_comp.c:792
#define SPI_OK_CONNECT
Definition: spi.h:47
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:693
Definition: fmgr.h:53
MemoryContext fn_mcxt
Definition: fmgr.h:62
int SPI_connect(void)
Definition: spi.c:84
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int SPI_finish(void)
Definition: spi.c:147
#define MemSet(start, val, len)
Definition: c.h:853
void FreeExecutorState(EState *estate)
Definition: execUtils.c:168
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ERROR
Definition: elog.h:43
unsigned long use_count
Definition: plpgsql.h:876
const char * SPI_result_code_string(int code)
Definition: spi.c:1509
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
EState * CreateExecutorState(void)
Definition: execUtils.c:72
uintptr_t Datum
Definition: postgres.h:374
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:56
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:648
#define SPI_OK_FINISH
Definition: spi.h:48
#define PG_RE_THROW()
Definition: elog.h:314
#define DatumGetPointer(X)
Definition: postgres.h:557
Datum plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, EState *simple_eval_estate)
Definition: pl_exec.c:329
void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: pl_exec.c:7107
char * source_text
Definition: parsenodes.h:2665
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
Datum plpgsql_validator ( PG_FUNCTION_ARGS  )

Definition at line 394 of file pl_handler.c.

References check_function_bodies, CheckFunctionValidatorAccess(), FunctionCallInfoData::context, CurrentMemoryContext, elog, ereport, errcode(), errmsg(), ERROR, EVTTRIGGEROID, FunctionCallInfoData::flinfo, FmgrInfo::fn_mcxt, FmgrInfo::fn_oid, format_type_be(), get_func_arg_info(), get_typtype(), GETSTRUCT, HeapTupleIsValid, i, IsPolymorphicType, MemSet, ObjectIdGetDatum, OPAQUEOID, PG_GETARG_OID, PG_RETURN_VOID, plpgsql_compile(), PROCOID, RECORDOID, ReleaseSysCache(), SearchSysCache1, SPI_connect(), SPI_finish(), SPI_OK_CONNECT, SPI_OK_FINISH, SPI_result_code_string(), T_EventTriggerData, T_TriggerData, TRIGGEROID, EventTriggerData::type, TriggerData::type, TYPTYPE_PSEUDO, and VOIDOID.

395 {
396  Oid funcoid = PG_GETARG_OID(0);
397  HeapTuple tuple;
398  Form_pg_proc proc;
399  char functyptype;
400  int numargs;
401  Oid *argtypes;
402  char **argnames;
403  char *argmodes;
404  bool is_dml_trigger = false;
405  bool is_event_trigger = false;
406  int i;
407 
408  if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
409  PG_RETURN_VOID();
410 
411  /* Get the new function's pg_proc entry */
412  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
413  if (!HeapTupleIsValid(tuple))
414  elog(ERROR, "cache lookup failed for function %u", funcoid);
415  proc = (Form_pg_proc) GETSTRUCT(tuple);
416 
417  functyptype = get_typtype(proc->prorettype);
418 
419  /* Disallow pseudotype result */
420  /* except for TRIGGER, RECORD, VOID, or polymorphic */
421  if (functyptype == TYPTYPE_PSEUDO)
422  {
423  /* we assume OPAQUE with no arguments means a trigger */
424  if (proc->prorettype == TRIGGEROID ||
425  (proc->prorettype == OPAQUEOID && proc->pronargs == 0))
426  is_dml_trigger = true;
427  else if (proc->prorettype == EVTTRIGGEROID)
428  is_event_trigger = true;
429  else if (proc->prorettype != RECORDOID &&
430  proc->prorettype != VOIDOID &&
431  !IsPolymorphicType(proc->prorettype))
432  ereport(ERROR,
433  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
434  errmsg("PL/pgSQL functions cannot return type %s",
435  format_type_be(proc->prorettype))));
436  }
437 
438  /* Disallow pseudotypes in arguments (either IN or OUT) */
439  /* except for polymorphic */
440  numargs = get_func_arg_info(tuple,
441  &argtypes, &argnames, &argmodes);
442  for (i = 0; i < numargs; i++)
443  {
444  if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO)
445  {
446  if (!IsPolymorphicType(argtypes[i]))
447  ereport(ERROR,
448  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
449  errmsg("PL/pgSQL functions cannot accept type %s",
450  format_type_be(argtypes[i]))));
451  }
452  }
453 
454  /* Postpone body checks if !check_function_bodies */
456  {
457  FunctionCallInfoData fake_fcinfo;
458  FmgrInfo flinfo;
459  int rc;
460  TriggerData trigdata;
461  EventTriggerData etrigdata;
462 
463  /*
464  * Connect to SPI manager (is this needed for compilation?)
465  */
466  if ((rc = SPI_connect()) != SPI_OK_CONNECT)
467  elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));
468 
469  /*
470  * Set up a fake fcinfo with just enough info to satisfy
471  * plpgsql_compile().
472  */
473  MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
474  MemSet(&flinfo, 0, sizeof(flinfo));
475  fake_fcinfo.flinfo = &flinfo;
476  flinfo.fn_oid = funcoid;
477  flinfo.fn_mcxt = CurrentMemoryContext;
478  if (is_dml_trigger)
479  {
480  MemSet(&trigdata, 0, sizeof(trigdata));
481  trigdata.type = T_TriggerData;
482  fake_fcinfo.context = (Node *) &trigdata;
483  }
484  else if (is_event_trigger)
485  {
486  MemSet(&etrigdata, 0, sizeof(etrigdata));
487  etrigdata.type = T_EventTriggerData;
488  fake_fcinfo.context = (Node *) &etrigdata;
489  }
490 
491  /* Test-compile the function */
492  plpgsql_compile(&fake_fcinfo, true);
493 
494  /*
495  * Disconnect from SPI manager
496  */
497  if ((rc = SPI_finish()) != SPI_OK_FINISH)
498  elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
499  }
500 
501  ReleaseSysCache(tuple);
502 
503  PG_RETURN_VOID();
504 }
#define SPI_OK_CONNECT
Definition: spi.h:47
Definition: fmgr.h:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
MemoryContext fn_mcxt
Definition: fmgr.h:62
int SPI_connect(void)
Definition: spi.c:84
fmNodePtr context
Definition: fmgr.h:72
int SPI_finish(void)
Definition: spi.c:147
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:791
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
char get_typtype(Oid typid)
Definition: lsyscache.c:2347
#define MemSet(start, val, len)
Definition: c.h:853
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
bool check_function_bodies
Definition: guc.c:449
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
FmgrInfo * flinfo
Definition: fmgr.h:71
#define VOIDOID
Definition: pg_type.h:678
#define OPAQUEOID
Definition: pg_type.h:688
PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
Definition: pl_comp.c:135
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define IsPolymorphicType(typid)
Definition: pg_type.h:733
bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
Definition: fmgr.c:2412
#define TRIGGEROID
Definition: pg_type.h:680
const char * SPI_result_code_string(int code)
Definition: spi.c:1509
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define RECORDOID
Definition: pg_type.h:668
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
Oid fn_oid
Definition: fmgr.h:56
#define PG_RETURN_VOID()
Definition: fmgr.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define EVTTRIGGEROID
Definition: pg_type.h:682
#define SPI_OK_FINISH
Definition: spi.h:48
#define TYPTYPE_PSEUDO
Definition: pg_type.h:712
int errmsg(const char *fmt,...)
Definition: elog.c:797
NodeTag type
Definition: trigger.h:32
int i
#define elog
Definition: elog.h:219

Variable Documentation

PG_MODULE_MAGIC

Definition at line 34 of file pl_handler.c.

bool plpgsql_check_asserts = true

Definition at line 48 of file pl_handler.c.

Referenced by _PG_init(), and exec_stmt_assert().

int plpgsql_extra_errors

Definition at line 53 of file pl_handler.c.

Referenced by do_compile(), and plpgsql_extra_errors_assign_hook().

char* plpgsql_extra_errors_string = NULL

Definition at line 51 of file pl_handler.c.

Referenced by _PG_init().

int plpgsql_extra_warnings

Definition at line 52 of file pl_handler.c.

Referenced by do_compile(), and plpgsql_extra_warnings_assign_hook().

char* plpgsql_extra_warnings_string = NULL

Definition at line 50 of file pl_handler.c.

Referenced by _PG_init().

bool plpgsql_print_strict_params = false

Definition at line 46 of file pl_handler.c.

Referenced by _PG_init(), do_compile(), and plpgsql_compile_inline().

int plpgsql_variable_conflict = PLPGSQL_RESOLVE_ERROR

Definition at line 44 of file pl_handler.c.

Referenced by _PG_init(), do_compile(), and plpgsql_compile_inline().

const struct config_enum_entry variable_conflict_options[]
static
Initial value:
= {
{"error", PLPGSQL_RESOLVE_ERROR, false},
{"use_variable", PLPGSQL_RESOLVE_VARIABLE, false},
{"use_column", PLPGSQL_RESOLVE_COLUMN, false},
{NULL, 0, false}
}
#define NULL
Definition: c.h:226

Definition at line 37 of file pl_handler.c.