diff options
| author | Laurent Mignon (ACSONE) <laurent.mignon@acsone.eu> | 2020-07-10 10:43:38 +0000 |
|---|---|---|
| committer | Raphael Collet <rco@odoo.com> | 2020-10-20 08:43:02 +0000 |
| commit | 09bf7bd760136ddf55fc7e695a4b6c08d5fc4fed (patch) | |
| tree | 7256c2776168a67c945e17fd4965205c09291354 /odoo/sql_db.py | |
| parent | 436a94c0335120c2e6f0a91b5c8247e0a787e3a8 (diff) | |
[FIX] core: Ensure that rollback hooks are called when the cursor is closed
Before this change the rollback hooks were never called since rollback() was never explicitely called by the framework. At the end of a transaction, if no error occurs the famework call commit() on the odoo cursor. In all cases, the transaction ends with a call to close(). Into the implementation of _close() rollback() is called on the underlying connection to ensure that not committed changes are rollbacked. That's the reason why despite the fact that rollback() was not called on the Odoo cursor, changes are not committed into the db in case of exception. To keep the same behaviour and avoid to have to explicitely call rollback() on the odoo cursor to trigger the execution of registered rollback hooks, these hooks are now processed in _close(). Since the list of registered hooks is emptied if commit() is called, we are sure that rollback hooks are only executed in case of rollback.
OPW #2294911
closes odoo/odoo#60334
X-original-commit: dce9a05f3a5d37fab711c8ca3c5444941f98e814
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Diffstat (limited to 'odoo/sql_db.py')
| -rw-r--r-- | odoo/sql_db.py | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/odoo/sql_db.py b/odoo/sql_db.py index 1c15f4e4a2d..c5af069728e 100644 --- a/odoo/sql_db.py +++ b/odoo/sql_db.py @@ -107,6 +107,8 @@ class BaseCursor: def __init__(self): self.precommit = tools.Callbacks() self.postcommit = tools.Callbacks() + self.prerollback = tools.Callbacks() + self.postrollback = tools.Callbacks() @contextmanager @check @@ -378,10 +380,11 @@ class Cursor(BaseCursor): # collected as fast as they should). The problem is probably due in # part because browse records keep a reference to the cursor. del self._obj - self._closed = True - # Clean the underlying connection. - self._cnx.rollback() + # Clean the underlying connection, and run rollback hooks. + self.rollback() + + self._closed = True if leak: self._cnx.leaked = True @@ -433,7 +436,7 @@ class Cursor(BaseCursor): if event == 'commit': self.postcommit.add(func) elif event == 'rollback': - raise NotImplementedError() + self.postrollback.add(func) @check def commit(self): @@ -441,6 +444,8 @@ class Cursor(BaseCursor): flush_env(self) self.precommit.run() result = self._cnx.commit() + self.prerollback.clear() + self.postrollback.clear() self.postcommit.run() return result @@ -450,7 +455,9 @@ class Cursor(BaseCursor): clear_env(self) self.precommit.clear() self.postcommit.clear() + self.prerollback.run() result = self._cnx.rollback() + self.postrollback.run() return result @check @@ -496,8 +503,8 @@ class TestCursor(BaseCursor): def close(self): if not self._closed: + self.rollback() self._closed = True - self._cursor.execute('ROLLBACK TO SAVEPOINT "%s"' % self._savepoint) self._lock.release() def autocommit(self, on): @@ -509,16 +516,19 @@ class TestCursor(BaseCursor): flush_env(self) self.precommit.run() self._cursor.execute('SAVEPOINT "%s"' % self._savepoint) - # ignore post-commit hooks - self.postcommit.clear() + self.prerollback.clear() + self.postrollback.clear() + self.postcommit.clear() # TestCursor ignores post-commit hooks @check def rollback(self): """ Perform an SQL `ROLLBACK` """ clear_env(self) self.precommit.clear() - self._cursor.execute('ROLLBACK TO SAVEPOINT "%s"' % self._savepoint) self.postcommit.clear() + self.prerollback.run() + self._cursor.execute('ROLLBACK TO SAVEPOINT "%s"' % self._savepoint) + self.postrollback.run() def __getattr__(self, name): value = getattr(self._cursor, name) |
