diff options
Diffstat (limited to 'django/db/backends/sqlite3')
| -rw-r--r-- | django/db/backends/sqlite3/base.py | 12 | ||||
| -rw-r--r-- | django/db/backends/sqlite3/schema.py | 11 |
2 files changed, 16 insertions, 7 deletions
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index 6ead2b2d48..9b0be56862 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -215,11 +215,13 @@ class DatabaseWrapper(BaseDatabaseWrapper): self.connection.isolation_level = level def disable_constraint_checking(self): - if self.in_atomic_block: - # sqlite3 cannot disable constraint checking inside a transaction. - return False - self.cursor().execute('PRAGMA foreign_keys = OFF') - return True + with self.cursor() as cursor: + cursor.execute('PRAGMA foreign_keys = OFF') + # Foreign key constraints cannot be turned off while in a multi- + # statement transaction. Fetch the current state of the pragma + # to determine if constraints are effectively disabled. + enabled = cursor.execute('PRAGMA foreign_keys').fetchone()[0] + return not bool(enabled) def enable_constraint_checking(self): self.cursor().execute('PRAGMA foreign_keys = ON') diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py index e0d8135cbd..0954c66aaf 100644 --- a/django/db/backends/sqlite3/schema.py +++ b/django/db/backends/sqlite3/schema.py @@ -19,8 +19,15 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): def __enter__(self): # Some SQLite schema alterations need foreign key constraints to be - # disabled. Enforce it here for the duration of the transaction. - self.connection.disable_constraint_checking() + # disabled. Enforce it here for the duration of the schema edition. + if not self.connection.disable_constraint_checking(): + raise NotSupportedError( + 'SQLite schema editor cannot be used while foreign key ' + 'constraint checks are enabled. Make sure to disable them ' + 'before entering a transaction.atomic() context because ' + '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__() |
