Opened 39 hours ago
#35833 new Bug
Annotation yielding an empty set causes entire QuerySet to become empty
Reported by: | Jacob Walls | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 5.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
With a nullable JSONField in my model:
class TileModel(models.Model): provisionaledits = JSONField(null=True)
If I then annotate with a set-returning function (e.g. JSONB_ARRAY_ELEMENTS on postgres) that happens to return an empty set, the entire QuerySet is zeroed out.
In [1]: from django.db.models import Func, F In [2]: from arches.app.models.models import TileModel In [3]: class JsonbArrayElements(Func): ...: arity = 1 ...: contains_subquery = True # Django 5.2: set_returning = True ...: function = "JSONB_ARRAY_ELEMENTS" ...: In [4]: TileModel.objects.count() Out[4]: 9 In [5]: TileModel.objects.annotate(empty_set=JsonbArrayElements(F("provisionaledits"))) Out[5]: <QuerySet []>
I distilled this from a more complicated failure. If it helps, here is a query that fails more helpfully when you actually have JSON in the queried field but still can't extract array elements because it's not an array:
In [14]: TileModel.objects.create(provisionaledits={}) Out[14]: <TileModel: TileModel object (6ee450f7-b516-4c61-b6e7-52e876b878fe)> In [15]: TileModel.objects.annotate(no_longer_empty=JsonbArrayElements(F("provisionaledits"))) Out[15]: DataError: cannot extract elements from an object
I guess I would expect an error in both cases instead of an empty queryset in the former. At the very least, I would only expect the annotation to yield some sort of empty value, not for the whole queryset to silently become empty.