PostgreSQL Source Code  git master
pl_handler.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pl_handler.c - Handler for the PL/pgSQL
4  * procedural language
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/pl/plpgsql/src/pl_handler.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include "access/htup_details.h"
19 #include "catalog/pg_proc.h"
20 #include "catalog/pg_type.h"
21 #include "funcapi.h"
22 #include "miscadmin.h"
23 #include "plpgsql.h"
24 #include "utils/builtins.h"
25 #include "utils/guc.h"
26 #include "utils/lsyscache.h"
27 #include "utils/syscache.h"
28 #include "utils/varlena.h"
29 
30 static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source);
31 static void plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra);
32 static void plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra);
33 
35 
36 /* Custom GUC variable */
38  {"error", PLPGSQL_RESOLVE_ERROR, false},
39  {"use_variable", PLPGSQL_RESOLVE_VARIABLE, false},
40  {"use_column", PLPGSQL_RESOLVE_COLUMN, false},
41  {NULL, 0, false}
42 };
43 
45 
47 
49 
54 
55 /* Hook for plugins */
57 
58 
59 static bool
60 plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source)
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, "too_many_rows") == 0)
94  extrachecks |= PLPGSQL_XCHECK_TOOMANYROWS;
95  else if (pg_strcasecmp(tok, "strict_multi_assignment") == 0)
97  else if (pg_strcasecmp(tok, "all") == 0 || pg_strcasecmp(tok, "none") == 0)
98  {
99  GUC_check_errdetail("Key word \"%s\" cannot be combined with other key words.", tok);
100  pfree(rawstring);
101  list_free(elemlist);
102  return false;
103  }
104  else
105  {
106  GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
107  pfree(rawstring);
108  list_free(elemlist);
109  return false;
110  }
111  }
112 
113  pfree(rawstring);
114  list_free(elemlist);
115  }
116 
117  myextra = (int *) malloc(sizeof(int));
118  if (!myextra)
119  return false;
120  *myextra = extrachecks;
121  *extra = (void *) myextra;
122 
123  return true;
124 }
125 
126 static void
127 plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra)
128 {
129  plpgsql_extra_warnings = *((int *) extra);
130 }
131 
132 static void
133 plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra)
134 {
135  plpgsql_extra_errors = *((int *) extra);
136 }
137 
138 
139 /*
140  * _PG_init() - library load-time initialization
141  *
142  * DO NOT make this static nor change its name!
143  */
144 void
145 _PG_init(void)
146 {
147  /* Be sure we do initialization only once (should be redundant now) */
148  static bool inited = false;
149 
150  if (inited)
151  return;
152 
154 
155  DefineCustomEnumVariable("plpgsql.variable_conflict",
156  gettext_noop("Sets handling of conflicts between PL/pgSQL variable names and table column names."),
157  NULL,
160  variable_conflict_options,
161  PGC_SUSET, 0,
162  NULL, NULL, NULL);
163 
164  DefineCustomBoolVariable("plpgsql.print_strict_params",
165  gettext_noop("Print information about parameters in the DETAIL part of the error messages generated on INTO ... STRICT failures."),
166  NULL,
168  false,
169  PGC_USERSET, 0,
170  NULL, NULL, NULL);
171 
172  DefineCustomBoolVariable("plpgsql.check_asserts",
173  gettext_noop("Perform checks given in ASSERT statements."),
174  NULL,
176  true,
177  PGC_USERSET, 0,
178  NULL, NULL, NULL);
179 
180  DefineCustomStringVariable("plpgsql.extra_warnings",
181  gettext_noop("List of programming constructs that should produce a warning."),
182  NULL,
184  "none",
188  NULL);
189 
190  DefineCustomStringVariable("plpgsql.extra_errors",
191  gettext_noop("List of programming constructs that should produce an error."),
192  NULL,
194  "none",
198  NULL);
199 
200  EmitWarningsOnPlaceholders("plpgsql");
201 
205 
206  /* Set up a rendezvous point with optional instrumentation plugin */
207  plpgsql_plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin");
208 
209  inited = true;
210 }
211 
212 /* ----------
213  * plpgsql_call_handler
214  *
215  * The PostgreSQL function manager and trigger manager
216  * call this function for execution of PL/pgSQL procedures.
217  * ----------
218  */
220 
221 Datum
223 {
224  bool nonatomic;
225  PLpgSQL_function *func;
226  PLpgSQL_execstate *save_cur_estate;
227  ResourceOwner procedure_resowner;
228  volatile Datum retval = (Datum) 0;
229  int rc;
230 
231  nonatomic = fcinfo->context &&
232  IsA(fcinfo->context, CallContext) &&
233  !castNode(CallContext, fcinfo->context)->atomic;
234 
235  /*
236  * Connect to SPI manager
237  */
238  if ((rc = SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0)) != SPI_OK_CONNECT)
239  elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));
240 
241  /* Find or compile the function */
242  func = plpgsql_compile(fcinfo, false);
243 
244  /* Must save and restore prior value of cur_estate */
245  save_cur_estate = func->cur_estate;
246 
247  /* Mark the function as busy, so it can't be deleted from under us */
248  func->use_count++;
249 
250  /*
251  * If we'll need a procedure-lifespan resowner to execute any CALL or DO
252  * statements, create it now. Since this resowner is not tied to any
253  * parent, failing to free it would result in process-lifespan leaks.
254  * Therefore, be very wary of adding any code between here and the PG_TRY
255  * block.
256  */
257  procedure_resowner =
258  (nonatomic && func->requires_procedure_resowner) ?
259  ResourceOwnerCreate(NULL, "PL/pgSQL procedure resources") : NULL;
260 
261  PG_TRY();
262  {
263  /*
264  * Determine if called as function or trigger and call appropriate
265  * subhandler
266  */
267  if (CALLED_AS_TRIGGER(fcinfo))
269  (TriggerData *) fcinfo->context));
270  else if (CALLED_AS_EVENT_TRIGGER(fcinfo))
271  {
273  (EventTriggerData *) fcinfo->context);
274  /* there's no return value in this case */
275  }
276  else
277  retval = plpgsql_exec_function(func, fcinfo,
278  NULL, NULL,
279  procedure_resowner,
280  !nonatomic);
281  }
282  PG_FINALLY();
283  {
284  /* Decrement use-count, restore cur_estate */
285  func->use_count--;
286  func->cur_estate = save_cur_estate;
287 
288  /* Be sure to release the procedure resowner if any */
289  if (procedure_resowner)
290  {
291  ResourceOwnerReleaseAllPlanCacheRefs(procedure_resowner);
292  ResourceOwnerDelete(procedure_resowner);
293  }
294  }
295  PG_END_TRY();
296 
297  /*
298  * Disconnect from SPI manager
299  */
300  if ((rc = SPI_finish()) != SPI_OK_FINISH)
301  elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
302 
303  return retval;
304 }
305 
306 /* ----------
307  * plpgsql_inline_handler
308  *
309  * Called by PostgreSQL to execute an anonymous code block
310  * ----------
311  */
313 
314 Datum
316 {
317  LOCAL_FCINFO(fake_fcinfo, 0);
319  PLpgSQL_function *func;
320  FmgrInfo flinfo;
321  EState *simple_eval_estate;
322  ResourceOwner simple_eval_resowner;
323  Datum retval;
324  int rc;
325 
326  /*
327  * Connect to SPI manager
328  */
329  if ((rc = SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC)) != SPI_OK_CONNECT)
330  elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));
331 
332  /* Compile the anonymous code block */
333  func = plpgsql_compile_inline(codeblock->source_text);
334 
335  /* Mark the function as busy, just pro forma */
336  func->use_count++;
337 
338  /*
339  * Set up a fake fcinfo with just enough info to satisfy
340  * plpgsql_exec_function(). In particular note that this sets things up
341  * with no arguments passed.
342  */
343  MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
344  MemSet(&flinfo, 0, sizeof(flinfo));
345  fake_fcinfo->flinfo = &flinfo;
346  flinfo.fn_oid = InvalidOid;
347  flinfo.fn_mcxt = CurrentMemoryContext;
348 
349  /*
350  * Create a private EState and resowner for simple-expression execution.
351  * Notice that these are NOT tied to transaction-level resources; they
352  * must survive any COMMIT/ROLLBACK the DO block executes, since we will
353  * unconditionally try to clean them up below. (Hence, be wary of adding
354  * anything that could fail between here and the PG_TRY block.) See the
355  * comments for shared_simple_eval_estate.
356  *
357  * Because this resowner isn't tied to the calling transaction, we can
358  * also use it as the "procedure" resowner for any CALL statements. That
359  * helps reduce the opportunities for failure here.
360  */
361  simple_eval_estate = CreateExecutorState();
362  simple_eval_resowner =
363  ResourceOwnerCreate(NULL, "PL/pgSQL DO block simple expressions");
364 
365  /* And run the function */
366  PG_TRY();
367  {
368  retval = plpgsql_exec_function(func, fake_fcinfo,
369  simple_eval_estate,
370  simple_eval_resowner,
371  simple_eval_resowner, /* see above */
372  codeblock->atomic);
373  }
374  PG_CATCH();
375  {
376  /*
377  * We need to clean up what would otherwise be long-lived resources
378  * accumulated by the failed DO block, principally cached plans for
379  * statements (which can be flushed by plpgsql_free_function_memory),
380  * execution trees for simple expressions, which are in the private
381  * EState, and cached-plan refcounts held by the private resowner.
382  *
383  * Before releasing the private EState, we must clean up any
384  * simple_econtext_stack entries pointing into it, which we can do by
385  * invoking the subxact callback. (It will be called again later if
386  * some outer control level does a subtransaction abort, but no harm
387  * is done.) We cheat a bit knowing that plpgsql_subxact_cb does not
388  * pay attention to its parentSubid argument.
389  */
392  0, NULL);
393 
394  /* Clean up the private EState and resowner */
395  FreeExecutorState(simple_eval_estate);
396  ResourceOwnerReleaseAllPlanCacheRefs(simple_eval_resowner);
397  ResourceOwnerDelete(simple_eval_resowner);
398 
399  /* Function should now have no remaining use-counts ... */
400  func->use_count--;
401  Assert(func->use_count == 0);
402 
403  /* ... so we can free subsidiary storage */
405 
406  /* And propagate the error */
407  PG_RE_THROW();
408  }
409  PG_END_TRY();
410 
411  /* Clean up the private EState and resowner */
412  FreeExecutorState(simple_eval_estate);
413  ResourceOwnerReleaseAllPlanCacheRefs(simple_eval_resowner);
414  ResourceOwnerDelete(simple_eval_resowner);
415 
416  /* Function should now have no remaining use-counts ... */
417  func->use_count--;
418  Assert(func->use_count == 0);
419 
420  /* ... so we can free subsidiary storage */
422 
423  /*
424  * Disconnect from SPI manager
425  */
426  if ((rc = SPI_finish()) != SPI_OK_FINISH)
427  elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
428 
429  return retval;
430 }
431 
432 /* ----------
433  * plpgsql_validator
434  *
435  * This function attempts to validate a PL/pgSQL function at
436  * CREATE FUNCTION time.
437  * ----------
438  */
440 
441 Datum
443 {
444  Oid funcoid = PG_GETARG_OID(0);
445  HeapTuple tuple;
446  Form_pg_proc proc;
447  char functyptype;
448  int numargs;
449  Oid *argtypes;
450  char **argnames;
451  char *argmodes;
452  bool is_dml_trigger = false;
453  bool is_event_trigger = false;
454  int i;
455 
456  if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
457  PG_RETURN_VOID();
458 
459  /* Get the new function's pg_proc entry */
460  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
461  if (!HeapTupleIsValid(tuple))
462  elog(ERROR, "cache lookup failed for function %u", funcoid);
463  proc = (Form_pg_proc) GETSTRUCT(tuple);
464 
465  functyptype = get_typtype(proc->prorettype);
466 
467  /* Disallow pseudotype result */
468  /* except for TRIGGER, EVTTRIGGER, RECORD, VOID, or polymorphic */
469  if (functyptype == TYPTYPE_PSEUDO)
470  {
471  if (proc->prorettype == TRIGGEROID)
472  is_dml_trigger = true;
473  else if (proc->prorettype == EVENT_TRIGGEROID)
474  is_event_trigger = true;
475  else if (proc->prorettype != RECORDOID &&
476  proc->prorettype != VOIDOID &&
477  !IsPolymorphicType(proc->prorettype))
478  ereport(ERROR,
479  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
480  errmsg("PL/pgSQL functions cannot return type %s",
481  format_type_be(proc->prorettype))));
482  }
483 
484  /* Disallow pseudotypes in arguments (either IN or OUT) */
485  /* except for RECORD and polymorphic */
486  numargs = get_func_arg_info(tuple,
487  &argtypes, &argnames, &argmodes);
488  for (i = 0; i < numargs; i++)
489  {
490  if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO)
491  {
492  if (argtypes[i] != RECORDOID &&
493  !IsPolymorphicType(argtypes[i]))
494  ereport(ERROR,
495  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
496  errmsg("PL/pgSQL functions cannot accept type %s",
497  format_type_be(argtypes[i]))));
498  }
499  }
500 
501  /* Postpone body checks if !check_function_bodies */
503  {
504  LOCAL_FCINFO(fake_fcinfo, 0);
505  FmgrInfo flinfo;
506  int rc;
507  TriggerData trigdata;
508  EventTriggerData etrigdata;
509 
510  /*
511  * Connect to SPI manager (is this needed for compilation?)
512  */
513  if ((rc = SPI_connect()) != SPI_OK_CONNECT)
514  elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));
515 
516  /*
517  * Set up a fake fcinfo with just enough info to satisfy
518  * plpgsql_compile().
519  */
520  MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
521  MemSet(&flinfo, 0, sizeof(flinfo));
522  fake_fcinfo->flinfo = &flinfo;
523  flinfo.fn_oid = funcoid;
524  flinfo.fn_mcxt = CurrentMemoryContext;
525  if (is_dml_trigger)
526  {
527  MemSet(&trigdata, 0, sizeof(trigdata));
528  trigdata.type = T_TriggerData;
529  fake_fcinfo->context = (Node *) &trigdata;
530  }
531  else if (is_event_trigger)
532  {
533  MemSet(&etrigdata, 0, sizeof(etrigdata));
534  etrigdata.type = T_EventTriggerData;
535  fake_fcinfo->context = (Node *) &etrigdata;
536  }
537 
538  /* Test-compile the function */
539  plpgsql_compile(fake_fcinfo, true);
540 
541  /*
542  * Disconnect from SPI manager
543  */
544  if ((rc = SPI_finish()) != SPI_OK_FINISH)
545  elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
546  }
547 
548  ReleaseSysCache(tuple);
549 
550  PG_RETURN_VOID();
551 }
PLpgSQL_function * plpgsql_compile_inline(char *proc_source)
Definition: pl_comp.c:848
#define SPI_OK_CONNECT
Definition: spi.h:81
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:737
Definition: fmgr.h:56
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:40
#define IsA(nodeptr, _type_)
Definition: nodes.h:584
PG_FUNCTION_INFO_V1(plpgsql_call_handler)
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
MemoryContext fn_mcxt
Definition: fmgr.h:65
void plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
Definition: pl_exec.c:1147
#define TEXTDOMAIN
Definition: elog.h:158
int SPI_connect_ext(int options)
Definition: spi.c:104
Definition: guc.h:165
char * plpgsql_extra_warnings_string
Definition: pl_handler.c:50
int SPI_connect(void)
Definition: spi.c:98
#define castNode(_type_, nodeptr)
Definition: nodes.h:602
#define GUC_check_errdetail
Definition: guc.h:417
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT
Definition: plpgsql.h:1199
char * pstrdup(const char *in)
Definition: mcxt.c:1187
#define PLPGSQL_XCHECK_NONE
Definition: plpgsql.h:1196
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
int SPI_finish(void)
Definition: spi.c:185
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1268
void ResourceOwnerDelete(ResourceOwner owner)
Definition: resowner.c:723
void plpgsql_HashTableInit(void)
Definition: pl_comp.c:2588
#define PLPGSQL_XCHECK_SHADOWVAR
Definition: plpgsql.h:1197
#define gettext_noop(x)
Definition: c.h:1197
Definition: nodes.h:533
int plpgsql_extra_errors
Definition: pl_handler.c:53
int errcode(int sqlerrcode)
Definition: elog.c:694
char get_typtype(Oid typid)
Definition: lsyscache.c:2576
#define MemSet(start, val, len)
Definition: c.h:1008
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
bool check_function_bodies
Definition: guc.c:530
unsigned int Oid
Definition: postgres_ext.h:31
void ** find_rendezvous_variable(const char *varName)
Definition: dfmgr.c:671
void ResourceOwnerReleaseAllPlanCacheRefs(ResourceOwner owner)
Definition: resowner.c:704
bool requires_procedure_resowner
Definition: plpgsql.h:1022
Datum plpgsql_inline_handler(PG_FUNCTION_ARGS)
Definition: pl_handler.c:315
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:9085
Datum plpgsql_validator(PG_FUNCTION_ARGS)
Definition: pl_handler.c:442
char * plpgsql_extra_errors_string
Definition: pl_handler.c:51
GucSource
Definition: guc.h:105
#define malloc(a)
Definition: header.h:50
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
void pfree(void *pointer)
Definition: mcxt.c:1057
PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
Definition: pl_comp.c:136
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1025
bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
Definition: fmgr.c:2038
#define SPI_OPT_NONATOMIC
Definition: spi.h:99
unsigned long use_count
Definition: plpgsql.h:1026
Definition: guc.h:75
void EmitWarningsOnPlaceholders(const char *className)
Definition: guc.c:9113
int plpgsql_extra_warnings
Definition: pl_handler.c:52
const char * SPI_result_code_string(int code)
Definition: spi.c:1862
static const struct config_enum_entry variable_conflict_options[]
Definition: pl_handler.c:37
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3741
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define PLPGSQL_XCHECK_TOOMANYROWS
Definition: plpgsql.h:1198
void _PG_init(void)
Definition: pl_handler.c:145
PLpgSQL_plugin ** plpgsql_plugin_ptr
Definition: pl_handler.c:56
EState * CreateExecutorState(void)
Definition: execUtils.c:90
static void plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra)
Definition: pl_handler.c:127
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
#define PG_FINALLY()
Definition: elog.h:325
PG_MODULE_MAGIC
Definition: pl_handler.c:34
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:9060
uintptr_t Datum
Definition: postgres.h:367
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3582
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, EState *simple_eval_estate, ResourceOwner simple_eval_resowner, ResourceOwner procedure_resowner, bool atomic)
Definition: pl_exec.c:471
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:155
bool plpgsql_print_strict_params
Definition: pl_handler.c:46
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
int plpgsql_variable_conflict
Definition: pl_handler.c:44
#define PG_CATCH()
Definition: elog.h:318
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3527
static rewind_source * source
Definition: pg_rewind.c:79
static void plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra)
Definition: pl_handler.c:133
#define SPI_OK_FINISH
Definition: spi.h:82
#define PG_RE_THROW()
Definition: elog.h:349
#define DatumGetPointer(X)
Definition: postgres.h:549
int errmsg(const char *fmt,...)
Definition: elog.c:905
NodeTag type
Definition: trigger.h:32
void list_free(List *list)
Definition: list.c:1391
#define elog(elevel,...)
Definition: elog.h:227
int i
void pg_bindtextdomain(const char *domain)
Definition: miscinit.c:1683
void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: pl_exec.c:8372
static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source)
Definition: pl_handler.c:60
char * source_text
Definition: parsenodes.h:2931
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func, TriggerData *trigdata)
Definition: pl_exec.c:907
bool plpgsql_check_asserts
Definition: pl_handler.c:48
#define PG_TRY()
Definition: elog.h:308
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:8974
Definition: pg_list.h:50
Datum plpgsql_call_handler(PG_FUNCTION_ARGS)
Definition: pl_handler.c:222
#define PG_END_TRY()
Definition: elog.h:333
#define GUC_LIST_INPUT
Definition: guc.h:205
#define PLPGSQL_XCHECK_ALL
Definition: plpgsql.h:1200
void plpgsql_xact_cb(XactEvent event, void *arg)
Definition: pl_exec.c:8330
ResourceOwner ResourceOwnerCreate(ResourceOwner parent, const char *name)
Definition: resowner.c:425