Ticket #16047: 2-fix-psycopg2-autocommit.patch

File 2-fix-psycopg2-autocommit.patch, 4.7 KB (added by Brodie Rao, 13 years ago)
  • django/db/backends/__init__.py

    # HG changeset patch
    # User Brodie Rao <brodie@sf.io>
    # Date 1331584552 25200
    # Node ID c0b83639098449a3e1acc538bb8d83602d4449d6
    # Parent  95cddfdbec66b6851789d8bce7257b46de1dec41
    psycopg2: restore autocommit when leaving transaction management
    
    diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
    a b class BaseDatabaseWrapper(object):  
    108108        over to the surrounding block, as a commit will commit all changes, even
    109109        those from outside. (Commits are on connection level.)
    110110        """
    111         self._leave_transaction_management(self.is_managed())
    112111        if self.transaction_state:
    113112            del self.transaction_state[-1]
    114113        else:
    115114            raise TransactionManagementError("This code isn't under transaction "
    116115                "management")
     116        # Note that it is intentional we pop first one entry from the
     117        # transaction_state stack, and then use the topmost entry (given by
     118        # is_managed()) for _leave_transaction_management(). Refs #16047.
     119        self._leave_transaction_management(self.is_managed())
    117120        if self._dirty:
    118121            self.rollback()
    119122            raise TransactionManagementError("Transaction managed block ended with "
  • tests/regressiontests/transactions_regress/tests.py

    diff --git a/tests/regressiontests/transactions_regress/tests.py b/tests/regressiontests/transactions_regress/tests.py
    a b  
    11from __future__ import absolute_import
    22
    33from django.core.exceptions import ImproperlyConfigured
    4 from django.db import connection, transaction
     4from django.db import connection, connections, transaction, DEFAULT_DB_ALIAS
    55from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
    66from django.test import TransactionTestCase, skipUnlessDBFeature
    77from django.test.utils import override_settings
    8 from django.utils.unittest import skipIf
     8from django.utils.unittest import skipIf, skipUnless
    99
    1010from .models import Mod, M2mA, M2mB
    1111
    class TestTransactionClosing(Transaction  
    175175        self.test_failing_query_transaction_closed()
    176176
    177177
     178class TestPostgresAutocommit(TransactionTestCase):
     179    """
     180    Tests to make sure psycopg2's autocommit mode is restored after entering
     181    and leaving transaction management. Refs #16047.
     182    """
     183    def setUp(self):
     184        from psycopg2.extensions import (ISOLATION_LEVEL_AUTOCOMMIT,
     185                                         ISOLATION_LEVEL_READ_COMMITTED)
     186        self._autocommit = ISOLATION_LEVEL_AUTOCOMMIT
     187        self._read_committed = ISOLATION_LEVEL_READ_COMMITTED
     188
     189        # We want a clean backend with autocommit = True, so
     190        # first we need to do a bit of work to have that.
     191        self._old_backend = connections[DEFAULT_DB_ALIAS]
     192        settings = self._old_backend.settings_dict.copy()
     193        settings['OPTIONS']['autocommit'] = True
     194        new_backend = self._old_backend.__class__(settings, DEFAULT_DB_ALIAS)
     195        connections[DEFAULT_DB_ALIAS] = new_backend
     196
     197    def test_initial_autocommit_state(self):
     198        self.assertTrue(connection.features.uses_autocommit)
     199        self.assertEqual(connection.isolation_level, self._autocommit)
     200
     201    def test_transaction_management(self):
     202        transaction.enter_transaction_management()
     203        transaction.managed(True)
     204        self.assertEqual(connection.isolation_level, self._read_committed)
     205
     206        transaction.leave_transaction_management()
     207        self.assertEqual(connection.isolation_level, self._autocommit)
     208
     209    def test_transaction_stacking(self):
     210        transaction.enter_transaction_management()
     211        transaction.managed(True)
     212        self.assertEqual(connection.isolation_level, self._read_committed)
     213
     214        transaction.enter_transaction_management()
     215        self.assertEqual(connection.isolation_level, self._read_committed)
     216
     217        transaction.leave_transaction_management()
     218        self.assertEqual(connection.isolation_level, self._read_committed)
     219
     220        transaction.leave_transaction_management()
     221        self.assertEqual(connection.isolation_level, self._autocommit)
     222
     223    def tearDown(self):
     224        connections[DEFAULT_DB_ALIAS] = self._old_backend
     225
     226TestPostgresAutocommit = skipUnless(connection.vendor == 'postgresql',
     227    "This test only valid for PostgreSQL")(TestPostgresAutocommit)
     228TestPostgresAutoCommit = skipUnlessDBFeature('supports_transactions')(
     229    TestPostgresAutocommit)
     230
     231
    178232class TestManyToManyAddTransaction(TransactionTestCase):
    179233    def test_manyrelated_add_commit(self):
    180234        "Test for https://code.djangoproject.com/ticket/16818"
Back to Top