Fixed #14098 -- Prevented crash for introspection errors in inspectdb
Thanks Tim Graham for the review.
This commit is contained in:
parent
441c537b66
commit
4c18a8a378
@ -6,6 +6,7 @@ from collections import OrderedDict
|
|||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from django.db import DEFAULT_DB_ALIAS, connections
|
from django.db import DEFAULT_DB_ALIAS, connections
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
@ -57,25 +58,32 @@ class Command(BaseCommand):
|
|||||||
if table_name_filter is not None and callable(table_name_filter):
|
if table_name_filter is not None and callable(table_name_filter):
|
||||||
if not table_name_filter(table_name):
|
if not table_name_filter(table_name):
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
relations = connection.introspection.get_relations(cursor, table_name)
|
||||||
|
except NotImplementedError:
|
||||||
|
relations = {}
|
||||||
|
try:
|
||||||
|
indexes = connection.introspection.get_indexes(cursor, table_name)
|
||||||
|
except NotImplementedError:
|
||||||
|
indexes = {}
|
||||||
|
try:
|
||||||
|
constraints = connection.introspection.get_constraints(cursor, table_name)
|
||||||
|
except NotImplementedError:
|
||||||
|
constraints = {}
|
||||||
|
table_description = connection.introspection.get_table_description(cursor, table_name)
|
||||||
|
except Exception as e:
|
||||||
|
yield "# Unable to inspect table '%s'" % table_name
|
||||||
|
yield "# The error was: %s" % force_text(e)
|
||||||
|
continue
|
||||||
|
|
||||||
yield ''
|
yield ''
|
||||||
yield ''
|
yield ''
|
||||||
yield 'class %s(models.Model):' % table2model(table_name)
|
yield 'class %s(models.Model):' % table2model(table_name)
|
||||||
known_models.append(table2model(table_name))
|
known_models.append(table2model(table_name))
|
||||||
try:
|
|
||||||
relations = connection.introspection.get_relations(cursor, table_name)
|
|
||||||
except NotImplementedError:
|
|
||||||
relations = {}
|
|
||||||
try:
|
|
||||||
indexes = connection.introspection.get_indexes(cursor, table_name)
|
|
||||||
except NotImplementedError:
|
|
||||||
indexes = {}
|
|
||||||
try:
|
|
||||||
constraints = connection.introspection.get_constraints(cursor, table_name)
|
|
||||||
except NotImplementedError:
|
|
||||||
constraints = {}
|
|
||||||
used_column_names = [] # Holds column names used in the table so far
|
used_column_names = [] # Holds column names used in the table so far
|
||||||
column_to_field_name = {} # Maps column names to names of model fields
|
column_to_field_name = {} # Maps column names to names of model fields
|
||||||
for row in connection.introspection.get_table_description(cursor, table_name):
|
for row in table_description:
|
||||||
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
||||||
extra_params = OrderedDict() # Holds Field parameters such as 'db_column'.
|
extra_params = OrderedDict() # Holds Field parameters such as 'db_column'.
|
||||||
column_name = row[0]
|
column_name = row[0]
|
||||||
|
@ -6,7 +6,8 @@ from unittest import skipUnless
|
|||||||
|
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, mock, skipUnlessDBFeature
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from django.utils.six import PY3, StringIO
|
from django.utils.six import PY3, StringIO
|
||||||
|
|
||||||
from .models import ColumnTypes
|
from .models import ColumnTypes
|
||||||
@ -268,3 +269,17 @@ class InspectDBTestCase(TestCase):
|
|||||||
self.assertIn("big_int_field = models.BigIntegerField()", output)
|
self.assertIn("big_int_field = models.BigIntegerField()", output)
|
||||||
finally:
|
finally:
|
||||||
connection.introspection.data_types_reverse = orig_data_types_reverse
|
connection.introspection.data_types_reverse = orig_data_types_reverse
|
||||||
|
|
||||||
|
def test_introspection_errors(self):
|
||||||
|
"""
|
||||||
|
Introspection errors should not crash the command, and the error should
|
||||||
|
be visible in the output.
|
||||||
|
"""
|
||||||
|
out = StringIO()
|
||||||
|
with mock.patch('django.db.backends.base.introspection.BaseDatabaseIntrospection.table_names',
|
||||||
|
return_value=['nonexistent']):
|
||||||
|
call_command('inspectdb', stdout=out)
|
||||||
|
output = force_text(out.getvalue())
|
||||||
|
self.assertIn("# Unable to inspect table 'nonexistent'", output)
|
||||||
|
# The error message depends on the backend
|
||||||
|
self.assertIn("# The error was:", output)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user