Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #19360 -- Raised an explicit exception for aggregates on date/t…

…ime fields in sqlite3

Thanks lsaffre for the report and Chris Medrela for the initial
patch.
  • Loading branch information...
commit eb6c107624930c97390185fdbf7f887c50665808 1 parent 2e55cf5
@slurms slurms authored claudep committed
View
13 django/db/backends/sqlite3/base.py
@@ -18,6 +18,8 @@
from django.db.backends.sqlite3.client import DatabaseClient
from django.db.backends.sqlite3.creation import DatabaseCreation
from django.db.backends.sqlite3.introspection import DatabaseIntrospection
+from django.db.models import fields
+from django.db.models.sql import aggregates
from django.utils.dateparse import parse_date, parse_datetime, parse_time
from django.utils.functional import cached_property
from django.utils.safestring import SafeBytes
@@ -127,6 +129,17 @@ def bulk_batch_size(self, fields, objs):
limit = 999 if len(fields) > 1 else 500
return (limit // len(fields)) if len(fields) > 0 else len(objs)
+ def check_aggregate_support(self, aggregate):
+ bad_fields = (fields.DateField, fields.DateTimeField, fields.TimeField)
+ bad_aggregates = (aggregates.Sum, aggregates.Avg,
+ aggregates.Variance, aggregates.StdDev)
+ if (isinstance(aggregate.source, bad_fields) and
+ isinstance(aggregate, bad_aggregates)):
+ raise NotImplementedError(
+ 'You cannot use Sum, Avg, StdDev and Variance aggregations '
+ 'on date/time fields in sqlite3 '
+ 'since date/time is saved as text.')
+
def date_extract_sql(self, lookup_type, field_name):
# sqlite doesn't support extract, so we fake it with the user-defined
# function django_extract that's registered in connect(). Note that
View
8 docs/ref/models/querysets.txt
@@ -2188,6 +2188,14 @@ Django provides the following aggregation functions in the
aggregate functions, see
:doc:`the topic guide on aggregation </topics/db/aggregation>`.
+.. warning::
+
+ SQLite can't handle aggregation on date/time fields out of the box.
+ This is because there are no native date/time fields in SQLite and Django
+ currently emulates these features using a text field. Attempts to use
+ aggregation on date/time fields in SQLite will raise
+ ``NotImplementedError``.
+
Avg
~~~
View
11 tests/regressiontests/backends/models.py
@@ -75,3 +75,14 @@ class Article(models.Model):
def __str__(self):
return self.headline
+
+
+@python_2_unicode_compatible
+class Item(models.Model):
+ name = models.CharField(max_length=30)
+ date = models.DateField()
+ time = models.TimeField()
+ last_modified = models.DateTimeField()
+
+ def __str__(self):
+ return self.name
View
18 tests/regressiontests/backends/tests.py
@@ -12,6 +12,7 @@
IntegrityError, transaction)
from django.db.backends.signals import connection_created
from django.db.backends.postgresql_psycopg2 import version as pg_version
+from django.db.models import fields, Sum, Avg, Variance, StdDev
from django.db.utils import ConnectionHandler, DatabaseError, load_backend
from django.test import (TestCase, skipUnlessDBFeature, skipIfDBFeature,
TransactionTestCase)
@@ -362,6 +363,22 @@ def test_parameter_escaping(self):
self.assertTrue(int(response))
+class SqlliteAggregationTests(TestCase):
+ """
+ #19360: Raise NotImplementedError when aggregating on date/time fields.
+ """
+ @unittest.skipUnless(connection.vendor == 'sqlite',
+ "No need to check SQLite aggregation semantics")
+ def test_aggregation(self):
+ for aggregate in (Sum, Avg, Variance, StdDev):
+ self.assertRaises(NotImplementedError,
+ models.Item.objects.all().aggregate, aggregate('time'))
+ self.assertRaises(NotImplementedError,
+ models.Item.objects.all().aggregate, aggregate('date'))
+ self.assertRaises(NotImplementedError,
+ models.Item.objects.all().aggregate, aggregate('last_modified'))
+
+
class BackendTestCase(TestCase):
def create_squares_with_executemany(self, args):
@@ -400,7 +417,6 @@ def test_cursor_executemany_with_iterator(self):
self.create_squares_with_executemany(args)
self.assertEqual(models.Square.objects.count(), 9)
-
def test_unicode_fetches(self):
#6254: fetchone, fetchmany, fetchall return strings as unicode objects
qn = connection.ops.quote_name
Please sign in to comment.
Something went wrong with that request. Please try again.