summaryrefslogtreecommitdiffstats
path: root/Modules/_sqlite
diff options
context:
space:
mode:
authorErlend Egeberg Aasland <erlend.aasland@innova.no>2021-08-25 10:59:42 (GMT)
committerGitHub <noreply@github.com>2021-08-25 10:59:42 (GMT)
commit7ecd3425d45a37efbc745788dfe21df0286c785a (patch)
tree5480bf4db64fadf5ad4e2e931464c8278443ea28 /Modules/_sqlite
parent3df0fc89bc2714f5ef03e36a926bc795dcd5e05a (diff)
downloadcpython-7ecd3425d45a37efbc745788dfe21df0286c785a.zip
cpython-7ecd3425d45a37efbc745788dfe21df0286c785a.tar.gz
cpython-7ecd3425d45a37efbc745788dfe21df0286c785a.tar.bz2
bpo-27334: roll back transaction if sqlite3 context manager fails to commit (GH-26202)
Co-authored-by: Luca Citi Co-authored-by: Berker Peksag <berker.peksag@gmail.com>
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r--Modules/_sqlite/connection.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 8ad5f5f..1bc0455 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -1785,17 +1785,31 @@ pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type,
PyObject *exc_value, PyObject *exc_tb)
/*[clinic end generated code: output=0705200e9321202a input=bd66f1532c9c54a7]*/
{
- const char* method_name;
+ int commit = 0;
PyObject* result;
if (exc_type == Py_None && exc_value == Py_None && exc_tb == Py_None) {
- method_name = "commit";
- } else {
- method_name = "rollback";
+ commit = 1;
+ result = pysqlite_connection_commit_impl(self);
}
-
- result = PyObject_CallMethod((PyObject*)self, method_name, NULL);
- if (!result) {
+ else {
+ result = pysqlite_connection_rollback_impl(self);
+ }
+
+ if (result == NULL) {
+ if (commit) {
+ /* Commit failed; try to rollback in order to unlock the database.
+ * If rollback also fails, chain the exceptions. */
+ PyObject *exc, *val, *tb;
+ PyErr_Fetch(&exc, &val, &tb);
+ result = pysqlite_connection_rollback_impl(self);
+ if (result == NULL) {
+ _PyErr_ChainExceptions(exc, val, tb);
+ }
+ else {
+ PyErr_Restore(exc, val, tb);
+ }
+ }
return NULL;
}
Py_DECREF(result);