diff options
| author | Simon Charette <charettes@users.noreply.github.com> | 2018-12-22 17:47:48 -0500 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2018-12-22 17:47:48 -0500 |
| commit | ce8b65ac5e8e20912c36ab5c714ddf11de3b664c (patch) | |
| tree | 4950c014c671cd76d2da83a70bd1183470bcea73 /django/db/backends/sqlite3/operations.py | |
| parent | d5af14aa84dc5ec913859e787b269fb8029d63cd (diff) | |
Fixed #30054 -- Implemented cascaded flush on SQLite.
This is required to maintain foreign key integrity when using
TransactionTestCase.available_apps.
Refs #30033, #14204, #20483.
Diffstat (limited to 'django/db/backends/sqlite3/operations.py')
| -rw-r--r-- | django/db/backends/sqlite3/operations.py | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/django/db/backends/sqlite3/operations.py b/django/db/backends/sqlite3/operations.py index cd71afb23b..858e10ef84 100644 --- a/django/db/backends/sqlite3/operations.py +++ b/django/db/backends/sqlite3/operations.py @@ -159,6 +159,27 @@ class DatabaseOperations(BaseDatabaseOperations): return -1 def sql_flush(self, style, tables, sequences, allow_cascade=False): + if tables and allow_cascade: + # Simulate TRUNCATE CASCADE by recursively collecting the tables + # referencing the tables to be flushed. + query = """ + WITH tables AS ( + %s + UNION + SELECT sqlite_master.name + FROM sqlite_master + JOIN tables ON ( + sql REGEXP %%s || tables.name || %%s + ) + ) SELECT name FROM tables; + """ % ' UNION '.join("SELECT '%s' name" % table for table in tables) + params = ( + r'(?i)\s+references\s+("|\')?', + r'("|\')?\s*\(', + ) + with self.connection.cursor() as cursor: + results = cursor.execute(query, params) + tables = [row[0] for row in results.fetchall()] sql = ['%s %s %s;' % ( style.SQL_KEYWORD('DELETE'), style.SQL_KEYWORD('FROM'), @@ -168,12 +189,6 @@ class DatabaseOperations(BaseDatabaseOperations): # sql_flush() implementations). Just return SQL at this point return sql - def execute_sql_flush(self, using, sql_list): - # To prevent possible violation of foreign key constraints, deactivate - # constraints outside of the transaction created in super(). - with self.connection.constraint_checks_disabled(): - super().execute_sql_flush(using, sql_list) - def adapt_datetimefield_value(self, value): if value is None: return None |
