2 * PL/Python main entry points
4 * src/pl/plpython/plpy_main.c
50/* static state for Python library conflict detection */
54/* initialize global variables */
57/* this doesn't need to be global; use PLy_current_execution_context() */
67 * Set up a shared bitmask variable telling which Python version(s) are
68 * loaded into this process's address space. If there's more than one, we
69 * cannot call into libpython for fear of causing crashes. But postpone
70 * the actual failure for later, so that operations like pg_restore can
71 * load more than one plpython library so long as they don't try to do
72 * anything much with the language.
74 * While we only support Python 3 these days, somebody might create an
75 * out-of-tree version adding back support for Python 2. Conflicts with
76 * such an extension should be detected.
79 if (!(*bitmask_ptr))
/* am I the first? */
81 /* Retain pointer to the agreed-on shared variable ... */
83 /* ... and announce my presence */
87 * This should be safe even in the presence of conflicting plpythons, and
88 * it's necessary to do it before possibly throwing a conflict error, or
89 * the error message won't get localized.
95 * Perform one-time setup of PL/Python, after checking for a conflict
96 * with other versions of Python.
101 static bool inited =
false;
104 * Check for multiple Python libraries before actively doing anything with
105 * libpython. This must be repeated on each entry to PL/Python, in case a
106 * conflicting library got loaded since we last looked.
108 * It is attractive to weaken this error from FATAL to ERROR, but there
109 * would be corner cases, so it seems best to be conservative.
113 (
errmsg(
"multiple Python libraries are present in session"),
114 errdetail(
"Only one Python major version can be used in one session.")));
116 /* The rest should only be done once per session */
122 PyImport_ImportModule(
"plpy");
125 if (PyErr_Occurred())
138 * This should be called only once, from PLy_initialize. Initialize the Python
139 * interpreter and global data.
144 static PyObject *PLy_interp_safe_globals = NULL;
147 mainmod = PyImport_AddModule(
"__main__");
148 if (mainmod == NULL || PyErr_Occurred())
152 PLy_interp_safe_globals = PyDict_New();
153 if (PLy_interp_safe_globals == NULL)
175 /* Do this only after making sure we need to do something */
178 /* Get the new function's pg_proc entry */
181 elog(
ERROR,
"cache lookup failed for function %u", funcoid);
188 /* We can't validate triggers against any particular table ... */
204 nonatomic = fcinfo->context &&
208 /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
212 * Push execution context onto stack. It is important that this get
213 * popped again, so avoid putting anything that could throw error between
214 * here and the PG_TRY.
220 Oid funcoid = fcinfo->flinfo->fn_oid;
224 * Setup error traceback support for ereport(). Note that the PG_TRY
225 * structure pops this for us again at exit, so we needn't do that
226 * explicitly, nor do we risk the callback getting called after we've
227 * destroyed the exec_ctx.
230 plerrcontext.
arg = exec_ctx;
266 /* Destroy the execution context */
284 /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
288 MemSet(&flinfo, 0,
sizeof(flinfo));
289 fake_fcinfo->flinfo = &flinfo;
295 "__plpython_inline_block",
301 * This is currently sufficient to get PLy_exec_function to work, but
302 * someday we might need to be honest and use PLy_output_setup_func.
307 * Push execution context onto stack. It is important that this get
308 * popped again, so avoid putting anything that could throw error between
309 * here and the PG_TRY.
316 * Setup error traceback support for ereport().
317 * plpython_inline_error_callback doesn't currently need exec_ctx, but
318 * for consistency with plpython3_call_handler we do it the same way.
321 plerrcontext.
arg = exec_ctx;
338 /* Destroy the execution context */
341 /* Now clean up the transient procedure we made */
352 switch (procStruct->prorettype)
357 case EVENT_TRIGGEROID:
394 elog(
ERROR,
"no Python function is currently executing");
403 * A scratch context might never be needed in a given plpython procedure,
404 * so allocate it on first request.
409 "PL/Python scratch context",
419 /* Pick a memory context similar to what SPI uses. */
436 elog(
ERROR,
"no Python function is currently executing");
#define MemSet(start, val, len)
void ** find_rendezvous_variable(const char *varName)
int errdetail(const char *fmt,...)
ErrorContextCallback * error_context_stack
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
#define SizeForFunctionCallInfo(nargs)
#define PG_GETARG_DATUM(n)
#define LOCAL_FCINFO(name, nargs)
bool check_function_bodies
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
char * MemoryContextStrdup(MemoryContext context, const char *string)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext TopTransactionContext
void pfree(void *pointer)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
MemoryContext PortalContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
void pg_bindtextdomain(const char *domain)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
FormData_pg_proc * Form_pg_proc
void PLy_exec_event_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc)
Datum PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
HeapTuple PLy_exec_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc)
static int plpython_version_bitmask
Datum plpython3_validator(PG_FUNCTION_ARGS)
PyObject * PLy_interp_globals
static int * plpython_version_bitmask_ptr
static void PLy_initialize(void)
PG_FUNCTION_INFO_V1(plpython3_validator)
static PLyTrigType PLy_procedure_is_trigger(Form_pg_proc procStruct)
static void plpython_inline_error_callback(void *arg)
static PLyExecutionContext * PLy_execution_contexts
Datum plpython3_inline_handler(PG_FUNCTION_ARGS)
PLyExecutionContext * PLy_current_execution_context(void)
static void plpython_error_callback(void *arg)
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
PG_MODULE_MAGIC_EXT(.name="plpython",.version=PG_VERSION)
static PLyExecutionContext * PLy_push_execution_context(bool atomic_context)
static void PLy_pop_execution_context(void)
static void PLy_init_interp(void)
Datum plpython3_call_handler(PG_FUNCTION_ARGS)
PyMODINIT_FUNC PyInit_plpy(void)
char * PLy_procedure_name(PLyProcedure *proc)
void init_procedure_caches(void)
PLyProcedure * PLy_procedure_get(Oid fn_oid, Oid fn_rel, PLyTrigType is_trigger)
void PLy_procedure_compile(PLyProcedure *proc, const char *src)
void PLy_procedure_delete(PLyProcedure *proc)
List * explicit_subtransactions
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
#define RelationGetRelid(relation)
int SPI_connect_ext(int options)
#define SPI_OPT_NONATOMIC
struct ErrorContextCallback * previous
void(* callback)(void *arg)
struct PLyExecutionContext * next
MemoryContext scratch_ctx
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define CALLED_AS_TRIGGER(fcinfo)