Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#31805 closed Bug (fixed)

MySQL Schema tests fail when table names are case-insensitive.

Reported by: Ahmad A. Hussein Owned by: Mariusz Felisiak
Component: Testing framework Version: dev
Severity: Normal Keywords: mysql, schema, windows
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Both tests fail with the same error message:

ERROR: test_alter_int_pk_to_bigautofield_pk (schema.tests.SchemaTests)
ERROR: test_alter_int_pk_to_int_unique (schema.tests.SchemaTests)
django.db.utils.OperationalError: (1050, "Table 'integerpk' already exists")

Tested on Windows with python3.8 and MySQL8.0

Change History (15)

comment:1 by Mariusz Felisiak, 4 years ago

It's probably not related with running tests on Windows. Can you check a value of the lower_case_table_names parameter? and share a stacktrace.

comment:2 by Mariusz Felisiak, 4 years ago

Resolution: needsinfo
Status: newclosed

comment:3 by Ahmad A. Hussein, 4 years ago

ERROR: test_alter_int_pk_to_bigautofield_pk (schema.tests.SchemaTests)
Should be able to rename an IntegerField(primary_key=True) to
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 82, in _execute
    return self.cursor.execute(sql)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\mysql\base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 209, in execute
    res = self._query(query)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 315, in _query
    db.query(q)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\connections.py", line 239, in query
    _mysql.connection.query(self, query)
MySQLdb._exceptions.OperationalError: (1050, "Table 'integerpk' already exists")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\ahmad\Desktop\Projects\DjangoGSOC\tests\schema\tests.py", line 1345, in test_alter_int_pk_to_bigautofield_pk
    editor.create_model(IntegerPK)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\base\schema.py", line 324, in create_model
    self.execute(sql, params or None)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\base\schema.py", line 142, in execute
    cursor.execute(sql, params)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 82, in _execute
    return self.cursor.execute(sql)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\mysql\base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 209, in execute
    res = self._query(query)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 315, in _query
    db.query(q)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\connections.py", line 239, in query
    _mysql.connection.query(self, query)
django.db.utils.OperationalError: (1050, "Table 'integerpk' already exists")

----------------------------------------------------------------------
CREATE TABLE `INTEGERPK` (`i` integer NOT NULL PRIMARY KEY, `j` integer NOT NULL UNIQUE); (params None)
(0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
(0.094) None; args=None
(0.000) SET foreign_key_checks=0; args=None
(0.016) SHOW FULL TABLES; args=None
(0.000) SET foreign_key_checks=1; args=None

======================================================================
ERROR: test_alter_int_pk_to_int_unique (schema.tests.SchemaTests)
Should be able to rename an IntegerField(primary_key=True) to
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 82, in _execute
    return self.cursor.execute(sql)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\mysql\base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 209, in execute
    res = self._query(query)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 315, in _query
    db.query(q)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\connections.py", line 239, in query
    _mysql.connection.query(self, query)
MySQLdb._exceptions.OperationalError: (1050, "Table 'integerpk' already exists")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\ahmad\Desktop\Projects\DjangoGSOC\tests\schema\tests.py", line 1383, in test_alter_int_pk_to_int_unique
    editor.create_model(IntegerPK)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\base\schema.py", line 324, in create_model
    self.execute(sql, params or None)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\base\schema.py", line 142, in execute
    cursor.execute(sql, params)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\utils.py", line 82, in _execute
    return self.cursor.execute(sql)
  File "c:\users\ahmad\desktop\projects\djangogsoc\django\db\backends\mysql\base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 209, in execute
    res = self._query(query)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\cursors.py", line 315, in _query
    db.query(q)
  File "C:\Users\ahmad\Envs\parallelpr\lib\site-packages\MySQLdb\connections.py", line 239, in query
    _mysql.connection.query(self, query)
django.db.utils.OperationalError: (1050, "Table 'integerpk' already exists")

----------------------------------------------------------------------
CREATE TABLE `INTEGERPK` (`i` integer NOT NULL PRIMARY KEY, `j` integer NOT NULL UNIQUE); (params None)
(0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
(0.000) None; args=None
(0.000) SET foreign_key_checks=0; args=None
(0.000) SHOW FULL TABLES; args=None
(0.000) SET foreign_key_checks=1; args=None

----------------------------------------------------------------------
Ran 132 tests in 1083.874s

FAILED (errors=2, skipped=18)
Destroying test database for alias 'default'...

Value for lower_case_table_names is 1 (default on Windows)

comment:4 by Mariusz Felisiak, 4 years ago

Do you run tests on the current master, I'm confused because we have 131 tests in SchemaTests and 19 tests are skipped on MySQL 8+. So it looks that you have an extra tests (132 in logs) maybe it causes an isolation issue. Also can you reproduce this issue when running these two tests in isolation?

comment:5 by Ahmad A. Hussein, 4 years ago

Yes, I'm running on the latest master. The reason for the extra test is because I'm running tests on the entire schema app, not just SchemaTests. The extra test is from SchemaLoggerTests.

Running the tests on just SchemaTests gives the same errors.

Running the tests in complete isolation though gives a successful test run.

comment:6 by Mariusz Felisiak, 4 years ago

Can you also check a storage engine and sql_mode? Sorry for so many questions.

comment:7 by Ahmad A. Hussein, 4 years ago

Feel free to ask! I'm sorry I'm not much help debugging this.

Storage engine is InnoDB

sqlmode is sql-mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"`
I've ran into two new errors as well. I'm going to try to debug them and I'll update with info once I do.

======================================================================
ERROR: aggregation.tests (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: aggregation.tests
Traceback (most recent call last):
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 219, in ensure_connection
    self.connect()
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 200, in connect
    self.connection = self.get_new_connection(conn_params)
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 234, in get_new_connection
    return Database.connect(**conn_params)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\__init__.py", line 130, in Connect
    return Connection(*args, **kwargs)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\connections.py", line 185, in __init__
    super().__init__(*args, **kwargs2)
MySQLdb._exceptions.OperationalError: (1049, "Unknown database 'main'")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "c:\users\ahmad\appdata\local\programs\python\python38\lib\unittest\loader.py", line 436, in _find_test_path
    module = self._get_module_from_name(name)
  File "c:\users\ahmad\appdata\local\programs\python\python38\lib\unittest\loader.py", line 377, in _get_module_from_name
    __import__(name)
  File "C:\Users\ahmad\Desktop\Projects\DjangoMain\tests\aggregation\tests.py", line 21, in <module>
    class AggregateTestCase(TestCase):
  File "C:\Users\ahmad\Desktop\Projects\DjangoMain\tests\aggregation\tests.py", line 1208, in AggregateTestCase
    connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode,
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\__init__.py", line 28, in __getattr__
    return getattr(connections[DEFAULT_DB_ALIAS], item)
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 398, in sql_mode
    sql_mode = self.mysql_server_data['sql_mode']
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 359, in mysql_server_data
    with self.temporary_connection() as cursor:
  File "c:\users\ahmad\appdata\local\programs\python\python38\lib\contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 603, in temporary_connection
    with self.cursor() as cursor:
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 259, in cursor
    return self._cursor()
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 235, in _cursor
    self.ensure_connection()
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 219, in ensure_connection
    self.connect()
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 219, in ensure_connection
    self.connect()
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 200, in connect
    self.connection = self.get_new_connection(conn_params)
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 234, in get_new_connection
    return Database.connect(**conn_params)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\__init__.py", line 130, in Connect
    return Connection(*args, **kwargs)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\connections.py", line 185, in __init__
    super().__init__(*args, **kwargs2)
django.db.utils.OperationalError: (1049, "Unknown database 'main'")


----------------------------------------------------------------------
Ran 15 tests in 2.695s

FAILED (errors=1)
Destroying test database for alias 'default'...

(djangodev) C:\Users\ahmad\Desktop\Projects\DjangoMain\tests>runtests.py --parallel=1 --settings=test_mysql annotations
Testing against Django installed in 'c:\users\ahmad\desktop\projects\djangomain\django'
System check identified no issues (0 silenced).
E
======================================================================
ERROR: annotations.tests (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: annotations.tests
Traceback (most recent call last):
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 219, in ensure_connection
    self.connect()
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 200, in connect
    self.connection = self.get_new_connection(conn_params)
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 234, in get_new_connection
    return Database.connect(**conn_params)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\__init__.py", line 130, in Connect
    return Connection(*args, **kwargs)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\connections.py", line 185, in __init__
    super().__init__(*args, **kwargs2)
MySQLdb._exceptions.OperationalError: (1049, "Unknown database 'main'")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "c:\users\ahmad\appdata\local\programs\python\python38\lib\unittest\loader.py", line 436, in _find_test_path
    module = self._get_module_from_name(name)
  File "c:\users\ahmad\appdata\local\programs\python\python38\lib\unittest\loader.py", line 377, in _get_module_from_name
    __import__(name)
  File "C:\Users\ahmad\Desktop\Projects\DjangoMain\tests\annotations\tests.py", line 33, in <module>
    class NonAggregateAnnotationTestCase(TestCase):
  File "C:\Users\ahmad\Desktop\Projects\DjangoMain\tests\annotations\tests.py", line 650, in NonAggregateAnnotationTestCase
    connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode,
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\__init__.py", line 28, in __getattr__
    return getattr(connections[DEFAULT_DB_ALIAS], item)
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 398, in sql_mode
    sql_mode = self.mysql_server_data['sql_mode']
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 359, in mysql_server_data
    with self.temporary_connection() as cursor:
  File "c:\users\ahmad\appdata\local\programs\python\python38\lib\contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 603, in temporary_connection
    with self.cursor() as cursor:
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 259, in cursor
    return self._cursor()
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 235, in _cursor
    self.ensure_connection()
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 219, in ensure_connection
    self.connect()
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 219, in ensure_connection
    self.connect()
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\base\base.py", line 200, in connect
    self.connection = self.get_new_connection(conn_params)
  File "c:\users\ahmad\desktop\projects\djangomain\django\utils\asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "c:\users\ahmad\desktop\projects\djangomain\django\db\backends\mysql\base.py", line 234, in get_new_connection
    return Database.connect(**conn_params)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\__init__.py", line 130, in Connect
    return Connection(*args, **kwargs)
  File "C:\Users\ahmad\Envs\djangodev\lib\site-packages\MySQLdb\connections.py", line 185, in __init__
    super().__init__(*args, **kwargs2)
django.db.utils.OperationalError: (1049, "Unknown database 'main'")

comment:8 by Mariusz Felisiak, 4 years ago

Component: Database layer (models, ORM)Testing framework
Has patch: set
Resolution: needsinfo
Status: closednew
Summary: MySQL Schema tests fail on WindowsMySQL Schema tests fail when table names are case-insensitive.
Triage Stage: UnreviewedAccepted

comment:9 by Mariusz Felisiak, 4 years ago

Owner: changed from nobody to Mariusz Felisiak
Status: newassigned

Thanks Carlton for confirmation!

comment:10 by Carlton Gibson, 4 years ago

I see this on Windows 10 with MySQL 8.

...
MySQLdb._exceptions.OperationalError: (1050, "Table 'integerpk' already exists")

...
Ran 131 tests in 42.172s

FAILED (errors=2, skipped=18)
Destroying test database for alias 'default'...
(django) PS C:\Users\carlt\src\django\tests> django-admin.exe shell --settings=test_mysql
Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.db import connection
>>> connection.features.ignores_table_name_case
True

The adjustment in Mariusz´ PR fixes the failure.

comment:11 by Carlton Gibson, 4 years ago

Triage Stage: AcceptedReady for checkin

comment:12 by GitHub <noreply@…>, 4 years ago

Resolution: fixed
Status: assignedclosed

In fd53db8:

Fixed #31805 -- Fixed SchemaTests.tearDown() when table names are case-insensitive.

comment:13 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

In 2ff2084c:

[3.1.x] Fixed #31805 -- Fixed SchemaTests.tearDown() when table names are case-insensitive.

Backport of fd53db842c35c994dbd54196dd38a908f3676b1a from master

comment:14 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

In dcb27ead:

[3.0.x] Fixed #31805 -- Fixed SchemaTests.tearDown() when table names are case-insensitive.

Backport of fd53db842c35c994dbd54196dd38a908f3676b1a from master

comment:15 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

In eb815938:

[2.2.x] Fixed #31805 -- Fixed SchemaTests.tearDown() when table names are case-insensitive.

Backport of fd53db842c35c994dbd54196dd38a908f3676b1a from master

Note: See TracTickets for help on using tickets.
Back to Top