Opened 14 years ago
Closed 9 years ago
#15020 closed Bug (fixed)
Redundant joins generated when using reverse foreign key
Reported by: | Andy Durdin | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | me@… | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
A query using a reverse foreign key generates a left outer join to a related table and a second, redundant left outer join to the original table.
Tested in Django 1.1 and trunk r15147, and found to be an issue in both.
Using these models:
from django.db import models class Original(models.Model): pass # Don't need anything more for this test class Reference(models.Model): original = models.ForeignKey(Original, primary_key=True)
Background: the Reference
model is used for storing and testing set membership; an Original
instance is a member of the set iff its PK is in the Reference
table.
Incorrect query was generated for this queryset:
Original.objects.filter(reference__pk__isnull=True)
Generated SQL:
SELECT `fkpk_original`.`id` FROM `fkpk_original` LEFT OUTER JOIN `fkpk_reference` ON (`fkpk_original`.`id` = `fkpk_reference`.`original_id`) LEFT OUTER JOIN `fkpk_original` T3 ON (`fkpk_reference`.`original_id` = T3.`id`) WHERE T3.`id` IS NULL
Expected SQL:
SELECT `fkpk_original`.`id` FROM `fkpk_original` LEFT OUTER JOIN `fkpk_reference` ON (`fkpk_original`.`id` = `fkpk_reference`.`original_id`) WHERE `fkpk_reference`.`original_id` IS NULL
Notes
An incorrect query is also generated for the following queryset; however this seems to be covered by #14056:
Original.objects.filter(reference__pk__isnull=False)
Change History (7)
comment:1 by , 14 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 14 years ago
To clarify: I found incorrect queries when I was using the two variations on this queryset, ...isnull=True
, and ...isnull=False
. I presumed that they were related, since it was only a parameter to the queryset that I was changing. I found #14056 when searching to see if this was a reported issue, and found that its description and patch matched and fixed only the second of the two incorrect queries. That could be coincidental; I wasn't able to follow the query generation well enough to know.
comment:3 by , 14 years ago
Owner: | changed from | to
---|---|
Status: | assigned → new |
Not sure how this got assigned to me
comment:4 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:7 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Seems to be fixed in Django 1.6.
I'm not sure I see the connection with #14056, but this certainly appears to be a problem. I'm going to guess that it's the primary_key=True on a ForeignKey that is causing the confusion.