diff options
| author | Pankrat <lhaehne@gmail.com> | 2016-01-30 21:46:28 +0100 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2016-02-05 09:09:05 -0500 |
| commit | f91a04621ea8d7a657ff755645d823026257e898 (patch) | |
| tree | 2b06f3ce1cbb8e5f04499838154cf715ff76ce5b /django | |
| parent | 0edb8a146fd6c60f4c3b1ad0a4a89963962f22af (diff) | |
Fixed #25833 -- Added support for non-atomic migrations.
Added the Migration.atomic attribute which can be set to False
for non-atomic migrations.
Diffstat (limited to 'django')
| -rw-r--r-- | django/core/management/commands/sqlmigrate.py | 3 | ||||
| -rw-r--r-- | django/db/backends/base/schema.py | 7 | ||||
| -rw-r--r-- | django/db/migrations/executor.py | 6 | ||||
| -rw-r--r-- | django/db/migrations/migration.py | 10 | ||||
| -rw-r--r-- | django/db/migrations/operations/special.py | 4 |
5 files changed, 20 insertions, 10 deletions
diff --git a/django/core/management/commands/sqlmigrate.py b/django/core/management/commands/sqlmigrate.py index 14c2742c07..b858b2b805 100644 --- a/django/core/management/commands/sqlmigrate.py +++ b/django/core/management/commands/sqlmigrate.py @@ -51,6 +51,9 @@ class Command(BaseCommand): migration_name, app_label)) targets = [(app_label, migration.name)] + # Show begin/end around output only for atomic migrations + self.output_transaction = migration.atomic + # Make a plan that represents just the requested migrations and show SQL # for it plan = [(executor.loader.graph.nodes[targets[0]], options['backwards'])] diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index 35dcb2e296..a9d84e114d 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -69,17 +69,18 @@ class BaseDatabaseSchemaEditor(object): sql_create_pk = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s PRIMARY KEY (%(columns)s)" sql_delete_pk = "ALTER TABLE %(table)s DROP CONSTRAINT %(name)s" - def __init__(self, connection, collect_sql=False): + def __init__(self, connection, collect_sql=False, atomic=True): self.connection = connection self.collect_sql = collect_sql if self.collect_sql: self.collected_sql = [] + self.atomic_migration = self.connection.features.can_rollback_ddl and atomic # State-managing methods def __enter__(self): self.deferred_sql = [] - if self.connection.features.can_rollback_ddl: + if self.atomic_migration: self.atomic = atomic(self.connection.alias) self.atomic.__enter__() return self @@ -88,7 +89,7 @@ class BaseDatabaseSchemaEditor(object): if exc_type is None: for sql in self.deferred_sql: self.execute(sql) - if self.connection.features.can_rollback_ddl: + if self.atomic_migration: self.atomic.__exit__(exc_type, exc_value, traceback) # Core utility functions diff --git a/django/db/migrations/executor.py b/django/db/migrations/executor.py index b1a8383100..805b6cac87 100644 --- a/django/db/migrations/executor.py +++ b/django/db/migrations/executor.py @@ -170,7 +170,7 @@ class MigrationExecutor(object): statements = [] state = None for migration, backwards in plan: - with self.connection.schema_editor(collect_sql=True) as schema_editor: + with self.connection.schema_editor(collect_sql=True, atomic=migration.atomic) as schema_editor: if state is None: state = self.loader.project_state((migration.app_label, migration.name), at_end=False) if not backwards: @@ -194,7 +194,7 @@ class MigrationExecutor(object): fake = True if not fake: # Alright, do it normally - with self.connection.schema_editor() as schema_editor: + with self.connection.schema_editor(atomic=migration.atomic) as schema_editor: state = migration.apply(state, schema_editor) # For replacement migrations, record individual statuses if migration.replaces: @@ -214,7 +214,7 @@ class MigrationExecutor(object): if self.progress_callback: self.progress_callback("unapply_start", migration, fake) if not fake: - with self.connection.schema_editor() as schema_editor: + with self.connection.schema_editor(atomic=migration.atomic) as schema_editor: state = migration.unapply(state, schema_editor) # For replacement migrations, record individual statuses if migration.replaces: diff --git a/django/db/migrations/migration.py b/django/db/migrations/migration.py index 7641eb45bc..732dcb82e8 100644 --- a/django/db/migrations/migration.py +++ b/django/db/migrations/migration.py @@ -48,6 +48,10 @@ class Migration(object): # introspection. If False, never perform introspection. initial = None + # Whether to wrap the whole migration in a transaction. Only has an effect + # on database backends which support transactional DDL. + atomic = True + def __init__(self, name, app_label): self.name = name self.app_label = app_label @@ -114,8 +118,10 @@ class Migration(object): old_state = project_state.clone() operation.state_forwards(self.app_label, project_state) # Run the operation - if not schema_editor.connection.features.can_rollback_ddl and operation.atomic: - # We're forcing a transaction on a non-transactional-DDL backend + atomic_operation = operation.atomic or (self.atomic and operation.atomic is not False) + if not schema_editor.atomic_migration and atomic_operation: + # Force a transaction on a non-transactional-DDL backend or an + # atomic operation inside a non-atomic migration. with atomic(schema_editor.connection.alias): operation.database_forwards(self.app_label, schema_editor, old_state, project_state) else: diff --git a/django/db/migrations/operations/special.py b/django/db/migrations/operations/special.py index a7da3cc81c..cd1e2479db 100644 --- a/django/db/migrations/operations/special.py +++ b/django/db/migrations/operations/special.py @@ -139,7 +139,7 @@ class RunPython(Operation): reduces_to_sql = False - def __init__(self, code, reverse_code=None, atomic=True, hints=None, elidable=False): + def __init__(self, code, reverse_code=None, atomic=None, hints=None, elidable=False): self.atomic = atomic # Forwards code if not callable(code): @@ -161,7 +161,7 @@ class RunPython(Operation): } if self.reverse_code is not None: kwargs['reverse_code'] = self.reverse_code - if self.atomic is not True: + if self.atomic is not None: kwargs['atomic'] = self.atomic if self.hints: kwargs['hints'] = self.hints |
