DB-API: ensure that undo/redo operations are in a low-level db transaction

This commit is contained in:
Doug Blank 2016-05-12 16:33:52 -04:00
parent 636903bbc7
commit aa9246dde4
2 changed files with 57 additions and 8 deletions

View File

@ -139,15 +139,22 @@ class DbGenericUndo(DbUndo):
subitems = transaction.get_recnos()
# Process all records in the transaction
for record_id in subitems:
(key, trans_type, handle, old_data, new_data) = \
pickle.loads(self.undodb[record_id])
try:
self.db.transaction_backend_begin()
for record_id in subitems:
(key, trans_type, handle, old_data, new_data) = \
pickle.loads(self.undodb[record_id])
if key == REFERENCE_KEY:
self.undo_reference(new_data, handle, self.mapbase[key])
else:
self.undo_data(new_data, handle, self.mapbase[key],
db.emit, SIGBASE[key])
self.db.transaction_backend_commit()
except:
self.db.transaction_backend_abort()
raise
if key == REFERENCE_KEY:
self.undo_reference(new_data, handle, self.mapbase[key])
else:
self.undo_data(new_data, handle, self.mapbase[key],
db.emit, SIGBASE[key])
# Notify listeners
if db.undo_callback:
db.undo_callback(_("_Undo %s")
@ -847,6 +854,27 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
return self.get_table_func(table_name)
return None
def transaction_backend_begin(self):
"""
Lowlevel interface to the backend transaction.
Executes a db BEGIN;
"""
pass
def transaction_backend_commit(self):
"""
Lowlevel interface to the backend transaction.
Executes a db END;
"""
pass
def transaction_backend_abort(self):
"""
Lowlevel interface to the backend transaction.
Executes a db ROLLBACK;
"""
pass
def transaction_begin(self, transaction):
"""
Transactions are handled automatically by the db layer.

View File

@ -329,6 +329,27 @@ class DBAPI(DbGeneric):
def close_backend(self):
self.dbapi.close()
def transaction_backend_begin(self):
"""
Lowlevel interface to the backend transaction.
Executes a db BEGIN;
"""
self.dbapi.begin()
def transaction_backend_commit(self):
"""
Lowlevel interface to the backend transaction.
Executes a db END;
"""
self.dbapi.commit()
def transaction_backend_abort(self):
"""
Lowlevel interface to the backend transaction.
Executes a db ROLLBACK;
"""
self.dbapi.rollback()
def transaction_begin(self, transaction):
"""
Transactions are handled automatically by the db layer.