Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#34267 closed Bug (fixed)

QuerySet.union() crashes with IndexError when getting cached results.

Reported by: Raphaël Stefanini Owned by: Francesco Panico
Component: Database layer (models, ORM) Version: 4.2
Severity: Release blocker Keywords:
Cc: Simon Charette Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Raphaël Stefanini)

I tried 4.2a1 today on my project and I noticed pagination was broken on one view.

After little investigation I manage to reproduce an error:

Event is a model with set a Foreignkey

>> events = Event.objects.all()
>> events_without_set = events.filter(set__isnull=True)
>> one_event_of_each_set = (
        events.filter(set__isnull=False)
               .order_by("set_id")
               .distinct("set_id")
)
>> my_list = events_without_set.union(one_event_of_each_set)
>> my_list.count()
212
>> my_list[2]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/venv/lib/python3.11/site-packages/django/db/models/query.py", line 450, in __getitem__
    return qs._result_cache[0]
           ~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range

With django 4.1.5 my_list[2] returns an event.

Change History (11)

comment:1 by Raphaël Stefanini, 2 years ago

Description: modified (diff)

comment:2 by Raphaël Stefanini, 2 years ago

Component: UncategorizedDatabase layer (models, ORM)

comment:3 by Mariusz Felisiak, 2 years ago

Cc: Simon Charette added
Severity: NormalRelease blocker
Summary: Error with Union queryset not being paginableQuerySet.union() crashes with IndexError when getting cached results.
Triage Stage: UnreviewedAccepted

Thanks for testing the alpha release!

Regression in 3d734c09ff0138441dfe0a59010435871d17950f.

comment:4 by Francesco Panico, 2 years ago

Owner: changed from nobody to Francesco Panico
Status: newassigned

comment:5 by Simon Charette, 2 years ago

It seems that the issue is likely due the if sliced branch which was hoping to port the optimization that made union().exists() have all the involved subqueries augmented with LIMIT 1 if supported by the backend.

I believe that this optimization can likely be removed since backends are likely smart enough to perform this optimization themselves when EXISTS is used.

comment:6 by Francesco Panico, 2 years ago

Has patch: set

comment:7 by Mariusz Felisiak, 2 years ago

Patch needs improvement: set

comment:8 by Francesco Panico, 2 years ago

Patch needs improvement: unset

comment:9 by Mariusz Felisiak, 2 years ago

Triage Stage: AcceptedReady for checkin

comment:10 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

Resolution: fixed
Status: assignedclosed

In cc8aa6bf:

Fixed #34267 -- Fixed sliced QuerySet.union() crash.

Regression in 3d734c09ff0138441dfe0a59010435871d17950f.

Thanks Raphaël Stefanini for the report.

comment:11 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

In 84927e1:

[4.2.x] Fixed #34267 -- Fixed sliced QuerySet.union() crash.

Regression in 3d734c09ff0138441dfe0a59010435871d17950f.

Thanks Raphaël Stefanini for the report.

Backport of cc8aa6bf9c127a493e6dd005012b9e6397b3f319 from main

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