diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index febc246e09..d60ff7937d 100644
|
a
|
b
|
class CursorWrapper:
|
| 61 | 61 | codes_for_integrityerror = ( |
| 62 | 62 | 1048, # Column cannot be null |
| 63 | 63 | 1690, # BIGINT UNSIGNED value is out of range |
| | 64 | 3819, # CHECK constraint is violated |
| 64 | 65 | 4025, # CHECK constraint failed |
| 65 | 66 | ) |
| 66 | 67 | |
diff --git a/django/db/backends/mysql/features.py b/django/db/backends/mysql/features.py
index 229e26a750..5800ad6c95 100644
|
a
|
b
|
class DatabaseFeatures(BaseDatabaseFeatures):
|
| 89 | 89 | |
| 90 | 90 | @cached_property |
| 91 | 91 | def supports_column_check_constraints(self): |
| 92 | | return self.connection.mysql_is_mariadb and self.connection.mysql_version >= (10, 2, 1) |
| | 92 | if self.connection.mysql_is_mariadb: |
| | 93 | return self.connection.mysql_version >= (10, 2, 1) |
| | 94 | return self.connection.mysql_version >= (8, 0, 16) |
| 93 | 95 | |
| 94 | 96 | supports_table_check_constraints = property(operator.attrgetter('supports_column_check_constraints')) |
| 95 | 97 | |
| … |
… |
class DatabaseFeatures(BaseDatabaseFeatures):
|
| 99 | 101 | version = self.connection.mysql_version |
| 100 | 102 | if (version >= (10, 2, 22) and version < (10, 3)) or version >= (10, 3, 10): |
| 101 | 103 | return True |
| 102 | | return False |
| | 104 | return self.connection.mysql_version >= (8, 0, 16) |
| 103 | 105 | |
| 104 | 106 | @cached_property |
| 105 | 107 | def has_select_for_update_skip_locked(self): |
diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py
index 82637d15fb..a014b87916 100644
|
a
|
b
|
class DatabaseIntrospection(BaseDatabaseIntrospection):
|
| 209 | 209 | if self.connection.features.can_introspect_check_constraints: |
| 210 | 210 | unnamed_constraints_index = 0 |
| 211 | 211 | columns = {info.name for info in self.get_table_description(cursor, table_name)} |
| 212 | | type_query = """ |
| 213 | | SELECT c.constraint_name, c.check_clause |
| 214 | | FROM information_schema.check_constraints AS c |
| 215 | | WHERE |
| 216 | | c.constraint_schema = DATABASE() AND |
| 217 | | c.table_name = %s |
| 218 | | """ |
| | 212 | if self.connection.mysql_is_mariadb: |
| | 213 | type_query = """ |
| | 214 | SELECT c.constraint_name, c.check_clause |
| | 215 | FROM information_schema.check_constraints AS c |
| | 216 | WHERE |
| | 217 | c.constraint_schema = DATABASE() AND |
| | 218 | c.table_name = %s |
| | 219 | """ |
| | 220 | else: |
| | 221 | type_query = """ |
| | 222 | SELECT cc.constraint_name, cc.check_clause |
| | 223 | FROM |
| | 224 | information_schema.check_constraints AS cc, |
| | 225 | information_schema.table_constraints AS tc |
| | 226 | WHERE |
| | 227 | cc.constraint_schema = DATABASE() AND |
| | 228 | tc.table_schema = cc.constraint_schema AND |
| | 229 | cc.constraint_name = tc.constraint_name AND |
| | 230 | tc.constraint_type = 'CHECK' AND |
| | 231 | tc.table_name = %s |
| | 232 | """ |
| 219 | 233 | cursor.execute(type_query, [table_name]) |
| 220 | 234 | for constraint, check_clause in cursor.fetchall(): |
| 221 | 235 | constraint_columns = self._parse_constraint_columns(check_clause, columns) |
diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py
index d138606791..d379965c27 100644
|
a
|
b
|
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
| 28 | 28 | sql_delete_pk = "ALTER TABLE %(table)s DROP PRIMARY KEY" |
| 29 | 29 | |
| 30 | 30 | sql_create_index = 'CREATE INDEX %(name)s ON %(table)s (%(columns)s)%(extra)s' |
| 31 | | # The name of the column check constraint is the same as the field name on |
| 32 | | # MariaDB. Adding IF EXISTS clause prevents migrations crash. Constraint is |
| 33 | | # removed during a "MODIFY" column statement. |
| 34 | | sql_delete_check = 'ALTER TABLE %(table)s DROP CONSTRAINT IF EXISTS %(name)s' |
| | 31 | |
| | 32 | @property |
| | 33 | def sql_delete_check(self): |
| | 34 | if self.connection.mysql_is_mariadb: |
| | 35 | # The name of the column check constraint is the same as the field |
| | 36 | # name on MariaDB. Adding IF EXISTS clause prevents migrations |
| | 37 | # crash. Constraint is removed during a "MODIFY" column statement. |
| | 38 | return 'ALTER TABLE %(table)s DROP CONSTRAINT IF EXISTS %(name)s' |
| | 39 | return 'ALTER TABLE %(table)s DROP CHECK %(name)s' |
| 35 | 40 | |
| 36 | 41 | def quote_value(self, value): |
| 37 | 42 | self.connection.ensure_connection() |