diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py index 2e0bf6467..692013081 100644 --- a/gramps/gen/db/generic.py +++ b/gramps/gen/db/generic.py @@ -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. diff --git a/gramps/plugins/database/dbapi.py b/gramps/plugins/database/dbapi.py index 096792b3a..1874700cb 100644 --- a/gramps/plugins/database/dbapi.py +++ b/gramps/plugins/database/dbapi.py @@ -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.