[2.1.x] Fixed #29827 -- Fixed reuse of test databases with --keepdb on MySQL.

Regression in e1253bc26f.
Backport of 9a88c6dd6a from master.
This commit is contained in:
Sergey Fedoseev 2018-10-26 04:37:41 +05:00 committed by Tim Graham
parent 4529287af2
commit 69603b3e71
3 changed files with 16 additions and 11 deletions

View File

@ -19,17 +19,7 @@ class DatabaseCreation(BaseDatabaseCreation):
def _execute_create_test_db(self, cursor, parameters, keepdb=False): def _execute_create_test_db(self, cursor, parameters, keepdb=False):
try: try:
if keepdb: super()._execute_create_test_db(cursor, parameters, keepdb)
# If the database should be kept, add "IF NOT EXISTS" to avoid
# "database exists" error, also temporarily disable "database
# exists" warning.
cursor.execute('''
SET @_tmp_sql_notes := @@sql_notes, sql_notes = 0;
CREATE DATABASE IF NOT EXISTS %(dbname)s %(suffix)s;
SET sql_notes = @_tmp_sql_notes;
''' % parameters)
else:
super()._execute_create_test_db(cursor, parameters, keepdb)
except Exception as e: except Exception as e:
if len(e.args) < 1 or e.args[0] != 1007: if len(e.args) < 1 or e.args[0] != 1007:
# All errors except "database exists" (1007) cancel tests. # All errors except "database exists" (1007) cancel tests.
@ -49,6 +39,9 @@ class DatabaseCreation(BaseDatabaseCreation):
try: try:
self._execute_create_test_db(cursor, test_db_params, keepdb) self._execute_create_test_db(cursor, test_db_params, keepdb)
except Exception: except Exception:
if keepdb:
# If the database should be kept, skip everything else.
return
try: try:
if verbosity >= 1: if verbosity >= 1:
print("Destroying old test database for alias %s..." % ( print("Destroying old test database for alias %s..." % (
@ -59,7 +52,9 @@ class DatabaseCreation(BaseDatabaseCreation):
except Exception as e: except Exception as e:
sys.stderr.write("Got an error recreating the test database: %s\n" % e) sys.stderr.write("Got an error recreating the test database: %s\n" % e)
sys.exit(2) sys.exit(2)
self._clone_db(source_database_name, target_database_name)
def _clone_db(self, source_database_name, target_database_name):
dump_cmd = DatabaseClient.settings_to_cmd_args(self.connection.settings_dict) dump_cmd = DatabaseClient.settings_to_cmd_args(self.connection.settings_dict)
dump_cmd[0] = 'mysqldump' dump_cmd[0] = 'mysqldump'
dump_cmd[-1] = source_database_name dump_cmd[-1] = source_database_name

View File

@ -14,3 +14,6 @@ Bugfixes
* Fixed a regression in Django 1.11 where ``django-admin shell`` may hang * Fixed a regression in Django 1.11 where ``django-admin shell`` may hang
on startup (:ticket:`29774`). on startup (:ticket:`29774`).
* Fixed a regression in Django 2.0 where test databases aren't reused with
``manage.py test --keepdb`` on MySQL (:ticket:`29827`).

View File

@ -43,3 +43,10 @@ class DatabaseCreationTests(SimpleTestCase):
with self.patch_test_db_creation(self._execute_raise_access_denied): with self.patch_test_db_creation(self._execute_raise_access_denied):
with self.assertRaises(SystemExit): with self.assertRaises(SystemExit):
creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False) creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False)
def test_clone_test_db_database_exists(self):
creation = DatabaseCreation(connection)
with self.patch_test_db_creation(self._execute_raise_database_exists):
with mock.patch.object(DatabaseCreation, '_clone_db') as _clone_db:
creation._clone_test_db('suffix', verbosity=0, keepdb=True)
_clone_db.assert_not_called()