mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #26351 -- Added MySQL check to warn about strict mode option
Thanks Adam Chainz for the initial implementation in django-mysql. Thanks Adam Chainz, Tim Graham, and Shai Berger for the reviews.
This commit is contained in:
		| @@ -1,8 +1,31 @@ | ||||
| from django.core import checks | ||||
| from django.db.backends.base.validation import BaseDatabaseValidation | ||||
| from django.utils.version import get_docs_version | ||||
|  | ||||
|  | ||||
| class DatabaseValidation(BaseDatabaseValidation): | ||||
|     def check(self, **kwargs): | ||||
|         issues = super(DatabaseValidation, self).check(**kwargs) | ||||
|         issues.extend(self._check_sql_mode(**kwargs)) | ||||
|         return issues | ||||
|  | ||||
|     def _check_sql_mode(self, **kwargs): | ||||
|         with self.connection.cursor() as cursor: | ||||
|             cursor.execute("SELECT @@sql_mode") | ||||
|             sql_mode = cursor.fetchone() | ||||
|         modes = set(sql_mode[0].split(',')) | ||||
|         if not (modes & {'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES'}): | ||||
|             return [checks.Warning( | ||||
|                 "MySQL Strict Mode is not set for database connection '%s'" % self.connection.alias, | ||||
|                 hint="MySQL's Strict Mode fixes many data integrity problems in MySQL, " | ||||
|                      "such as data truncation upon insertion, by escalating warnings into " | ||||
|                      "errors. It is strongly recommended you activate it. See: " | ||||
|                      "https://docs.djangoproject.com/en/%s/ref/databases/#mysql-sql-mode" | ||||
|                      % (get_docs_version(),), | ||||
|                 id='mysql.W002', | ||||
|             )] | ||||
|         return [] | ||||
|  | ||||
|     def check_field(self, field, **kwargs): | ||||
|         """ | ||||
|         MySQL has the following field length restriction: | ||||
|   | ||||
| @@ -592,6 +592,8 @@ If you're using MySQL, the following checks will be performed: | ||||
|  | ||||
| * **mysql.E001**: MySQL does not allow unique ``CharField``\s to have a | ||||
|   ``max_length`` > 255. | ||||
| * **mysql.W002**: MySQL Strict Mode is not set for database connection | ||||
|   '<alias>'. See also :ref:`mysql-sql-mode`. | ||||
|  | ||||
| Templates | ||||
| --------- | ||||
|   | ||||
| @@ -31,3 +31,28 @@ class DatabaseCheckTests(TestCase): | ||||
|         with mock.patch('django.db.backends.base.validation.BaseDatabaseValidation.check') as mocked_check: | ||||
|             run_checks(tags=[Tags.database]) | ||||
|             self.assertTrue(mocked_check.called) | ||||
|  | ||||
|     @unittest.skipUnless(connection.vendor == 'mysql', 'Test only for MySQL') | ||||
|     def test_mysql_strict_mode(self): | ||||
|         good_sql_modes = [ | ||||
|             'STRICT_TRANS_TABLES,STRICT_ALL_TABLES', | ||||
|             'STRICT_TRANS_TABLES', | ||||
|             'STRICT_ALL_TABLES', | ||||
|         ] | ||||
|         for response in good_sql_modes: | ||||
|             with mock.patch( | ||||
|                 'django.db.backends.utils.CursorWrapper.fetchone', create=True, | ||||
|                 return_value=(response,) | ||||
|             ): | ||||
|                 self.assertEqual(self.func(None), []) | ||||
|  | ||||
|         bad_sql_modes = ['', 'WHATEVER'] | ||||
|         for response in bad_sql_modes: | ||||
|             with mock.patch( | ||||
|                 'django.db.backends.utils.CursorWrapper.fetchone', create=True, | ||||
|                 return_value=(response,) | ||||
|             ): | ||||
|                 # One warning for each database alias | ||||
|                 result = self.func(None) | ||||
|                 self.assertEqual(len(result), 2) | ||||
|                 self.assertEqual([r.id for r in result], ['mysql.W002', 'mysql.W002']) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user