test_mysql.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import unittest
  2. from contextlib import contextmanager
  3. from django.core.exceptions import ImproperlyConfigured
  4. from django.db import connection
  5. from django.test import TestCase, override_settings
  6. @contextmanager
  7. def get_connection():
  8. new_connection = connection.copy()
  9. yield new_connection
  10. new_connection.close()
  11. @override_settings(DEBUG=True)
  12. @unittest.skipUnless(connection.vendor == 'mysql', 'MySQL specific test.')
  13. class MySQLTests(TestCase):
  14. read_committed = 'read committed'
  15. repeatable_read = 'repeatable read'
  16. isolation_values = {
  17. level: level.replace(' ', '-').upper()
  18. for level in (read_committed, repeatable_read)
  19. }
  20. @classmethod
  21. def setUpClass(cls):
  22. super().setUpClass()
  23. configured_isolation_level = connection.isolation_level or cls.isolation_values[cls.repeatable_read]
  24. cls.configured_isolation_level = configured_isolation_level.upper()
  25. cls.other_isolation_level = (
  26. cls.read_committed
  27. if configured_isolation_level != cls.isolation_values[cls.read_committed]
  28. else cls.repeatable_read
  29. )
  30. @staticmethod
  31. def get_isolation_level(connection):
  32. with connection.cursor() as cursor:
  33. cursor.execute("SELECT @@session.tx_isolation")
  34. return cursor.fetchone()[0]
  35. def test_auto_is_null_auto_config(self):
  36. query = 'set sql_auto_is_null = 0'
  37. connection.init_connection_state()
  38. last_query = connection.queries[-1]['sql'].lower()
  39. if connection.features.is_sql_auto_is_null_enabled:
  40. self.assertIn(query, last_query)
  41. else:
  42. self.assertNotIn(query, last_query)
  43. def test_connect_isolation_level(self):
  44. self.assertEqual(self.get_isolation_level(connection), self.configured_isolation_level)
  45. def test_setting_isolation_level(self):
  46. with get_connection() as new_connection:
  47. new_connection.settings_dict['OPTIONS']['isolation_level'] = self.other_isolation_level
  48. self.assertEqual(
  49. self.get_isolation_level(new_connection),
  50. self.isolation_values[self.other_isolation_level]
  51. )
  52. def test_uppercase_isolation_level(self):
  53. # Upper case values are also accepted in 'isolation_level'.
  54. with get_connection() as new_connection:
  55. new_connection.settings_dict['OPTIONS']['isolation_level'] = self.other_isolation_level.upper()
  56. self.assertEqual(
  57. self.get_isolation_level(new_connection),
  58. self.isolation_values[self.other_isolation_level]
  59. )
  60. def test_default_isolation_level(self):
  61. # If not specified in settings, the default is read committed.
  62. with get_connection() as new_connection:
  63. new_connection.settings_dict['OPTIONS'].pop('isolation_level', None)
  64. self.assertEqual(
  65. self.get_isolation_level(new_connection),
  66. self.isolation_values[self.read_committed]
  67. )
  68. def test_isolation_level_validation(self):
  69. new_connection = connection.copy()
  70. new_connection.settings_dict['OPTIONS']['isolation_level'] = 'xxx'
  71. msg = (
  72. "Invalid transaction isolation level 'xxx' specified.\n"
  73. "Use one of 'read committed', 'read uncommitted', "
  74. "'repeatable read', 'serializable', or None."
  75. )
  76. with self.assertRaisesMessage(ImproperlyConfigured, msg):
  77. new_connection.cursor()