Fixed #34967 -- Fixed queryset crash when grouping by constants on SQLite < 3.39.

On SQLite < 3.39, this forces a GROUP BY clause with a HAVING clause
when no grouping is specified.

Co-authored-by: Simon Charette <charette.s@gmail.com>
This commit is contained in:
David Sanders 2023-11-13 00:45:52 +11:00 committed by Mariusz Felisiak
parent 1b56b24f81
commit b863c5ffde
4 changed files with 23 additions and 0 deletions

View File

@ -231,6 +231,13 @@ class BaseDatabaseOperations:
)
return "%s"
def force_group_by(self):
"""
Return a GROUP BY clause to use with a HAVING clause when no grouping
is specified.
"""
return []
def force_no_ordering(self):
"""
Return a list used in the "ORDER BY" clause to force no ordering at

View File

@ -14,6 +14,8 @@ from django.utils import timezone
from django.utils.dateparse import parse_date, parse_datetime, parse_time
from django.utils.functional import cached_property
from .base import Database
class DatabaseOperations(BaseDatabaseOperations):
cast_char_field_without_max_length = "text"
@ -439,3 +441,6 @@ class DatabaseOperations(BaseDatabaseOperations):
update_fields,
unique_fields,
)
def force_group_by(self):
return ["GROUP BY TRUE"] if Database.sqlite_version_info < (3, 39) else []

View File

@ -877,6 +877,8 @@ class SQLCompiler:
if self._meta_ordering:
order_by = None
if having:
if not grouping:
result.extend(self.connection.ops.force_group_by())
result.append("HAVING %s" % having)
params.extend(h_params)

View File

@ -2126,6 +2126,15 @@ class AggregateTestCase(TestCase):
qs = Publisher.objects.filter(pk__in=author_qs)
self.assertCountEqual(qs, [self.p1, self.p2, self.p3, self.p4])
def test_having_with_no_group_by(self):
author_qs = (
Author.objects.values(static_value=Value("static-value"))
.annotate(sum=Sum("age"))
.filter(sum__gte=0)
.values_list("sum", flat=True)
)
self.assertEqual(list(author_qs), [337])
class AggregateAnnotationPruningTests(TestCase):
@classmethod