v1-0004-plpython-Streamline-initialization.patch

text/plain

Filename: v1-0004-plpython-Streamline-initialization.patch
Type: text/plain
Part: 3
Message: PL/Python initialization cleanup
From 247ea7aa96df56253754e88c17974488ea09e39b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
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