Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added an API to control database-level autocommit.

  • Loading branch information...
commit f5156194945661d217523d6648dfb9b48707ec95 1 parent 7aacde8
Aymeric Augustin aaugustin authored
14 django/db/backends/__init__.py
View
@@ -44,6 +44,7 @@ def __init__(self, settings_dict, alias=DEFAULT_DB_ALIAS,
self.savepoint_state = 0
# Transaction management related attributes
+ self.autocommit = False
self.transaction_state = []
# Tracks if the connection is believed to be in transaction. This is
# set somewhat aggressively, as the DBAPI doesn't make it easy to
@@ -232,6 +233,12 @@ def _leave_transaction_management(self, managed):
"""
pass
+ def _set_autocommit(self, autocommit):
+ """
+ Backend-specific implementation to enable or disable autocommit.
+ """
+ raise NotImplementedError
+
##### Generic transaction management methods #####
def enter_transaction_management(self, managed=True, forced=False):
@@ -274,6 +281,13 @@ def leave_transaction_management(self):
raise TransactionManagementError(
"Transaction managed block ended with pending COMMIT/ROLLBACK")
+ def set_autocommit(self, autocommit=True):
+ """
+ Enable or disable autocommit.
+ """
+ self._set_autocommit(autocommit)
+ self.autocommit = autocommit
+
def abort(self):
"""
Roll back any ongoing transaction and clean the transaction state
6 django/db/backends/creation.py
View
@@ -1,6 +1,7 @@
import hashlib
import sys
import time
+import warnings
from django.conf import settings
from django.db.utils import load_backend
@@ -466,7 +467,10 @@ def set_autocommit(self):
anymore by Django code. Kept for compatibility with user code that
might use it.
"""
- pass
+ warnings.warn(
+ "set_autocommit was moved from BaseDatabaseCreation to "
+ "BaseDatabaseWrapper.", PendingDeprecationWarning, stacklevel=2)
+ return self.connection.set_autocommit()
def _prepare_for_test_db_ddl(self):
"""
1  django/db/backends/dummy/base.py
View
@@ -57,6 +57,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
_savepoint_rollback = ignore
_enter_transaction_management = complain
_leave_transaction_management = ignore
+ _set_autocommit = complain
set_dirty = complain
set_clean = complain
commit_unless_managed = complain
3  django/db/backends/mysql/base.py
View
@@ -445,6 +445,9 @@ def _rollback(self):
except Database.NotSupportedError:
pass
+ def _set_autocommit(self, autocommit):
+ self.connection.autocommit(autocommit)
+
def disable_constraint_checking(self):
"""
Disables foreign key checks, primarily for use in adding rows with forward references. Always returns True,
3  django/db/backends/oracle/base.py
View
@@ -612,6 +612,9 @@ def _commit(self):
def _savepoint_commit(self, sid):
pass
+ def _set_autocommit(self, autocommit):
+ self.connection.autocommit = autocommit
+
def check_constraints(self, table_names=None):
"""
To check constraints, we set constraints to immediate. Then, when, we're done we must ensure they
3  django/db/backends/oracle/creation.py
View
@@ -273,6 +273,3 @@ def test_db_signature(self):
settings_dict['NAME'],
self._test_database_user(),
)
-
- def set_autocommit(self):
- self.connection.connection.autocommit = True
8 django/db/backends/postgresql_psycopg2/base.py
View
@@ -201,6 +201,14 @@ def _set_isolation_level(self, level):
self.isolation_level = level
self.features.uses_savepoints = bool(level)
+ def _set_autocommit(self, autocommit):
+ if autocommit:
+ level = psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT
+ else:
+ level = self.settings_dict["OPTIONS"].get('isolation_level',
+ psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED)
+ self._set_isolation_level(level)
+
def set_dirty(self):
if ((self.transaction_state and self.transaction_state[-1]) or
not self.features.uses_autocommit):
3  django/db/backends/postgresql_psycopg2/creation.py
View
@@ -78,9 +78,6 @@ def get_index_sql(index_name, opclass=''):
' text_pattern_ops'))
return output
- def set_autocommit(self):
- self._prepare_for_test_db_ddl()
-
def _prepare_for_test_db_ddl(self):
"""Rollback and close the active transaction."""
# Make sure there is an open connection.
11 django/db/backends/sqlite3/base.py
View
@@ -355,6 +355,17 @@ def close(self):
if self.settings_dict['NAME'] != ":memory:":
BaseDatabaseWrapper.close(self)
+ def _set_autocommit(self, autocommit):
+ if autocommit:
+ level = None
+ else:
+ # sqlite3's internal default is ''. It's different from None.
+ # See Modules/_sqlite/connection.c.
+ level = ''
+ # 'isolation_level' is a misleading API.
+ # SQLite always runs at the SERIALIZABLE isolation level.
+ self.connection.isolation_level = level
+
def check_constraints(self, table_names=None):
"""
Checks each table name in `table_names` for rows with invalid foreign key references. This method is
3  django/db/backends/sqlite3/creation.py
View
@@ -72,9 +72,6 @@ def _destroy_test_db(self, test_database_name, verbosity):
# Remove the SQLite database file
os.remove(test_database_name)
- def set_autocommit(self):
- self.connection.connection.isolation_level = None
-
def test_db_signature(self):
"""
Returns a tuple that uniquely identifies a test database.
12 django/db/transaction.py
View
@@ -39,6 +39,18 @@ def get_connection(using=None):
using = DEFAULT_DB_ALIAS
return connections[using]
+def get_autocommit(using=None):
+ """
+ Get the autocommit status of the connection.
+ """
+ return get_connection(using).autocommit
+
+def set_autocommit(using=None, autocommit=True):
+ """
+ Set the autocommit status of the connection.
+ """
+ return get_connection(using).set_autocommit(autocommit)
+
def abort(using=None):
"""
Roll back any ongoing transactions and clean the transaction management
3  django/test/testcases.py
View
@@ -63,6 +63,7 @@ def to_list(value):
value = [value]
return value
+real_set_autocommit = transaction.set_autocommit
real_commit = transaction.commit
real_rollback = transaction.rollback
real_enter_transaction_management = transaction.enter_transaction_management
@@ -73,6 +74,7 @@ def nop(*args, **kwargs):
return
def disable_transaction_methods():
+ transaction.set_autocommit = nop
transaction.commit = nop
transaction.rollback = nop
transaction.enter_transaction_management = nop
@@ -80,6 +82,7 @@ def disable_transaction_methods():
transaction.abort = nop
def restore_transaction_methods():
+ transaction.set_autocommit = real_set_autocommit
transaction.commit = real_commit
transaction.rollback = real_rollback
transaction.enter_transaction_management = real_enter_transaction_management
7 docs/internals/deprecation.txt
View
@@ -348,9 +348,10 @@ these changes.
* Remove the backward compatible shims introduced to rename the attributes
``ChangeList.root_query_set`` and ``ChangeList.query_set``.
-* The private API ``django.db.close_connection`` will be removed.
-
-* The private API ``django.transaction.managed`` will be removed.
+* The following private APIs will be removed:
+ - ``django.db.close_connection()``
+ - ``django.db.backends.creation.BaseDatabaseCreation.set_autocommit()``
+ - ``django.db.transaction.managed()``
2.0
---
17 docs/topics/db/transactions.txt
View
@@ -208,6 +208,23 @@ This applies to all database operations, not just write operations. Even
if your transaction only reads from the database, the transaction must
be committed or rolled back before you complete a request.
+.. _managing-autocommit:
+
+Managing autocommit
+===================
+
+.. versionadded:: 1.6
+
+Django provides a straightforward API to manage the autocommit state of each
+database connection, if you need to.
+
+.. function:: get_autocommit(using=None)
+
+.. function:: set_autocommit(using=None, autocommit=True)
+
+These functions take a ``using`` argument which should be the name of a
+database. If it isn't provided, Django uses the ``"default"`` database.
+
.. _deactivate-transaction-management:
How to globally deactivate transaction management
Please sign in to comment.
Something went wrong with that request. Please try again.