diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index df2a6fb96e7..4a68d9d6f24 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -79,6 +79,20 @@ def CheckStatementAvailable(self): cur.fetchone() cur.fetchone() + def CheckErrorMsgDecodeError(self): + # When porting the module to Python 3.0, the error message about + # decoding errors disappeared. This verifies they're back again. + failure = None + try: + self.con.execute("select 'xxx' || ? || 'yyy' colname", (bytes(bytearray([250])),)).fetchone() + failure = "should have raised an OperationalError with detailed description" + except sqlite.OperationalError as e: + msg = e.args[0] + if not msg.startswith("Could not decode to UTF-8 column 'colname' with text 'xxx"): + failure = "OperationalError did not have expected description text" + if failure: + self.fail(failure) + def suite(): regression_suite = unittest.makeSuite(RegressionTests, "Check") return unittest.TestSuite((regression_suite,)) diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 6b81851213c..0bd317ad7e6 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -295,6 +295,8 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) const char* val_str; char buf[200]; const char* colname; + PyObject* buf_bytes; + PyObject* error_obj; Py_BEGIN_ALLOW_THREADS numcols = sqlite3_data_count(self->statement->st); @@ -363,7 +365,19 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) } PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column '%s' with text '%s'", colname , val_str); - PyErr_SetString(pysqlite_OperationalError, buf); + buf_bytes = PyBytes_FromStringAndSize(buf, strlen(buf)); + if (!buf_bytes) { + PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8"); + } else { + error_obj = PyUnicode_FromEncodedObject(buf_bytes, "ascii", "replace"); + if (!error_obj) { + PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8"); + Py_DECREF(error_obj); + } else { + PyErr_SetObject(pysqlite_OperationalError, error_obj); + } + Py_DECREF(buf_bytes); + } } } else if (self->connection->text_factory == (PyObject*)&PyString_Type) { converted = PyString_FromString(val_str);