From 3e43d24ad36d45cace57e6a7efd34638577ae744 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Mon, 19 Dec 2016 12:13:31 +0100 Subject: [PATCH] Refs #19884 -- Added CharField max_length introspection on Oracle. --- django/db/backends/oracle/features.py | 1 - django/db/backends/oracle/introspection.py | 18 +++++++++++++----- tests/inspectdb/tests.py | 1 - tests/introspection/tests.py | 2 -- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/django/db/backends/oracle/features.py b/django/db/backends/oracle/features.py index e2840e0fe8..d30c149ad2 100644 --- a/django/db/backends/oracle/features.py +++ b/django/db/backends/oracle/features.py @@ -21,7 +21,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): has_bulk_insert = True supports_tablespaces = True supports_sequence_reset = False - can_introspect_max_length = False can_introspect_time_field = False atomic_transactions = False supports_combined_alters = False diff --git a/django/db/backends/oracle/introspection.py b/django/db/backends/oracle/introspection.py index 8b5aec7680..7af2a18a8d 100644 --- a/django/db/backends/oracle/introspection.py +++ b/django/db/backends/oracle/introspection.py @@ -62,11 +62,19 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): "Returns a description of the table, with the DB-API cursor.description interface." # user_tab_columns gives data default for columns cursor.execute(""" - SELECT column_name, data_default + SELECT + column_name, + data_default, + CASE + WHEN char_used IS NULL THEN data_length + ELSE char_length + END as internal_size FROM user_tab_cols WHERE table_name = UPPER(%s)""", [table_name]) - columns_default = {column: default if default != 'NULL' else None for column, default in cursor.fetchall()} - + field_map = { + column: (internal_size, default if default != 'NULL' else None) + for column, default, internal_size in cursor.fetchall() + } self.cache_bust_counter += 1 cursor.execute("SELECT * FROM {} WHERE ROWNUM < 2 AND {} > 0".format( self.connection.ops.quote_name(table_name), @@ -74,9 +82,9 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): description = [] for desc in cursor.description: name = force_text(desc[0]) # cx_Oracle always returns a 'str' on both Python 2 and 3 - default = columns_default[name] + internal_size, default = field_map[name] name = name % {} # cx_Oracle, for some reason, doubles percent signs. - description.append(FieldInfo(*(name.lower(),) + desc[1:] + (default,))) + description.append(FieldInfo(*(name.lower(),) + desc[1:3] + (internal_size,) + desc[4:] + (default,))) return description def table_name_converter(self, name): diff --git a/tests/inspectdb/tests.py b/tests/inspectdb/tests.py index d1ca549fb0..3f09b72986 100644 --- a/tests/inspectdb/tests.py +++ b/tests/inspectdb/tests.py @@ -58,7 +58,6 @@ class InspectDBTestCase(TestCase): assertFieldType = self.make_field_type_asserter() # Inspecting Oracle DB doesn't produce correct results (#19884): - # - it gets max_length wrong: it returns a number of bytes. # - it reports fields as blank=True when they aren't. if (connection.features.can_introspect_max_length and not connection.features.interprets_empty_strings_as_nulls): diff --git a/tests/introspection/tests.py b/tests/introspection/tests.py index 369b9b1586..a8ce01b2b2 100644 --- a/tests/introspection/tests.py +++ b/tests/introspection/tests.py @@ -83,8 +83,6 @@ class IntrospectionTests(TransactionTestCase): 'SmallIntegerField' if connection.features.can_introspect_small_integer_field else 'IntegerField'] ) - # The following test fails on Oracle due to #17202 (can't correctly - # inspect the length of character columns). @skipUnlessDBFeature('can_introspect_max_length') def test_get_table_description_col_lengths(self): with connection.cursor() as cursor: