plpython-traceback-bug.patch
text/x-patch
Filename: plpython-traceback-bug.patch
Type: text/x-patch
Part: 0
Message:
Re: pl/python tracebacks v2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/pl/plpython/plpython.c | 0 | 0 |
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 9352580..b2333b8 100644
*** a/src/pl/plpython/plpython.c
--- b/src/pl/plpython/plpython.c
*************** get_source_line(const char *src, int lin
*** 4507,4512 ****
--- 4507,4520 ----
if (next == NULL)
return pstrdup(s);
+ /*
+ * Sanity check, next < s if the line was all-whitespace, which should
+ * never happen if Python reported an frame created on that line, but
+ * check anyway.
+ */
+ if (next < s)
+ return NULL;
+
return pnstrdup(s, next - s);
}
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4603,4608 ****
--- 4611,4617 ----
PyObject *volatile code = NULL;
PyObject *volatile name = NULL;
PyObject *volatile lineno = NULL;
+ PyObject *volatile filename = NULL;
PG_TRY();
{
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4621,4626 ****
--- 4630,4639 ----
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();
{
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4628,4633 ****
--- 4641,4647 ----
Py_XDECREF(code);
Py_XDECREF(name);
Py_XDECREF(lineno);
+ Py_XDECREF(filename);
PG_RE_THROW();
}
PG_END_TRY();
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4638,4643 ****
--- 4652,4658 ----
char *proname;
char *fname;
char *line;
+ char *plain_filename;
long plain_lineno;
/*
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4651,4656 ****
--- 4666,4672 ----
fname = PyString_AsString(name);
proname = PLy_procedure_name(PLy_curr_procedure);
+ plain_filename = PyString_AsString(filename);
plain_lineno = PyInt_AsLong(lineno);
if (proname == NULL)
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4662,4668 ****
&tbstr, "\n PL/Python function \"%s\", line %ld, in %s",
proname, plain_lineno - 1, fname);
! if (PLy_curr_procedure)
{
/*
* If we know the current procedure, append the exact
--- 4678,4686 ----
&tbstr, "\n PL/Python function \"%s\", line %ld, in %s",
proname, plain_lineno - 1, fname);
! /* the 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
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4670,4676 ****
* traceback.py 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.
*/
line = get_source_line(PLy_curr_procedure->src, plain_lineno);
if (line)
--- 4688,4696 ----
* traceback.py 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. However,
! * 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)
*************** PLy_traceback(char **xmsg, char **tbmsg,
*** 4685,4690 ****
--- 4705,4711 ----
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;