0
0
mirror of https://github.com/django/django.git synced 2024-11-21 19:09:18 +01:00

Grouped JSONArrayAgg tests into one standalone, modified docs to include versionadded, added comment to clarify default behaviour of JSONArrayAgg when dealing with empty sets on sqlite.

This commit is contained in:
lufafajoshua 2024-10-31 09:23:24 +03:00
parent 3597d503cf
commit 1f0221bbf5
3 changed files with 89 additions and 81 deletions

View File

@ -223,9 +223,9 @@ class JSONArrayAgg(Aggregate):
arity = 1
def as_sql(self, compiler, connection, **extra_context):
if not connection.features.supports_aggregate_filter_clause:
if self.filter and not connection.features.supports_aggregate_filter_clause:
raise NotSupportedError(
"JSONArrayAgg is not supported on this database backend."
"JSONArrayAgg(filter) is not supported on this database backend."
)
return super().as_sql(compiler, connection, **extra_context)
@ -233,8 +233,10 @@ class JSONArrayAgg(Aggregate):
sql, params = self.as_sql(
compiler, connection, function="JSON_GROUP_ARRAY", **extra_context
)
# JSON_GROUP_ARRAY defaults to returning an empty array on an empty set.
if (default := self.default) == []:
return sql, params
# Ensure Count() is against the exact same parameters (filter, distinct)
count = self.copy()
count.__class__ = Count
count_sql, count_params = compiler.compile(count)

View File

@ -4050,6 +4050,8 @@ by the aggregate.
``JSONArrayAgg``
~~~~~~~~~~~~~~~~
.. versionadded:: 5.1
.. class:: JSONArrayAgg(expression, output_field=None, sample=False, filter=None, default=None, **extra)
Converts each expression to a JSON value and returns a single JSON array

View File

@ -2159,85 +2159,6 @@ class AggregateTestCase(TestCase):
)
self.assertEqual(list(author_qs), [337])
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg(self):
vals = Store.objects.aggregate(jsonarrayagg=JSONArrayAgg("name"))
self.assertEqual(
vals,
{"jsonarrayagg": ["Amazon.com", "Books.com", "Mamma and Pappa's Books"]},
)
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_datefield(self):
vals = Book.objects.aggregate(jsonarrayagg=JSONArrayAgg("pubdate"))
self.assertEqual(
vals,
{
"jsonarrayagg": [
"2007-12-06",
"2008-03-03",
"2008-06-23",
"2008-11-03",
"1995-01-15",
"1991-10-15",
]
},
)
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_decimalfield(self):
vals = Book.objects.aggregate(jsonarrayagg=JSONArrayAgg("price"))
self.assertEqual(
vals, {"jsonarrayagg": [30.0, 23.09, 29.69, 29.69, 82.8, 75.0]}
)
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_integerfield(self):
vals = Book.objects.aggregate(jsonarrayagg=JSONArrayAgg("pages"))
self.assertEqual(vals, {"jsonarrayagg": [447, 528, 300, 350, 1132, 946]})
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_filter(self):
vals = Author.objects.aggregate(
jsonarrayagg=JSONArrayAgg("age", filter=Q(age__gt=29))
)
self.assertEqual(vals, {"jsonarrayagg": [34, 35, 45, 37, 57, 46]})
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_empty_result_set(self):
Author.objects.all().delete()
val = Author.objects.aggregate(jsonarrayagg=JSONArrayAgg("age"))
self.assertEqual(val, {"jsonarrayagg": None})
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_default_set(self):
Author.objects.all().delete()
val = Author.objects.aggregate(
jsonarrayagg=JSONArrayAgg("name", default=["<empty>"])
)
self.assertEqual(val, {"jsonarrayagg": ["<empty>"]})
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_distinct_false(self):
val = Author.objects.aggregate(jsonarrayagg=JSONArrayAgg("age", distinct=False))
self.assertEqual(val, {"jsonarrayagg": [34, 35, 45, 29, 37, 29, 25, 57, 46]})
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_distinct_true(self):
msg = "JSONArrayAgg does not allow distinct."
with self.assertRaisesMessage(TypeError, msg):
JSONArrayAgg("age", distinct=True)
@skipIfDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_not_supported(self):
msg = "JSONArrayAgg is not supported on this database backend."
with self.assertRaisesMessage(NotSupportedError, msg):
Author.objects.aggregate(arrayagg=JSONArrayAgg("age"))
class AggregateAnnotationPruningTests(TestCase):
@classmethod
@ -2439,3 +2360,86 @@ class AggregateAnnotationPruningTests(TestCase):
)
)
self.assertEqual(qs.count(), 3)
class JSONArrayAggTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.a1 = Author.objects.create(name="Adrian Holovaty", age=34)
cls.a2 = Author.objects.create(name="Jacob Kaplan-Moss", age=35)
cls.a3 = Author.objects.create(name="Brad Dayley", age=45)
cls.p1 = Publisher.objects.create(
name="Apress", num_awards=3, duration=datetime.timedelta(days=1)
)
cls.b1 = Book.objects.create(
isbn="159059725",
name="The Definitive Guide to Django: Web Development Done Right",
pages=447,
rating=4.5,
price=Decimal("30.00"),
contact=cls.a1,
publisher=cls.p1,
pubdate=datetime.date(2007, 12, 6),
)
def test_JSONArrayAgg(self):
vals = Author.objects.aggregate(jsonarrayagg=JSONArrayAgg("name"))
self.assertEqual(
vals,
{"jsonarrayagg": ["Adrian Holovaty", "Jacob Kaplan-Moss", "Brad Dayley"]},
)
def test_JSONArrayAgg_datefield(self):
vals = Book.objects.aggregate(jsonarrayagg=JSONArrayAgg("pubdate"))
self.assertEqual(
vals,
{
"jsonarrayagg": [
"2007-12-06",
]
},
)
def test_JSONArrayAgg_decimalfield(self):
vals = Book.objects.aggregate(jsonarrayagg=JSONArrayAgg("price"))
self.assertEqual(vals, {"jsonarrayagg": [30.0]})
def test_JSONArrayAgg_integerfield(self):
vals = Book.objects.aggregate(jsonarrayagg=JSONArrayAgg("pages"))
self.assertEqual(vals, {"jsonarrayagg": [447]})
@skipUnlessDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_filter(self):
vals = Author.objects.aggregate(
jsonarrayagg=JSONArrayAgg("age", filter=Q(age__gt=35))
)
self.assertEqual(vals, {"jsonarrayagg": [45]})
def test_JSONArrayAgg_empty_result_set(self):
Author.objects.all().delete()
val = Author.objects.aggregate(jsonarrayagg=JSONArrayAgg("age"))
self.assertEqual(val, {"jsonarrayagg": None})
def test_JSONArrayAgg_default_set(self):
Author.objects.all().delete()
val = Author.objects.aggregate(
jsonarrayagg=JSONArrayAgg("name", default=["<empty>"])
)
self.assertEqual(val, {"jsonarrayagg": ["<empty>"]})
def test_JSONArrayAgg_distinct_true(self):
msg = "JSONArrayAgg does not allow distinct."
with self.assertRaisesMessage(TypeError, msg):
JSONArrayAgg("age", distinct=True)
@skipIfDBFeature("supports_aggregate_filter_clause")
def test_JSONArrayAgg_not_supported(self):
msg = "JSONArrayAgg(filter) is not supported on this database backend."
with self.assertRaisesMessage(NotSupportedError, msg):
Author.objects.aggregate(arrayagg=JSONArrayAgg("age", filter=Q(age__gt=35)))