Ticket #9964: 9964-make-managed-transactions-dirty.patch
File 9964-make-managed-transactions-dirty.patch, 6.9 KB (added by , 14 years ago) |
---|
-
django/db/backends/__init__.py
22 22 self.alias = alias 23 23 self.vendor = 'unknown' 24 24 self.use_debug_cursor = None 25 self.on_used = None 25 26 26 27 def __eq__(self, other): 27 28 return self.settings_dict == other.settings_dict … … 78 79 if (self.use_debug_cursor or 79 80 (self.use_debug_cursor is None and settings.DEBUG)): 80 81 return self.make_debug_cursor(cursor) 82 # Used by transaction mechanism to be notified that db was used 83 if self.on_used: 84 self.on_used() 81 85 return cursor 82 86 83 87 def make_debug_cursor(self, cursor): -
django/db/transaction.py
67 67 if thread_ident not in dirty or using not in dirty[thread_ident]: 68 68 dirty.setdefault(thread_ident, {}) 69 69 dirty[thread_ident][using] = False 70 def set_dirty_if_managed(): 71 if is_managed(using): set_dirty(using) 72 connection.on_used = set_dirty_if_managed 70 73 connection._enter_transaction_management(managed) 71 74 72 75 def leave_transaction_management(using=None): -
tests/regressiontests/transaction_regress/tests.py
1 from django.test import TransactionTestCase 2 from django.db import connection, transaction 3 from django.db.transaction import \ 4 commit_on_success, commit_manually, \ 5 TransactionManagementError 6 from models import Mod 7 8 class Test9964(TransactionTestCase): 9 10 def test_raw_committed_on_success(self): 11 12 @commit_on_success 13 def raw_sql(): 14 cursor = connection.cursor() 15 cursor.execute("INSERT into transaction_regress_mod (id,fld) values (17,18)") 16 17 raw_sql() 18 transaction.rollback() 19 try: 20 obj = Mod.objects.get(pk=17) 21 self.assertEqual(obj.fld, 18) 22 except Mod.DoesNotExist: 23 self.fail("transaction with raw sql not committed") 24 25 def test_commit_manually_enforced(self): 26 @commit_manually 27 def non_comitter(): 28 _ = Mod.objects.count() 29 30 self.assertRaises(TransactionManagementError, non_comitter) 31 32 def test_commit_manually_commit_ok(self): 33 @commit_manually 34 def committer(): 35 _ = Mod.objects.count() 36 transaction.commit() 37 38 try: 39 committer() 40 except TransactionManagementError: 41 self.fail("Commit did not clear the transaction state") 42 43 def test_commit_manually_rollback_ok(self): 44 @commit_manually 45 def roller_back(): 46 _ = Mod.objects.count() 47 transaction.rollback() 48 49 try: 50 roller_back() 51 except TransactionManagementError: 52 self.fail("Rollback did not clear the transaction state") 53 54 def test_commit_manually_enforced_after_commit(self): 55 @commit_manually 56 def fake_committer(): 57 _ = Mod.objects.count() 58 transaction.commit() 59 _ = Mod.objects.count() 60 61 self.assertRaises(TransactionManagementError, fake_committer) 62 -
tests/regressiontests/transaction_regress/models.py
1 from django.db import models 2 3 class Mod(models.Model): 4 fld = models.IntegerField() -
tests/regressiontests/fixtures_regress/tests.py
613 613 614 614 def test_ticket_11101(self): 615 615 """Test that fixtures can be rolled back (ticket #11101).""" 616 ticket_11101 = transaction.commit_ manually(self.ticket_11101)616 ticket_11101 = transaction.commit_on_success(self.ticket_11101) 617 617 ticket_11101() -
docs/topics/db/sql.txt
231 231 232 232 Transactions and raw SQL 233 233 ------------------------ 234 If you are using transaction decorators (such as ``commit_on_success``) to235 wrap your views and provide transaction control, you don't have to make a236 manual call to ``transaction.commit_unless_managed()`` -- you can manually237 commit if you want to, but you aren't required to, since the decorator will238 commit for you. However, if you don't manually commit your changes, you will239 need to manually mark the transaction as dirty, using240 ``transaction.set_dirty()``::241 234 242 @commit_on_success 243 def my_custom_sql_view(request, value): 244 from django.db import connection, transaction 245 cursor = connection.cursor() 235 .. versionchanged:: 1.3 246 236 247 # Data modifying operation 248 cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [value]) 237 If you write functions that modify the database via raw SQL, you need to 238 consider the transaction management mode they run under. If this may be 239 Django's default mode (by default or using the ``auto_commit`` 240 decorator), you need to make manual calls to 241 ``transaction.commit_unless_managed()`` to make sure the changes are 242 committed. If you are using transaction decorators (such as 243 ``commit_on_success``) to wrap your views and provide transaction 244 control, you don't have to make such calls. 249 245 250 # Since we modified data, mark the transaction as dirty251 transaction.set_dirty()252 246 253 # Data retrieval operation. This doesn't dirty the transaction,254 # so no call to set_dirty() is required.255 cursor.execute("SELECT foo FROM bar WHERE baz = %s", [value])256 row = cursor.fetchone()257 258 return render_to_response('template.html', {'row': row})259 260 The call to ``set_dirty()`` is made automatically when you use the Django ORM261 to make data modifying database calls. However, when you use raw SQL, Django262 has no way of knowing if your SQL modifies data or not. The manual call to263 ``set_dirty()`` ensures that Django knows that there are modifications that264 must be committed.265 266 247 Connections and cursors 267 248 ----------------------- 268 249