Opened 6 years ago
Closed 6 years ago
#29530 closed Bug (fixed)
Chaining .annotate() on models generates wrong SQL aliases.
Reported by: | Volodymyr | Owned by: | Mariusz Felisiak |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 2.0 |
Severity: | Normal | Keywords: | annotate, INNER JOIN, model, |
Cc: | Mariusz Felisiak | 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
I simplified my models code as I could, keeping necessary fields.
So with these models given:
class Station(models.Model): pass class Route(models.Model): """ just ties route nodes together """ pass class RouteNode(models.Model): """ Class that handles many-to-many relationship between stations and routes. """ route = models.ForeignKey(Route, on_delete=models.CASCADE) station = models.ForeignKey(Station, on_delete=models.CASCADE) duration = models.DurationField() class Trip(models.Model): route = models.ForeignKey(Route, on_delete=models.DO_NOTHING)
I try to query them like:
Trip.objects.filter( route__routenode__station=1 ).annotate( board_station_duration=F('route__routenode__duration'), ).filter( route__routenode__station=2, ).annotate( dest_station_duration=F('route__routenode__duration'), )
The code above being run on environment with
Django 2.0, Python 3.6.2, DB engine : psycopg2
generates the following SQL, so "board_station_duration" and "dest_station_duration" referencing same field of same routenode record.
SELECT -- not-relevant to this ticket fields -- "routenode"."duration" AS "board_station_duration", "routenode"."duration" AS "dest_station_duration" FROM "trip" INNER JOIN "route" ON ("trip"."route_id" = "route"."id") INNER JOIN "routenode" ON ("route"."id" = "routenode"."route_id") INNER JOIN "routenode" T5 ON ("route"."id" = T5."route_id") WHERE ("routenode"."station_id" = 1 AND T5."station_id" = 2);
And the same python code being run on env
Django 1.10, Python 2.7.14, DB engine : psycopg2
generates the following SQL (as expected), so "board_station_duration" and "dest_station_duration" referencing fields of different routenode record.
SELECT -- not-relevant to this ticket fields -- "routenode"."duration" AS "board_station_duration", T5."duration" AS "dest_station_duration" FROM "trip" INNER JOIN "route" ON ("trip"."route_id" = "route"."id") INNER JOIN "routenode" ON ("route"."id" = "routenode"."route_id") INNER JOIN "routenode" T5 ON ("route"."id" = T5."route_id") WHERE ("routenode"."station_id" = 1 AND T5."station_id" = 2);
Attachments (1)
Change History (11)
comment:1 by , 6 years ago
Cc: | added |
---|
by , 6 years ago
Attachment: | 29530.diff added |
---|
comment:2 by , 6 years ago
Triage Stage: | Unreviewed → Accepted |
---|
I reproduced this issue and prepared regression test in our test suite. I will bisect it to check if that should be marked as a release blocker.
comment:5 by , 6 years ago
Thanks. It passes on Django 1.10 but only on Python 2.7, it fails on Python 3.6 🤯
Replying to Volodymyr:
Django 1.10, Python 2.7.14, DB engine : psycopg2
comment:6 by , 6 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:7 by , 6 years ago
Bisected to the 8d66bffbae8e5a230da51c7638d24fdbd327a96b on Python 2.7
commit 8d66bffbae8e5a230da51c7638d24fdbd327a96b Author: Bo Marchman <bo.marchman@gmail.com> Date: Thu Mar 2 09:36:25 2017 -0500 [1.11.x] Fixed #26522 -- Fixed a nondeterministic AssertionError in QuerySet combining. Thanks Andrew Brown for the test case. Backport of 9bbb6e2d2536c4ac20dc13a94c1f80494e51f8d9 from master
It is related with changing self.alias_map
to OrderedDict()
. That's why it doesn't work on Python 3.6.
comment:9 by , 6 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Regression test.