* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.33 2003/06/11 18:33:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.34 2003/06/25 01:18:58 momjian Exp $
*
*********************************************************************
*/
#include "utils/syscache.h"
#include <Python.h>
+#include <compile.h>
+#include <eval.h>
#include "plpython.h"
/* convert Postgresql Datum or tuple into a PyObject.
* tuple type */
PLyTypeInfo args[FUNC_MAX_ARGS];
int nargs;
- PyObject *interp; /* restricted interpreter instance */
- PyObject *reval; /* interpreter return */
PyObject *code; /* compiled procedure code */
PyObject *statics; /* data saved across calls, local scope */
PyObject *globals; /* data saved across calls, global score */
*/
static void PLy_init_all(void);
static void PLy_init_interp(void);
-static void PLy_init_safe_interp(void);
static void PLy_init_plpy(void);
-/* Helper functions used during initialization */
-static int populate_methods(PyObject * klass, PyMethodDef * methods);
-static PyObject *build_tuple(char *string_list[], int len);
-
/* error handler. collects the current Python exception, if any,
* and appends it to the error and sends it to elog
*/
static void PLy_output_tuple_funcs(PLyTypeInfo *, TupleDesc);
static void PLy_input_tuple_funcs(PLyTypeInfo *, TupleDesc);
-/* RExec methods
- */
-static PyObject *PLy_r_open(PyObject * self, PyObject * args);
-
/* conversion functions
*/
static PyObject *PLyDict_FromTuple(PLyTypeInfo *, HeapTuple, TupleDesc);
static volatile int PLy_restart_in_progress = 0;
static PyObject *PLy_interp_globals = NULL;
-static PyObject *PLy_interp_safe = NULL;
static PyObject *PLy_interp_safe_globals = NULL;
-static PyObject *PLy_importable_modules = NULL;
-static PyObject *PLy_ok_posix_names = NULL;
-static PyObject *PLy_ok_sys_names = NULL;
static PyObject *PLy_procedure_cache = NULL;
-static char *PLy_importable_modules_list[] = {
- "array",
- "bisect",
- "binascii",
- "calendar",
- "cmath",
- "codecs",
- "errno",
- "marshal",
- "math",
- "md5",
- "mpz",
- "operator",
- "pcre",
- "pickle",
- "random",
- "re",
- "regex",
- "sre",
- "sha",
- "string",
- "StringIO",
- "struct",
- "time",
- "whrandom",
- "zlib"
-};
-
-static char *PLy_ok_posix_names_list[] = {
- /* None for now */
-};
-
-static char *PLy_ok_sys_names_list[] = {
- "byteeorder",
- "copyright",
- "getdefaultencoding",
- "getrefcount",
- "hexrevision",
- "maxint",
- "maxunicode",
- "platform",
- "version",
- "version_info"
-};
-
/* Python exceptions
*/
static PyObject *PLy_exc_error = NULL;
current = PLy_last_procedure;
PLy_last_procedure = proc;
PyDict_SetItemString(proc->globals, kargs, vargs);
- rv = PyObject_CallFunction(proc->reval, "O", proc->code);
+ rv = PyEval_EvalCode( (PyCodeObject*)proc->code, proc->globals, proc->globals);
PLy_last_procedure = current;
if ((rv == NULL) || (PyErr_Occurred()))
for (i = 0; i < FUNC_MAX_ARGS; i++)
PLy_typeinfo_init(&proc->args[i]);
proc->nargs = 0;
- proc->code = proc->interp = proc->reval = proc->statics = NULL;
+ proc->code = proc->statics = NULL;
proc->globals = proc->me = NULL;
SAVE_EXC();
void
PLy_procedure_compile(PLyProcedure * proc, const char *src)
{
- PyObject *module,
- *crv = NULL;
+ PyObject *crv = NULL;
char *msrc;
enter();
- /*
- * get an instance of rexec.RExec for the function
- */
- proc->interp = PyObject_CallMethod(PLy_interp_safe, "RExec", NULL);
- if ((proc->interp == NULL) || (PyErr_Occurred()))
- PLy_elog(ERROR, "Unable to create rexec.RExec instance");
-
- proc->reval = PyObject_GetAttrString(proc->interp, "r_eval");
- if ((proc->reval == NULL) || (PyErr_Occurred()))
- PLy_elog(ERROR, "Unable to get method `r_eval' from rexec.RExec");
-
- /*
- * add a __main__ module to the function's interpreter
- */
- module = PyObject_CallMethod(proc->interp, "add_module", "s", "__main__");
- if ((module == NULL) || (PyErr_Occurred()))
- PLy_elog(ERROR, "Unable to get module `__main__' from rexec.RExec");
-
- /*
- * add plpy module to the interpreters main dictionary
- */
- proc->globals = PyModule_GetDict(module);
- if ((proc->globals == NULL) || (PyErr_Occurred()))
- PLy_elog(ERROR, "Unable to get `__main__.__dict__' from rexec.RExec");
-
- /*
- * why the hell won't r_import or r_exec('import plpy') work?
- */
- module = PyDict_GetItemString(PLy_interp_globals, "plpy");
- if ((module == NULL) || (PyErr_Occurred()))
- PLy_elog(ERROR, "Unable to get `plpy'");
- Py_INCREF(module);
- PyDict_SetItemString(proc->globals, "plpy", module);
+ proc->globals = PyDict_Copy(PLy_interp_globals);
/*
* SD is private preserved data between calls GD is global data shared
*/
proc->statics = PyDict_New();
PyDict_SetItemString(proc->globals, "SD", proc->statics);
- PyDict_SetItemString(proc->globals, "GD", PLy_interp_safe_globals);
/*
* insert the function code into the interpreter
*/
msrc = PLy_procedure_munge_source(proc->pyname, src);
- crv = PyObject_CallMethod(proc->interp, "r_exec", "s", msrc);
+ crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
free(msrc);
if ((crv != NULL) && (!PyErr_Occurred()))
enter();
Py_XDECREF(proc->code);
- Py_XDECREF(proc->interp);
- Py_XDECREF(proc->reval);
Py_XDECREF(proc->statics);
Py_XDECREF(proc->globals);
Py_XDECREF(proc->me);
Py_Initialize();
PLy_init_interp();
PLy_init_plpy();
- PLy_init_safe_interp();
if (PyErr_Occurred())
PLy_elog(FATAL, "Untrapped error in initialization.");
PLy_procedure_cache = PyDict_New();
PLy_elog(ERROR, "Unable to import '__main__' module.");
Py_INCREF(mainmod);
PLy_interp_globals = PyModule_GetDict(mainmod);
+ PLy_interp_safe_globals = PyDict_New();
+ PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
Py_DECREF(mainmod);
if ((PLy_interp_globals == NULL) || (PyErr_Occurred()))
PLy_elog(ERROR, "Unable to initialize globals.");
elog(ERROR, "Unable to init plpy.");
}
-/*
- * New RExec methods
- */
-
-PyObject *
-PLy_r_open(PyObject * self, PyObject * args)
-{
- PyErr_SetString(PyExc_IOError, "can't open files in restricted mode");
- return NULL;
-}
-
-
-static PyMethodDef PLy_r_exec_methods[] = {
- {"r_open", (PyCFunction) PLy_r_open, METH_VARARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
-/*
- * Init new RExec
- */
-
-void
-PLy_init_safe_interp(void)
-{
- PyObject *rmod,
- *rexec,
- *rexec_dict;
- char *rname = "rexec";
- int len;
-
- enter();
-
- rmod = PyImport_ImportModuleEx(rname, PLy_interp_globals,
- PLy_interp_globals, Py_None);
- if ((rmod == NULL) || (PyErr_Occurred()))
- PLy_elog(ERROR, "Unable to import %s.", rname);
- PyDict_SetItemString(PLy_interp_globals, rname, rmod);
- PLy_interp_safe = rmod;
-
- len = sizeof(PLy_importable_modules_list) / sizeof(char *);
- PLy_importable_modules = build_tuple(PLy_importable_modules_list, len);
-
- len = sizeof(PLy_ok_posix_names_list) / sizeof(char *);
- PLy_ok_posix_names = build_tuple(PLy_ok_posix_names_list, len);
-
- len = sizeof(PLy_ok_sys_names_list) / sizeof(char *);
- PLy_ok_sys_names = build_tuple(PLy_ok_sys_names_list, len);
-
- PLy_interp_safe_globals = PyDict_New();
- if (PLy_interp_safe_globals == NULL)
- PLy_elog(ERROR, "Unable to create shared global dictionary.");
-
- /*
- * get an rexec.RExec class
- */
- rexec = PyDict_GetItemString(PyModule_GetDict(rmod), "RExec");
-
- if (rexec == NULL || !PyClass_Check(rexec))
- PLy_elog(ERROR, "Unable to get RExec object.");
-
-
- rexec_dict = ((PyClassObject *) rexec)->cl_dict;
-
- /*
- * tweak the list of permitted modules, posix and sys functions
- */
- PyDict_SetItemString(rexec_dict, "ok_builtin_modules", PLy_importable_modules);
- PyDict_SetItemString(rexec_dict, "ok_posix_names", PLy_ok_posix_names);
- PyDict_SetItemString(rexec_dict, "ok_sys_names", PLy_ok_sys_names);
-
- /*
- * change the r_open behavior
- */
- if (populate_methods(rexec, PLy_r_exec_methods))
- PLy_elog(ERROR, "Failed to update RExec methods.");
-}
-
-/* Helper function to build tuples from string lists */
-static
-PyObject *
-build_tuple(char *string_list[], int len)
-{
- PyObject *tup = PyTuple_New(len);
- int i;
-
- for (i = 0; i < len; i++)
- {
- PyObject *m = PyString_FromString(string_list[i]);
-
- PyTuple_SetItem(tup, i, m);
- }
- return tup;
-}
-
-/* Helper function for populating a class with method wrappers. */
-static int
-populate_methods(PyObject * klass, PyMethodDef * methods)
-{
- if (!klass || !methods)
- return 0;
-
- for (; methods->ml_name; ++methods)
- {
-
- /* get a wrapper for the built-in function */
- PyObject *func = PyCFunction_New(methods, NULL);
- PyObject *meth;
- int status;
-
- if (!func)
- return -1;
-
- /* turn the function into an unbound method */
- if (!(meth = PyMethod_New(func, NULL, klass)))
- {
- Py_DECREF(func);
- return -1;
- }
-
- /* add method to dictionary */
- status = PyDict_SetItemString(((PyClassObject *) klass)->cl_dict,
- methods->ml_name, meth);
- Py_DECREF(meth);
- Py_DECREF(func);
-
- /* stop now if an error occurred, otherwise do the next method */
- if (status)
- return status;
- }
- return 0;
-}
-
-
/* the python interface to the elog function
* don't confuse these with PLy_elog
*/