PostgreSQL Source Code  git master
plpy_main.c
Go to the documentation of this file.
1 /*
2  * PL/Python main entry points
3  *
4  * src/pl/plpython/plpy_main.c
5  */
6 
7 #include "postgres.h"
8 
9 #include "access/htup_details.h"
10 #include "catalog/pg_proc.h"
11 #include "catalog/pg_type.h"
12 #include "commands/trigger.h"
13 #include "executor/spi.h"
14 #include "miscadmin.h"
15 #include "plpy_elog.h"
16 #include "plpy_exec.h"
17 #include "plpy_main.h"
18 #include "plpy_plpymodule.h"
19 #include "plpy_procedure.h"
20 #include "plpy_subxactobject.h"
21 #include "plpython.h"
22 #include "utils/guc.h"
23 #include "utils/memutils.h"
24 #include "utils/rel.h"
25 #include "utils/syscache.h"
26 
27 /*
28  * exported functions
29  */
30 
31 #if PY_MAJOR_VERSION >= 3
32 /* Use separate names to avoid clash in pg_pltemplate */
33 #define plpython_validator plpython3_validator
34 #define plpython_call_handler plpython3_call_handler
35 #define plpython_inline_handler plpython3_inline_handler
36 #endif
37 
38 extern void _PG_init(void);
39 
41 
45 
46 #if PY_MAJOR_VERSION < 3
47 /* Define aliases plpython2_call_handler etc */
51 #endif
52 
53 
54 static bool PLy_procedure_is_trigger(Form_pg_proc procStruct);
55 static void plpython_error_callback(void *arg);
56 static void plpython_inline_error_callback(void *arg);
57 static void PLy_init_interp(void);
58 
59 static PLyExecutionContext *PLy_push_execution_context(bool atomic_context);
60 static void PLy_pop_execution_context(void);
61 
62 /* static state for Python library conflict detection */
63 static int *plpython_version_bitmask_ptr = NULL;
64 static int plpython_version_bitmask = 0;
65 
66 /* initialize global variables */
67 PyObject *PLy_interp_globals = NULL;
68 
69 /* this doesn't need to be global; use PLy_current_execution_context() */
71 
72 
73 void
74 _PG_init(void)
75 {
76  int **bitmask_ptr;
77 
78  /*
79  * Set up a shared bitmask variable telling which Python version(s) are
80  * loaded into this process's address space. If there's more than one, we
81  * cannot call into libpython for fear of causing crashes. But postpone
82  * the actual failure for later, so that operations like pg_restore can
83  * load more than one plpython library so long as they don't try to do
84  * anything much with the language.
85  */
86  bitmask_ptr = (int **) find_rendezvous_variable("plpython_version_bitmask");
87  if (!(*bitmask_ptr)) /* am I the first? */
88  *bitmask_ptr = &plpython_version_bitmask;
89  /* Retain pointer to the agreed-on shared variable ... */
90  plpython_version_bitmask_ptr = *bitmask_ptr;
91  /* ... and announce my presence */
92  *plpython_version_bitmask_ptr |= (1 << PY_MAJOR_VERSION);
93 
94  /*
95  * This should be safe even in the presence of conflicting plpythons, and
96  * it's necessary to do it before possibly throwing a conflict error, or
97  * the error message won't get localized.
98  */
100 }
101 
102 /*
103  * Perform one-time setup of PL/Python, after checking for a conflict
104  * with other versions of Python.
105  */
106 static void
108 {
109  static bool inited = false;
110 
111  /*
112  * Check for multiple Python libraries before actively doing anything with
113  * libpython. This must be repeated on each entry to PL/Python, in case a
114  * conflicting library got loaded since we last looked.
115  *
116  * It is attractive to weaken this error from FATAL to ERROR, but there
117  * would be corner cases, so it seems best to be conservative.
118  */
119  if (*plpython_version_bitmask_ptr != (1 << PY_MAJOR_VERSION))
120  ereport(FATAL,
121  (errmsg("multiple Python libraries are present in session"),
122  errdetail("Only one Python major version can be used in one session.")));
123 
124  /* The rest should only be done once per session */
125  if (inited)
126  return;
127 
128 #if PY_MAJOR_VERSION >= 3
129  PyImport_AppendInittab("plpy", PyInit_plpy);
130 #endif
131  Py_Initialize();
132 #if PY_MAJOR_VERSION >= 3
133  PyImport_ImportModule("plpy");
134 #endif
135  PLy_init_interp();
136  PLy_init_plpy();
137  if (PyErr_Occurred())
138  PLy_elog(FATAL, "untrapped error in initialization");
139 
141 
143 
144  PLy_execution_contexts = NULL;
145 
146  inited = true;
147 }
148 
149 /*
150  * This should be called only once, from PLy_initialize. Initialize the Python
151  * interpreter and global data.
152  */
153 static void
155 {
156  static PyObject *PLy_interp_safe_globals = NULL;
157  PyObject *mainmod;
158 
159  mainmod = PyImport_AddModule("__main__");
160  if (mainmod == NULL || PyErr_Occurred())
161  PLy_elog(ERROR, "could not import \"__main__\" module");
162  Py_INCREF(mainmod);
163  PLy_interp_globals = PyModule_GetDict(mainmod);
164  PLy_interp_safe_globals = PyDict_New();
165  if (PLy_interp_safe_globals == NULL)
166  PLy_elog(ERROR, NULL);
167  PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
168  Py_DECREF(mainmod);
169  if (PLy_interp_globals == NULL || PyErr_Occurred())
170  PLy_elog(ERROR, "could not initialize globals");
171 }
172 
173 Datum
175 {
176  Oid funcoid = PG_GETARG_OID(0);
177  HeapTuple tuple;
178  Form_pg_proc procStruct;
179  bool is_trigger;
180 
181  if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
182  PG_RETURN_VOID();
183 
185  PG_RETURN_VOID();
186 
187  /* Do this only after making sure we need to do something */
188  PLy_initialize();
189 
190  /* Get the new function's pg_proc entry */
191  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
192  if (!HeapTupleIsValid(tuple))
193  elog(ERROR, "cache lookup failed for function %u", funcoid);
194  procStruct = (Form_pg_proc) GETSTRUCT(tuple);
195 
196  is_trigger = PLy_procedure_is_trigger(procStruct);
197 
198  ReleaseSysCache(tuple);
199 
200  /* We can't validate triggers against any particular table ... */
201  PLy_procedure_get(funcoid, InvalidOid, is_trigger);
202 
203  PG_RETURN_VOID();
204 }
205 
206 #if PY_MAJOR_VERSION < 3
207 Datum
209 {
210  /* call plpython validator with our fcinfo so it gets our oid */
211  return plpython_validator(fcinfo);
212 }
213 #endif /* PY_MAJOR_VERSION < 3 */
214 
215 Datum
217 {
218  bool nonatomic;
219  Datum retval;
220  PLyExecutionContext *exec_ctx;
221  ErrorContextCallback plerrcontext;
222 
223  PLy_initialize();
224 
225  nonatomic = fcinfo->context &&
226  IsA(fcinfo->context, CallContext) &&
227  !castNode(CallContext, fcinfo->context)->atomic;
228 
229  /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
230  if (SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0) != SPI_OK_CONNECT)
231  elog(ERROR, "SPI_connect failed");
232 
233  /*
234  * Push execution context onto stack. It is important that this get
235  * popped again, so avoid putting anything that could throw error between
236  * here and the PG_TRY.
237  */
238  exec_ctx = PLy_push_execution_context(!nonatomic);
239 
240  PG_TRY();
241  {
242  Oid funcoid = fcinfo->flinfo->fn_oid;
243  PLyProcedure *proc;
244 
245  /*
246  * Setup error traceback support for ereport(). Note that the PG_TRY
247  * structure pops this for us again at exit, so we needn't do that
248  * explicitly, nor do we risk the callback getting called after we've
249  * destroyed the exec_ctx.
250  */
251  plerrcontext.callback = plpython_error_callback;
252  plerrcontext.arg = exec_ctx;
253  plerrcontext.previous = error_context_stack;
254  error_context_stack = &plerrcontext;
255 
256  if (CALLED_AS_TRIGGER(fcinfo))
257  {
258  Relation tgrel = ((TriggerData *) fcinfo->context)->tg_relation;
259  HeapTuple trv;
260 
261  proc = PLy_procedure_get(funcoid, RelationGetRelid(tgrel), true);
262  exec_ctx->curr_proc = proc;
263  trv = PLy_exec_trigger(fcinfo, proc);
264  retval = PointerGetDatum(trv);
265  }
266  else
267  {
268  proc = PLy_procedure_get(funcoid, InvalidOid, false);
269  exec_ctx->curr_proc = proc;
270  retval = PLy_exec_function(fcinfo, proc);
271  }
272  }
273  PG_CATCH();
274  {
276  PyErr_Clear();
277  PG_RE_THROW();
278  }
279  PG_END_TRY();
280 
281  /* Destroy the execution context */
283 
284  return retval;
285 }
286 
287 #if PY_MAJOR_VERSION < 3
288 Datum
290 {
291  return plpython_call_handler(fcinfo);
292 }
293 #endif /* PY_MAJOR_VERSION < 3 */
294 
295 Datum
297 {
298  LOCAL_FCINFO(fake_fcinfo, 0);
300  FmgrInfo flinfo;
301  PLyProcedure proc;
302  PLyExecutionContext *exec_ctx;
303  ErrorContextCallback plerrcontext;
304 
305  PLy_initialize();
306 
307  /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
308  if (SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC) != SPI_OK_CONNECT)
309  elog(ERROR, "SPI_connect failed");
310 
311  MemSet(fcinfo, 0, SizeForFunctionCallInfo(0));
312  MemSet(&flinfo, 0, sizeof(flinfo));
313  fake_fcinfo->flinfo = &flinfo;
314  flinfo.fn_oid = InvalidOid;
315  flinfo.fn_mcxt = CurrentMemoryContext;
316 
317  MemSet(&proc, 0, sizeof(PLyProcedure));
319  "__plpython_inline_block",
321  proc.pyname = MemoryContextStrdup(proc.mcxt, "__plpython_inline_block");
322  proc.langid = codeblock->langOid;
323 
324  /*
325  * This is currently sufficient to get PLy_exec_function to work, but
326  * someday we might need to be honest and use PLy_output_setup_func.
327  */
328  proc.result.typoid = VOIDOID;
329 
330  /*
331  * Push execution context onto stack. It is important that this get
332  * popped again, so avoid putting anything that could throw error between
333  * here and the PG_TRY.
334  */
335  exec_ctx = PLy_push_execution_context(codeblock->atomic);
336 
337  PG_TRY();
338  {
339  /*
340  * Setup error traceback support for ereport().
341  * plpython_inline_error_callback doesn't currently need exec_ctx, but
342  * for consistency with plpython_call_handler we do it the same way.
343  */
345  plerrcontext.arg = exec_ctx;
346  plerrcontext.previous = error_context_stack;
347  error_context_stack = &plerrcontext;
348 
349  PLy_procedure_compile(&proc, codeblock->source_text);
350  exec_ctx->curr_proc = &proc;
351  PLy_exec_function(fake_fcinfo, &proc);
352  }
353  PG_CATCH();
354  {
356  PLy_procedure_delete(&proc);
357  PyErr_Clear();
358  PG_RE_THROW();
359  }
360  PG_END_TRY();
361 
362  /* Destroy the execution context */
364 
365  /* Now clean up the transient procedure we made */
366  PLy_procedure_delete(&proc);
367 
368  PG_RETURN_VOID();
369 }
370 
371 #if PY_MAJOR_VERSION < 3
372 Datum
374 {
375  return plpython_inline_handler(fcinfo);
376 }
377 #endif /* PY_MAJOR_VERSION < 3 */
378 
379 static bool
381 {
382  return (procStruct->prorettype == TRIGGEROID ||
383  (procStruct->prorettype == OPAQUEOID &&
384  procStruct->pronargs == 0));
385 }
386 
387 static void
389 {
390  PLyExecutionContext *exec_ctx = (PLyExecutionContext *) arg;
391 
392  if (exec_ctx->curr_proc)
393  {
394  if (exec_ctx->curr_proc->is_procedure)
395  errcontext("PL/Python procedure \"%s\"",
396  PLy_procedure_name(exec_ctx->curr_proc));
397  else
398  errcontext("PL/Python function \"%s\"",
399  PLy_procedure_name(exec_ctx->curr_proc));
400  }
401 }
402 
403 static void
405 {
406  errcontext("PL/Python anonymous code block");
407 }
408 
411 {
412  if (PLy_execution_contexts == NULL)
413  elog(ERROR, "no Python function is currently executing");
414 
415  return PLy_execution_contexts;
416 }
417 
420 {
421  /*
422  * A scratch context might never be needed in a given plpython procedure,
423  * so allocate it on first request.
424  */
425  if (context->scratch_ctx == NULL)
426  context->scratch_ctx =
428  "PL/Python scratch context",
430  return context->scratch_ctx;
431 }
432 
433 static PLyExecutionContext *
434 PLy_push_execution_context(bool atomic_context)
435 {
436  PLyExecutionContext *context;
437 
438  /* Pick a memory context similar to what SPI uses. */
439  context = (PLyExecutionContext *)
441  sizeof(PLyExecutionContext));
442  context->curr_proc = NULL;
443  context->scratch_ctx = NULL;
444  context->next = PLy_execution_contexts;
445  PLy_execution_contexts = context;
446  return context;
447 }
448 
449 static void
451 {
453 
454  if (context == NULL)
455  elog(ERROR, "no Python function is currently executing");
456 
457  PLy_execution_contexts = context->next;
458 
459  if (context->scratch_ctx)
461  pfree(context);
462 }
HeapTuple PLy_exec_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc)
Definition: plpy_exec.c:305
#define NIL
Definition: pg_list.h:65
MemoryContext scratch_ctx
Definition: plpy_main.h:21
#define SPI_OK_CONNECT
Definition: spi.h:53
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
Datum plpython2_call_handler(PG_FUNCTION_ARGS)
Definition: plpy_main.c:289
PG_MODULE_MAGIC
Definition: plpy_main.c:40
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
MemoryContext TopTransactionContext
Definition: mcxt.c:49
MemoryContext fn_mcxt
Definition: fmgr.h:65
Datum plpython2_inline_handler(PG_FUNCTION_ARGS)
Definition: plpy_main.c:373
static void PLy_init_interp(void)
Definition: plpy_main.c:154
#define TEXTDOMAIN
Definition: elog.h:144
int SPI_connect_ext(int options)
Definition: spi.c:95
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
Datum plpython_call_handler(PG_FUNCTION_ARGS)
Definition: plpy_main.c:216
Datum plpython_validator(PG_FUNCTION_ARGS)
Definition: plpy_main.c:174
static PLyExecutionContext * PLy_push_execution_context(bool atomic_context)
Definition: plpy_main.c:434
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
void init_procedure_caches(void)
void PLy_procedure_delete(PLyProcedure *proc)
void PLy_procedure_compile(PLyProcedure *proc, const char *src)
#define MemSet(start, val, len)
Definition: c.h:962
bool check_function_bodies
Definition: guc.c:503
unsigned int Oid
Definition: postgres_ext.h:31
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:410
void ** find_rendezvous_variable(const char *varName)
Definition: dfmgr.c:671
void(* callback)(void *arg)
Definition: elog.h:256
struct ErrorContextCallback * previous
Definition: elog.h:255
MemoryContext PortalContext
Definition: mcxt.c:53
ErrorContextCallback * error_context_stack
Definition: elog.c:91
PLyProcedure * PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
static void PLy_pop_execution_context(void)
Definition: plpy_main.c:450
void pfree(void *pointer)
Definition: mcxt.c:1056
char * PLy_procedure_name(PLyProcedure *proc)
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static int * plpython_version_bitmask_ptr
Definition: plpy_main.c:63
bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
Definition: fmgr.c:1986
#define SPI_OPT_NONATOMIC
Definition: spi.h:71
static int plpython_version_bitmask
Definition: plpy_main.c:64
static bool PLy_procedure_is_trigger(Form_pg_proc procStruct)
Definition: plpy_main.c:380
#define FATAL
Definition: elog.h:52
MemoryContext mcxt
#define PLy_elog
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
PyObject * PLy_interp_globals
Definition: plpy_main.c:67
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
int errdetail(const char *fmt,...)
Definition: elog.c:955
List * explicit_subtransactions
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define ereport(elevel, rest)
Definition: elog.h:141
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static void PLy_initialize(void)
Definition: plpy_main.c:107
static void plpython_inline_error_callback(void *arg)
Definition: plpy_main.c:404
PLyProcedure * curr_proc
Definition: plpy_main.h:20
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum plpython_inline_handler(PG_FUNCTION_ARGS)
Definition: plpy_main.c:296
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 PG_RETURN_VOID()
Definition: fmgr.h:339
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define PG_CATCH()
Definition: elog.h:332
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
static PLyExecutionContext * PLy_execution_contexts
Definition: plpy_main.c:70
#define PG_RE_THROW()
Definition: elog.h:363
#define DatumGetPointer(X)
Definition: postgres.h:549
void _PG_init(void)
Definition: plpy_main.c:74
PLyObToDatum result
int errmsg(const char *fmt,...)
Definition: elog.c:822
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173
PG_FUNCTION_INFO_V1(plpython_validator)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
struct PLyExecutionContext * next
Definition: plpy_main.h:22
void PLy_init_plpy(void)
#define elog(elevel,...)
Definition: elog.h:228
void pg_bindtextdomain(const char *domain)
Definition: miscinit.c:1607
Datum plpython2_validator(PG_FUNCTION_ARGS)
Definition: plpy_main.c:208
#define errcontext
Definition: elog.h:183
void * arg
char * source_text
Definition: parsenodes.h:2861
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
Datum PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
Definition: plpy_exec.c:55
#define PG_TRY()
Definition: elog.h:322
static void plpython_error_callback(void *arg)
Definition: plpy_main.c:388
#define RelationGetRelid(relation)
Definition: rel.h:422
#define PG_END_TRY()
Definition: elog.h:347
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:419