Fixed #27533 -- Fixed inspectdb crash if a unique constraint uses an unsupported type.
This commit is contained in:
parent
a170dac887
commit
9aca67bea8
1
AUTHORS
1
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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue