PostgreSQL Source Code git master
Loading...
Searching...
No Matches
plpy_procedure.c
Go to the documentation of this file.
1/*
2 * Python procedure manipulation for plpython
3 *
4 * src/pl/plpython/plpy_procedure.c
5 */
6
7#include "postgres.h"
8
9#include "catalog/pg_proc.h"
10#include "catalog/pg_type.h"
12#include "commands/trigger.h"
13#include "funcapi.h"
14#include "plpy_elog.h"
15#include "plpy_exec.h"
16#include "plpy_main.h"
17#include "plpy_procedure.h"
18#include "plpy_util.h"
19#include "utils/builtins.h"
20#include "utils/funccache.h"
21#include "utils/syscache.h"
22
23static void PLy_procedure_create(PLyProcedure *proc,
25 Oid fn_oid,
26 PLyTrigType is_trigger);
27static char *PLy_procedure_munge_source(const char *name, const char *src);
28static void PLy_compile_callback(FunctionCallInfo fcinfo,
31 CachedFunction *cfunc,
32 bool forValidator);
33static void PLy_delete_callback(CachedFunction *cfunc);
34static void RemovePLyProcedureCache(void *arg);
35
36
37/*
38 * PLy_procedure_name: get the name of the specified procedure.
39 *
40 * NB: this returns the SQL name, not the internal Python procedure name
41 */
42char *
44{
45 if (proc == NULL)
46 return "<unknown procedure>";
47 return proc->proname;
48}
49
50/*
51 * PLy_procedure_get: returns a PLyProcedureCache struct for the function,
52 * making it valid if necessary.
53 *
54 * The PLyProcedureCache contains a pointer to the long-lived PLyProcedure
55 * (managed by funccache.c) and execution-specific state like SRF state.
56 *
57 * For SRFs, if we are resuming execution (srfstate->iter != NULL), we skip
58 * revalidation and continue using the same PLyProcedure to ensure consistent
59 * behavior throughout the SRF execution.
60 */
63{
64 FmgrInfo *finfo = fcinfo->flinfo;
66 PLyProcedure *proc;
67
68 /*
69 * If this is the first execution for this FmgrInfo, set up a cache struct
70 * (initially containing null pointers). The cache must live as long as
71 * the FmgrInfo, so it goes in fn_mcxt. Also set up a memory context
72 * callback that will be invoked when fn_mcxt is reset/deleted.
73 */
74 pcache = finfo->fn_extra;
75 if (pcache == NULL)
76 {
79
80 pcache->fcontext = finfo->fn_mcxt;
82 pcache->mcb.arg = pcache;
83
85
86 finfo->fn_extra = pcache;
87 }
88
89 /*
90 * If we are resuming execution of a set-returning function, just keep
91 * using the same cache. We do not ask funccache.c to re-validate the
92 * PLyProcedure: we want to run to completion using the function's initial
93 * definition.
94 *
95 * A live iterator (srfstate->iter != NULL) reliably means a genuine
96 * resume: when an iteration ends for any reason, srfstate->iter is reset
97 * to NULL (see comments for PLy_function_cleanup_srfstate).
98 */
99 if (pcache->srfstate != NULL && pcache->srfstate->iter != NULL)
100 {
101 Assert(pcache->proc != NULL);
102 return pcache;
103 }
104
105 /*
106 * Look up, or re-validate, the long-lived hash entry. Like SQL-language
107 * functions, make the hash key depend on the result of
108 * get_call_result_type() when that's composite, so that we can safely
109 * assume that we'll build a new hash entry if the composite rowtype
110 * changes.
111 */
112 proc = (PLyProcedure *)
114 (CachedFunction *) pcache->proc,
117 sizeof(PLyProcedure),
118 true,
120
121 /*
122 * Install the hash pointer in the PLyProcedureCache, and increment its
123 * use count to reflect that. If cached_function_compile gave us back a
124 * different hash entry than we were using before, we must decrement that
125 * one's use count.
126 */
127 if (proc != pcache->proc)
128 {
129 if (pcache->proc != NULL)
130 {
131 Assert(pcache->proc->cfunc.use_count > 0);
132 pcache->proc->cfunc.use_count--;
133 }
134 pcache->proc = proc;
135 proc->cfunc.use_count++;
136 }
137
138 return pcache;
139}
140
141/*
142 * Create (well, fill in) a new PLyProcedure structure
143 */
144static void
147 Oid fn_oid,
148 PLyTrigType is_trigger)
149{
150 char procName[NAMEDATALEN + 256];
152 MemoryContext cxt;
154 int rv;
155 char *ptr;
156
158 rv = snprintf(procName, sizeof(procName),
159 "__plpython_procedure_%s_%u",
160 NameStr(procStruct->proname),
161 fn_oid);
162 if (rv >= sizeof(procName) || rv < 0)
163 elog(ERROR, "procedure name would overrun buffer");
164
165 /* Replace any not-legal-in-Python-names characters with '_' */
166 for (ptr = procName; *ptr; ptr++)
167 {
168 if (!((*ptr >= 'A' && *ptr <= 'Z') ||
169 (*ptr >= 'a' && *ptr <= 'z') ||
170 (*ptr >= '0' && *ptr <= '9')))
171 *ptr = '_';
172 }
173
174 /* Create long-lived context that all procedure info will live in */
176 "PL/Python function",
178
180
181 proc->mcxt = cxt;
182
183 PG_TRY();
184 {
187 bool isnull;
188 char *procSource;
189 int i;
190
191 proc->proname = pstrdup(NameStr(procStruct->proname));
193 proc->pyname = pstrdup(procName);
194 proc->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
195 proc->is_setof = procStruct->proretset;
196 proc->is_procedure = (procStruct->prokind == PROKIND_PROCEDURE);
197 proc->is_trigger = is_trigger;
198 proc->src = NULL;
199 proc->argnames = NULL;
200 proc->args = NULL;
201 proc->nargs = 0;
202 proc->langid = procStruct->prolang;
205 &isnull);
207 proc->code = NULL;
208 proc->statics = NULL;
209 proc->globals = NULL;
210 proc->calldepth = 0;
211 proc->argstack = NULL;
212
213 /*
214 * get information required for output conversion of the return value,
215 * but only if this isn't a trigger.
216 */
217 if (is_trigger == PLPY_NOT_TRIGGER)
218 {
219 Oid rettype = procStruct->prorettype;
222
225 elog(ERROR, "cache lookup failed for type %u", rettype);
227
228 /* Disallow pseudotype result, except for void or record */
229 if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
230 {
231 if (rettype == VOIDOID ||
232 rettype == RECORDOID)
233 /* okay */ ;
234 else if (rettype == TRIGGEROID || rettype == EVENT_TRIGGEROID)
237 errmsg("trigger functions can only be called as triggers")));
238 else
241 errmsg("PL/Python functions cannot return type %s",
242 format_type_be(rettype))));
243 }
244
245 /* set up output function for procedure result */
246 PLy_output_setup_func(&proc->result, proc->mcxt,
247 rettype, -1, proc);
248
250 }
251 else
252 {
253 /*
254 * In a trigger function, we use proc->result and proc->result_in
255 * for converting tuples, but we don't yet have enough info to set
256 * them up. PLy_exec_trigger will deal with it.
257 */
258 proc->result.typoid = InvalidOid;
260 }
261
262 /*
263 * Now get information required for input conversion of the
264 * procedure's arguments. Note that we ignore output arguments here.
265 * If the function returns record, those I/O functions will be set up
266 * when the function is first called.
267 */
268 if (procStruct->pronargs)
269 {
270 Oid *types;
271 char **names,
272 *modes;
273 int pos,
274 total;
275
276 /* extract argument type info from the pg_proc tuple */
277 total = get_func_arg_info(procTup, &types, &names, &modes);
278
279 /* count number of in+inout args into proc->nargs */
280 if (modes == NULL)
281 proc->nargs = total;
282 else
283 {
284 /* proc->nargs was initialized to 0 above */
285 for (i = 0; i < total; i++)
286 {
287 if (modes[i] != PROARGMODE_OUT &&
289 (proc->nargs)++;
290 }
291 }
292
293 /* Allocate arrays for per-input-argument data */
294 proc->argnames = (char **) palloc0_array(char *, proc->nargs);
296
297 for (i = pos = 0; i < total; i++)
298 {
301
302 if (modes &&
303 (modes[i] == PROARGMODE_OUT ||
305 continue; /* skip OUT arguments */
306
307 Assert(types[i] == procStruct->proargtypes.values[pos]);
308
312 elog(ERROR, "cache lookup failed for type %u", types[i]);
314
315 /* disallow pseudotype arguments */
316 if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
319 errmsg("PL/Python functions cannot accept type %s",
321
322 /* set up I/O function info */
323 PLy_input_setup_func(&proc->args[pos], proc->mcxt,
324 types[i], -1, /* typmod not known */
325 proc);
326
327 /* get argument name */
328 proc->argnames[pos] = names ? pstrdup(names[i]) : NULL;
329
331
332 pos++;
333 }
334 }
335
336 /*
337 * get the text of the function.
338 */
342
344
346 }
347 PG_CATCH();
348 {
351 PG_RE_THROW();
352 }
353 PG_END_TRY();
354
356}
357
358/*
359 * Insert the procedure into the Python interpreter
360 */
361void
362PLy_procedure_compile(PLyProcedure *proc, const char *src)
363{
364 PyObject *crv = NULL;
365 char *msrc;
367
369
370 /*
371 * SD is private preserved data between calls. GD is global data shared by
372 * all functions
373 */
374 proc->statics = PyDict_New();
375 if (!proc->statics)
377 PyDict_SetItemString(proc->globals, "SD", proc->statics);
378
379 /*
380 * insert the function code into the interpreter
381 */
383 /* Save the mangled source for later inclusion in tracebacks */
384 proc->src = MemoryContextStrdup(proc->mcxt, msrc);
386 if (code0)
388 pfree(msrc);
389
390 if (crv != NULL)
391 {
392 int clen;
393 char call[NAMEDATALEN + 256];
394
395 Py_DECREF(crv);
396
397 /*
398 * compile a call to the function
399 */
400 clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
401 if (clen < 0 || clen >= sizeof(call))
402 elog(ERROR, "string would overflow buffer");
403 proc->code = Py_CompileString(call, "<string>", Py_eval_input);
404 if (proc->code != NULL)
405 return;
406 }
407
408 if (proc->proname)
409 PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
410 proc->proname);
411 else
412 PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
413}
414
415void
417{
418 Py_XDECREF(proc->code);
419 Py_XDECREF(proc->statics);
420 Py_XDECREF(proc->globals);
422}
423
424static char *
425PLy_procedure_munge_source(const char *name, const char *src)
426{
427 char *mrc,
428 *mp;
429 const char *sp;
430 size_t mlen;
431 int plen;
432
433 /*
434 * room for function source and the def statement
435 */
436 mlen = (strlen(src) * 2) + strlen(name) + 16;
437
438 mrc = palloc(mlen);
439 plen = snprintf(mrc, mlen, "def %s():\n\t", name);
440 Assert(plen >= 0 && plen < mlen);
441
442 sp = src;
443 mp = mrc + plen;
444
445 while (*sp != '\0')
446 {
447 if (*sp == '\r' && *(sp + 1) == '\n')
448 sp++;
449
450 if (*sp == '\n' || *sp == '\r')
451 {
452 *mp++ = '\n';
453 *mp++ = '\t';
454 sp++;
455 }
456 else
457 *mp++ = *sp++;
458 }
459 *mp++ = '\n';
460 *mp++ = '\n';
461 *mp = '\0';
462
463 if (mp > (mrc + mlen))
464 elog(FATAL, "buffer overrun in PLy_procedure_munge_source");
465
466 return mrc;
467}
468
469/*
470 * Compile callback for funccache.c.
471 *
472 * cached_function_compile() calls this when it needs to (re)compile the
473 * long-lived PLyProcedure for a function. The CachedFunction handed to us is
474 * pre-zeroed workspace of size sizeof(PLyProcedure); we just have to fill in
475 * the PL/Python-specific fields.
476 */
477static void
481 CachedFunction *cfunc,
482 bool forValidator)
483{
484 PLyProcedure *proc = (PLyProcedure *) cfunc;
485 Oid fn_oid = fcinfo->flinfo->fn_oid;
486 PLyTrigType is_trigger;
487
488 /*
489 * Derive the trigger type from the call context, matching what
490 * plpython3_call_handler dispatches on.
491 */
492 if (CALLED_AS_TRIGGER(fcinfo))
493 is_trigger = PLPY_TRIGGER;
494 else if (CALLED_AS_EVENT_TRIGGER(fcinfo))
495 is_trigger = PLPY_EVENT_TRIGGER;
496 else
497 is_trigger = PLPY_NOT_TRIGGER;
498
499 PLy_procedure_create(proc, procTup, fn_oid, is_trigger);
500}
501
502/*
503 * Deletion callback for funccache.c.
504 *
505 * cached_function_compile() calls this when it discards a cache entry, which
506 * only happens once the entry's use count has dropped to zero. We must free
507 * the subsidiary data but not the CachedFunction struct itself.
508 */
509static void
511{
512 PLyProcedure *proc = (PLyProcedure *) cfunc;
513
514 Assert(proc->cfunc.use_count == 0);
515 Assert(proc->calldepth == 0);
516
518}
519
520/*
521 * MemoryContext callback function
522 *
523 * We register this in the memory context that contains a PLyProcedureCache
524 * struct (that is, the FmgrInfo's fn_mcxt). When the memory context is reset
525 * or deleted, we release the reference count (if any) that the cache holds on
526 * the long-lived hash entry. Note that this will happen even during error
527 * aborts.
528 *
529 * This is also our opportunity to release the Python references held by an
530 * interrupted set-returning function. ShutdownPLyFunction() handles that for
531 * routine in-query cancellation cases, but it does not run during an error
532 * abort; this callback does, so it is the backstop that prevents leaking the
533 * SRF's iterator and saved arguments when a query errors out mid-iteration.
534 */
535static void
537{
539
540 /* Release any Python state left behind by an interrupted SRF */
542
543 /* Release reference count on PLyProcedure */
544 if (pcache->proc != NULL)
545 {
546 Assert(pcache->proc->cfunc.use_count > 0);
547 pcache->proc->cfunc.use_count--;
548 pcache->proc = NULL;
549 }
550
551 /* We needn't free the pcache object itself, context cleanup does that */
552}
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:894
#define Assert(condition)
Definition c.h:1002
struct typedefs * types
Definition ecpg.c:30
Datum arg
Definition elog.c:1323
int errcode(int sqlerrcode)
Definition elog.c:875
#define PG_RE_THROW()
Definition elog.h:407
#define FATAL
Definition elog.h:42
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define ERROR
Definition elog.h:40
#define PG_CATCH(...)
Definition elog.h:384
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
#define palloc0_array(type, count)
Definition fe_memutils.h:92
char * format_type_be(Oid type_oid)
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition funcapi.c:1382
CachedFunction * cached_function_compile(FunctionCallInfo fcinfo, CachedFunction *function, CachedFunctionCompileCallback ccallback, CachedFunctionDeleteCallback dcallback, Size cacheEntrySize, bool includeResultType, bool forValidator)
Definition funccache.c:480
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
int i
Definition isn.c:77
#define PLy_elog
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1897
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
char * pstrdup(const char *in)
Definition mcxt.c:1910
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition mcxt.c:585
void pfree(void *pointer)
Definition mcxt.c:1619
MemoryContext TopMemoryContext
Definition mcxt.c:167
void * palloc(Size size)
Definition mcxt.c:1390
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:475
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition mcxt.c:664
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
#define NAMEDATALEN
#define NIL
Definition pg_list.h:68
List * oid_array_to_list(Datum datum)
Definition pg_proc.c:1230
END_CATALOG_STRUCT typedef FormData_pg_proc * Form_pg_proc
Definition pg_proc.h:140
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
void PLy_function_cleanup_srfstate(PLyProcedureCache *pcache)
Definition plpy_exec.c:357
PyObject * PLy_interp_globals
Definition plpy_main.c:46
char * PLy_procedure_name(PLyProcedure *proc)
static void PLy_procedure_create(PLyProcedure *proc, HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
static void PLy_compile_callback(FunctionCallInfo fcinfo, HeapTuple procTup, const CachedFunctionHashKey *hashkey, CachedFunction *cfunc, bool forValidator)
PLyProcedureCache * PLy_procedure_get(FunctionCallInfo fcinfo, bool forValidator)
static void PLy_delete_callback(CachedFunction *cfunc)
static char * PLy_procedure_munge_source(const char *name, const char *src)
static void RemovePLyProcedureCache(void *arg)
void PLy_procedure_compile(PLyProcedure *proc, const char *src)
void PLy_procedure_delete(PLyProcedure *proc)
PLyTrigType
@ PLPY_EVENT_TRIGGER
@ PLPY_TRIGGER
@ PLPY_NOT_TRIGGER
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
#define snprintf
Definition port.h:261
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
#define InvalidOid
unsigned int Oid
static int fb(int x)
uint64 use_count
Definition funccache.h:117
void * fn_extra
Definition fmgr.h:64
MemoryContext fn_mcxt
Definition fmgr.h:65
Oid fn_oid
Definition fmgr.h:59
FmgrInfo * flinfo
Definition fmgr.h:87
PLyDatumToOb * args
PLyTrigType is_trigger
PLyObToDatum result
PyObject * code
PLyDatumToOb result_in
PLySavedArgs * argstack
MemoryContext mcxt
CachedFunction cfunc
PyObject * globals
PyObject * statics
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
#define CALLED_AS_TRIGGER(fcinfo)
Definition trigger.h:26
const char * name