summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tänzer <neo@nhng.de>2015-06-07 02:05:36 +0200
committerTim Graham <timograham@gmail.com>2015-06-30 18:27:42 -0400
commit3bbaf84d6533fb61ac0038f2bbe52ee0d7b4fd10 (patch)
tree215672c8af92ac82e9995e2cb1cb10f291745f79
parentb64c0d4d613b5cabedbc9b847682fe14877537de (diff)
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.
-rw-r--r--django/db/models/expressions.py9
-rw-r--r--tests/aggregation_regress/tests.py14
2 files changed, 23 insertions, 0 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 43061933e6..3ace285704 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 cb469363a0..1e680dbdd9 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(