diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index c1ef625bb6..bacd998fa5 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -261,15 +261,17 @@ class DatabaseOperations(BaseDatabaseOperations): sql.append('%s %s;' % (style.SQL_KEYWORD('TRUNCATE'), style.SQL_FIELD(self.quote_name(table)))) sql.append('SET FOREIGN_KEY_CHECKS = 1;') - # 'ALTER TABLE table AUTO_INCREMENT = 1;'... style SQL statements - # to reset sequence indices - sql.extend(["%s %s %s %s %s;" % \ - (style.SQL_KEYWORD('ALTER'), - style.SQL_KEYWORD('TABLE'), - style.SQL_TABLE(self.quote_name(sequence['table'])), - style.SQL_KEYWORD('AUTO_INCREMENT'), - style.SQL_FIELD('= 1'), - ) for sequence in sequences]) + # Truncate already resets the AUTO_INCREMENT field from + # MySQL version 5.0.13 onwards. Refs #16961. + if self.connection.mysql_version < (5,0,13): + sql.extend( + ["%s %s %s %s %s;" % \ + (style.SQL_KEYWORD('ALTER'), + style.SQL_KEYWORD('TABLE'), + style.SQL_TABLE(self.quote_name(sequence['table'])), + style.SQL_KEYWORD('AUTO_INCREMENT'), + style.SQL_FIELD('= 1'), + ) for sequence in sequences]) return sql else: return [] diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py index d5b1ea82bf..9b28787c15 100644 --- a/tests/regressiontests/backends/tests.py +++ b/tests/regressiontests/backends/tests.py @@ -61,10 +61,34 @@ class OracleChecks(unittest.TestCase): def test_client_encoding(self): # If the backend is Oracle, test that the client encoding is set # correctly. This was broken under Cygwin prior to r14781. - c = connection.cursor() # Ensure the connection is initialized. + connection.cursor() # Ensure the connection is initialized. self.assertEqual(connection.connection.encoding, "UTF-8") self.assertEqual(connection.connection.nencoding, "UTF-8") +class MySQLTests(TestCase): + @unittest.skipUnless(connection.vendor == 'mysql', + "Test valid only for MySQL") + def test_autoincrement(self): + """ + Check that auto_increment fields are reset correctly by sql_flush(). + Before MySQL version 5.0.13 TRUNCATE did not do auto_increment reset. + Refs #16961. + """ + statements = connection.ops.sql_flush(no_style(), + tables=['test'], + sequences=[{ + 'table': 'test', + 'col': 'somecol', + }]) + found_reset = False + for sql in statements: + found_reset = found_reset or 'ALTER TABLE' in sql + if connection.mysql_version < (5,0,13): + self.assertTrue(found_reset) + else: + self.assertFalse(found_reset) + + class DateQuotingTest(TestCase): def test_django_date_trunc(self): diff --git a/tests/regressiontests/test_runner/models.py b/tests/regressiontests/test_runner/models.py index e69de29bb2..9a072e627c 100644 --- a/tests/regressiontests/test_runner/models.py +++ b/tests/regressiontests/test_runner/models.py @@ -0,0 +1,5 @@ +from django.db import models + +class Person(models.Model): + first_name = models.CharField(max_length=20) + last_name = models.CharField(max_length=20) diff --git a/tests/regressiontests/test_runner/tests.py b/tests/regressiontests/test_runner/tests.py index 2af4eb9750..9f8085b5b6 100644 --- a/tests/regressiontests/test_runner/tests.py +++ b/tests/regressiontests/test_runner/tests.py @@ -8,13 +8,15 @@ from optparse import make_option from django.core.exceptions import ImproperlyConfigured from django.core.management import call_command from django import db -from django.test import simple +from django.db import connection +from django.test import simple, TransactionTestCase from django.test.simple import DjangoTestSuiteRunner, get_tests from django.test.testcases import connections_support_transactions from django.utils import unittest from django.utils.importlib import import_module from ..admin_scripts.tests import AdminScriptTestCase +from .models import Person TEST_APP_OK = 'regressiontests.test_runner.valid_app.models' @@ -281,3 +283,24 @@ class Sqlite3InMemoryTestDbs(unittest.TestCase): self.assertTrue(connections_support_transactions(), msg) finally: db.connections = old_db_connections + + +class AutoIncrementResetTest(TransactionTestCase): + """ + Here we test creating the same model two times in different test methods, + and check that both times they get "1" as their PK value. That is, we test + that AutoField values start from 1 for each transactional test case. + """ + @unittest.skipIf(connection.vendor == 'oracle', + "Oracle's auto-increment fields are not reset between " + "tests") + def test_autoincrement_reset1(self): + p = Person.objects.create(first_name='Jack', last_name='Smith') + self.assertEquals(p.pk, 1) + + @unittest.skipIf(connection.vendor == 'oracle', + "Oracle's auto-increment fields are not reset between " + "tests") + def test_autoincrement_reset2(self): + p = Person.objects.create(first_name='Jack', last_name='Smith') + self.assertEquals(p.pk, 1)