Commit 3bbaf84d authored by Michael Tänzer's avatar Michael Tänzer Committed by Tim Graham
Browse files

Fixed #18247 -- Added cast to NUMERIC for Decimals on sqlite

On sqlite the SUM() of a decimal column doesn't have a NUMERIC type so
when comparing it to a string literal (which a Decimal gets converted to
in Django) it is not compared as expected.
parent b64c0d4d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -507,6 +507,15 @@ class Func(Expression):
        template = template or self.extra.get('template', self.template)
        return template % self.extra, params

    def as_sqlite(self, *args, **kwargs):
        sql, params = self.as_sql(*args, **kwargs)
        try:
            if self.output_field.get_internal_type() == 'DecimalField':
                sql = 'CAST(%s AS NUMERIC)' % sql
        except FieldError:
            pass
        return sql, params

    def copy(self):
        copy = super(Func, self).copy()
        copy.source_expressions = self.source_expressions[:]
+14 −0
Original line number Diff line number Diff line
@@ -349,6 +349,20 @@ class AggregationTests(TestCase):
            {'c__max': 3}
        )

    def test_decimal_aggregate_annotation_filter(self):
        """
        Filtering on an aggregate annotation with Decimal values should work.
        Requires special handling on SQLite (#18247).
        """
        self.assertEqual(
            len(Author.objects.annotate(sum=Sum('book_contact_set__price')).filter(sum__gt=Decimal(40))),
            1
        )
        self.assertEqual(
            len(Author.objects.annotate(sum=Sum('book_contact_set__price')).filter(sum__lte=Decimal(40))),
            4
        )

    def test_field_error(self):
        # Bad field requests in aggregates are caught and reported
        self.assertRaises(