From 328f5627ddfca3008dc5cf9f7da1ade0157ac74f Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Sun, 21 Oct 2018 09:08:05 +0200 Subject: [PATCH] Fixed #29870 -- Added DurationField introspection for Oracle and PostgreSQL. Thanks Tim Graham for the review. --- django/db/backends/base/features.py | 3 +++ django/db/backends/mysql/features.py | 1 + django/db/backends/oracle/introspection.py | 1 + django/db/backends/postgresql/introspection.py | 1 + django/db/backends/sqlite3/features.py | 1 + docs/releases/2.2.txt | 7 +++++++ tests/introspection/models.py | 1 + tests/introspection/tests.py | 17 +++++++++++------ 8 files changed, 26 insertions(+), 6 deletions(-) diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py index 3dd55e80b9..f724d01894 100644 --- a/django/db/backends/base/features.py +++ b/django/db/backends/base/features.py @@ -129,6 +129,9 @@ class BaseDatabaseFeatures: # Can the backend introspect an DecimalField, instead of an FloatField? can_introspect_decimal_field = True + # Can the backend introspect a DurationField, instead of a BigIntegerField? + can_introspect_duration_field = True + # Can the backend introspect an IPAddressField, instead of an CharField? can_introspect_ip_address_field = False diff --git a/django/db/backends/mysql/features.py b/django/db/backends/mysql/features.py index 96183b5c65..ebfd591196 100644 --- a/django/db/backends/mysql/features.py +++ b/django/db/backends/mysql/features.py @@ -15,6 +15,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_date_lookup_using_string = False can_introspect_autofield = True can_introspect_binary_field = False + can_introspect_duration_field = False can_introspect_small_integer_field = True can_introspect_positive_integer_field = True introspected_boolean_field_type = 'IntegerField' diff --git a/django/db/backends/oracle/introspection.py b/django/db/backends/oracle/introspection.py index f7ede7db13..e5597fd56c 100644 --- a/django/db/backends/oracle/introspection.py +++ b/django/db/backends/oracle/introspection.py @@ -18,6 +18,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): cx_Oracle.DATETIME: 'DateField', cx_Oracle.FIXED_CHAR: 'CharField', cx_Oracle.FIXED_NCHAR: 'CharField', + cx_Oracle.INTERVAL: 'DurationField', cx_Oracle.NATIVE_FLOAT: 'FloatField', cx_Oracle.NCHAR: 'CharField', cx_Oracle.NCLOB: 'TextField', diff --git a/django/db/backends/postgresql/introspection.py b/django/db/backends/postgresql/introspection.py index 77db6d5cbf..85538262cb 100644 --- a/django/db/backends/postgresql/introspection.py +++ b/django/db/backends/postgresql/introspection.py @@ -22,6 +22,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): 1083: 'TimeField', 1114: 'DateTimeField', 1184: 'DateTimeField', + 1186: 'DurationField', 1266: 'TimeField', 1700: 'DecimalField', 2950: 'UUIDField', diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py index 6cf23e08ce..9918e44386 100644 --- a/django/db/backends/sqlite3/features.py +++ b/django/db/backends/sqlite3/features.py @@ -15,6 +15,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_mixed_date_datetime_comparisons = False autocommits_when_autocommit_is_off = True can_introspect_decimal_field = False + can_introspect_duration_field = False can_introspect_positive_integer_field = True can_introspect_small_integer_field = True supports_transactions = True diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt index c6d1de1432..90099d9fc3 100644 --- a/docs/releases/2.2.txt +++ b/docs/releases/2.2.txt @@ -182,6 +182,9 @@ Management Commands * :option:`inspectdb --include-views` now creates models for materialized views on PostgreSQL. +* :djadmin:`inspectdb` now introspects :class:`~django.db.models.DurationField` + for Oracle and PostgreSQL. + Migrations ~~~~~~~~~~ @@ -274,6 +277,10 @@ Database backend API constraints or uniqueness errors while inserting or set ``DatabaseFeatures.supports_ignore_conflicts`` to ``False``. +* Third party database backends must implement introspection for + ``DurationField`` or set ``DatabaseFeatures.can_introspect_duration_field`` + to ``False``. + :mod:`django.contrib.gis` ------------------------- diff --git a/tests/introspection/models.py b/tests/introspection/models.py index 6c5c00a336..3a494037d2 100644 --- a/tests/introspection/models.py +++ b/tests/introspection/models.py @@ -24,6 +24,7 @@ class Reporter(models.Model): facebook_user_id = models.BigIntegerField(null=True) raw_data = models.BinaryField(null=True) small_int = models.SmallIntegerField() + interval = models.DurationField() class Meta: unique_together = ('first_name', 'last_name') diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index ed5556fc20..c61720d12b 100644 --- a/tests/introspection/tests.py +++ b/tests/introspection/tests.py @@ -77,11 +77,16 @@ class IntrospectionTests(TransactionTestCase): desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table) self.assertEqual( [datatype(r[1], r) for r in desc], - ['AutoField' if connection.features.can_introspect_autofield else 'IntegerField', - 'CharField', 'CharField', 'CharField', - 'BigIntegerField' if connection.features.can_introspect_big_integer_field else 'IntegerField', - 'BinaryField' if connection.features.can_introspect_binary_field else 'TextField', - 'SmallIntegerField' if connection.features.can_introspect_small_integer_field else 'IntegerField'] + [ + 'AutoField' if connection.features.can_introspect_autofield else 'IntegerField', + 'CharField', + 'CharField', + 'CharField', + 'BigIntegerField' if connection.features.can_introspect_big_integer_field else 'IntegerField', + 'BinaryField' if connection.features.can_introspect_binary_field else 'TextField', + 'SmallIntegerField' if connection.features.can_introspect_small_integer_field else 'IntegerField', + 'DurationField' if connection.features.can_introspect_duration_field else 'BigIntegerField', + ] ) def test_get_table_description_col_lengths(self): @@ -98,7 +103,7 @@ class IntrospectionTests(TransactionTestCase): nullable_by_backend = connection.features.interprets_empty_strings_as_nulls self.assertEqual( [r[6] for r in desc], - [False, nullable_by_backend, nullable_by_backend, nullable_by_backend, True, True, False] + [False, nullable_by_backend, nullable_by_backend, nullable_by_backend, True, True, False, False] ) @skipUnlessDBFeature('can_introspect_autofield')