PyObject *PLy_exc_spi_error = NULL;
-static void PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth);
+static void PLy_traceback(PyObject *e, PyObject *v, PyObject *tb,
+ char **xmsg, char **tbmsg, int *tb_depth);
static void PLy_get_spi_error_data(PyObject *exc, int *sqlerrcode, char **detail,
char **hint, char **query, int *position,
char **schema_name, char **table_name, char **column_name,
char *constraint_name = NULL;
PyErr_Fetch(&exc, &val, &tb);
+
if (exc != NULL)
{
+ PyErr_NormalizeException(&exc, &val, &tb);
+
if (PyErr_GivenExceptionMatches(val, PLy_exc_spi_error))
- PLy_get_spi_error_data(val, &sqlerrcode, &detail, &hint, &query, &position,
- &schema_name, &table_name, &column_name,
- &datatype_name, &constraint_name);
+ PLy_get_spi_error_data(val, &sqlerrcode,
+ &detail, &hint, &query, &position,
+ &schema_name, &table_name, &column_name,
+ &datatype_name, &constraint_name);
else if (PyErr_GivenExceptionMatches(val, PLy_exc_error))
PLy_get_error_data(val, &sqlerrcode, &detail, &hint,
- &schema_name, &table_name, &column_name,
- &datatype_name, &constraint_name);
+ &schema_name, &table_name, &column_name,
+ &datatype_name, &constraint_name);
else if (PyErr_GivenExceptionMatches(val, PLy_exc_fatal))
elevel = FATAL;
}
- PyErr_Restore(exc, val, tb);
- PLy_traceback(&xmsg, &tbmsg, &tb_depth);
+ /* this releases our refcount on tb! */
+ PLy_traceback(exc, val, tb,
+ &xmsg, &tbmsg, &tb_depth);
if (fmt)
{
(hint) ? errhint("%s", hint) : 0,
(query) ? internalerrquery(query) : 0,
(position) ? internalerrposition(position) : 0,
- (schema_name) ? err_generic_string(PG_DIAG_SCHEMA_NAME, schema_name) : 0,
- (table_name) ? err_generic_string(PG_DIAG_TABLE_NAME, table_name) : 0,
- (column_name) ? err_generic_string(PG_DIAG_COLUMN_NAME, column_name) : 0,
- (datatype_name) ? err_generic_string(PG_DIAG_DATATYPE_NAME, datatype_name) : 0,
- (constraint_name) ? err_generic_string(PG_DIAG_CONSTRAINT_NAME, constraint_name) : 0));
+ (schema_name) ? err_generic_string(PG_DIAG_SCHEMA_NAME,
+ schema_name) : 0,
+ (table_name) ? err_generic_string(PG_DIAG_TABLE_NAME,
+ table_name) : 0,
+ (column_name) ? err_generic_string(PG_DIAG_COLUMN_NAME,
+ column_name) : 0,
+ (datatype_name) ? err_generic_string(PG_DIAG_DATATYPE_NAME,
+ datatype_name) : 0,
+ (constraint_name) ? err_generic_string(PG_DIAG_CONSTRAINT_NAME,
+ constraint_name) : 0));
}
PG_CATCH();
{
pfree(xmsg);
if (tbmsg)
pfree(tbmsg);
+ Py_XDECREF(exc);
+ Py_XDECREF(val);
+
PG_RE_THROW();
}
PG_END_TRY();
pfree(xmsg);
if (tbmsg)
pfree(tbmsg);
+ Py_XDECREF(exc);
+ Py_XDECREF(val);
}
/*
- * Extract a Python traceback from the current exception.
+ * Extract a Python traceback from the given exception data.
*
* The exception error message is returned in xmsg, the traceback in
* tbmsg (both as palloc'd strings) and the traceback depth in
* tb_depth.
+ *
+ * We release refcounts on all the Python objects in the traceback stack,
+ * but not on e or v.
*/
static void
-PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
+PLy_traceback(PyObject *e, PyObject *v, PyObject *tb,
+ char **xmsg, char **tbmsg, int *tb_depth)
{
- PyObject *e,
- *v,
- *tb;
PyObject *e_type_o;
PyObject *e_module_o;
char *e_type_s = NULL;
StringInfoData tbstr;
/*
- * get the current exception
- */
- PyErr_Fetch(&e, &v, &tb);
-
- /*
- * oops, no exception, return
+ * if no exception, return nulls
*/
if (e == NULL)
{
return;
}
- PyErr_NormalizeException(&e, &v, &tb);
-
/*
* Format the exception and its value and put it in xmsg.
*/
Py_XDECREF(e_type_o);
Py_XDECREF(e_module_o);
Py_XDECREF(vob);
- Py_XDECREF(v);
- Py_DECREF(e);
}
/*
*/
static void
PLy_get_spi_error_data(PyObject *exc, int *sqlerrcode, char **detail,
- char **hint, char **query, int *position,
- char **schema_name, char **table_name, char **column_name,
- char **datatype_name, char **constraint_name)
+ char **hint, char **query, int *position,
+ char **schema_name, char **table_name,
+ char **column_name,
+ char **datatype_name, char **constraint_name)
{
- PyObject *spidata = NULL;
+ PyObject *spidata;
spidata = PyObject_GetAttrString(exc, "spidata");
if (spidata != NULL)
{
- PyArg_ParseTuple(spidata, "izzzizzzzz", sqlerrcode, detail, hint, query, position,
- schema_name, table_name, column_name,
- datatype_name, constraint_name);
+ PyArg_ParseTuple(spidata, "izzzizzzzz",
+ sqlerrcode, detail, hint, query, position,
+ schema_name, table_name, column_name,
+ datatype_name, constraint_name);
}
else
{
PLy_get_sqlerrcode(exc, sqlerrcode);
}
- PyErr_Clear();
- /* no elog here, we simply won't report the errhint, errposition etc */
Py_XDECREF(spidata);
}
/*
* Extract the error data from an Error.
+ *
* Note: position and query attributes are never set for Error so, unlike
* PLy_get_spi_error_data, this function doesn't return them.
*/
static void
PLy_get_error_data(PyObject *exc, int *sqlerrcode, char **detail, char **hint,
- char **schema_name, char **table_name, char **column_name,
- char **datatype_name, char **constraint_name)
+ char **schema_name, char **table_name, char **column_name,
+ char **datatype_name, char **constraint_name)
{
PLy_get_sqlerrcode(exc, sqlerrcode);
-
get_string_attr(exc, "detail", detail);
get_string_attr(exc, "hint", hint);
get_string_attr(exc, "schema_name", schema_name);
get_string_attr(exc, "column_name", column_name);
get_string_attr(exc, "datatype_name", datatype_name);
get_string_attr(exc, "constraint_name", constraint_name);
-
- PyErr_Clear();
- /* no elog here, we simply won't report the errhint, errposition etc */
}
/*