Changeset 7741
- Timestamp:
- 06/25/08 20:02:11 (5 months ago)
- Files:
-
- django/trunk/django/db/models/sql/query.py (modified) (3 diffs)
- django/trunk/tests/regressiontests/queries/models.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/db/models/sql/query.py
r7740 r7741 632 632 # add_filter, since the final column might not otherwise be part of 633 633 # the select set (so we can't order on it). 634 join = self.alias_map[alias] 635 if col == join[RHS_JOIN_COL]: 634 while 1: 635 join = self.alias_map[alias] 636 if col != join[RHS_JOIN_COL]: 637 break 636 638 self.unref_alias(alias) 637 639 alias = join[LHS_ALIAS] … … 831 833 for alias in self.join_map.get(t_ident, ()): 832 834 if alias not in exclusions: 835 if lhs_table and not self.alias_refcount[self.alias_map[alias][LHS_ALIAS]]: 836 # The LHS of this join tuple is no longer part of the 837 # query, so skip this possibility. 838 continue 833 839 self.ref_alias(alias) 834 840 if promote: … … 990 996 alias = join_list[-1] 991 997 992 iffinal > 1:998 while final > 1: 993 999 # An optimization: if the final join is against the same column as 994 1000 # we are comparing against, we can go back one step in the join 995 # chain and compare against the lhs of the join instead. The result 996 # (potentially) involves one less table join. 1001 # chain and compare against the lhs of the join instead (and then 1002 # repeat the optimization). The result, potentially, involves less 1003 # table joins. 997 1004 join = self.alias_map[alias] 998 if col == join[RHS_JOIN_COL]: 999 self.unref_alias(alias) 1000 alias = join[LHS_ALIAS] 1001 col = join[LHS_JOIN_COL] 1002 join_list = join_list[:-1] 1003 final -= 1 1004 if final == penultimate: 1005 penultimate = last.pop() 1005 if col != join[RHS_JOIN_COL]: 1006 break 1007 self.unref_alias(alias) 1008 alias = join[LHS_ALIAS] 1009 col = join[LHS_JOIN_COL] 1010 join_list = join_list[:-1] 1011 final -= 1 1012 if final == penultimate: 1013 penultimate = last.pop() 1006 1014 1007 1015 if (lookup_type == 'isnull' and value is True and not negate and django/trunk/tests/regressiontests/queries/models.py
r7740 r7741 135 135 def __unicode__(self): 136 136 return self.data 137 138 # An inter-related setup with multiple paths from Child to Detail. 139 class Detail(models.Model): 140 data = models.CharField(max_length=10) 141 142 class MemberManager(models.Manager): 143 def get_query_set(self): 144 return super(MemberManager, self).get_query_set().select_related("details") 145 146 class Member(models.Model): 147 name = models.CharField(max_length=10) 148 details = models.OneToOneField(Detail, primary_key=True) 149 150 objects = MemberManager() 151 152 class Child(models.Model): 153 person = models.OneToOneField(Member, primary_key=True) 154 parent = models.ForeignKey(Member, related_name="children") 137 155 138 156 … … 721 739 [u'e1', u'e2', None] 722 740 741 Similarly for select_related(), joins beyond an initial nullable join must 742 use outer joins so that all results are included. 743 >>> Report.objects.select_related("creator", "creator__extra").order_by("name") 744 [<Report: r1>, <Report: r2>, <Report: r3>] 745 746 When there are multiple paths to a table from another table, we have to be 747 careful not to accidentally reuse an inappropriate join when using 748 select_related(). We used to return the parent's Detail record here by mistake. 749 750 >>> d1 = Detail.objects.create(data="d1") 751 >>> d2 = Detail.objects.create(data="d2") 752 >>> m1 = Member.objects.create(name="m1", details=d1) 753 >>> m2 = Member.objects.create(name="m2", details=d2) 754 >>> c1 = Child.objects.create(person=m2, parent=m1) 755 >>> obj = m1.children.select_related("person__details")[0] 756 >>> obj.person.details.data 757 u'd2' 758 723 759 """} 724 760
