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.

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top