Opened 7 years ago
Closed 7 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 , 7 years ago
| Cc: | added |
|---|
by , 7 years ago
| Attachment: | 29530.diff added |
|---|
comment:2 by , 7 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 , 7 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 , 7 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:7 by , 7 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 , 7 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Regression test.