Consistently use "superuser" instead of "super user"
[pgsql.git] / src / pl / plpython / plpy_main.c
blob3eedaa80da7d4909c34ee1e01e987875c169b466
1 /*
2 * PL/Python main entry points
4 * src/pl/plpython/plpy_main.c
5 */
7 #include "postgres.h"
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"
28 * exported functions
31 #if PY_MAJOR_VERSION >= 3
32 /* Use separate names to reduce confusion */
33 #define plpython_validator plpython3_validator
34 #define plpython_call_handler plpython3_call_handler
35 #define plpython_inline_handler plpython3_inline_handler
36 #endif
38 extern void _PG_init(void);
40 PG_MODULE_MAGIC;
42 PG_FUNCTION_INFO_V1(plpython_validator);
43 PG_FUNCTION_INFO_V1(plpython_call_handler);
44 PG_FUNCTION_INFO_V1(plpython_inline_handler);
46 #if PY_MAJOR_VERSION < 3
47 /* Define aliases plpython2_call_handler etc */
48 PG_FUNCTION_INFO_V1(plpython2_validator);
49 PG_FUNCTION_INFO_V1(plpython2_call_handler);
50 PG_FUNCTION_INFO_V1(plpython2_inline_handler);
51 #endif
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);
59 static PLyExecutionContext *PLy_push_execution_context(bool atomic_context);
60 static void PLy_pop_execution_context(void);
62 /* static state for Python library conflict detection */
63 static int *plpython_version_bitmask_ptr = NULL;
64 static int plpython_version_bitmask = 0;
66 /* initialize global variables */
67 PyObject *PLy_interp_globals = NULL;
69 /* this doesn't need to be global; use PLy_current_execution_context() */
70 static PLyExecutionContext *PLy_execution_contexts = NULL;
73 void
74 _PG_init(void)
76 int **bitmask_ptr;
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.
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);
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.
99 pg_bindtextdomain(TEXTDOMAIN);
103 * Perform one-time setup of PL/Python, after checking for a conflict
104 * with other versions of Python.
106 static void
107 PLy_initialize(void)
109 static bool inited = false;
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.
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.
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.")));
124 /* The rest should only be done once per session */
125 if (inited)
126 return;
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");
140 init_procedure_caches();
142 explicit_subtransactions = NIL;
144 PLy_execution_contexts = NULL;
146 inited = true;
150 * This should be called only once, from PLy_initialize. Initialize the Python
151 * interpreter and global data.
153 static void
154 PLy_init_interp(void)
156 static PyObject *PLy_interp_safe_globals = NULL;
157 PyObject *mainmod;
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");
173 Datum
174 plpython_validator(PG_FUNCTION_ARGS)
176 Oid funcoid = PG_GETARG_OID(0);
177 HeapTuple tuple;
178 Form_pg_proc procStruct;
179 bool is_trigger;
181 if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
182 PG_RETURN_VOID();
184 if (!check_function_bodies)
185 PG_RETURN_VOID();
187 /* Do this only after making sure we need to do something */
188 PLy_initialize();
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);
196 is_trigger = PLy_procedure_is_trigger(procStruct);
198 ReleaseSysCache(tuple);
200 /* We can't validate triggers against any particular table ... */
201 PLy_procedure_get(funcoid, InvalidOid, is_trigger);
203 PG_RETURN_VOID();
206 #if PY_MAJOR_VERSION < 3
207 Datum
208 plpython2_validator(PG_FUNCTION_ARGS)
210 /* call plpython validator with our fcinfo so it gets our oid */
211 return plpython_validator(fcinfo);
213 #endif /* PY_MAJOR_VERSION < 3 */
215 Datum
216 plpython_call_handler(PG_FUNCTION_ARGS)
218 bool nonatomic;
219 Datum retval;
220 PLyExecutionContext *exec_ctx;
221 ErrorContextCallback plerrcontext;
223 PLy_initialize();
225 nonatomic = fcinfo->context &&
226 IsA(fcinfo->context, CallContext) &&
227 !castNode(CallContext, fcinfo->context)->atomic;
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");
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.
238 exec_ctx = PLy_push_execution_context(!nonatomic);
240 PG_TRY();
242 Oid funcoid = fcinfo->flinfo->fn_oid;
243 PLyProcedure *proc;
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.
251 plerrcontext.callback = plpython_error_callback;
252 plerrcontext.arg = exec_ctx;
253 plerrcontext.previous = error_context_stack;
254 error_context_stack = &plerrcontext;
256 if (CALLED_AS_TRIGGER(fcinfo))
258 Relation tgrel = ((TriggerData *) fcinfo->context)->tg_relation;
259 HeapTuple trv;
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);
266 else
268 proc = PLy_procedure_get(funcoid, InvalidOid, false);
269 exec_ctx->curr_proc = proc;
270 retval = PLy_exec_function(fcinfo, proc);
273 PG_CATCH();
275 PLy_pop_execution_context();
276 PyErr_Clear();
277 PG_RE_THROW();
279 PG_END_TRY();
281 /* Destroy the execution context */
282 PLy_pop_execution_context();
284 return retval;
287 #if PY_MAJOR_VERSION < 3
288 Datum
289 plpython2_call_handler(PG_FUNCTION_ARGS)
291 return plpython_call_handler(fcinfo);
293 #endif /* PY_MAJOR_VERSION < 3 */
295 Datum
296 plpython_inline_handler(PG_FUNCTION_ARGS)
298 LOCAL_FCINFO(fake_fcinfo, 0);
299 InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
300 FmgrInfo flinfo;
301 PLyProcedure proc;
302 PLyExecutionContext *exec_ctx;
303 ErrorContextCallback plerrcontext;
305 PLy_initialize();
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");
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;
317 MemSet(&proc, 0, sizeof(PLyProcedure));
318 proc.mcxt = AllocSetContextCreate(TopMemoryContext,
319 "__plpython_inline_block",
320 ALLOCSET_DEFAULT_SIZES);
321 proc.pyname = MemoryContextStrdup(proc.mcxt, "__plpython_inline_block");
322 proc.langid = codeblock->langOid;
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.
328 proc.result.typoid = VOIDOID;
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.
335 exec_ctx = PLy_push_execution_context(codeblock->atomic);
337 PG_TRY();
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.
344 plerrcontext.callback = plpython_inline_error_callback;
345 plerrcontext.arg = exec_ctx;
346 plerrcontext.previous = error_context_stack;
347 error_context_stack = &plerrcontext;
349 PLy_procedure_compile(&proc, codeblock->source_text);
350 exec_ctx->curr_proc = &proc;
351 PLy_exec_function(fake_fcinfo, &proc);
353 PG_CATCH();
355 PLy_pop_execution_context();
356 PLy_procedure_delete(&proc);
357 PyErr_Clear();
358 PG_RE_THROW();
360 PG_END_TRY();
362 /* Destroy the execution context */
363 PLy_pop_execution_context();
365 /* Now clean up the transient procedure we made */
366 PLy_procedure_delete(&proc);
368 PG_RETURN_VOID();
371 #if PY_MAJOR_VERSION < 3
372 Datum
373 plpython2_inline_handler(PG_FUNCTION_ARGS)
375 return plpython_inline_handler(fcinfo);
377 #endif /* PY_MAJOR_VERSION < 3 */
379 static bool
380 PLy_procedure_is_trigger(Form_pg_proc procStruct)
382 return (procStruct->prorettype == TRIGGEROID);
385 static void
386 plpython_error_callback(void *arg)
388 PLyExecutionContext *exec_ctx = (PLyExecutionContext *) arg;
390 if (exec_ctx->curr_proc)
392 if (exec_ctx->curr_proc->is_procedure)
393 errcontext("PL/Python procedure \"%s\"",
394 PLy_procedure_name(exec_ctx->curr_proc));
395 else
396 errcontext("PL/Python function \"%s\"",
397 PLy_procedure_name(exec_ctx->curr_proc));
401 static void
402 plpython_inline_error_callback(void *arg)
404 errcontext("PL/Python anonymous code block");
407 PLyExecutionContext *
408 PLy_current_execution_context(void)
410 if (PLy_execution_contexts == NULL)
411 elog(ERROR, "no Python function is currently executing");
413 return PLy_execution_contexts;
416 MemoryContext
417 PLy_get_scratch_context(PLyExecutionContext *context)
420 * A scratch context might never be needed in a given plpython procedure,
421 * so allocate it on first request.
423 if (context->scratch_ctx == NULL)
424 context->scratch_ctx =
425 AllocSetContextCreate(TopTransactionContext,
426 "PL/Python scratch context",
427 ALLOCSET_DEFAULT_SIZES);
428 return context->scratch_ctx;
431 static PLyExecutionContext *
432 PLy_push_execution_context(bool atomic_context)
434 PLyExecutionContext *context;
436 /* Pick a memory context similar to what SPI uses. */
437 context = (PLyExecutionContext *)
438 MemoryContextAlloc(atomic_context ? TopTransactionContext : PortalContext,
439 sizeof(PLyExecutionContext));
440 context->curr_proc = NULL;
441 context->scratch_ctx = NULL;
442 context->next = PLy_execution_contexts;
443 PLy_execution_contexts = context;
444 return context;
447 static void
448 PLy_pop_execution_context(void)
450 PLyExecutionContext *context = PLy_execution_contexts;
452 if (context == NULL)
453 elog(ERROR, "no Python function is currently executing");
455 PLy_execution_contexts = context->next;
457 if (context->scratch_ctx)
458 MemoryContextDelete(context->scratch_ctx);
459 pfree(context);