Opened 11 years ago
Closed 11 years ago
#20966 closed Bug (duplicate)
Wrong table referenced in query with multiple joins
Reported by: | stn | Owned by: | nobody |
---|---|---|---|
Component: | Uncategorized | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
With following example (using prehistoric Django v.1.4):
from django.db import models class AQuerySet(models.query.QuerySet): def filter_(self): return self.exclude(b__c__c2__x=1) def exclude_(self): return self.exclude(b__c__c2__x=1) class AManager(models.Manager): def get_query_set(self): return AQuerySet(self.model) def filter_(self): return self.get_query_set().filter_() def exclude_(self): return self.get_query_set().exclude_() # Create your models here. class A(models.Model): b = models.ForeignKey('example.B', null=True, blank=True, default=None) objects = AManager() @classmethod def setup_test(cls): A.teardown() c2 = C2.objects.create() b = B.objects.create(c=c2) b = B.objects.create(c=c2) B.objects.get(pk=1).delete() a = A.objects.create(b=b) @classmethod def teardown(cls): C2.objects.all().delete() C1.objects.all().delete() B.objects.all().delete() A.objects.all().delete() class B(models.Model): c = models.ForeignKey('example.C1', null=True, blank=True, default=None) class C1(models.Model): pass class C2(C1): x = models.IntegerField(default=1)
Code below returns same results for filter_, as well as exclude_ call. It seems that this part of SQL query:
WHERE NOT (("example_b"."c_id" IN (SELECT U1."id" FROM "example_b" U1))
selects c_id column from example_b table and compares it with id of B object. It has happened to me when using PostgreSQL, but this example was reproduced using SQLite3.
>>> A.setup_test() >>> [a.pk for a in A.objects.all()] [1] >>> [b.pk for b in B.objects.all()] [2] >>> [c.pk for c in C1.objects.all()] [1] >>> [c.pk for c in C2.objects.all()] [1] >>> A.objects.filter_() [<A: A object>] >>> A.objects.filter_().query <django.db.models.sql.query.Query object at 0x3b50250> >>> print A.objects.filter_().query SELECT "example_a"."id", "example_a"."b_id" FROM "example_a" INNER JOIN "example_b" ON ("example_a"."b_id" = "example_b"."id") INNER JOIN "example_c1" ON ("example_b"."c_id" = "example_c1"."id") INNER JOIN "example_c2" ON ("example_c1"."id" = "example_c2"."c1_ptr_id") WHERE "example_c2"."x" = 1 >>> A.objects.exclude_() [<A: A object>] >>> print A.objects.exclude_().query SELECT "example_a"."id", "example_a"."b_id" FROM "example_a" LEFT OUTER JOIN "example_b" ON ("example_a"."b_id" = "example_b"."id") LEFT OUTER JOIN "e xample_c1" ON ("example_b"."c_id" = "example_c1"."id") WHERE NOT (("example_b"."c_id" IN (SELECT U1."id" FROM "example_b" U1 INNER JOIN "example_c1" U 2 ON (U1."c_id" = U2."id") INNER JOIN "example_c2" U3 ON (U2."id" = U3."c1_ptr_id") WHERE (U3."x" = 1 AND U1."id" IS NOT NULL)) AND NOT ("example_b". "id" IS NULL) AND "example_c1"."id" IS NOT NULL)) >>> A.objects.exclude_().get().b.c.c2.x 1
As you can see, even though we have excluded objects with
self.exclude(b__c__c2__x=1)
we receive
A.objects.exclude_().get().b.c.c2.x == 1
Change History (1)
comment:1 by , 11 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Type: | Uncategorized → Bug |
Note:
See TracTickets
for help on using tickets.
Possible duplicate of #20788