diff --git a/django/db/backends/schema.py b/django/db/backends/schema.py index 64ba5b0740..4fc6601dfd 100644 --- a/django/db/backends/schema.py +++ b/django/db/backends/schema.py @@ -93,7 +93,11 @@ class BaseDatabaseSchemaEditor(object): # Log the command we're running, then run it logger.debug("%s; (params %r)" % (sql, params)) if self.collect_sql: - self.collected_sql.append((sql % tuple(map(self.quote_value, params))) + ";") + ending = "" if sql.endswith(";") else ";" + if params is not None: + self.collected_sql.append((sql % tuple(map(self.quote_value, params))) + ending) + else: + self.collected_sql.append(sql + ending) else: with self.connection.cursor() as cursor: cursor.execute(sql, params) diff --git a/docs/releases/1.7.2.txt b/docs/releases/1.7.2.txt index 9ed58bb217..c01dca9f58 100644 --- a/docs/releases/1.7.2.txt +++ b/docs/releases/1.7.2.txt @@ -91,3 +91,6 @@ Bugfixes the error message for cyclic dependencies much more helpful. * Added missing ``index_together`` handling for SQLite (:ticket:`23880`). + +* Fixed a crash when ``RunSQL`` SQL content was collected by the schema editor, + typically when using ``sqlmigrate`` (:ticket:`23909`). diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 05e0f22696..5f4dc553a2 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -1219,6 +1219,12 @@ class OperationTests(OperationTestBase): self.assertEqual(len(new_state.models["test_runsql", "somethingelse"].fields), 1) # Make sure there's no table self.assertTableNotExists("i_love_ponies") + # Test SQL collection + with connection.schema_editor(collect_sql=True) as editor: + operation.database_forwards("test_runsql", editor, project_state, new_state) + self.assertIn("LIKE '%%ponies';", "\n".join(editor.collected_sql)) + operation.database_backwards("test_runsql", editor, project_state, new_state) + self.assertIn("LIKE '%%Ponies%%';", "\n".join(editor.collected_sql)) # Test the database alteration with connection.schema_editor() as editor: operation.database_forwards("test_runsql", editor, project_state, new_state)