mirror of https://github.com/django/django.git
[3.2.x] Fixed #32374 -- Stopped recording migration application before deferred SQL.
Migrations cannot be recorded in the same transaction as its associated DDL operations when some of it is deferred until the schema editor context exits. Regression inc86a3d80a2
. Backport of0c42cdf0d2
from master
This commit is contained in:
parent
900b2ce92b
commit
6520ce5251
|
@ -225,8 +225,9 @@ class MigrationExecutor:
|
||||||
# Alright, do it normally
|
# Alright, do it normally
|
||||||
with self.connection.schema_editor(atomic=migration.atomic) as schema_editor:
|
with self.connection.schema_editor(atomic=migration.atomic) as schema_editor:
|
||||||
state = migration.apply(state, schema_editor)
|
state = migration.apply(state, schema_editor)
|
||||||
self.record_migration(migration)
|
if not schema_editor.deferred_sql:
|
||||||
migration_recorded = True
|
self.record_migration(migration)
|
||||||
|
migration_recorded = True
|
||||||
if not migration_recorded:
|
if not migration_recorded:
|
||||||
self.record_migration(migration)
|
self.record_migration(migration)
|
||||||
# Report progress
|
# Report progress
|
||||||
|
|
|
@ -684,6 +684,33 @@ class ExecutorTests(MigrationTestBase):
|
||||||
)
|
)
|
||||||
self.assertTableNotExists('record_migration_model')
|
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:
|
class FakeLoader:
|
||||||
def __init__(self, graph, applied):
|
def __init__(self, graph, applied):
|
||||||
|
|
Loading…
Reference in New Issue