#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 , 5 hours ago
Component: | Uncategorized → contrib.postgres |
---|---|
Keywords: | ArrayAgg added |
Resolution: | → invalid |
Status: | new → closed |
comment:2 by , 4 hours 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 , 4 hours ago
Django never mutates the value; it just sends it to the db adapter to include in the query.
comment:5 by , 3 hours 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,sum
of no rows returns null, not zero as one might expect, andarray_agg
returns null rather than an empty array when there are no input rows. Thecoalesce
function can be used to substitute zero or an empty array for null when necessary.
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
default
at the time.)You can use
default=Value([])
if you prefer. See https://docs.djangoproject.com/en/5.2/releases/4.0/#id2.