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.
This commit is contained in:
Michael Tänzer 2015-06-07 02:05:36 +02:00 committed by Tim Graham
parent b64c0d4d61
commit 3bbaf84d65
2 changed files with 23 additions and 0 deletions

View File

@ -507,6 +507,15 @@ class Func(Expression):
template = template or self.extra.get('template', self.template) template = template or self.extra.get('template', self.template)
return template % self.extra, params 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): def copy(self):
copy = super(Func, self).copy() copy = super(Func, self).copy()
copy.source_expressions = self.source_expressions[:] copy.source_expressions = self.source_expressions[:]

View File

@ -349,6 +349,20 @@ class AggregationTests(TestCase):
{'c__max': 3} {'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): def test_field_error(self):
# Bad field requests in aggregates are caught and reported # Bad field requests in aggregates are caught and reported
self.assertRaises( self.assertRaises(