#32786 closed Cleanup/optimization (fixed)
Make the subquery ordering clearing optimization more selectively
Reported by: | Hannes Ljungberg | Owned by: | Hannes Ljungberg |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | 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
This will allow to add support for Array subqueries on PostgreSQL. It appears like we would only have to adapt In.process_rhs
to do the clearing when the rhs
value is an instance of Query
and fullfils the requirements of clearing the ordering. As Simon commented in #32776 about this we would also want to keep clearing ordering for Exists
and and Queryset.exists()
and since these both end up running Query.exists()
which runs clear_ordering
we should be fine.
I looked around historically and found out that there've been an attempt at this before but it ended up being reverted due to some failures on Oracle. We'll need address these failures if they are still relevant.
Change History (15)
comment:1 by , 3 years ago
comment:2 by , 3 years ago
Cc: | added; removed |
---|
I looked around historically and found out that there've been an attempt at this before but it ended up being reverted due to some failures on Oracle. We'll need address these failures if they are still relevant.
Ah right I remember that, I'm curious to see what exactly it was breaking on Oracle again.
comment:3 by , 3 years ago
Has patch: | set |
---|---|
Patch needs improvement: | set |
Triage Stage: | Unreviewed → Accepted |
comment:4 by , 3 years ago
Needs tests: | set |
---|
comment:5 by , 3 years ago
Needs tests: | unset |
---|---|
Patch needs improvement: | unset |
comment:6 by , 3 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:9 by , 3 years ago
Do I may bring up this issue again? I've stumbled upon a similar issue as reported in #32658 or #32786. Both were closed as invalid. However, this change added a test case to Django's main branch (which will be 4.0 if I'm not wrong) that tests a scenario that’s pretty similar to the code in the application I’m migrating from 2.2 LTS to 3.2 LTS. The test case looks totally legit to me and not like an abuse of the ORM:
def test_ordering_isnt_cleared_for_array_subquery(self): inner_qs = AggregateTestModel.objects.order_by('-integer_field') qs = AggregateTestModel.objects.annotate( integers=Func( Subquery(inner_qs.values('integer_field')), function='ARRAY', output_field=ArrayField(base_field=IntegerField()), ), ) self.assertSequenceEqual( qs.first().integers, inner_qs.values_list('integer_field', flat=True), )
When adding this test case to the Django 2.2 code base, the test passes. When adding it to 3.2 it fails due to the removal of ordering. Of course in main it passes too. So to me this looks like a regression in 3.2.
I did a quick test and cherry-picked both changes form this ticket in my local 3.2 branch without much issues. Six tests in postgres_tests were failing because of different warnings, but the same six tests fail on a clean 3.2 branch on my machine too.
Wouldn’t it be an option to backport these changes to 3.2 to have a consistent behavior in 2.2, 3.2 and the upcoming 4.x release?
comment:10 by , 3 years ago
So to me this looks like a regression in 3.2.
This behavior was changed in Django 3.0 so per our backporting policy this means it doesn't qualify for a backport to 3.2.x, even if we consider it a regression.
See supported versions policy for more details.
comment:11 by , 3 years ago
A workaround until 4.0 is available is to add a high limit to the query, like qs[:99999]
. This will prevent the ordering from being cleared.
comment:12 by , 3 years ago
Ok, thanks for clarification, Mariusz! So we'll go with this high limit workaround for a few years since we settle on LTS versions before we get the old behavior back ;)
follow-up: 15 comment:14 by , 16 months ago
can this change be added to the changelog? specifically this code from django 3.2.x no longer succeeds:
without a deprecation period or a changelog entry I'm not certain what this _should_ be changed to. the commit message also doesn't help me much either
comment:15 by , 16 months ago
Replying to anthony sottile:
can this change be added to the changelog? specifically this code from django 3.2.x no longer succeeds:
without a deprecation period or a changelog entry I'm not certain what this _should_ be changed to. the commit message also doesn't help me much either
I guess is too late for the deprecation path, as per the workaround for 3.2, I believe that's described in comment 11 in this ticket: ticket:32786#comment:11
Messed up the CC:ing, sorry if anyone not related to this ticket got an email!