diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py index 84eca986440..817b1067e3f 100644 --- a/django/db/backends/sqlite3/features.py +++ b/django/db/backends/sqlite3/features.py @@ -26,7 +26,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_atomic_references_rename = Database.sqlite_version_info >= (3, 26, 0) can_create_inline_fk = False supports_paramstyle_pyformat = False - supports_sequence_reset = False can_clone_databases = True supports_temporal_subtraction = True ignores_table_name_case = True diff --git a/django/db/backends/sqlite3/operations.py b/django/db/backends/sqlite3/operations.py index 3f55332c99c..9510b5edd99 100644 --- a/django/db/backends/sqlite3/operations.py +++ b/django/db/backends/sqlite3/operations.py @@ -201,13 +201,33 @@ class DatabaseOperations(BaseDatabaseOperations): # Simulate TRUNCATE CASCADE by recursively collecting the tables # referencing the tables to be flushed. tables = set(chain.from_iterable(self._references_graph(table) for table in tables)) - # Note: No requirement for reset of auto-incremented indices (cf. other - # sql_flush() implementations). Just return SQL at this point - return ['%s %s %s;' % ( + sql = ['%s %s %s;' % ( style.SQL_KEYWORD('DELETE'), style.SQL_KEYWORD('FROM'), style.SQL_FIELD(self.quote_name(table)) ) for table in tables] + if reset_sequences: + sequences = [{'table': table} for table in tables] + sql.extend(self.sequence_reset_by_name_sql(style, sequences)) + return sql + + def sequence_reset_by_name_sql(self, style, sequences): + if not sequences: + return [] + return [ + '%s %s %s %s = 0 %s %s %s (%s);' % ( + style.SQL_KEYWORD('UPDATE'), + style.SQL_TABLE(self.quote_name('sqlite_sequence')), + style.SQL_KEYWORD('SET'), + style.SQL_FIELD(self.quote_name('seq')), + style.SQL_KEYWORD('WHERE'), + style.SQL_FIELD(self.quote_name('name')), + style.SQL_KEYWORD('IN'), + ', '.join([ + "'%s'" % sequence_info['table'] for sequence_info in sequences + ]), + ), + ] def adapt_datetimefield_value(self, value): if value is None: diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt index 4cf8183d4b0..ceb1b0f0bf9 100644 --- a/docs/releases/3.1.txt +++ b/docs/releases/3.1.txt @@ -320,6 +320,9 @@ Management Commands * The new :option:`dbshell -- ARGUMENTS ` option allows passing extra arguments to the command-line client for the database. +* The :djadmin:`flush` and :djadmin:`sqlflush` commands now include SQL to + reset sequences on SQLite. + Migrations ~~~~~~~~~~ diff --git a/tests/backends/sqlite/test_operations.py b/tests/backends/sqlite/test_operations.py index 0ee70061f8e..863a9785809 100644 --- a/tests/backends/sqlite/test_operations.py +++ b/tests/backends/sqlite/test_operations.py @@ -40,7 +40,6 @@ class SQLiteOperationsTests(TestCase): ) def test_sql_flush_sequences(self): - # sequences doesn't change statements on SQLite. self.assertEqual( connection.ops.sql_flush( no_style(), @@ -50,11 +49,12 @@ class SQLiteOperationsTests(TestCase): [ 'DELETE FROM "backends_person";', 'DELETE FROM "backends_tag";', + 'UPDATE "sqlite_sequence" SET "seq" = 0 WHERE "name" IN ' + '(\'backends_person\', \'backends_tag\');', ], ) def test_sql_flush_sequences_allow_cascade(self): - # sequences doesn't change statements on SQLite. statements = connection.ops.sql_flush( no_style(), [Person._meta.db_table, Tag._meta.db_table], @@ -63,7 +63,7 @@ class SQLiteOperationsTests(TestCase): ) self.assertEqual( # The tables are processed in an unordered set. - sorted(statements), + sorted(statements[:-1]), [ 'DELETE FROM "backends_person";', 'DELETE FROM "backends_tag";', @@ -72,3 +72,14 @@ class SQLiteOperationsTests(TestCase): 'zzzzzzzzzzzzzzzzzzzzzzz";', ], ) + self.assertIs(statements[-1].startswith( + 'UPDATE "sqlite_sequence" SET "seq" = 0 WHERE "name" IN (' + ), True) + self.assertIn("'backends_person'", statements[-1]) + self.assertIn("'backends_tag'", statements[-1]) + self.assertIn( + "'backends_verylongmodelnamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzz_m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzz'", + statements[-1], + )