diff options
Diffstat (limited to 'src/pl/plpython/plpy_elog.c')
-rw-r--r-- | src/pl/plpython/plpy_elog.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/src/pl/plpython/plpy_elog.c b/src/pl/plpython/plpy_elog.c index c375ac07fa8..70450d7d9e5 100644 --- a/src/pl/plpython/plpy_elog.c +++ b/src/pl/plpython/plpy_elog.c @@ -337,6 +337,31 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth) } /* + * Extract error code from SPIError's sqlstate attribute. + */ +static void +PLy_get_spi_sqlerrcode(PyObject *exc, int *sqlerrcode) +{ + PyObject *sqlstate; + char *buffer; + + sqlstate = PyObject_GetAttrString(exc, "sqlstate"); + if (sqlstate == NULL) + return; + + buffer = PyString_AsString(sqlstate); + if (strlen(buffer) == 5 && + strspn(buffer, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5) + { + *sqlerrcode = MAKE_SQLSTATE(buffer[0], buffer[1], buffer[2], + buffer[3], buffer[4]); + } + + Py_DECREF(sqlstate); +} + + +/* * Extract the error data from a SPIError */ static void @@ -345,13 +370,20 @@ PLy_get_spi_error_data(PyObject *exc, int *sqlerrcode, char **detail, char **hin PyObject *spidata = NULL; spidata = PyObject_GetAttrString(exc, "spidata"); - if (!spidata) - goto cleanup; - if (!PyArg_ParseTuple(spidata, "izzzi", sqlerrcode, detail, hint, query, position)) - goto cleanup; + if (spidata != NULL) + { + PyArg_ParseTuple(spidata, "izzzi", sqlerrcode, detail, hint, query, position); + } + else + { + /* + * If there's no spidata, at least set the sqlerrcode. This can happen + * if someone explicitly raises a SPI exception from Python code. + */ + PLy_get_spi_sqlerrcode(exc, sqlerrcode); + } -cleanup: PyErr_Clear(); /* no elog here, we simply won't report the errhint, errposition etc */ Py_XDECREF(spidata); |