Ticket #21134: 21134-failed-attempt.patch

File 21134-failed-attempt.patch, 5.4 KB (added by Aymeric Augustin, 11 years ago)
  • django/db/backends/__init__.py

    diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
    index ae9fdbb..add7aa6 100644
    a b class BaseDatabaseWrapper(object):  
    361361            raise TransactionManagementError(
    362362                "This is forbidden when an 'atomic' block is active.")
    363363
     364    def validate_no_broken_transaction(self):
     365        if self.needs_rollback:
     366            raise TransactionManagementError(
     367                "An error occurred in the current transaction. You can't "
     368                "execute queries until the end of the 'atomic' block.")
     369
    364370    def abort(self):
    365371        """
    366372        Roll back any ongoing transaction and clean the transaction state
  • django/db/backends/utils.py

    diff --git a/django/db/backends/utils.py b/django/db/backends/utils.py
    index 0e2aa45..432f760 100644
    a b class CursorWrapper(object):  
    1919        self.cursor = cursor
    2020        self.db = db
    2121
    22     SET_DIRTY_ATTRS = frozenset(['execute', 'executemany', 'callproc'])
    23     WRAP_ERROR_ATTRS = frozenset([
    24         'callproc', 'close', 'execute', 'executemany',
    25         'fetchone', 'fetchmany', 'fetchall', 'nextset'])
     22    WRAP_ERROR_ATTRS = frozenset(['fetchone', 'fetchmany', 'fetchall', 'nextset'])
    2623
    2724    def __getattr__(self, attr):
    28         if attr in CursorWrapper.SET_DIRTY_ATTRS:
    29             self.db.set_dirty()
    3025        cursor_attr = getattr(self.cursor, attr)
    3126        if attr in CursorWrapper.WRAP_ERROR_ATTRS:
    3227            return self.db.wrap_database_errors(cursor_attr)
    class CursorWrapper(object):  
    3631    def __iter__(self):
    3732        return iter(self.cursor)
    3833
     34    # The following methods cannot be implemented in __getattr__, because the
     35    # code must run when the method is invoked, not just when it is accessed.
    3936
    40 class CursorDebugWrapper(CursorWrapper):
     37    def callproc(self, procname, params=None):
     38        self.db.validate_no_broken_transaction()
     39        self.db.set_dirty()
     40        with self.db.wrap_database_errors:
     41            if params is None:
     42                return self.cursor.callproc(procname)
     43            else:
     44                return self.cursor.callproc(procname, params)
    4145
    4246    def execute(self, sql, params=None):
     47        self.db.validate_no_broken_transaction()
    4348        self.db.set_dirty()
     49        with self.db.wrap_database_errors:
     50            if params is None:
     51                return self.cursor.execute(sql)
     52            else:
     53                return self.cursor.execute(sql, params)
     54
     55    def executemany(self, sql, param_list):
     56        self.db.validate_no_broken_transaction()
     57        self.db.set_dirty()
     58        with self.db.wrap_database_errors:
     59            return self.cursor.executemany(sql, param_list)
     60
     61
     62class CursorDebugWrapper(CursorWrapper):
     63
     64    # XXX callproc isn't instrumented at this time.
     65
     66    def execute(self, sql, params=None):
    4467        start = time()
    4568        try:
    46             with self.db.wrap_database_errors:
    47                 if params is None:
    48                     # params default might be backend specific
    49                     return self.cursor.execute(sql)
    50                 return self.cursor.execute(sql, params)
     69            return super(CursorDebugWrapper, self).execute(sql, params)
    5170        finally:
    5271            stop = time()
    5372            duration = stop - start
    class CursorDebugWrapper(CursorWrapper):  
    6180            )
    6281
    6382    def executemany(self, sql, param_list):
    64         self.db.set_dirty()
    6583        start = time()
    6684        try:
    67             with self.db.wrap_database_errors:
    68                 return self.cursor.executemany(sql, param_list)
     85            return super(CursorDebugWrapper, self).executemany(sql, param_list)
    6986        finally:
    7087            stop = time()
    7188            duration = stop - start
  • django/db/transaction.py

    diff --git a/django/db/transaction.py b/django/db/transaction.py
    index 7509ad3..86a357f 100644
    a b import warnings  
    1616
    1717from functools import wraps
    1818
    19 from django.db import connections, DatabaseError, DEFAULT_DB_ALIAS
     19from django.db import (
     20        connections, DEFAULT_DB_ALIAS,
     21        DatabaseError, ProgrammingError)
    2022from django.utils.decorators import available_attrs
    2123
    2224
    23 class TransactionManagementError(Exception):
     25class TransactionManagementError(ProgrammingError):
    2426    """
    25     This exception is thrown when something bad happens with transaction
    26     management.
     27    This exception is thrown when transaction management is used improperly.
    2728    """
    2829    pass
    2930
  • tests/transactions/tests.py

    diff --git a/tests/transactions/tests.py b/tests/transactions/tests.py
    index 9cf8b4d..9521f60 100644
    a b class AtomicErrorsTests(TransactionTestCase):  
    336336            with self.assertRaises(transaction.TransactionManagementError):
    337337                transaction.leave_transaction_management()
    338338
     339    def test_atomic_prevents_running_more_queries_after_an_error(self):
     340        cursor = connection.cursor()
     341        with transaction.atomic():
     342            with self.assertRaises(DatabaseError):
     343                cursor.execute("INSERT INTO transactions_no_such_table (id) VALUES (0)")
     344            with self.assertRaises(transaction.TransactionManagementError):
     345                cursor.execute("INSERT INTO transactions_no_such_table (id) VALUES (0)")
    339346
    340347class AtomicMiscTests(TransactionTestCase):
    341348
Back to Top