mirror of
https://github.com/postgres/postgres.git
synced 2025-10-19 15:49:24 +03:00
plpython: Remove support for major version conflict detection
This essentially reverts commit866566a690
, which installed safeguards against loading plpython2 and plpython3 into the same process. We don't support plpython2 anymore, so this is obsolete. The Python and PL/Python initialization now happens again in _PG_init() rather than the first time a PL/Python call handler is invoked. (Often, these will be very close together.) I kept the separate PLy_initialize() function introduced by866566a690
to keep _PG_init() a bit modular. Reviewed-by: Mario González Troncoso <gonzalemario@gmail.com> Reviewed-by: Nathan Bossart <nathandbossart@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/9eb9feb6-1df3-4f0c-a0dc-9bcf35273111%40eisentraut.org
This commit is contained in:
@@ -39,6 +39,7 @@ PG_FUNCTION_INFO_V1(plpython3_call_handler);
|
|||||||
PG_FUNCTION_INFO_V1(plpython3_inline_handler);
|
PG_FUNCTION_INFO_V1(plpython3_inline_handler);
|
||||||
|
|
||||||
|
|
||||||
|
static void PLy_initialize(void);
|
||||||
static PLyTrigType PLy_procedure_is_trigger(Form_pg_proc procStruct);
|
static PLyTrigType PLy_procedure_is_trigger(Form_pg_proc procStruct);
|
||||||
static void plpython_error_callback(void *arg);
|
static void plpython_error_callback(void *arg);
|
||||||
static void plpython_inline_error_callback(void *arg);
|
static void plpython_inline_error_callback(void *arg);
|
||||||
@@ -47,10 +48,6 @@ static void PLy_init_interp(void);
|
|||||||
static PLyExecutionContext *PLy_push_execution_context(bool atomic_context);
|
static PLyExecutionContext *PLy_push_execution_context(bool atomic_context);
|
||||||
static void PLy_pop_execution_context(void);
|
static void PLy_pop_execution_context(void);
|
||||||
|
|
||||||
/* static state for Python library conflict detection */
|
|
||||||
static int *plpython_version_bitmask_ptr = NULL;
|
|
||||||
static int plpython_version_bitmask = 0;
|
|
||||||
|
|
||||||
/* initialize global variables */
|
/* initialize global variables */
|
||||||
PyObject *PLy_interp_globals = NULL;
|
PyObject *PLy_interp_globals = NULL;
|
||||||
|
|
||||||
@@ -61,62 +58,17 @@ static PLyExecutionContext *PLy_execution_contexts = NULL;
|
|||||||
void
|
void
|
||||||
_PG_init(void)
|
_PG_init(void)
|
||||||
{
|
{
|
||||||
int **bitmask_ptr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set up a shared bitmask variable telling which Python version(s) are
|
|
||||||
* loaded into this process's address space. If there's more than one, we
|
|
||||||
* cannot call into libpython for fear of causing crashes. But postpone
|
|
||||||
* the actual failure for later, so that operations like pg_restore can
|
|
||||||
* load more than one plpython library so long as they don't try to do
|
|
||||||
* anything much with the language.
|
|
||||||
*
|
|
||||||
* While we only support Python 3 these days, somebody might create an
|
|
||||||
* out-of-tree version adding back support for Python 2. Conflicts with
|
|
||||||
* such an extension should be detected.
|
|
||||||
*/
|
|
||||||
bitmask_ptr = (int **) find_rendezvous_variable("plpython_version_bitmask");
|
|
||||||
if (!(*bitmask_ptr)) /* am I the first? */
|
|
||||||
*bitmask_ptr = &plpython_version_bitmask;
|
|
||||||
/* Retain pointer to the agreed-on shared variable ... */
|
|
||||||
plpython_version_bitmask_ptr = *bitmask_ptr;
|
|
||||||
/* ... and announce my presence */
|
|
||||||
*plpython_version_bitmask_ptr |= (1 << PY_MAJOR_VERSION);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This should be safe even in the presence of conflicting plpythons, and
|
|
||||||
* it's necessary to do it before possibly throwing a conflict error, or
|
|
||||||
* the error message won't get localized.
|
|
||||||
*/
|
|
||||||
pg_bindtextdomain(TEXTDOMAIN);
|
pg_bindtextdomain(TEXTDOMAIN);
|
||||||
|
|
||||||
|
PLy_initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform one-time setup of PL/Python, after checking for a conflict
|
* Perform one-time setup of PL/Python.
|
||||||
* with other versions of Python.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
PLy_initialize(void)
|
PLy_initialize(void)
|
||||||
{
|
{
|
||||||
static bool inited = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for multiple Python libraries before actively doing anything with
|
|
||||||
* libpython. This must be repeated on each entry to PL/Python, in case a
|
|
||||||
* conflicting library got loaded since we last looked.
|
|
||||||
*
|
|
||||||
* It is attractive to weaken this error from FATAL to ERROR, but there
|
|
||||||
* would be corner cases, so it seems best to be conservative.
|
|
||||||
*/
|
|
||||||
if (*plpython_version_bitmask_ptr != (1 << PY_MAJOR_VERSION))
|
|
||||||
ereport(FATAL,
|
|
||||||
(errmsg("multiple Python libraries are present in session"),
|
|
||||||
errdetail("Only one Python major version can be used in one session.")));
|
|
||||||
|
|
||||||
/* The rest should only be done once per session */
|
|
||||||
if (inited)
|
|
||||||
return;
|
|
||||||
|
|
||||||
PyImport_AppendInittab("plpy", PyInit_plpy);
|
PyImport_AppendInittab("plpy", PyInit_plpy);
|
||||||
Py_Initialize();
|
Py_Initialize();
|
||||||
PyImport_ImportModule("plpy");
|
PyImport_ImportModule("plpy");
|
||||||
@@ -130,8 +82,6 @@ PLy_initialize(void)
|
|||||||
explicit_subtransactions = NIL;
|
explicit_subtransactions = NIL;
|
||||||
|
|
||||||
PLy_execution_contexts = NULL;
|
PLy_execution_contexts = NULL;
|
||||||
|
|
||||||
inited = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -172,9 +122,6 @@ plpython3_validator(PG_FUNCTION_ARGS)
|
|||||||
if (!check_function_bodies)
|
if (!check_function_bodies)
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
|
|
||||||
/* Do this only after making sure we need to do something */
|
|
||||||
PLy_initialize();
|
|
||||||
|
|
||||||
/* Get the new function's pg_proc entry */
|
/* Get the new function's pg_proc entry */
|
||||||
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
|
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
@@ -199,8 +146,6 @@ plpython3_call_handler(PG_FUNCTION_ARGS)
|
|||||||
PLyExecutionContext *exec_ctx;
|
PLyExecutionContext *exec_ctx;
|
||||||
ErrorContextCallback plerrcontext;
|
ErrorContextCallback plerrcontext;
|
||||||
|
|
||||||
PLy_initialize();
|
|
||||||
|
|
||||||
nonatomic = fcinfo->context &&
|
nonatomic = fcinfo->context &&
|
||||||
IsA(fcinfo->context, CallContext) &&
|
IsA(fcinfo->context, CallContext) &&
|
||||||
!castNode(CallContext, fcinfo->context)->atomic;
|
!castNode(CallContext, fcinfo->context)->atomic;
|
||||||
@@ -279,8 +224,6 @@ plpython3_inline_handler(PG_FUNCTION_ARGS)
|
|||||||
PLyExecutionContext *exec_ctx;
|
PLyExecutionContext *exec_ctx;
|
||||||
ErrorContextCallback plerrcontext;
|
ErrorContextCallback plerrcontext;
|
||||||
|
|
||||||
PLy_initialize();
|
|
||||||
|
|
||||||
/* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
|
/* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
|
||||||
SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC);
|
SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user