浏览代码

Refs #30591 -- Fixed introspection of check and unique column constraints on MariaDB.

Unnamed unique and check columns constraints have the same name as
a column. Ensure uniqueness by using custom names.

Thanks Adnan Umer for the report.
Mariusz Felisiak 5 年之前
父节点
当前提交
579909a13f
共有 3 个文件被更改,包括 16 次插入1 次删除
  1. 9 1
      django/db/backends/mysql/introspection.py
  2. 1 0
      tests/introspection/models.py
  3. 6 0
      tests/introspection/tests.py

+ 9 - 1
django/db/backends/mysql/introspection.py

@@ -207,6 +207,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                 constraints[constraint]['unique'] = True
         # Add check constraints.
         if self.connection.features.can_introspect_check_constraints:
+            unnamed_constraints_index = 0
             columns = {info.name for info in self.get_table_description(cursor, table_name)}
             type_query = """
                 SELECT c.constraint_name, c.check_clause
@@ -217,8 +218,15 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
             """
             cursor.execute(type_query, [table_name])
             for constraint, check_clause in cursor.fetchall():
+                constraint_columns = self._parse_constraint_columns(check_clause, columns)
+                # Ensure uniqueness of unnamed constraints. Unnamed unique
+                # and check columns constraints have the same name as
+                # a column.
+                if set(constraint_columns) == {constraint}:
+                    unnamed_constraints_index += 1
+                    constraint = '__unnamed_constraint_%s__' % unnamed_constraints_index
                 constraints[constraint] = {
-                    'columns': self._parse_constraint_columns(check_clause, columns),
+                    'columns': constraint_columns,
                     'primary_key': False,
                     'unique': False,
                     'index': False,

+ 1 - 0
tests/introspection/models.py

@@ -83,6 +83,7 @@ class Comment(models.Model):
 
 class CheckConstraintModel(models.Model):
     up_votes = models.PositiveIntegerField()
+    voting_number = models.PositiveIntegerField(unique=True)
 
     class Meta:
         required_db_features = {

+ 6 - 0
tests/introspection/tests.py

@@ -268,9 +268,15 @@ class IntrospectionTests(TransactionTestCase):
             elif details['columns'] == ['up_votes'] and details['check']:
                 assertDetails(details, ['up_votes'], check=True)
                 field_constraints.add(name)
+            elif details['columns'] == ['voting_number'] and details['check']:
+                assertDetails(details, ['voting_number'], check=True)
+                field_constraints.add(name)
             elif details['columns'] == ['ref'] and details['unique']:
                 assertDetails(details, ['ref'], unique=True)
                 field_constraints.add(name)
+            elif details['columns'] == ['voting_number'] and details['unique']:
+                assertDetails(details, ['voting_number'], unique=True)
+                field_constraints.add(name)
             elif details['columns'] == ['article_id'] and details['index']:
                 assertDetails(details, ['article_id'], index=True)
                 field_constraints.add(name)