1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Fixed #16047 -- Restore autocommit state correctly on psycopg2

When the postgresql_psycopg2 backend was used with DB-level autocommit
mode enabled, after entering transaction management and then leaving
it, the isolation level was never set back to autocommit mode.

Thanks brodie for report and working on this issue.
This commit is contained in:
Anssi Kääriäinen
2012-05-26 23:19:13 +03:00
parent da573fbb41
commit f572ee0c65
3 changed files with 76 additions and 7 deletions

View File

@@ -1,11 +1,11 @@
from __future__ import absolute_import
from django.core.exceptions import ImproperlyConfigured
from django.db import connection, transaction
from django.db import connection, connections, transaction, DEFAULT_DB_ALIAS
from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
from django.test import TransactionTestCase, skipUnlessDBFeature
from django.test.utils import override_settings
from django.utils.unittest import skipIf
from django.utils.unittest import skipIf, skipUnless
from .models import Mod, M2mA, M2mB
@@ -175,6 +175,62 @@ class TestTransactionClosing(TransactionTestCase):
self.test_failing_query_transaction_closed()
class TestPostgresAutocommit(TransactionTestCase):
"""
Tests to make sure psycopg2's autocommit mode is restored after entering
and leaving transaction management. Refs #16047.
"""
def setUp(self):
from psycopg2.extensions import (ISOLATION_LEVEL_AUTOCOMMIT,
ISOLATION_LEVEL_READ_COMMITTED)
self._autocommit = ISOLATION_LEVEL_AUTOCOMMIT
self._read_committed = ISOLATION_LEVEL_READ_COMMITTED
# We want a clean backend with autocommit = True, so
# first we need to do a bit of work to have that.
self._old_backend = connections[DEFAULT_DB_ALIAS]
settings = self._old_backend.settings_dict.copy()
opts = settings['OPTIONS'].copy()
opts['autocommit'] = True
settings['OPTIONS'] = opts
new_backend = self._old_backend.__class__(settings, DEFAULT_DB_ALIAS)
connections[DEFAULT_DB_ALIAS] = new_backend
def test_initial_autocommit_state(self):
self.assertTrue(connection.features.uses_autocommit)
self.assertEqual(connection.isolation_level, self._autocommit)
def test_transaction_management(self):
transaction.enter_transaction_management()
transaction.managed(True)
self.assertEqual(connection.isolation_level, self._read_committed)
transaction.leave_transaction_management()
self.assertEqual(connection.isolation_level, self._autocommit)
def test_transaction_stacking(self):
transaction.enter_transaction_management()
transaction.managed(True)
self.assertEqual(connection.isolation_level, self._read_committed)
transaction.enter_transaction_management()
self.assertEqual(connection.isolation_level, self._read_committed)
transaction.leave_transaction_management()
self.assertEqual(connection.isolation_level, self._read_committed)
transaction.leave_transaction_management()
self.assertEqual(connection.isolation_level, self._autocommit)
def tearDown(self):
connections[DEFAULT_DB_ALIAS] = self._old_backend
TestPostgresAutocommit = skipUnless(connection.vendor == 'postgresql',
"This test only valid for PostgreSQL")(TestPostgresAutocommit)
TestPostgresAutoCommit = skipUnlessDBFeature('supports_transactions')(
TestPostgresAutocommit)
class TestManyToManyAddTransaction(TransactionTestCase):
def test_manyrelated_add_commit(self):
"Test for https://code.djangoproject.com/ticket/16818"