From 247ea7aa96df56253754e88c17974488ea09e39b Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 30 Dec 2025 22:17:57 +0100 Subject: [PATCH v1 4/4] 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(). --- src/pl/plpython/plpy_main.c | 77 ++++++++++++++++--------------- src/pl/plpython/plpy_plpymodule.c | 25 +--------- src/pl/plpython/plpy_plpymodule.h | 1 - 3 files changed, 40 insertions(+), 63 deletions(-) diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c index 7673b5eca7b..482ca7a1ada 100644 --- a/src/pl/plpython/plpy_main.c +++ b/src/pl/plpython/plpy_main.c @@ -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,52 @@ static PLyExecutionContext *PLy_execution_contexts = NULL; void _PG_init(void) { - pg_bindtextdomain(TEXTDOMAIN); + PyObject *main_mod; + PyObject *main_dict; + PyObject *GD; + PyObject *plpy_mod; - PLy_initialize(); -} + pg_bindtextdomain(TEXTDOMAIN); -/* - * 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 get \"__main__\" module"); + Py_INCREF(main_mod); + + main_dict = PyModule_GetDict(main_mod); + + /* + * 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 \"plpy\" module"); + PyDict_SetItemString(main_dict, "plpy", plpy_mod); + if (PyErr_Occurred()) + PLy_elog(ERROR, "could not import \"plpy\" module"); + + Py_DECREF(main_mod); + if (PyErr_Occurred()) PLy_elog(FATAL, "untrapped error in initialization"); + Py_INCREF(main_dict); + PLy_interp_globals = main_dict; + init_procedure_caches(); explicit_subtransactions = NIL; @@ -84,30 +109,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) { diff --git a/src/pl/plpython/plpy_plpymodule.c b/src/pl/plpython/plpy_plpymodule.c index 2d76c6a5573..e24ad02e086 100644 --- a/src/pl/plpython/plpy_plpymodule.c +++ b/src/pl/plpython/plpy_plpymodule.c @@ -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 diff --git a/src/pl/plpython/plpy_plpymodule.h b/src/pl/plpython/plpy_plpymodule.h index 1ca3823daf2..88f902346a6 100644 --- a/src/pl/plpython/plpy_plpymodule.h +++ b/src/pl/plpython/plpy_plpymodule.h @@ -13,6 +13,5 @@ extern HTAB *PLy_spi_exceptions; PyMODINIT_FUNC PyInit_plpy(void); -extern void PLy_init_plpy(void); #endif /* PLPY_PLPYMODULE_H */ -- 2.52.0