|
|
|
|
/*
|
|
|
|
|
* PL/Python main entry points
|
|
|
|
|
*
|
|
|
|
|
* src/pl/plpython/plpy_main.c
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
|
|
#include "access/htup_details.h"
|
|
|
|
|
#include "catalog/pg_proc.h"
|
|
|
|
|
#include "catalog/pg_type.h"
|
|
|
|
|
#include "commands/trigger.h"
|
|
|
|
|
#include "executor/spi.h"
|
|
|
|
|
#include "miscadmin.h"
|
|
|
|
|
#include "utils/guc.h"
|
|
|
|
|
#include "utils/memutils.h"
|
|
|
|
|
#include "utils/rel.h"
|
|
|
|
|
#include "utils/syscache.h"
|
|
|
|
|
|
|
|
|
|
#include "plpython.h"
|
|
|
|
|
|
|
|
|
|
#include "plpy_main.h"
|
|
|
|
|
|
|
|
|
|
#include "plpy_elog.h"
|
|
|
|
|
#include "plpy_exec.h"
|
|
|
|
|
#include "plpy_plpymodule.h"
|
|
|
|
|
#include "plpy_procedure.h"
|
|
|
|
|
#include "plpy_subxactobject.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* exported functions
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
/* Use separate names to avoid clash in pg_pltemplate */
|
|
|
|
|
#define plpython_validator plpython3_validator
|
|
|
|
|
#define plpython_call_handler plpython3_call_handler
|
|
|
|
|
#define plpython_inline_handler plpython3_inline_handler
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
extern void _PG_init(void);
|
|
|
|
|
|
|
|
|
|
PG_MODULE_MAGIC;
|
|
|
|
|
|
|
|
|
|
PG_FUNCTION_INFO_V1(plpython_validator);
|
|
|
|
|
PG_FUNCTION_INFO_V1(plpython_call_handler);
|
|
|
|
|
PG_FUNCTION_INFO_V1(plpython_inline_handler);
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
|
/* Define aliases plpython2_call_handler etc */
|
|
|
|
|
PG_FUNCTION_INFO_V1(plpython2_validator);
|
|
|
|
|
PG_FUNCTION_INFO_V1(plpython2_call_handler);
|
|
|
|
|
PG_FUNCTION_INFO_V1(plpython2_inline_handler);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool 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(void);
|
|
|
|
|
static void PLy_pop_execution_context(void);
|
|
|
|
|
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
/* static state for Python library conflict detection */
|
|
|
|
|
static int *plpython_version_bitmask_ptr = NULL;
|
|
|
|
|
static int plpython_version_bitmask = 0;
|
|
|
|
|
|
|
|
|
|
/* initialize global variables */
|
|
|
|
|
PyObject *PLy_interp_globals = NULL;
|
|
|
|
|
|
|
|
|
|
/* this doesn't need to be global; use PLy_current_execution_context() */
|
|
|
|
|
static PLyExecutionContext *PLy_execution_contexts = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_PG_init(void)
|
|
|
|
|
{
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
int **bitmask_ptr;
|
|
|
|
|
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
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);
|
|
|
|
|
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
/*
|
|
|
|
|
* 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.
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
*/
|
|
|
|
|
pg_bindtextdomain(TEXTDOMAIN);
|
|
|
|
|
}
|
|
|
|
|
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
/*
|
|
|
|
|
* Perform one-time setup of PL/Python, after checking for a conflict
|
|
|
|
|
* with other versions of Python.
|
|
|
|
|
*/
|
|
|
|
|
static 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;
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
PyImport_AppendInittab("plpy", PyInit_plpy);
|
|
|
|
|
#endif
|
|
|
|
|
Py_Initialize();
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
PyImport_ImportModule("plpy");
|
|
|
|
|
#endif
|
|
|
|
|
PLy_init_interp();
|
|
|
|
|
PLy_init_plpy();
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PLy_elog(FATAL, "untrapped error in initialization");
|
|
|
|
|
|
|
|
|
|
init_procedure_caches();
|
|
|
|
|
|
|
|
|
|
explicit_subtransactions = NIL;
|
|
|
|
|
|
|
|
|
|
PLy_execution_contexts = NULL;
|
|
|
|
|
|
|
|
|
|
inited = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
* 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, "could not create globals");
|
|
|
|
|
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
|
|
|
|
|
plpython_validator(PG_FUNCTION_ARGS)
|
|
|
|
|
{
|
|
|
|
|
Oid funcoid = PG_GETARG_OID(0);
|
|
|
|
|
HeapTuple tuple;
|
|
|
|
|
Form_pg_proc procStruct;
|
|
|
|
|
bool is_trigger;
|
|
|
|
|
|
|
|
|
|
if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
|
|
|
|
|
PG_RETURN_VOID();
|
|
|
|
|
|
|
|
|
|
if (!check_function_bodies)
|
|
|
|
|
PG_RETURN_VOID();
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
|
|
|
|
|
/* Do this only after making sure we need to do something */
|
|
|
|
|
PLy_initialize();
|
|
|
|
|
|
|
|
|
|
/* Get the new function's pg_proc entry */
|
|
|
|
|
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
|
|
|
|
|
if (!HeapTupleIsValid(tuple))
|
|
|
|
|
elog(ERROR, "cache lookup failed for function %u", funcoid);
|
|
|
|
|
procStruct = (Form_pg_proc) GETSTRUCT(tuple);
|
|
|
|
|
|
|
|
|
|
is_trigger = PLy_procedure_is_trigger(procStruct);
|
|
|
|
|
|
|
|
|
|
ReleaseSysCache(tuple);
|
|
|
|
|
|
|
|
|
|
/* We can't validate triggers against any particular table ... */
|
|
|
|
|
PLy_procedure_get(funcoid, InvalidOid, is_trigger);
|
|
|
|
|
|
|
|
|
|
PG_RETURN_VOID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
|
Datum
|
|
|
|
|
plpython2_validator(PG_FUNCTION_ARGS)
|
|
|
|
|
{
|
|
|
|
|
/* call plpython validator with our fcinfo so it gets our oid */
|
|
|
|
|
return plpython_validator(fcinfo);
|
|
|
|
|
}
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
9 years ago
|
|
|
#endif /* PY_MAJOR_VERSION < 3 */
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
|
plpython_call_handler(PG_FUNCTION_ARGS)
|
|
|
|
|
{
|
|
|
|
|
Datum retval;
|
|
|
|
|
PLyExecutionContext *exec_ctx;
|
|
|
|
|
ErrorContextCallback plerrcontext;
|
|
|
|
|
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
PLy_initialize();
|
|
|
|
|
|
|
|
|
|
/* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
|
|
|
|
|
if (SPI_connect() != SPI_OK_CONNECT)
|
|
|
|
|
elog(ERROR, "SPI_connect failed");
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Push execution context onto stack. It is important that this get
|
|
|
|
|
* popped again, so avoid putting anything that could throw error between
|
|
|
|
|
* here and the PG_TRY. (plpython_error_callback expects the stack entry
|
|
|
|
|
* to be there, so we have to make the context first.)
|
|
|
|
|
*/
|
|
|
|
|
exec_ctx = PLy_push_execution_context();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Setup error traceback support for ereport()
|
|
|
|
|
*/
|
|
|
|
|
plerrcontext.callback = plpython_error_callback;
|
|
|
|
|
plerrcontext.previous = error_context_stack;
|
|
|
|
|
error_context_stack = &plerrcontext;
|
|
|
|
|
|
|
|
|
|
PG_TRY();
|
|
|
|
|
{
|
|
|
|
|
Oid funcoid = fcinfo->flinfo->fn_oid;
|
|
|
|
|
PLyProcedure *proc;
|
|
|
|
|
|
|
|
|
|
if (CALLED_AS_TRIGGER(fcinfo))
|
|
|
|
|
{
|
|
|
|
|
Relation tgrel = ((TriggerData *) fcinfo->context)->tg_relation;
|
|
|
|
|
HeapTuple trv;
|
|
|
|
|
|
|
|
|
|
proc = PLy_procedure_get(funcoid, RelationGetRelid(tgrel), true);
|
|
|
|
|
exec_ctx->curr_proc = proc;
|
|
|
|
|
trv = PLy_exec_trigger(fcinfo, proc);
|
|
|
|
|
retval = PointerGetDatum(trv);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
proc = PLy_procedure_get(funcoid, InvalidOid, false);
|
|
|
|
|
exec_ctx->curr_proc = proc;
|
|
|
|
|
retval = PLy_exec_function(fcinfo, proc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PG_CATCH();
|
|
|
|
|
{
|
|
|
|
|
PLy_pop_execution_context();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
PG_RE_THROW();
|
|
|
|
|
}
|
|
|
|
|
PG_END_TRY();
|
|
|
|
|
|
|
|
|
|
/* Pop the error context stack */
|
|
|
|
|
error_context_stack = plerrcontext.previous;
|
|
|
|
|
/* ... and then the execution context */
|
|
|
|
|
PLy_pop_execution_context();
|
|
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
|
Datum
|
|
|
|
|
plpython2_call_handler(PG_FUNCTION_ARGS)
|
|
|
|
|
{
|
|
|
|
|
return plpython_call_handler(fcinfo);
|
|
|
|
|
}
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
9 years ago
|
|
|
#endif /* PY_MAJOR_VERSION < 3 */
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
|
plpython_inline_handler(PG_FUNCTION_ARGS)
|
|
|
|
|
{
|
|
|
|
|
InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
|
|
|
|
|
FunctionCallInfoData fake_fcinfo;
|
|
|
|
|
FmgrInfo flinfo;
|
|
|
|
|
PLyProcedure proc;
|
|
|
|
|
PLyExecutionContext *exec_ctx;
|
|
|
|
|
ErrorContextCallback plerrcontext;
|
|
|
|
|
|
Avoid dump/reload problems when using both plpython2 and plpython3.
Commit 803716013dc1350f installed a safeguard against loading plpython2
and plpython3 at the same time, but asserted that both could still be
used in the same database, just not in the same session. However, that's
not actually all that practical because dumping and reloading will fail
(since both libraries necessarily get loaded into the restoring session).
pg_upgrade is even worse, because it checks for missing libraries by
loading every .so library mentioned in the entire installation into one
session, so that you can have only one across the whole cluster.
We can improve matters by not throwing the error immediately in _PG_init,
but only when and if we're asked to do something that requires calling
into libpython. This ameliorates both of the above situations, since
while execution of CREATE LANGUAGE, CREATE FUNCTION, etc will result in
loading plpython, it isn't asked to do anything interesting (at least
not if check_function_bodies is off, as it will be during a restore).
It's possible that this opens some corner-case holes in which a crash
could be provoked with sufficient effort. However, since plpython
only exists as an untrusted language, any such crash would require
superuser privileges, making it "don't do that" not a security issue.
To reduce the hazards in this area, the error is still FATAL when it
does get thrown.
Per a report from Paul Jones. Back-patch to 9.2, which is as far back
as the patch applies without work. (It could be made to work in 9.1,
but given the lack of previous complaints, I'm disinclined to expend
effort so far back. We've been pretty desultory about support for
Python 3 in 9.1 anyway.)
10 years ago
|
|
|
PLy_initialize();
|
|
|
|
|
|
|
|
|
|
/* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
|
|
|
|
|
if (SPI_connect() != SPI_OK_CONNECT)
|
|
|
|
|
elog(ERROR, "SPI_connect failed");
|
|
|
|
|
|
|
|
|
|
MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
|
|
|
|
|
MemSet(&flinfo, 0, sizeof(flinfo));
|
|
|
|
|
fake_fcinfo.flinfo = &flinfo;
|
|
|
|
|
flinfo.fn_oid = InvalidOid;
|
|
|
|
|
flinfo.fn_mcxt = CurrentMemoryContext;
|
|
|
|
|
|
|
|
|
|
MemSet(&proc, 0, sizeof(PLyProcedure));
|
|
|
|
|
proc.mcxt = AllocSetContextCreate(TopMemoryContext,
|
|
|
|
|
"__plpython_inline_block",
|
Add macros to make AllocSetContextCreate() calls simpler and safer.
I found that half a dozen (nearly 5%) of our AllocSetContextCreate calls
had typos in the context-sizing parameters. While none of these led to
especially significant problems, they did create minor inefficiencies,
and it's now clear that expecting people to copy-and-paste those calls
accurately is not a great idea. Let's reduce the risk of future errors
by introducing single macros that encapsulate the common use-cases.
Three such macros are enough to cover all but two special-purpose contexts;
those two calls can be left as-is, I think.
While this patch doesn't in itself improve matters for third-party
extensions, it doesn't break anything for them either, and they can
gradually adopt the simplified notation over time.
In passing, change TopMemoryContext to use the default allocation
parameters. Formerly it could only be extended 8K at a time. That was
probably reasonable when this code was written; but nowadays we create
many more contexts than we did then, so that it's not unusual to have a
couple hundred K in TopMemoryContext, even without considering various
dubious code that sticks other things there. There seems no good reason
not to let it use growing blocks like most other contexts.
Back-patch to 9.6, mostly because that's still close enough to HEAD that
it's easy to do so, and keeping the branches in sync can be expected to
avoid some future back-patching pain. The bugs fixed by these changes
don't seem to be significant enough to justify fixing them further back.
Discussion: <21072.1472321324@sss.pgh.pa.us>
9 years ago
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
|
|
|
|
proc.pyname = MemoryContextStrdup(proc.mcxt, "__plpython_inline_block");
|
|
|
|
|
proc.langid = codeblock->langOid;
|
Make PL/Python handle domain-type conversions correctly.
Fix PL/Python so that it can handle domains over composite, and so that
it enforces domain constraints correctly in other cases that were not
always done properly before. Notably, it didn't do arrays of domains
right (oversight in commit c12d570fa), and it failed to enforce domain
constraints when returning a composite type containing a domain field,
and if a transform function is being used for a domain's base type then
it failed to enforce domain constraints on the result. Also, in many
places it missed checking domain constraints on null values, because
the plpy_typeio code simply wasn't called for Py_None.
Rather than try to band-aid these problems, I made a significant
refactoring of the plpy_typeio logic. The existing design of recursing
for array and composite members is extended to also treat domains as
containers requiring recursion, and the APIs for the module are cleaned
up and simplified.
The patch also modifies plpy_typeio to rely on the typcache more than
it did before (which was pretty much not at all). This reduces the
need for repetitive lookups, and lets us get rid of an ad-hoc scheme
for detecting changes in composite types. I added a couple of small
features to typcache to help with that.
Although some of this is fixing bugs that long predate v11, I don't
think we should risk a back-patch: it's a significant amount of code
churn, and there've been no complaints from the field about the bugs.
Tom Lane, reviewed by Anthony Bykov
Discussion: https://postgr.es/m/24449.1509393613@sss.pgh.pa.us
8 years ago
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is currently sufficient to get PLy_exec_function to work, but
|
|
|
|
|
* someday we might need to be honest and use PLy_output_setup_func.
|
|
|
|
|
*/
|
|
|
|
|
proc.result.typoid = VOIDOID;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Push execution context onto stack. It is important that this get
|
|
|
|
|
* popped again, so avoid putting anything that could throw error between
|
|
|
|
|
* here and the PG_TRY. (plpython_inline_error_callback doesn't currently
|
|
|
|
|
* need the stack entry, but for consistency with plpython_call_handler we
|
|
|
|
|
* do it in this order.)
|
|
|
|
|
*/
|
|
|
|
|
exec_ctx = PLy_push_execution_context();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Setup error traceback support for ereport()
|
|
|
|
|
*/
|
|
|
|
|
plerrcontext.callback = plpython_inline_error_callback;
|
|
|
|
|
plerrcontext.previous = error_context_stack;
|
|
|
|
|
error_context_stack = &plerrcontext;
|
|
|
|
|
|
|
|
|
|
PG_TRY();
|
|
|
|
|
{
|
|
|
|
|
PLy_procedure_compile(&proc, codeblock->source_text);
|
|
|
|
|
exec_ctx->curr_proc = &proc;
|
|
|
|
|
PLy_exec_function(&fake_fcinfo, &proc);
|
|
|
|
|
}
|
|
|
|
|
PG_CATCH();
|
|
|
|
|
{
|
|
|
|
|
PLy_pop_execution_context();
|
|
|
|
|
PLy_procedure_delete(&proc);
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
PG_RE_THROW();
|
|
|
|
|
}
|
|
|
|
|
PG_END_TRY();
|
|
|
|
|
|
|
|
|
|
/* Pop the error context stack */
|
|
|
|
|
error_context_stack = plerrcontext.previous;
|
|
|
|
|
/* ... and then the execution context */
|
|
|
|
|
PLy_pop_execution_context();
|
|
|
|
|
|
|
|
|
|
/* Now clean up the transient procedure we made */
|
|
|
|
|
PLy_procedure_delete(&proc);
|
|
|
|
|
|
|
|
|
|
PG_RETURN_VOID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
|
Datum
|
|
|
|
|
plpython2_inline_handler(PG_FUNCTION_ARGS)
|
|
|
|
|
{
|
|
|
|
|
return plpython_inline_handler(fcinfo);
|
|
|
|
|
}
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
9 years ago
|
|
|
#endif /* PY_MAJOR_VERSION < 3 */
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
PLy_procedure_is_trigger(Form_pg_proc procStruct)
|
|
|
|
|
{
|
|
|
|
|
return (procStruct->prorettype == TRIGGEROID ||
|
|
|
|
|
(procStruct->prorettype == OPAQUEOID &&
|
|
|
|
|
procStruct->pronargs == 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
plpython_error_callback(void *arg)
|
|
|
|
|
{
|
|
|
|
|
PLyExecutionContext *exec_ctx = PLy_current_execution_context();
|
|
|
|
|
|
|
|
|
|
if (exec_ctx->curr_proc)
|
|
|
|
|
errcontext("PL/Python function \"%s\"",
|
|
|
|
|
PLy_procedure_name(exec_ctx->curr_proc));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
plpython_inline_error_callback(void *arg)
|
|
|
|
|
{
|
|
|
|
|
errcontext("PL/Python anonymous code block");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PLyExecutionContext *
|
|
|
|
|
PLy_current_execution_context(void)
|
|
|
|
|
{
|
|
|
|
|
if (PLy_execution_contexts == NULL)
|
|
|
|
|
elog(ERROR, "no Python function is currently executing");
|
|
|
|
|
|
|
|
|
|
return PLy_execution_contexts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MemoryContext
|
|
|
|
|
PLy_get_scratch_context(PLyExecutionContext *context)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* A scratch context might never be needed in a given plpython procedure,
|
|
|
|
|
* so allocate it on first request.
|
|
|
|
|
*/
|
|
|
|
|
if (context->scratch_ctx == NULL)
|
|
|
|
|
context->scratch_ctx =
|
|
|
|
|
AllocSetContextCreate(TopTransactionContext,
|
|
|
|
|
"PL/Python scratch context",
|
Add macros to make AllocSetContextCreate() calls simpler and safer.
I found that half a dozen (nearly 5%) of our AllocSetContextCreate calls
had typos in the context-sizing parameters. While none of these led to
especially significant problems, they did create minor inefficiencies,
and it's now clear that expecting people to copy-and-paste those calls
accurately is not a great idea. Let's reduce the risk of future errors
by introducing single macros that encapsulate the common use-cases.
Three such macros are enough to cover all but two special-purpose contexts;
those two calls can be left as-is, I think.
While this patch doesn't in itself improve matters for third-party
extensions, it doesn't break anything for them either, and they can
gradually adopt the simplified notation over time.
In passing, change TopMemoryContext to use the default allocation
parameters. Formerly it could only be extended 8K at a time. That was
probably reasonable when this code was written; but nowadays we create
many more contexts than we did then, so that it's not unusual to have a
couple hundred K in TopMemoryContext, even without considering various
dubious code that sticks other things there. There seems no good reason
not to let it use growing blocks like most other contexts.
Back-patch to 9.6, mostly because that's still close enough to HEAD that
it's easy to do so, and keeping the branches in sync can be expected to
avoid some future back-patching pain. The bugs fixed by these changes
don't seem to be significant enough to justify fixing them further back.
Discussion: <21072.1472321324@sss.pgh.pa.us>
9 years ago
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
|
|
|
|
return context->scratch_ctx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PLyExecutionContext *
|
|
|
|
|
PLy_push_execution_context(void)
|
|
|
|
|
{
|
|
|
|
|
PLyExecutionContext *context;
|
|
|
|
|
|
|
|
|
|
context = (PLyExecutionContext *)
|
|
|
|
|
MemoryContextAlloc(TopTransactionContext, sizeof(PLyExecutionContext));
|
|
|
|
|
context->curr_proc = NULL;
|
|
|
|
|
context->scratch_ctx = NULL;
|
|
|
|
|
context->next = PLy_execution_contexts;
|
|
|
|
|
PLy_execution_contexts = context;
|
|
|
|
|
return context;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
PLy_pop_execution_context(void)
|
|
|
|
|
{
|
|
|
|
|
PLyExecutionContext *context = PLy_execution_contexts;
|
|
|
|
|
|
|
|
|
|
if (context == NULL)
|
|
|
|
|
elog(ERROR, "no Python function is currently executing");
|
|
|
|
|
|
|
|
|
|
PLy_execution_contexts = context->next;
|
|
|
|
|
|
|
|
|
|
if (context->scratch_ctx)
|
|
|
|
|
MemoryContextDelete(context->scratch_ctx);
|
|
|
|
|
pfree(context);
|
|
|
|
|
}
|