aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pl/plpython/plpython.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 5e600daa96a..8108cfce2c0 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -4510,6 +4510,14 @@ get_source_line(const char *src, int lineno)
if (next == NULL)
return pstrdup(s);
+ /*
+ * Sanity check, next < s if the line was all-whitespace, which should
+ * never happen if Python reported a frame created on that line, but
+ * check anyway.
+ */
+ if (next < s)
+ return NULL;
+
return pnstrdup(s, next - s);
}
@@ -4606,6 +4614,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
PyObject *volatile code = NULL;
PyObject *volatile name = NULL;
PyObject *volatile lineno = NULL;
+ PyObject *volatile filename = NULL;
PG_TRY();
{
@@ -4624,6 +4633,10 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
name = PyObject_GetAttrString(code, "co_name");
if (name == NULL)
elog(ERROR, "could not get function name from Python code object");
+
+ filename = PyObject_GetAttrString(code, "co_filename");
+ if (filename == NULL)
+ elog(ERROR, "could not get file name from Python code object");
}
PG_CATCH();
{
@@ -4631,6 +4644,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
Py_XDECREF(code);
Py_XDECREF(name);
Py_XDECREF(lineno);
+ Py_XDECREF(filename);
PG_RE_THROW();
}
PG_END_TRY();
@@ -4641,6 +4655,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
char *proname;
char *fname;
char *line;
+ char *plain_filename;
long plain_lineno;
/*
@@ -4653,6 +4668,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
fname = PyString_AsString(name);
proname = PLy_procedure_name(PLy_curr_procedure);
+ plain_filename = PyString_AsString(filename);
plain_lineno = PyInt_AsLong(lineno);
if (proname == NULL)
@@ -4664,7 +4680,9 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
&tbstr, "\n PL/Python function \"%s\", line %ld, in %s",
proname, plain_lineno - 1, fname);
- if (PLy_curr_procedure)
+ /* function code object was compiled with "<string>" as the filename */
+ if (PLy_curr_procedure && plain_filename != NULL &&
+ strcmp(plain_filename, "<string>") == 0)
{
/*
* If we know the current procedure, append the exact line
@@ -4672,7 +4690,8 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
* module behavior. We could store the already line-split
* source to avoid splitting it every time, but producing a
* traceback is not the most important scenario to optimize
- * for.
+ * for. But we do not go as far as traceback.py in reading
+ * the source of imported modules.
*/
line = get_source_line(PLy_curr_procedure->src, plain_lineno);
if (line)
@@ -4687,6 +4706,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
Py_DECREF(code);
Py_DECREF(name);
Py_DECREF(lineno);
+ Py_DECREF(filename);
/* Release the current frame and go to the next one. */
tb_prev = tb;