Opened 13 years ago
Closed 13 years ago
#18583 closed Bug (fixed)
exclude generates wrong SQL query
| Reported by: | Rebecca Breu | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.4 |
| Severity: | Normal | Keywords: | query exclude sql sprints-django-ar |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
exclude generates a wrong SQL query in a certain setup. Given the following models:
class A(models.Model): pass class AGroups(models.Model): a = models.ForeignKey(A, related_name='groups') group = models.ForeignKey(Group) class B(models.Model): a = models.ForeignKey(A) class C(models.Model): b = models.ForeignKey(B)
Then the following:
g = Group.objects.create(name='foo') C.objects.exclude(b__a__groups__group__in=[g])
generates the following query:
SELECT "books_c"."id", "books_c"."name", "books_c"."b_id" FROM "books_c"
INNER JOIN "books_b" ON ("books_c"."b_id" = "books_b"."id")
INNER JOIN "books_a" ON ("books_b"."a_id" = "books_a"."id")
WHERE NOT (("books_b"."a_id" IN (
SELECT U1."id" FROM "books_b" U1
INNER JOIN "books_a" U2 ON (U1."a_id" = U2."id")
INNER JOIN "books_agroups" U3 ON (U2."id" = U3."a_id")
WHERE (U3."group_id" IN (3) AND U1."id" IS NOT NULL)
)
AND "books_a"."id" IS NOT NULL)) LIMIT 21
Line 4 should be
WHERE NOT (("books_b"."id" IN (
instead.
The same issue happens with
agroups = AGroups.objects.filter(group__in=[g]) C.objects.exclude(b__a__groups__in=agroups)
This one works:
b_excludes = B.objects.filter(a__groups__group__in=[g]) C.objects.exclude(b__in=b_excludes)
(Using Django 1.4, Python 2.7.3rc2, sqlite)
See attachment for more testing code.
Attachments (2)
Change History (5)
by , 13 years ago
comment:1 by , 13 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|---|
| Type: | Uncategorized → Bug |
by , 13 years ago
| Attachment: | 18583.diff added |
|---|
comment:2 by , 13 years ago
This bug is invalid, as the generated SQL is correct.
Given this full example:
#models
from django.utils.encoding import python_2_unicode_compatible
from django.contrib.auth.models import Group
# Models for #19659
@python_2_unicode_compatible
class A(models.Model):
pass
def __str__(self):
return str(self.pk)
@python_2_unicode_compatible
class B(models.Model):
a = models.ForeignKey(A)
def __str__(self):
return str(self.pk)
@python_2_unicode_compatible
class C(models.Model):
b = models.ForeignKey(B)
def __str__(self):
return str(self.pk)
@python_2_unicode_compatible
class D(models.Model):
a = models.ForeignKey(A)
group = models.ForeignKey(Group)
def __str__(self):
return str(self.pk)
The following query:
C.objects.exclude(b__a__d__group__in=[foo]).order_by('pk')
Results in:
SELECT "queries_c"."id", "queries_c"."b_id" FROM "queries_c"
INNER JOIN "queries_b" ON ("queries_c"."b_id" = "queries_b"."id")
WHERE NOT (("queries_b"."a_id" IN
(SELECT U3."a_id" FROM "queries_d" U3 WHERE U3."group_id" IN (1))
AND "queries_b"."a_id" IS NOT NULL))
Which is correct, as the filtering is taken to the a.id field (see the inner SELECT).
Attached is a diff which adds tests showing the query is returning expected results.
comment:3 by , 13 years ago
| Keywords: | sprints-django-ar added |
|---|---|
| Resolution: | → fixed |
| Status: | new → closed |
this shows as working in current HEAD.
I've managed to reproduce this in the HEAD