Opened 6 hours ago

Closed 5 hours ago

Last modified 3 hours ago

#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 Jacob Walls, 5 hours ago

Component: Uncategorizedcontrib.postgres
Keywords: ArrayAgg added
Resolution: invalid
Status: newclosed

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.

comment:2 by Simon Charette, 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.

Last edited 4 hours ago by Simon Charette (previous) (diff)

comment:3 by Markus Amalthea Magnuson, 4 hours ago

Why is [] safe to use here (rather than list)?

comment:4 by Jacob Walls, 4 hours ago

Django never mutates the value; it just sends it to the db adapter to include in the query.

comment:5 by Simon Charette, 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, and array_agg returns null rather than an empty array when there are no input rows. The coalesce function can be used to substitute zero or an empty array for null when necessary.

Version 0, edited 3 hours ago by Simon Charette (next)
Note: See TracTickets for help on using tickets.
Back to Top