summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sinov <sihaelov@gmail.com>2016-12-13 21:38:09 +1000
committerTim Graham <timograham@gmail.com>2018-03-21 12:28:16 -0400
commit9aca67bea8d42e6c1889f16e5ce297cfc23b91a2 (patch)
tree19b7ebd6b5a324a5be2a3a5da66d8b208635225b
parenta170dac887ba17afb0adb7a837410dd26471f097 (diff)
Fixed #27533 -- Fixed inspectdb crash if a unique constraint uses an unsupported type.
-rw-r--r--AUTHORS1
-rw-r--r--django/core/management/commands/inspectdb.py16
-rw-r--r--tests/inspectdb/models.py1
-rw-r--r--tests/inspectdb/tests.py28
4 files changed, 40 insertions, 6 deletions
diff --git a/AUTHORS b/AUTHORS
index cf632452c6..e62c079413 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -567,6 +567,7 @@ answer newbie questions, and generally made Django that much better:
Michael Placentra II <someone@michaelplacentra2.net>
Michael Radziej <mir@noris.de>
Michael Schwarz <michi.schwarz@gmail.com>
+ Michael Sinov <sihaelov@gmail.com>
Michael Thornhill <michael.thornhill@gmail.com>
Michal Chruszcz <troll@pld-linux.org>
michal@plovarna.cz
diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py
index 31c4ae062b..c84ce14739 100644
--- a/django/core/management/commands/inspectdb.py
+++ b/django/core/management/commands/inspectdb.py
@@ -269,16 +269,24 @@ class Command(BaseCommand):
to the given database table name.
"""
unique_together = []
+ has_unsupported_constraint = False
for params in constraints.values():
if params['unique']:
columns = params['columns']
+ if None in columns:
+ has_unsupported_constraint = True
+ columns = [x for x in columns if x is not None]
if len(columns) > 1:
unique_together.append(str(tuple(column_to_field_name[c] for c in columns)))
managed_comment = " # Created from a view. Don't remove." if is_view else ""
- meta = ["",
- " class Meta:",
- " managed = False%s" % managed_comment,
- " db_table = '%s'" % table_name]
+ meta = ['']
+ if has_unsupported_constraint:
+ meta.append(' # A unique constraint could not be introspected.')
+ meta += [
+ ' class Meta:',
+ ' managed = False%s' % managed_comment,
+ ' db_table = %r' % table_name
+ ]
if unique_together:
tup = '(' + ', '.join(unique_together) + ',)'
meta += [" unique_together = %s" % tup]
diff --git a/tests/inspectdb/models.py b/tests/inspectdb/models.py
index 8c660658cd..20f6b5e940 100644
--- a/tests/inspectdb/models.py
+++ b/tests/inspectdb/models.py
@@ -17,6 +17,7 @@ class PeopleData(models.Model):
class PeopleMoreData(models.Model):
people_unique = models.ForeignKey(People, models.CASCADE, unique=True)
+ message = models.ForeignKey(Message, models.CASCADE, blank=True, null=True)
license = models.CharField(max_length=255)
diff --git a/tests/inspectdb/tests.py b/tests/inspectdb/tests.py
index b6bbf0b2dd..e994b2cb74 100644
--- a/tests/inspectdb/tests.py
+++ b/tests/inspectdb/tests.py
@@ -7,6 +7,8 @@ from django.db import connection
from django.db.backends.base.introspection import TableInfo
from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
+from .models import PeopleMoreData
+
def inspectdb_tables_only(table_name):
"""
@@ -21,6 +23,7 @@ def special_table_only(table_name):
class InspectDBTestCase(TestCase):
+ unique_re = re.compile(r'.*unique_together = \((.+),\).*')
def test_stealth_table_name_filter_option(self):
out = StringIO()
@@ -212,8 +215,7 @@ class InspectDBTestCase(TestCase):
call_command('inspectdb', 'inspectdb_uniquetogether', stdout=out)
output = out.getvalue()
self.assertIn(" unique_together = (('", output)
- unique_re = re.compile(r'.*unique_together = \((.+),\).*')
- unique_together_match = re.findall(unique_re, output)
+ unique_together_match = re.findall(self.unique_re, output)
# There should be one unique_together tuple.
self.assertEqual(len(unique_together_match), 1)
fields = unique_together_match[0]
@@ -225,6 +227,28 @@ class InspectDBTestCase(TestCase):
# are given an integer suffix.
self.assertIn("('non_unique_column', 'non_unique_column_0')", fields)
+ @skipUnless(connection.vendor == 'postgresql', 'PostgreSQL specific SQL')
+ def test_unsupported_unique_together(self):
+ """Unsupported index types (COALESCE here) are skipped."""
+ with connection.cursor() as c:
+ c.execute(
+ 'CREATE UNIQUE INDEX Findex ON %s '
+ '(id, people_unique_id, COALESCE(message_id, -1))' % PeopleMoreData._meta.db_table
+ )
+ try:
+ out = StringIO()
+ call_command(
+ 'inspectdb',
+ table_name_filter=lambda tn: tn.startswith(PeopleMoreData._meta.db_table),
+ stdout=out,
+ )
+ output = out.getvalue()
+ self.assertIn('# A unique constraint could not be introspected.', output)
+ self.assertEqual(re.findall(self.unique_re, output), ["('id', 'people_unique')"])
+ finally:
+ with connection.cursor() as c:
+ c.execute('DROP INDEX Findex')
+
@skipUnless(connection.vendor == 'sqlite',
"Only patched sqlite's DatabaseIntrospection.data_types_reverse for this test")
def test_custom_fields(self):