Commit 59a65598 authored by Anssi Kääriäinen's avatar Anssi Kääriäinen
Browse files

Fixed #13844 -- Avoid converting unknown db values to float

This patch removes an unconditional float(value) conversion from db
backend default convert_values() method. This can cause problems when
aggregating over character fields for example. In addition, Oracle
and SQLite already return the bare value from their convert_values().

In the long term the converting should be done by fields, and the
fields should then call database backend specific converters when
needed. The current setup is inflexible for 3rd party fields.

Thanks to Merlijn van Deen for the original patch.
parent 5513480f
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -878,19 +878,19 @@ class BaseDatabaseOperations(object):
        return self.year_lookup_bounds(value)

    def convert_values(self, value, field):
        """Coerce the value returned by the database backend into a consistent type that
        is compatible with the field type.
        """
        Coerce the value returned by the database backend into a consistent type
        that is compatible with the field type.
        """
        internal_type = field.get_internal_type()
        if internal_type == 'DecimalField':
            return value
        elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
        elif (internal_type and (internal_type.endswith('IntegerField')
                                 or internal_type == 'AutoField')):
            return int(value)
        elif internal_type in ('DateField', 'DateTimeField', 'TimeField'):
            return value
        # No field, or the field isn't known to be a decimal or integer
        # Default to a float
        return float(value)
        return value

    def check_aggregate_support(self, aggregate_func):
        """Check that the backend supports the provided aggregate
+12 −0
Original line number Diff line number Diff line
@@ -866,3 +866,15 @@ class AggregationTests(TestCase):
            ['Peter Norvig'],
            lambda b: b.name
        )

    def test_type_conversion(self):
        # The database backend convert_values function should not try to covert
        # CharFields to float. Refs #13844.
        from django.db.models import CharField
        from django.db import connection
        testData = 'not_a_float_value'
        testField = CharField()
        self.assertEqual(
            connection.ops.convert_values(testData, testField),
            testData
        )