diff --git a/src/pl/plpython/expected/plpython3_path_guc.out b/src/pl/plpython/expected/plpython3_path_guc.out new file mode 100644 index 000000000000..36800df553f9 --- /dev/null +++ b/src/pl/plpython/expected/plpython3_path_guc.out @@ -0,0 +1,39 @@ +-- +-- Tests for functions that return set PYTHONPATH guc only for gpdb6 plpython3 +-- +LOAD 'plpython3'; +show plpython3.python_path; + plpython3.python_path +----------------------- + +(1 row) + +set plpython3.python_path='/foo'; +show plpython3.python_path; + plpython3.python_path +----------------------- + /foo +(1 row) + +-- Set up test path functions first. +CREATE FUNCTION test_path_added() +RETURNS text AS $$ + import sys + return str(sys.path[0]) +$$ language plpython3u; +SELECT test_path_added(); + test_path_added +----------------- + /foo +(1 row) + +-- when the plpython init can not set again -- +set plpython3.python_path='/bar'; +ERROR: SET PYTHONPATH failed, the GUC value can only be changed before initializing the python interpreter. +-- run again the path will not change still /foo -- +SELECT test_path_added(); + test_path_added +----------------- + /foo +(1 row) + diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c index e29fb744d314..4425d593d57a 100644 --- a/src/pl/plpython/plpy_main.c +++ b/src/pl/plpython/plpy_main.c @@ -17,6 +17,8 @@ #include "utils/rel.h" #include "utils/syscache.h" +#include "cdb/cdbvars.h" + #include "plpython.h" #include "plpy_main.h" @@ -81,6 +83,23 @@ void PLy_handle_cancel_interrupt(void); bool PLy_enter_python_intepreter = false; +static bool inited = false; + +/* GUC variables */ +#if PY_MAJOR_VERSION >= 3 +static char *plpython3_path = NULL; + +static bool +plpython3_check_python_path(char **newval, void **extra, GucSource source) { + if (inited) + { + GUC_check_errmsg("SET PYTHONPATH failed, the GUC value can only be changed before initializing the python interpreter."); + return false; + } + return true; +} +#endif + void _PG_init(void) { @@ -137,6 +156,18 @@ _PG_init(void) prev_cancel_pending_hook = cancel_pending_hook; cancel_pending_hook = PLy_handle_cancel_interrupt; +#if PY_MAJOR_VERSION >= 3 + DefineCustomStringVariable("plpython3.python_path", + gettext_noop("PYTHONPATH for plpython3."), + NULL, + &plpython3_path, + "", // default path need to set empty for init + PGC_USERSET, + GUC_GPDB_NEED_SYNC, + plpython3_check_python_path, + NULL, + NULL); +#endif pg_bindtextdomain(TEXTDOMAIN); } @@ -148,7 +179,6 @@ _PG_init(void) static void PLy_initialize(void) { - static bool inited = false; /* * Check for multiple Python libraries before actively doing anything with @@ -162,18 +192,23 @@ PLy_initialize(void) ereport(FATAL, (errmsg("multiple Python libraries are present in session"), errdetail("Only one Python major version can be used in one session."))); - +#if PY_MAJOR_VERSION >= 3 + /* PYTHONPATH and PYTHONHOME has been set to GPDB's python2.7 in Postmaster when + * gpstart. So for plpython3u, we need to unset PYTHONPATH and PYTHONHOME. + * if user set PYTHONPATH then we set it in the env + */ + if (plpython3_path && *plpython3_path) + setenv("PYTHONPATH", plpython3_path, 1); + else + unsetenv("PYTHONPATH"); + unsetenv("PYTHONHOME"); +#endif /* The rest should only be done once per session */ if (inited) return; #if PY_MAJOR_VERSION >= 3 PyImport_AppendInittab("plpy", PyInit_plpy); - /* PYTHONPATH and PYTHONHOME has been set to GPDB's python2.7 in Postmaster when - * gpstart. So for plpython3u, we need to unset PYTHONPATH and PYTHONHOME. - */ - unsetenv("PYTHONPATH"); - unsetenv("PYTHONHOME"); #endif Py_Initialize(); #if PY_MAJOR_VERSION >= 3 diff --git a/src/pl/plpython/sql/plpython3_path_guc.sql b/src/pl/plpython/sql/plpython3_path_guc.sql new file mode 100644 index 000000000000..e686e7670771 --- /dev/null +++ b/src/pl/plpython/sql/plpython3_path_guc.sql @@ -0,0 +1,23 @@ +-- +-- Tests for functions that return set PYTHONPATH guc only for gpdb6 plpython3 +-- +LOAD 'plpython3'; +show plpython3.python_path; + +set plpython3.python_path='/foo'; +show plpython3.python_path; + +-- Set up test path functions first. +CREATE FUNCTION test_path_added() +RETURNS text AS $$ + import sys + return str(sys.path[0]) +$$ language plpython3u; + +SELECT test_path_added(); + +-- when the plpython init can not set again -- +set plpython3.python_path='/bar'; + +-- run again the path will not change still /foo -- +SELECT test_path_added(); diff --git a/src/pl/plpython3/Makefile b/src/pl/plpython3/Makefile index 3752adfa1245..2769e32c19f5 100644 --- a/src/pl/plpython3/Makefile +++ b/src/pl/plpython3/Makefile @@ -92,6 +92,7 @@ REGRESS = \ plpython_schema \ plpython_populate \ plpython_test \ + plpython3_path_guc \ plpython_do \ plpython_global \ plpython_import \