summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/migrations/executor.py5
-rw-r--r--tests/migrations/test_executor.py27
2 files changed, 30 insertions, 2 deletions
diff --git a/django/db/migrations/executor.py b/django/db/migrations/executor.py
index 83d624e08a..57042a8690 100644
--- a/django/db/migrations/executor.py
+++ b/django/db/migrations/executor.py
@@ -225,8 +225,9 @@ class MigrationExecutor:
# Alright, do it normally
with self.connection.schema_editor(atomic=migration.atomic) as schema_editor:
state = migration.apply(state, schema_editor)
- self.record_migration(migration)
- migration_recorded = True
+ if not schema_editor.deferred_sql:
+ self.record_migration(migration)
+ migration_recorded = True
if not migration_recorded:
self.record_migration(migration)
# Report progress
diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py
index 8cab8732c4..e61d8f1276 100644
--- a/tests/migrations/test_executor.py
+++ b/tests/migrations/test_executor.py
@@ -684,6 +684,33 @@ class ExecutorTests(MigrationTestBase):
)
self.assertTableNotExists('record_migration_model')
+ def test_migrations_not_applied_on_deferred_sql_failure(self):
+ """Migrations are not recorded if deferred SQL application fails."""
+ class DeferredSQL:
+ def __str__(self):
+ raise DatabaseError('Failed to apply deferred SQL')
+
+ class Migration(migrations.Migration):
+ atomic = False
+
+ def apply(self, project_state, schema_editor, collect_sql=False):
+ schema_editor.deferred_sql.append(DeferredSQL())
+
+ executor = MigrationExecutor(connection)
+ with self.assertRaisesMessage(DatabaseError, 'Failed to apply deferred SQL'):
+ executor.apply_migration(
+ ProjectState(),
+ Migration('0001_initial', 'deferred_sql'),
+ )
+ # The migration isn't recorded as applied since it failed.
+ migration_recorder = MigrationRecorder(connection)
+ self.assertIs(
+ migration_recorder.migration_qs.filter(
+ app='deferred_sql', name='0001_initial',
+ ).exists(),
+ False,
+ )
+
class FakeLoader:
def __init__(self, graph, applied):