From 579909a13feb958f75d1d77e9995cef8f2b9c2a3 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Mon, 26 Aug 2019 09:15:37 +0200 Subject: [PATCH] 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. --- django/db/backends/mysql/introspection.py | 10 +++++++++- tests/introspection/models.py | 1 + tests/introspection/tests.py | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py index 05e73c78dc..82637d15fb 100644 --- a/django/db/backends/mysql/introspection.py +++ b/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, diff --git a/tests/introspection/models.py b/tests/introspection/models.py index 6f43359dd4..c3f6338176 100644 --- a/tests/introspection/models.py +++ b/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 = { diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index 91b6ec732e..5e6fd3d741 100644 --- a/tests/introspection/tests.py +++ b/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)