diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py index 30d44c4796..8afc7eb516 100644 --- a/django/db/backends/base/features.py +++ b/django/db/backends/base/features.py @@ -143,6 +143,10 @@ class BaseDatabaseFeatures: # Can the backend introspect a TimeField, instead of a DateTimeField? can_introspect_time_field = True + # Some backends may not be able to differentiate BigAutoField from other + # fields such as AutoField. + introspected_big_auto_field_type = 'BigAutoField' + # Some backends may not be able to differentiate BooleanField from other # fields such as IntegerField. introspected_boolean_field_type = 'BooleanField' diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py index 69a42cdc02..19e949899f 100644 --- a/django/db/backends/sqlite3/features.py +++ b/django/db/backends/sqlite3/features.py @@ -16,10 +16,12 @@ class DatabaseFeatures(BaseDatabaseFeatures): max_query_params = 999 supports_mixed_date_datetime_comparisons = False autocommits_when_autocommit_is_off = sys.version_info < (3, 6) + can_introspect_autofield = True can_introspect_decimal_field = False can_introspect_duration_field = False can_introspect_positive_integer_field = True can_introspect_small_integer_field = True + introspected_big_auto_field_type = 'AutoField' supports_transactions = True atomic_transactions = False can_rollback_ddl = True diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py index 8ed043ba67..490606c64d 100644 --- a/django/db/backends/sqlite3/introspection.py +++ b/django/db/backends/sqlite3/introspection.py @@ -1,12 +1,15 @@ import re +from collections import namedtuple import sqlparse from django.db.backends.base.introspection import ( - BaseDatabaseIntrospection, FieldInfo, TableInfo, + BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo, ) from django.db.models.indexes import Index +FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('pk',)) + field_size_re = re.compile(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$') @@ -57,6 +60,14 @@ class FlexibleFieldLookupDict: class DatabaseIntrospection(BaseDatabaseIntrospection): data_types_reverse = FlexibleFieldLookupDict() + def get_field_type(self, data_type, description): + field_type = super().get_field_type(data_type, description) + if description.pk and field_type in {'BigIntegerField', 'IntegerField'}: + # No support for BigAutoField as SQLite treats all integer primary + # keys as signed 64-bit integers. + return 'AutoField' + return field_type + def get_table_list(self, cursor): """Return a list of table and view names in the current database.""" # Skip the sqlite_sequence system table used for autoincrement key @@ -82,6 +93,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): None, info['null_ok'], info['default'], + info['pk'] == 1, ) for info in self._table_info(cursor, table_name) ] diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt index 65f53c1a49..c8515d5ba6 100644 --- a/docs/releases/2.2.txt +++ b/docs/releases/2.2.txt @@ -192,7 +192,8 @@ Management Commands created child tables instead the parent. * :djadmin:`inspectdb` now introspects :class:`~django.db.models.DurationField` - for Oracle and PostgreSQL. + for Oracle and PostgreSQL, and :class:`~django.db.models.AutoField` for + SQLite. * On Oracle, :djadmin:`dbshell` is wrapped with ``rlwrap``, if available. ``rlwrap`` provides a command history and editing of keyboard input. diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index a616ee0f98..4eb868e907 100644 --- a/tests/introspection/tests.py +++ b/tests/introspection/tests.py @@ -110,7 +110,7 @@ class IntrospectionTests(TransactionTestCase): def test_bigautofield(self): with connection.cursor() as cursor: desc = connection.introspection.get_table_description(cursor, City._meta.db_table) - self.assertIn('BigAutoField', [datatype(r[1], r) for r in desc]) + self.assertIn(connection.features.introspected_big_auto_field_type, [datatype(r[1], r) for r in desc]) # Regression test for #9991 - 'real' types in postgres @skipUnlessDBFeature('has_real_datatype')