summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2014-05-07 14:28:34 -0700
committerAndrew Godwin <andrew@aeracode.org>2014-05-07 14:28:34 -0700
commit5a917cfef319df33ca30a3b27bd0b0533b8e63bb (patch)
tree867d316127e3bbf11fb114c6ba8910d611832974 /django
parente9a456d11b5b63389b466ed435ef3915f0e79e4c (diff)
Fixed #22496: Data migrations get transactions again!
Diffstat (limited to 'django')
-rw-r--r--django/db/migrations/migration.py17
-rw-r--r--django/db/migrations/operations/base.py4
-rw-r--r--django/db/migrations/operations/special.py3
3 files changed, 21 insertions, 3 deletions
diff --git a/django/db/migrations/migration.py b/django/db/migrations/migration.py
index 3d7f47f0fa..708de5393d 100644
--- a/django/db/migrations/migration.py
+++ b/django/db/migrations/migration.py
@@ -1,4 +1,5 @@
from __future__ import unicode_literals
+from django.db.transaction import atomic
class Migration(object):
@@ -97,7 +98,13 @@ class Migration(object):
new_state = project_state.clone()
operation.state_forwards(self.app_label, new_state)
# Run the operation
- operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
+ if not schema_editor.connection.features.can_rollback_ddl and operation.atomic:
+ # We're forcing a transaction on a non-transactional-DDL backend
+ with atomic(schema_editor.connection.alias):
+ operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
+ else:
+ # Normal behaviour
+ operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
# Switch states
project_state = new_state
return project_state
@@ -129,7 +136,13 @@ class Migration(object):
# Now run them in reverse
to_run.reverse()
for operation, to_state, from_state in to_run:
- operation.database_backwards(self.app_label, schema_editor, from_state, to_state)
+ if not schema_editor.connection.features.can_rollback_ddl and operation.atomic:
+ # We're forcing a transaction on a non-transactional-DDL backend
+ with atomic(schema_editor.connection.alias):
+ operation.database_backwards(self.app_label, schema_editor, from_state, to_state)
+ else:
+ # Normal behaviour
+ operation.database_backwards(self.app_label, schema_editor, from_state, to_state)
return project_state
diff --git a/django/db/migrations/operations/base.py b/django/db/migrations/operations/base.py
index 7e93fb7836..d0ab0a39ad 100644
--- a/django/db/migrations/operations/base.py
+++ b/django/db/migrations/operations/base.py
@@ -24,6 +24,10 @@ class Operation(object):
# Can this migration be represented as SQL? (things like RunPython cannot)
reduces_to_sql = True
+ # Should this operation be forced as atomic even on backends with no
+ # DDL transaction support (i.e., does it have no DDL, like RunPython)
+ atomic = False
+
serialization_expand_args = []
def __new__(cls, *args, **kwargs):
diff --git a/django/db/migrations/operations/special.py b/django/db/migrations/operations/special.py
index a80096cb32..b7ffbbbd29 100644
--- a/django/db/migrations/operations/special.py
+++ b/django/db/migrations/operations/special.py
@@ -86,7 +86,8 @@ class RunPython(Operation):
reduces_to_sql = False
- def __init__(self, code, reverse_code=None):
+ def __init__(self, code, reverse_code=None, atomic=True):
+ self.atomic = atomic
# Forwards code
if not callable(code):
raise ValueError("RunPython must be supplied with a callable")