diff --git a/django/db/migrations/executor.py b/django/db/migrations/executor.py index a78c09b5182..420fbca8b85 100644 --- a/django/db/migrations/executor.py +++ b/django/db/migrations/executor.py @@ -71,9 +71,9 @@ class MigrationExecutor(object): with self.connection.schema_editor(collect_sql=True) as schema_editor: project_state = self.loader.graph.project_state((migration.app_label, migration.name), at_end=False) if not backwards: - migration.apply(project_state, schema_editor) + migration.apply(project_state, schema_editor, collect_sql=True) else: - migration.unapply(project_state, schema_editor) + migration.unapply(project_state, schema_editor, collect_sql=True) statements.extend(schema_editor.collected_sql) return statements diff --git a/django/db/migrations/migration.py b/django/db/migrations/migration.py index f65b6b2d0c1..06da84179bd 100644 --- a/django/db/migrations/migration.py +++ b/django/db/migrations/migration.py @@ -67,7 +67,7 @@ class Migration(object): operation.state_forwards(self.app_label, new_state) return new_state - def apply(self, project_state, schema_editor): + def apply(self, project_state, schema_editor, collect_sql=False): """ Takes a project_state representing all migrations prior to this one and a schema_editor for a live database and applies the migration @@ -77,6 +77,14 @@ class Migration(object): Migrations. """ for operation in self.operations: + # If this operation cannot be represented as SQL, place a comment + # there instead + if collect_sql and not operation.reduces_to_sql: + schema_editor.collected_sql.append("--") + schema_editor.collected_sql.append("-- MIGRATION NOW PERFORMS OPERATION THAT CANNOT BE WRITTEN AS SQL:") + schema_editor.collected_sql.append("-- %s" % operation.describe()) + schema_editor.collected_sql.append("--") + continue # Get the state after the operation has run new_state = project_state.clone() operation.state_forwards(self.app_label, new_state) @@ -86,7 +94,7 @@ class Migration(object): project_state = new_state return project_state - def unapply(self, project_state, schema_editor): + def unapply(self, project_state, schema_editor, collect_sql=False): """ Takes a project_state representing all migrations prior to this one and a schema_editor for a live database and applies the migration @@ -95,8 +103,17 @@ class Migration(object): # We need to pre-calculate the stack of project states to_run = [] for operation in self.operations: + # If this operation cannot be represented as SQL, place a comment + # there instead + if collect_sql and not operation.reduces_to_sql: + schema_editor.collected_sql.append("--") + schema_editor.collected_sql.append("-- MIGRATION NOW PERFORMS OPERATION THAT CANNOT BE WRITTEN AS SQL:") + schema_editor.collected_sql.append("-- %s" % operation.describe()) + schema_editor.collected_sql.append("--") + continue + # If it's irreversible, error out if not operation.reversible: - raise Migration.IrreversibleError("Operation %s in %s is not reversible" % (operation, sekf)) + raise Migration.IrreversibleError("Operation %s in %s is not reversible" % (operation, self)) new_state = project_state.clone() operation.state_forwards(self.app_label, new_state) to_run.append((operation, project_state, new_state)) diff --git a/django/db/migrations/operations/special.py b/django/db/migrations/operations/special.py index 7bd4ac2117b..89b13c46a04 100644 --- a/django/db/migrations/operations/special.py +++ b/django/db/migrations/operations/special.py @@ -132,3 +132,6 @@ class RunPython(Operation): def database_backwards(self, app_label, schema_editor, from_state, to_state): raise NotImplementedError("You cannot reverse this operation") + + def describe(self): + return "Raw Python operation"