diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py index aa24024f91..c61b0609d5 100644 --- a/django/db/backends/sqlite3/features.py +++ b/django/db/backends/sqlite3/features.py @@ -25,7 +25,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_transactions = True atomic_transactions = False can_rollback_ddl = True - supports_atomic_references_rename = False + supports_atomic_references_rename = Database.version_info >= (3, 26, 0) supports_paramstyle_pyformat = False supports_sequence_reset = False can_clone_databases = True diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py index 7c3648cff2..3992d86651 100644 --- a/django/db/backends/sqlite3/schema.py +++ b/django/db/backends/sqlite3/schema.py @@ -27,13 +27,11 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): 'SQLite3 does not support disabling them in the middle of ' 'a multi-statement transaction.' ) - self.connection.cursor().execute('PRAGMA legacy_alter_table = ON') return super().__enter__() def __exit__(self, exc_type, exc_value, traceback): super().__exit__(exc_type, exc_value, traceback) self.connection.check_constraints() - self.connection.cursor().execute('PRAGMA legacy_alter_table = OFF') self.connection.enable_constraint_checking() def quote_value(self, value): @@ -84,11 +82,12 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): return False def alter_db_table(self, model, old_db_table, new_db_table, disable_constraints=True): - if disable_constraints and self._is_referenced_by_fk_constraint(old_db_table): + if (not self.connection.features.supports_atomic_references_rename and + disable_constraints and self._is_referenced_by_fk_constraint(old_db_table)): if self.connection.in_atomic_block: raise NotSupportedError(( 'Renaming the %r table while in a transaction is not ' - 'supported on SQLite because it would break referential ' + 'supported on SQLite < 3.26 because it would break referential ' 'integrity. Try adding `atomic = False` to the Migration class.' ) % old_db_table) self.connection.enable_constraint_checking() @@ -102,11 +101,12 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): table_name = model._meta.db_table _, old_column_name = old_field.get_attname_column() if (new_field.name != old_field_name and + not self.connection.features.supports_atomic_references_rename and self._is_referenced_by_fk_constraint(table_name, old_column_name, ignore_self=True)): if self.connection.in_atomic_block: raise NotSupportedError(( 'Renaming the %r.%r column while in a transaction is not ' - 'supported on SQLite because it would break referential ' + 'supported on SQLite < 3.26 because it would break referential ' 'integrity. Try adding `atomic = False` to the Migration class.' ) % (model._meta.db_table, old_field_name)) with atomic(self.connection.alias): diff --git a/tests/backends/sqlite/tests.py b/tests/backends/sqlite/tests.py index 46122dc38b..c5b9569eac 100644 --- a/tests/backends/sqlite/tests.py +++ b/tests/backends/sqlite/tests.py @@ -121,8 +121,8 @@ class SchemaTests(TransactionTestCase): new_field.set_attributes_from_name('renamed') msg = ( "Renaming the 'backends_author'.'name' column while in a " - "transaction is not supported on SQLite because it would break " - "referential integrity. Try adding `atomic = False` to the " + "transaction is not supported on SQLite < 3.26 because it would " + "break referential integrity. Try adding `atomic = False` to the " "Migration class." ) with self.assertRaisesMessage(NotSupportedError, msg): @@ -136,7 +136,7 @@ class SchemaTests(TransactionTestCase): """ msg = ( "Renaming the 'backends_author' table while in a transaction is " - "not supported on SQLite because it would break referential " + "not supported on SQLite < 3.26 because it would break referential " "integrity. Try adding `atomic = False` to the Migration class." ) with self.assertRaisesMessage(NotSupportedError, msg):