1
0
mirror of https://github.com/postgres/postgres.git synced 2026-01-26 09:41:40 +03:00

plpython: Streamline initialization

The initialization of PL/Python (the Python interpreter, the global
state, the plpy module) was arranged confusingly across different
functions with unclear and confusing boundaries.  For example,
PLy_init_interp() said "Initialize the Python interpreter ..." but it
didn't actually do this, and PLy_init_plpy() said "initialize plpy
module" but it didn't do that either.  After this change, all the
global initialization is called directly from _PG_init(), and the plpy
module initialization is all called from its registered initialization
function PyInit_plpy().

Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewed-by: li carol <carol.li2025@outlook.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Discussion: https://www.postgresql.org/message-id/f31333f1-fbb7-4098-b209-bf2d71fbd4f3%40eisentraut.org
This commit is contained in:
Peter Eisentraut
2026-01-15 12:11:52 +01:00
parent 3263a893fb
commit da265a8717
3 changed files with 41 additions and 63 deletions

View File

@@ -39,11 +39,9 @@ PG_FUNCTION_INFO_V1(plpython3_call_handler);
PG_FUNCTION_INFO_V1(plpython3_inline_handler);
static void PLy_initialize(void);
static PLyTrigType PLy_procedure_is_trigger(Form_pg_proc procStruct);
static void plpython_error_callback(void *arg);
static void plpython_inline_error_callback(void *arg);
static void PLy_init_interp(void);
static PLyExecutionContext *PLy_push_execution_context(bool atomic_context);
static void PLy_pop_execution_context(void);
@@ -58,25 +56,53 @@ static PLyExecutionContext *PLy_execution_contexts = NULL;
void
_PG_init(void)
{
PyObject *main_mod;
PyObject *main_dict;
PyObject *GD;
PyObject *plpy_mod;
pg_bindtextdomain(TEXTDOMAIN);
PLy_initialize();
}
/*
* Perform one-time setup of PL/Python.
*/
static void
PLy_initialize(void)
{
/* Add plpy to table of built-in modules. */
PyImport_AppendInittab("plpy", PyInit_plpy);
/* Initialize Python interpreter. */
Py_Initialize();
PyImport_ImportModule("plpy");
PLy_init_interp();
PLy_init_plpy();
main_mod = PyImport_AddModule("__main__");
if (main_mod == NULL || PyErr_Occurred())
PLy_elog(ERROR, "could not import \"%s\" module", "__main__");
Py_INCREF(main_mod);
main_dict = PyModule_GetDict(main_mod);
if (main_dict == NULL)
PLy_elog(ERROR, NULL);
/*
* Set up GD.
*/
GD = PyDict_New();
if (GD == NULL)
PLy_elog(ERROR, NULL);
PyDict_SetItemString(main_dict, "GD", GD);
/*
* Import plpy.
*/
plpy_mod = PyImport_ImportModule("plpy");
if (plpy_mod == NULL)
PLy_elog(ERROR, "could not import \"%s\" module", "plpy");
if (PyDict_SetItemString(main_dict, "plpy", plpy_mod) == -1)
PLy_elog(ERROR, NULL);
if (PyErr_Occurred())
PLy_elog(FATAL, "untrapped error in initialization");
Py_INCREF(main_dict);
PLy_interp_globals = main_dict;
Py_DECREF(main_mod);
init_procedure_caches();
explicit_subtransactions = NIL;
@@ -84,30 +110,6 @@ PLy_initialize(void)
PLy_execution_contexts = NULL;
}
/*
* This should be called only once, from PLy_initialize. Initialize the Python
* interpreter and global data.
*/
static void
PLy_init_interp(void)
{
static PyObject *PLy_interp_safe_globals = NULL;
PyObject *mainmod;
mainmod = PyImport_AddModule("__main__");
if (mainmod == NULL || PyErr_Occurred())
PLy_elog(ERROR, "could not import \"__main__\" module");
Py_INCREF(mainmod);
PLy_interp_globals = PyModule_GetDict(mainmod);
PLy_interp_safe_globals = PyDict_New();
if (PLy_interp_safe_globals == NULL)
PLy_elog(ERROR, NULL);
PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
Py_DECREF(mainmod);
if (PLy_interp_globals == NULL || PyErr_Occurred())
PLy_elog(ERROR, "could not initialize globals");
}
Datum
plpython3_validator(PG_FUNCTION_ARGS)
{

View File

@@ -133,35 +133,12 @@ PyInit_plpy(void)
PLy_add_exceptions(m);
return m;
}
void
PLy_init_plpy(void)
{
PyObject *main_mod,
*main_dict,
*plpy_mod;
/*
* initialize plpy module
*/
PLy_plan_init_type();
PLy_result_init_type();
PLy_subtransaction_init_type();
PLy_cursor_init_type();
/*
* initialize main module, and add plpy
*/
main_mod = PyImport_AddModule("__main__");
main_dict = PyModule_GetDict(main_mod);
plpy_mod = PyImport_AddModule("plpy");
if (plpy_mod == NULL)
PLy_elog(ERROR, "could not import \"plpy\" module");
PyDict_SetItemString(main_dict, "plpy", plpy_mod);
if (PyErr_Occurred())
PLy_elog(ERROR, "could not import \"plpy\" module");
return m;
}
static void

View File

@@ -13,6 +13,5 @@ extern HTAB *PLy_spi_exceptions;
PyMODINIT_FUNC PyInit_plpy(void);
extern void PLy_init_plpy(void);
#endif /* PLPY_PLPYMODULE_H */