diff options
Diffstat (limited to 'django/db')
| -rw-r--r-- | django/db/__init__.py | 13 | ||||
| -rw-r--r-- | django/db/backends/__init__.py | 11 | ||||
| -rw-r--r-- | django/db/transaction.py | 15 | ||||
| -rw-r--r-- | django/db/utils.py | 3 |
4 files changed, 40 insertions, 2 deletions
diff --git a/django/db/__init__.py b/django/db/__init__.py index b1980488df..94eca13d41 100644 --- a/django/db/__init__.py +++ b/django/db/__init__.py @@ -42,8 +42,17 @@ backend = load_backend(connection.settings_dict['ENGINE']) # Register an event that closes the database connection # when a Django request is finished. def close_connection(**kwargs): - for conn in connections.all(): - conn.close() + # Avoid circular imports + from django.db import transaction + for conn in connections: + try: + transaction.abort(conn) + connections[conn].close() + except Exception: + # The connection's state is unknown, so it has to be + # abandoned. This could happen for example if the network + # connection has a failure. + del connections[conn] signals.request_finished.connect(close_connection) # Register an event that resets connection.queries diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 7dc5456827..bbb5a5b294 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -88,6 +88,17 @@ class BaseDatabaseWrapper(object): return self.cursor().execute(self.ops.savepoint_commit_sql(sid)) + def abort(self): + """ + Roll back any ongoing transaction and clean the transaction state + stack. + """ + if self._dirty: + self._rollback() + self._dirty = False + while self.transaction_state: + self.leave_transaction_management() + def enter_transaction_management(self, managed=True): """ Enters transaction management for a running thread. It must be balanced with diff --git a/django/db/transaction.py b/django/db/transaction.py index f3ce2b2335..dd7e2f4dcb 100644 --- a/django/db/transaction.py +++ b/django/db/transaction.py @@ -24,6 +24,21 @@ class TransactionManagementError(Exception): """ pass +def abort(using=None): + """ + Roll back any ongoing transactions and clean the transaction management + state of the connection. + + This method is to be used only in cases where using balanced + leave_transaction_management() calls isn't possible. For example after a + request has finished, the transaction state isn't known, yet the connection + must be cleaned up for the next request. + """ + if using is None: + using = DEFAULT_DB_ALIAS + connection = connections[using] + connection.abort() + def enter_transaction_management(managed=True, using=None): """ Enters transaction management for a running thread. It must be balanced with diff --git a/django/db/utils.py b/django/db/utils.py index 91fa774ed4..943e3e3f73 100644 --- a/django/db/utils.py +++ b/django/db/utils.py @@ -99,6 +99,9 @@ class ConnectionHandler(object): def __setitem__(self, key, value): setattr(self._connections, key, value) + def __delitem__(self, key): + delattr(self._connections, key) + def __iter__(self): return iter(self.databases) |
