From 3bbaf84d6533fb61ac0038f2bbe52ee0d7b4fd10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Sun, 7 Jun 2015 02:05:36 +0200 Subject: [PATCH] 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. --- django/db/models/expressions.py | 9 +++++++++ tests/aggregation_regress/tests.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 43061933e6c..3ace2857044 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -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[:] diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py index cb469363a01..1e680dbdd9c 100644 --- a/tests/aggregation_regress/tests.py +++ b/tests/aggregation_regress/tests.py @@ -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(