#36638 closed Uncategorized (invalid)
The default for ArrayAgg should be an empty list rather than None
| Reported by: | Markus Amalthea Magnuson | Owned by: | |
|---|---|---|---|
| Component: | contrib.postgres | Version: | 5.2 |
| Severity: | Normal | Keywords: | ArrayAgg |
| Cc: | Markus Amalthea Magnuson | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I would expect (in Python, broadly) a function that returns a list of values to always return a list. What is the reasoning behind this not being the case for ArrayAgg? Instead, the default value is None when there are no values, and I'm sure there is a good reason for this.
Change History (5)
comment:1 by , 3 weeks ago
| Component: | Uncategorized → contrib.postgres |
|---|---|
| Keywords: | ArrayAgg added |
| Resolution: | → invalid |
| Status: | new → closed |
comment:2 by , 3 weeks ago
You can use
default=Value([])if you prefer.
Small FYI that you don't have to do the Value wrapping for ArrayField expressions, passing default=[] works just fine.
Value wrapping is only necessary when passing a str literal as they default to field references ('field' is equivalent to F('field')) instead of value literals like any other Python literal does. That's the reason why Value wrapping is necessary for JSONBAgg and StringAgg though.
comment:4 by , 3 weeks ago
Django never mutates the value; it just sends it to the db adapter to include in the query.
comment:5 by , 3 weeks ago
In other words, the ARRAY_AGG Postgres function returns NULL on an empty set.
Passing default=[] wraps the ARRAY_AGG in COALESCE to default to the provided value
SELECT COALESCE(ARRAY_AGG(field), '{}'::text[])
Per Postgres documentation linked above
It should be noted that except for
count, these functions return a null value when no rows are selected. In particular,sumof no rows returns null, not zero as one might expect, andarray_aggreturns null rather than an empty array when there are no input rows. Thecoalescefunction can be used to substitute zero or an empty array for null when necessary.
Concretely this means that Aggregate(default) is a nicer way to express Coalesce(Aggregate(...), default).
See #10929 and fee87345967b3d917b618533585076cbfa43451b: Django used to do that, but deprecated it and removed it in 5.0, due to it being inconsistent with other aggregates. (The inconsistency was a compromise given the lack of
defaultat the time.)You can use
default=Value([])if you prefer. See https://docs.djangoproject.com/en/5.2/releases/4.0/#id2.