Fixed #31275 -- Optimized sql_flush() without resetting sequences on MySQL.
Co-Authored-By: Simon Charette <charettes@users.noreply.github.com>
This commit is contained in:
parent
75520e1767
commit
89032876f4
1
AUTHORS
1
AUTHORS
|
@ -585,6 +585,7 @@ answer newbie questions, and generally made Django that much better:
|
|||
Martin von Gagern <gagern@google.com>
|
||||
Mart Sõmermaa <http://mrts.pri.ee/>
|
||||
Marty Alchin <gulopine@gamemusic.org>
|
||||
Masashi Shibata <m.shibata1020@gmail.com>
|
||||
masonsimon+django@gmail.com
|
||||
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
|
||||
Massimo Scamarcia <massimo.scamarcia@gmail.com>
|
||||
|
|
|
@ -194,21 +194,40 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
return 'RETURNING %s' % ', '.join(columns), ()
|
||||
|
||||
def sql_flush(self, style, tables, sequences, allow_cascade=False):
|
||||
# NB: The generated SQL below is specific to MySQL
|
||||
# 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
|
||||
# to clear all tables of all data
|
||||
if tables:
|
||||
sql = ['SET FOREIGN_KEY_CHECKS = 0;']
|
||||
for table in tables:
|
||||
sql.append('%s %s;' % (
|
||||
style.SQL_KEYWORD('TRUNCATE'),
|
||||
style.SQL_FIELD(self.quote_name(table)),
|
||||
))
|
||||
sql.append('SET FOREIGN_KEY_CHECKS = 1;')
|
||||
sql.extend(self.sequence_reset_by_name_sql(style, sequences))
|
||||
return sql
|
||||
else:
|
||||
if not tables:
|
||||
return []
|
||||
sql = ['SET FOREIGN_KEY_CHECKS = 0;']
|
||||
tables = set(tables)
|
||||
with_sequences = set(s['table'] for s in sequences)
|
||||
# It's faster to TRUNCATE tables that require a sequence reset since
|
||||
# ALTER TABLE AUTO_INCREMENT is slower than TRUNCATE.
|
||||
sql.extend(
|
||||
'%s %s;' % (
|
||||
style.SQL_KEYWORD('TRUNCATE'),
|
||||
style.SQL_FIELD(self.quote_name(table_name)),
|
||||
) for table_name in tables.intersection(with_sequences)
|
||||
)
|
||||
# Otherwise issue a simple DELETE since it's faster than TRUNCATE
|
||||
# and preserves sequences.
|
||||
sql.extend(
|
||||
'%s %s %s;' % (
|
||||
style.SQL_KEYWORD('DELETE'),
|
||||
style.SQL_KEYWORD('FROM'),
|
||||
style.SQL_FIELD(self.quote_name(table_name)),
|
||||
) for table_name in tables.difference(with_sequences)
|
||||
)
|
||||
sql.append('SET FOREIGN_KEY_CHECKS = 1;')
|
||||
return sql
|
||||
|
||||
def sequence_reset_by_name_sql(self, style, sequences):
|
||||
return [
|
||||
'%s %s %s %s = 1;' % (
|
||||
style.SQL_KEYWORD('ALTER'),
|
||||
style.SQL_KEYWORD('TABLE'),
|
||||
style.SQL_FIELD(self.quote_name(sequence_info['table'])),
|
||||
style.SQL_FIELD('AUTO_INCREMENT'),
|
||||
) for sequence_info in sequences
|
||||
]
|
||||
|
||||
def validate_autopk_value(self, value):
|
||||
# MySQLism: zero in AUTO_INCREMENT field does not work. Refs #17653.
|
||||
|
|
|
@ -347,6 +347,10 @@ Models
|
|||
* :meth:`.QuerySet.bulk_create` now sets the primary key on objects when using
|
||||
MariaDB 10.5+.
|
||||
|
||||
* The ``DatabaseOperations.sql_flush()`` method now generates more efficient
|
||||
SQL on MySQL by using ``DELETE`` instead of ``TRUNCATE`` statements for
|
||||
tables which don't require resetting sequences.
|
||||
|
||||
Pagination
|
||||
~~~~~~~~~~
|
||||
|
||||
|
@ -415,6 +419,12 @@ Tests
|
|||
* :class:`~django.test.runner.DiscoverRunner` now skips running the system
|
||||
checks on databases not :ref:`referenced by tests<testing-multi-db>`.
|
||||
|
||||
* :class:`~django.test.TransactionTestCase` teardown is now faster on MySQL
|
||||
due to :djadmin:`flush` command improvements. As a side effect the latter
|
||||
doesn't automatically reset sequences on teardown anymore. Enable
|
||||
:attr:`.TransactionTestCase.reset_sequences` if your tests require this
|
||||
feature.
|
||||
|
||||
URLs
|
||||
~~~~
|
||||
|
||||
|
|
Loading…
Reference in New Issue