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-2025, 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
30static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source);
31static void plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra);
32static 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
51static char *plpgsql_extra_errors_string = NULL;
54
55/* Hook for plugins */
57
58
59static bool
60plpgsql_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 *) guc_malloc(LOG, sizeof(int));
118 if (!myextra)
119 return false;
120 *myextra = extrachecks;
121 *extra = myextra;
122
123 return true;
124}
125
126static void
127plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra)
128{
129 plpgsql_extra_warnings = *((int *) extra);
130}
131
132static void
133plpgsql_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 */
144void
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,
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 MarkGUCPrefixReserved("plpgsql");
201
205
206 /* Set up a rendezvous point with optional instrumentation 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
221Datum
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 SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0);
239
240 /* Find or compile the function */
241 func = plpgsql_compile(fcinfo, false);
242
243 /* Must save and restore prior value of cur_estate */
244 save_cur_estate = func->cur_estate;
245
246 /* Mark the function as busy, so it can't be deleted from under us */
247 func->use_count++;
248
249 /*
250 * If we'll need a procedure-lifespan resowner to execute any CALL or DO
251 * statements, create it now. Since this resowner is not tied to any
252 * parent, failing to free it would result in process-lifespan leaks.
253 * Therefore, be very wary of adding any code between here and the PG_TRY
254 * block.
255 */
256 procedure_resowner =
257 (nonatomic && func->requires_procedure_resowner) ?
258 ResourceOwnerCreate(NULL, "PL/pgSQL procedure resources") : NULL;
259
260 PG_TRY();
261 {
262 /*
263 * Determine if called as function or trigger and call appropriate
264 * subhandler
265 */
266 if (CALLED_AS_TRIGGER(fcinfo))
268 (TriggerData *) fcinfo->context));
269 else if (CALLED_AS_EVENT_TRIGGER(fcinfo))
270 {
272 (EventTriggerData *) fcinfo->context);
273 /* there's no return value in this case */
274 }
275 else
276 retval = plpgsql_exec_function(func, fcinfo,
277 NULL, NULL,
278 procedure_resowner,
279 !nonatomic);
280 }
281 PG_FINALLY();
282 {
283 /* Decrement use-count, restore cur_estate */
284 func->use_count--;
285 func->cur_estate = save_cur_estate;
286
287 /* Be sure to release the procedure resowner if any */
288 if (procedure_resowner)
289 {
290 ReleaseAllPlanCacheRefsInOwner(procedure_resowner);
291 ResourceOwnerDelete(procedure_resowner);
292 }
293 }
294 PG_END_TRY();
295
296 /*
297 * Disconnect from SPI manager
298 */
299 if ((rc = SPI_finish()) != SPI_OK_FINISH)
300 elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
301
302 return retval;
303}
304
305/* ----------
306 * plpgsql_inline_handler
307 *
308 * Called by PostgreSQL to execute an anonymous code block
309 * ----------
310 */
312
313Datum
315{
316 LOCAL_FCINFO(fake_fcinfo, 0);
318 PLpgSQL_function *func;
319 FmgrInfo flinfo;
320 EState *simple_eval_estate;
321 ResourceOwner simple_eval_resowner;
322 Datum retval;
323 int rc;
324
325 /*
326 * Connect to SPI manager
327 */
328 SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC);
329
330 /* Compile the anonymous code block */
331 func = plpgsql_compile_inline(codeblock->source_text);
332
333 /* Mark the function as busy, just pro forma */
334 func->use_count++;
335
336 /*
337 * Set up a fake fcinfo with just enough info to satisfy
338 * plpgsql_exec_function(). In particular note that this sets things up
339 * with no arguments passed.
340 */
341 MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
342 MemSet(&flinfo, 0, sizeof(flinfo));
343 fake_fcinfo->flinfo = &flinfo;
344 flinfo.fn_oid = InvalidOid;
346
347 /*
348 * Create a private EState and resowner for simple-expression execution.
349 * Notice that these are NOT tied to transaction-level resources; they
350 * must survive any COMMIT/ROLLBACK the DO block executes, since we will
351 * unconditionally try to clean them up below. (Hence, be wary of adding
352 * anything that could fail between here and the PG_TRY block.) See the
353 * comments for shared_simple_eval_estate.
354 *
355 * Because this resowner isn't tied to the calling transaction, we can
356 * also use it as the "procedure" resowner for any CALL statements. That
357 * helps reduce the opportunities for failure here.
358 */
359 simple_eval_estate = CreateExecutorState();
360 simple_eval_resowner =
361 ResourceOwnerCreate(NULL, "PL/pgSQL DO block simple expressions");
362
363 /* And run the function */
364 PG_TRY();
365 {
366 retval = plpgsql_exec_function(func, fake_fcinfo,
367 simple_eval_estate,
368 simple_eval_resowner,
369 simple_eval_resowner, /* see above */
370 codeblock->atomic);
371 }
372 PG_CATCH();
373 {
374 /*
375 * We need to clean up what would otherwise be long-lived resources
376 * accumulated by the failed DO block, principally cached plans for
377 * statements (which can be flushed by plpgsql_free_function_memory),
378 * execution trees for simple expressions, which are in the private
379 * EState, and cached-plan refcounts held by the private resowner.
380 *
381 * Before releasing the private EState, we must clean up any
382 * simple_econtext_stack entries pointing into it, which we can do by
383 * invoking the subxact callback. (It will be called again later if
384 * some outer control level does a subtransaction abort, but no harm
385 * is done.) We cheat a bit knowing that plpgsql_subxact_cb does not
386 * pay attention to its parentSubid argument.
387 */
390 0, NULL);
391
392 /* Clean up the private EState and resowner */
393 FreeExecutorState(simple_eval_estate);
394 ReleaseAllPlanCacheRefsInOwner(simple_eval_resowner);
395 ResourceOwnerDelete(simple_eval_resowner);
396
397 /* Function should now have no remaining use-counts ... */
398 func->use_count--;
399 Assert(func->use_count == 0);
400
401 /* ... so we can free subsidiary storage */
403
404 /* And propagate the error */
405 PG_RE_THROW();
406 }
407 PG_END_TRY();
408
409 /* Clean up the private EState and resowner */
410 FreeExecutorState(simple_eval_estate);
411 ReleaseAllPlanCacheRefsInOwner(simple_eval_resowner);
412 ResourceOwnerDelete(simple_eval_resowner);
413
414 /* Function should now have no remaining use-counts ... */
415 func->use_count--;
416 Assert(func->use_count == 0);
417
418 /* ... so we can free subsidiary storage */
420
421 /*
422 * Disconnect from SPI manager
423 */
424 if ((rc = SPI_finish()) != SPI_OK_FINISH)
425 elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
426
427 return retval;
428}
429
430/* ----------
431 * plpgsql_validator
432 *
433 * This function attempts to validate a PL/pgSQL function at
434 * CREATE FUNCTION time.
435 * ----------
436 */
438
439Datum
441{
442 Oid funcoid = PG_GETARG_OID(0);
443 HeapTuple tuple;
444 Form_pg_proc proc;
445 char functyptype;
446 int numargs;
447 Oid *argtypes;
448 char **argnames;
449 char *argmodes;
450 bool is_dml_trigger = false;
451 bool is_event_trigger = false;
452 int i;
453
454 if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
456
457 /* Get the new function's pg_proc entry */
458 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
459 if (!HeapTupleIsValid(tuple))
460 elog(ERROR, "cache lookup failed for function %u", funcoid);
461 proc = (Form_pg_proc) GETSTRUCT(tuple);
462
463 functyptype = get_typtype(proc->prorettype);
464
465 /* Disallow pseudotype result */
466 /* except for TRIGGER, EVTTRIGGER, RECORD, VOID, or polymorphic */
467 if (functyptype == TYPTYPE_PSEUDO)
468 {
469 if (proc->prorettype == TRIGGEROID)
470 is_dml_trigger = true;
471 else if (proc->prorettype == EVENT_TRIGGEROID)
472 is_event_trigger = true;
473 else if (proc->prorettype != RECORDOID &&
474 proc->prorettype != VOIDOID &&
475 !IsPolymorphicType(proc->prorettype))
477 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
478 errmsg("PL/pgSQL functions cannot return type %s",
479 format_type_be(proc->prorettype))));
480 }
481
482 /* Disallow pseudotypes in arguments (either IN or OUT) */
483 /* except for RECORD and polymorphic */
484 numargs = get_func_arg_info(tuple,
485 &argtypes, &argnames, &argmodes);
486 for (i = 0; i < numargs; i++)
487 {
488 if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO)
489 {
490 if (argtypes[i] != RECORDOID &&
491 !IsPolymorphicType(argtypes[i]))
493 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
494 errmsg("PL/pgSQL functions cannot accept type %s",
495 format_type_be(argtypes[i]))));
496 }
497 }
498
499 /* Postpone body checks if !check_function_bodies */
501 {
502 LOCAL_FCINFO(fake_fcinfo, 0);
503 FmgrInfo flinfo;
504 int rc;
505 TriggerData trigdata;
506 EventTriggerData etrigdata;
507
508 /*
509 * Connect to SPI manager (is this needed for compilation?)
510 */
511 SPI_connect();
512
513 /*
514 * Set up a fake fcinfo with just enough info to satisfy
515 * plpgsql_compile().
516 */
517 MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
518 MemSet(&flinfo, 0, sizeof(flinfo));
519 fake_fcinfo->flinfo = &flinfo;
520 flinfo.fn_oid = funcoid;
522 if (is_dml_trigger)
523 {
524 MemSet(&trigdata, 0, sizeof(trigdata));
525 trigdata.type = T_TriggerData;
526 fake_fcinfo->context = (Node *) &trigdata;
527 }
528 else if (is_event_trigger)
529 {
530 MemSet(&etrigdata, 0, sizeof(etrigdata));
531 etrigdata.type = T_EventTriggerData;
532 fake_fcinfo->context = (Node *) &etrigdata;
533 }
534
535 /* Test-compile the function */
536 plpgsql_compile(fake_fcinfo, true);
537
538 /*
539 * Disconnect from SPI manager
540 */
541 if ((rc = SPI_finish()) != SPI_OK_FINISH)
542 elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
543 }
544
545 ReleaseSysCache(tuple);
546
548}
#define gettext_noop(x)
Definition: c.h:1150
#define Assert(condition)
Definition: c.h:812
#define MemSet(start, val, len)
Definition: c.h:974
void ** find_rendezvous_variable(const char *varName)
Definition: dfmgr.c:593
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define PG_RE_THROW()
Definition: elog.h:412
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define ERROR
Definition: elog.h:39
#define PG_CATCH(...)
Definition: elog.h:381
#define TEXTDOMAIN
Definition: elog.h:152
#define elog(elevel,...)
Definition: elog.h:225
#define PG_FINALLY(...)
Definition: elog.h:388
#define ereport(elevel,...)
Definition: elog.h:149
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:49
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
EState * CreateExecutorState(void)
Definition: execUtils.c:88
bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
Definition: fmgr.c:2145
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1379
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:5243
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:5218
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:638
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:5132
void MarkGUCPrefixReserved(const char *className)
Definition: guc.c:5279
#define GUC_check_errdetail
Definition: guc.h:476
#define GUC_LIST_INPUT
Definition: guc.h:210
GucSource
Definition: guc.h:108
@ PGC_SUSET
Definition: guc.h:74
@ PGC_USERSET
Definition: guc.h:75
bool check_function_bodies
Definition: guc_tables.c:511
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
int i
Definition: isn.c:72
void list_free(List *list)
Definition: list.c:1546
char get_typtype(Oid typid)
Definition: lsyscache.c:2629
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void pg_bindtextdomain(const char *domain)
Definition: miscinit.c:1936
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define lfirst(lc)
Definition: pg_list.h:172
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static rewind_source * source
Definition: pg_rewind.c:89
void plpgsql_HashTableInit(void)
Definition: pl_comp.c:2607
PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
Definition: pl_comp.c:135
PLpgSQL_function * plpgsql_compile_inline(char *proc_source)
Definition: pl_comp.c:850
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:477
HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func, TriggerData *trigdata)
Definition: pl_exec.c:919
void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: pl_exec.c:8524
void plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
Definition: pl_exec.c:1159
void plpgsql_xact_cb(XactEvent event, void *arg)
Definition: pl_exec.c:8482
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:727
int plpgsql_variable_conflict
Definition: pl_handler.c:44
static void plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra)
Definition: pl_handler.c:133
bool plpgsql_check_asserts
Definition: pl_handler.c:48
static const struct config_enum_entry variable_conflict_options[]
Definition: pl_handler.c:37
int plpgsql_extra_warnings
Definition: pl_handler.c:52
Datum plpgsql_call_handler(PG_FUNCTION_ARGS)
Definition: pl_handler.c:222
void _PG_init(void)
Definition: pl_handler.c:145
static char * plpgsql_extra_errors_string
Definition: pl_handler.c:51
Datum plpgsql_inline_handler(PG_FUNCTION_ARGS)
Definition: pl_handler.c:314
PG_FUNCTION_INFO_V1(plpgsql_call_handler)
PG_MODULE_MAGIC
Definition: pl_handler.c:34
bool plpgsql_print_strict_params
Definition: pl_handler.c:46
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:127
int plpgsql_extra_errors
Definition: pl_handler.c:53
static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source)
Definition: pl_handler.c:60
static char * plpgsql_extra_warnings_string
Definition: pl_handler.c:50
Datum plpgsql_validator(PG_FUNCTION_ARGS)
Definition: pl_handler.c:440
void ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner)
Definition: plancache.c:2232
#define PLPGSQL_XCHECK_SHADOWVAR
Definition: plpgsql.h:1204
#define PLPGSQL_XCHECK_ALL
Definition: plpgsql.h:1207
@ PLPGSQL_RESOLVE_COLUMN
Definition: plpgsql.h:187
@ PLPGSQL_RESOLVE_ERROR
Definition: plpgsql.h:185
@ PLPGSQL_RESOLVE_VARIABLE
Definition: plpgsql.h:186
#define PLPGSQL_XCHECK_NONE
Definition: plpgsql.h:1203
#define PLPGSQL_XCHECK_TOOMANYROWS
Definition: plpgsql.h:1205
#define PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT
Definition: plpgsql.h:1206
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
ResourceOwner ResourceOwnerCreate(ResourceOwner parent, const char *name)
Definition: resowner.c:413
void ResourceOwnerDelete(ResourceOwner owner)
Definition: resowner.c:854
const char * SPI_result_code_string(int code)
Definition: spi.c:1972
int SPI_connect(void)
Definition: spi.c:94
int SPI_finish(void)
Definition: spi.c:182
int SPI_connect_ext(int options)
Definition: spi.c:100
#define SPI_OPT_NONATOMIC
Definition: spi.h:102
#define SPI_OK_FINISH
Definition: spi.h:83
Definition: fmgr.h:57
MemoryContext fn_mcxt
Definition: fmgr.h:65
Oid fn_oid
Definition: fmgr.h:59
char * source_text
Definition: parsenodes.h:3516
Definition: pg_list.h:54
Definition: nodes.h:129
bool requires_procedure_resowner
Definition: plpgsql.h:1011
unsigned long use_count
Definition: plpgsql.h:1015
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1014
NodeTag type
Definition: trigger.h:33
Definition: guc.h:170
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:26
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3432
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:790
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3796
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3856
@ SUBXACT_EVENT_ABORT_SUB
Definition: xact.h:144