Opened 10 years ago
Closed 9 years ago
#23622 closed Bug (fixed)
Subquery doesn't respect order when not bound to a __pk__ field.
Reported by: | ris | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.7 |
Severity: | Normal | Keywords: | subquery order distinct |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Fix for bug #20600 doesn't seem to have covered all cases.
Using django git fa4b6482df08d308fe88044b8c8bf981c6225fb8 (stable/1.7.x), postgres backend.
Example models.py:
class ModelA ( models.Model ): pass class ModelB ( models.Model ): modela_fk = models.ForeignKey ( ModelA ) field_b0 = models.IntegerField ( null = True ) field_b1 = models.DateField ()
Enter some data:
import datetime a1 = ModelA () a1.save () a2 = ModelA () a2.save () ModelB ( modela_fk = a1 , field_b0 = 123 , field_b1 = datetime.date ( 2013 , 1 , 6 ) ).save () ModelB ( modela_fk = a1 , field_b0 = 23 , field_b1 = datetime.date ( 2011 , 6 , 6 ) ).save () ModelB ( modela_fk = a1 , field_b0 = 234 , field_b1 = datetime.date ( 2011 , 9 , 2 ) ).save () ModelB ( modela_fk = a1 , field_b0 = 12 , field_b1 = datetime.date ( 2012 , 9 , 15 ) ).save () ModelB ( modela_fk = a2 , field_b0 = 567 , field_b1 = datetime.date ( 2014 , 3 , 1 ) ).save () ModelB ( modela_fk = a2 , field_b0 = 76 , field_b1 = datetime.date ( 2011 , 3 , 3 ) ).save () ModelB ( modela_fk = a2 , field_b0 = 7 , field_b1 = datetime.date ( 2012 , 10 , 20 ) ).save () ModelB ( modela_fk = a2 , field_b0 = 56 , field_b1 = datetime.date ( 2011 , 1 , 27 ) ).save ()
Some queries:
qx = ( Q ( modelb__pk__in = ModelB.objects.order_by ( "modela_fk" , "-field_b1" ).distinct ( "modela_fk" ) ) & Q ( modelb__field_b0__gte = 50 ) ) qy = ( Q ( modelb__in = ModelB.objects.order_by ( "modela_fk" , "-field_b1" ).distinct ( "modela_fk" ) ) & Q ( modelb__field_b0__gte = 50 ) )
(only difference being modelb__pk__in
vs modelb__in
)
and...
>>> frozenset ( ModelA.objects.filter ( qx ).values_list ( "pk" , flat = True ) ) == frozenset ( ModelA.objects.filter ( qy ).values_list ( "pk" , flat = True ) ) False
We see this is because
>>> str ( ModelA.objects.filter ( qx ).query ) 'SELECT "dummy_modela"."id" FROM "dummy_modela" INNER JOIN "dummy_modelb" ON ( "dummy_modela"."id" = "dummy_modelb"."modela_fk_id" ) WHERE ("dummy_modelb"."id" IN (SELECT DISTINCT ON ("dummy_modelb"."modela_fk_id") "dummy_modelb"."id" FROM "dummy_modelb" ORDER BY "dummy_modelb"."modela_fk_id" ASC, "dummy_modelb"."field_b1" DESC) AND "dummy_modelb"."field_b0" >= 50)' >>> str ( ModelA.objects.filter ( qy ).query ) 'SELECT "dummy_modela"."id" FROM "dummy_modela" INNER JOIN "dummy_modelb" ON ( "dummy_modela"."id" = "dummy_modelb"."modela_fk_id" ) WHERE ("dummy_modelb"."id" IN (SELECT DISTINCT ON ("dummy_modelb"."modela_fk_id") "dummy_modelb"."id" FROM "dummy_modelb") AND "dummy_modelb"."field_b0" >= 50)'
qy
's SQL is missing the ORDER BY clause. This is a bit of an unexpected gotcha.
Change History (5)
comment:1 by , 10 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 10 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
Unassigning myself for now as I'm a bit busier than anticipated and am not sure I'll be able to fix it in a timely fashion.
comment:3 by , 10 years ago
I've also just realized (in #23791) that adding a .values ( "pk" )
also removes the ORDER BY
clause of the subquery
comment:5 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I've been able to reproduce this on my machine. Looks like a bug to me, and I'll take a look at the code and try to fix it.