Fixed #22738 -- Abstracted boolean field type introspection
Thanks maxi for the report, Shai Berger for his help with the patch and Tim Graham for the review.
This commit is contained in:
parent
45840927d3
commit
dbdae3a755
|
@ -614,8 +614,8 @@ class BaseDatabaseFeatures(object):
|
|||
# Can the backend introspect an BinaryField, instead of an TextField?
|
||||
can_introspect_binary_field = True
|
||||
|
||||
# Can the backend introspect an BooleanField, instead of an IntegerField?
|
||||
can_introspect_boolean_field = True
|
||||
# What is the type returned when the backend introspect a BooleanField?
|
||||
introspected_boolean_field_type = 'BooleanField'
|
||||
|
||||
# Can the backend introspect an DecimalField, instead of an FloatField?
|
||||
can_introspect_decimal_field = True
|
||||
|
|
|
@ -178,7 +178,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
supports_regex_backreferencing = False
|
||||
supports_date_lookup_using_string = False
|
||||
can_introspect_binary_field = False
|
||||
can_introspect_boolean_field = False
|
||||
introspected_boolean_field_type = 'IntegerField'
|
||||
can_introspect_small_integer_field = True
|
||||
supports_timezones = False
|
||||
requires_explicit_null_ordering_when_grouping = True
|
||||
|
|
|
@ -125,6 +125,20 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
# select for update with limit can be achieved on Oracle, but not with the current backend.
|
||||
supports_select_for_update_with_limit = False
|
||||
|
||||
@cached_property
|
||||
def introspected_boolean_field_type(self):
|
||||
"""
|
||||
Some versions of Oracle -- we've seen this on 11.2.0.1 and suspect
|
||||
it goes back -- have a weird bug where, when an integer column is
|
||||
defined with a default, its precision is later reported on introspection
|
||||
as 0, regardless of the real precision. For Django introspection, this
|
||||
means that such columns are reported as IntegerField even if they are
|
||||
really BigIntegerField or BooleanField.
|
||||
|
||||
The bug is solved in Oracle 11.2.0.2 and up.
|
||||
"""
|
||||
return 'IntegerField' if self.connection.oracle_full_version < '11.2.0.2' else 'BooleanField'
|
||||
|
||||
|
||||
class DatabaseOperations(BaseDatabaseOperations):
|
||||
compiler_module = "django.db.backends.oracle.compiler"
|
||||
|
@ -735,20 +749,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
except ValueError:
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def version_has_default_introspection_bug(self):
|
||||
"""
|
||||
Some versions of Oracle -- we've seen this on 11.2.0.1 and suspect
|
||||
it goes back -- have a weird bug where, when an integer column is
|
||||
defined with a default, its precision is later reported on introspection
|
||||
as 0, regardless of the real precision. For Django introspection, this
|
||||
means that such columns are reported as IntegerField even if they are
|
||||
really BigIntegerField or BooleanField.
|
||||
|
||||
The bug is solved in Oracle 11.2.0.2 and up.
|
||||
"""
|
||||
return self.oracle_full_version < '11.2.0.2'
|
||||
|
||||
|
||||
class OracleParam(object):
|
||||
"""
|
||||
|
|
|
@ -87,18 +87,19 @@ class InspectDBTestCase(TestCase):
|
|||
else:
|
||||
assertFieldType('big_int_field', "models.IntegerField()")
|
||||
|
||||
if connection.features.can_introspect_boolean_field:
|
||||
if connection.features.introspected_boolean_field_type == 'BooleanField':
|
||||
assertFieldType('bool_field', "models.BooleanField()")
|
||||
if connection.features.can_introspect_null:
|
||||
assertFieldType('null_bool_field', "models.NullBooleanField()")
|
||||
else:
|
||||
assertFieldType('null_bool_field', "models.BooleanField()")
|
||||
else:
|
||||
assertFieldType('bool_field', "models.IntegerField()")
|
||||
field_type = connection.features.introspected_boolean_field_type
|
||||
assertFieldType('bool_field', "models.{}()".format(field_type))
|
||||
if connection.features.can_introspect_null:
|
||||
assertFieldType('null_bool_field', "models.IntegerField(blank=True, null=True)")
|
||||
assertFieldType('null_bool_field', "models.{}(blank=True, null=True)".format(field_type))
|
||||
else:
|
||||
assertFieldType('null_bool_field', "models.IntegerField()")
|
||||
assertFieldType('null_bool_field', "models.{}()".format(field_type))
|
||||
|
||||
if connection.features.can_introspect_decimal_field:
|
||||
assertFieldType('decimal_field', "models.DecimalField(max_digits=6, decimal_places=1)")
|
||||
|
|
|
@ -313,15 +313,8 @@ class SchemaTests(TransactionTestCase):
|
|||
# Ensure the field is right afterwards
|
||||
columns = self.column_classes(Author)
|
||||
# BooleanField are stored as TINYINT(1) on MySQL.
|
||||
field_type, field_info = columns['awesome']
|
||||
if connection.vendor == 'mysql':
|
||||
self.assertEqual(field_type, 'IntegerField')
|
||||
self.assertEqual(field_info.precision, 1)
|
||||
elif connection.vendor == 'oracle' and connection.version_has_default_introspection_bug:
|
||||
self.assertEqual(field_type, 'IntegerField')
|
||||
self.assertEqual(field_info.precision, 0)
|
||||
else:
|
||||
self.assertEqual(field_type, 'BooleanField')
|
||||
field_type = columns['awesome'][0]
|
||||
self.assertEqual(field_type, connection.features.introspected_boolean_field_type)
|
||||
|
||||
def test_add_field_default_transform(self):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue