diff options
author | Paveł Tyślacki <pavel.tyslacki@gmail.com> | 2019-02-28 00:47:29 +0300 |
---|---|---|
committer | Tim Graham <timograham@gmail.com> | 2019-03-13 10:24:28 -0400 |
commit | 782d85b6dfa191e67c0f1d572641d8236c79174c (patch) | |
tree | 8ca589140652b19f60941c5ff2d361ed81d491d7 /tests/introspection | |
parent | 406de977ea1a6429535d21240e3ecdac06d4516c (diff) | |
download | django-782d85b6dfa191e67c0f1d572641d8236c79174c.tar.gz |
Fixed #30183 -- Added introspection of inline SQLite constraints.
Diffstat (limited to 'tests/introspection')
-rw-r--r-- | tests/introspection/models.py | 18 | ||||
-rw-r--r-- | tests/introspection/tests.py | 59 |
2 files changed, 76 insertions, 1 deletions
diff --git a/tests/introspection/models.py b/tests/introspection/models.py index 32acc323bd..fa663de2fd 100644 --- a/tests/introspection/models.py +++ b/tests/introspection/models.py @@ -58,3 +58,21 @@ class ArticleReporter(models.Model): class Meta: managed = False + + +class Comment(models.Model): + ref = models.UUIDField(unique=True) + article = models.ForeignKey(Article, models.CASCADE, db_index=True) + email = models.EmailField() + pub_date = models.DateTimeField() + up_votes = models.PositiveIntegerField() + body = models.TextField() + + class Meta: + constraints = [ + models.CheckConstraint(name='up_votes_gte_0_check', check=models.Q(up_votes__gte=0)), + models.UniqueConstraint(fields=['article', 'email', 'pub_date'], name='article_email_pub_date_uniq'), + ] + indexes = [ + models.Index(fields=['email', 'pub_date'], name='email_pub_date_idx'), + ] diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index d851352cae..10524cdacb 100644 --- a/tests/introspection/tests.py +++ b/tests/introspection/tests.py @@ -5,7 +5,7 @@ from django.db.models import Index from django.db.utils import DatabaseError from django.test import TransactionTestCase, skipUnlessDBFeature -from .models import Article, ArticleReporter, City, District, Reporter +from .models import Article, ArticleReporter, City, Comment, District, Reporter class IntrospectionTests(TransactionTestCase): @@ -211,3 +211,60 @@ class IntrospectionTests(TransactionTestCase): self.assertEqual(val['orders'], ['ASC'] * len(val['columns'])) indexes_verified += 1 self.assertEqual(indexes_verified, 4) + + def test_get_constraints(self): + def assertDetails(details, cols, primary_key=False, unique=False, index=False, check=False, foreign_key=None): + # Different backends have different values for same constraints: + # PRIMARY KEY UNIQUE CONSTRAINT UNIQUE INDEX + # MySQL pk=1 uniq=1 idx=1 pk=0 uniq=1 idx=1 pk=0 uniq=1 idx=1 + # PostgreSQL pk=1 uniq=1 idx=0 pk=0 uniq=1 idx=0 pk=0 uniq=1 idx=1 + # SQLite pk=1 uniq=0 idx=0 pk=0 uniq=1 idx=0 pk=0 uniq=1 idx=1 + if details['primary_key']: + details['unique'] = True + if details['unique']: + details['index'] = False + self.assertEqual(details['columns'], cols) + self.assertEqual(details['primary_key'], primary_key) + self.assertEqual(details['unique'], unique) + self.assertEqual(details['index'], index) + self.assertEqual(details['check'], check) + self.assertEqual(details['foreign_key'], foreign_key) + + with connection.cursor() as cursor: + constraints = connection.introspection.get_constraints(cursor, Comment._meta.db_table) + # Test custom constraints + custom_constraints = { + 'article_email_pub_date_uniq', + 'email_pub_date_idx', + } + if connection.features.supports_column_check_constraints: + custom_constraints.add('up_votes_gte_0_check') + assertDetails(constraints['up_votes_gte_0_check'], ['up_votes'], check=True) + assertDetails(constraints['article_email_pub_date_uniq'], ['article_id', 'email', 'pub_date'], unique=True) + assertDetails(constraints['email_pub_date_idx'], ['email', 'pub_date'], index=True) + # Test field constraints + field_constraints = set() + for name, details in constraints.items(): + if name in custom_constraints: + continue + elif details['columns'] == ['up_votes'] and details['check']: + assertDetails(details, ['up_votes'], 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'] == ['article_id'] and details['index']: + assertDetails(details, ['article_id'], index=True) + field_constraints.add(name) + elif details['columns'] == ['id'] and details['primary_key']: + assertDetails(details, ['id'], primary_key=True, unique=True) + field_constraints.add(name) + elif details['columns'] == ['article_id'] and details['foreign_key']: + assertDetails(details, ['article_id'], foreign_key=('introspection_article', 'id')) + field_constraints.add(name) + elif details['check']: + # Some databases (e.g. Oracle) include additional check + # constraints. + field_constraints.add(name) + # All constraints are accounted for. + self.assertEqual(constraints.keys() ^ (custom_constraints | field_constraints), set()) |