Changeset 8832
- Timestamp:
- 09/01/08 21:16:41 (3 months ago)
- Files:
-
- django/trunk/django/db/models/sql/constants.py (modified) (1 diff)
- django/trunk/django/db/models/sql/query.py (modified) (3 diffs)
- django/trunk/tests/regressiontests/queries/models.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/db/models/sql/constants.py
r7490 r8832 16 16 17 17 # Constants to make looking up tuple values clearer. 18 # Join lists 18 # Join lists (indexes into the tuples that are values in the alias_map 19 # dictionary in the Query class). 19 20 TABLE_NAME = 0 20 21 RHS_ALIAS = 1 django/trunk/django/db/models/sql/query.py
r8831 r8832 717 717 self.table_map[alias] = [alias] 718 718 self.alias_refcount[alias] = 1 719 #self.alias_map[alias] = None720 719 self.tables.append(alias) 721 720 return alias, True … … 1189 1188 connector = AND 1190 1189 for child in q_object.children: 1190 if connector == OR: 1191 refcounts_before = self.alias_refcount.copy() 1191 1192 if isinstance(child, Node): 1192 1193 self.where.start_subtree(connector) … … 1196 1197 self.add_filter(child, connector, q_object.negated, 1197 1198 can_reuse=used_aliases) 1199 if connector == OR: 1200 # Aliases that were newly added or not used at all need to 1201 # be promoted to outer joins if they are nullable relations. 1202 # (they shouldn't turn the whole conditional into the empty 1203 # set just because they don't match anything). 1204 # FIXME: There's some (a lot of!) overlap with the similar 1205 # OR promotion in add_filter(). It's not quite identical, 1206 # but is very similar. So pulling out the common bits is 1207 # something for later (code smell: too much indentation 1208 # here) 1209 considered = {} 1210 for alias in self.tables: 1211 if alias not in used_aliases: 1212 continue 1213 if (alias not in refcounts_before or 1214 self.alias_refcount[alias] == 1215 refcounts_before[alias]): 1216 parent = self.alias_map[alias][LHS_ALIAS] 1217 must_promote = considered.get(parent, False) 1218 promoted = self.promote_alias(alias, must_promote) 1219 considered[alias] = must_promote or promoted 1198 1220 connector = q_object.connector 1199 1221 if q_object.negated: django/trunk/tests/regressiontests/queries/models.py
r8794 r8832 224 224 name = models.CharField(max_length=20) 225 225 order = models.IntegerField() 226 226 227 227 def __unicode__(self): 228 228 return self.name 229 229 230 230 __test__ = {'API_TESTS':""" 231 231 >>> t1 = Tag.objects.create(name='t1') … … 238 238 >>> n2 = Note.objects.create(note='n2', misc='bar') 239 239 >>> n3 = Note.objects.create(note='n3', misc='foo') 240 241 >>> ann1 = Annotation.objects.create(name='a1', tag=t1) 242 >>> ann1.notes.add(n1) 243 >>> ann2 = Annotation.objects.create(name='a2', tag=t4) 244 >>> ann2.notes.add(n2, n3) 240 245 241 246 Create these out of order so that sorting by 'id' will be different to sorting … … 843 848 844 849 Bug #7277 845 >>> ann1 = Annotation.objects.create(name='a1', tag=t1)846 >>> ann1.notes.add(n1)847 850 >>> n1.annotation_set.filter(Q(tag=t5) | Q(tag__children=t5) | Q(tag__children__children=t5)) 848 851 [<Annotation: a1>] … … 932 935 >>> ReservedName.objects.all().order_by('order') 933 936 [<ReservedName: b>, <ReservedName: a>] 934 935 937 >>> ReservedName.objects.extra(select={'stuff':'name'}, order_by=('order','stuff')) 936 938 [<ReservedName: b>, <ReservedName: a>] 937 939 940 Bug #8439 -- complex combinations of conjunctions, disjunctions and nullable 941 relations. 942 >>> Author.objects.filter(Q(item__note__extrainfo=e2)|Q(report=r1, name='xyz')) 943 [<Author: a2>] 944 >>> Author.objects.filter(Q(report=r1, name='xyz')|Q(item__note__extrainfo=e2)) 945 [<Author: a2>] 946 >>> Annotation.objects.filter(Q(tag__parent=t1)|Q(notes__note='n1', name='a1')) 947 [<Annotation: a1>] 948 >>> xx = ExtraInfo.objects.create(info='xx', note=n3) 949 >>> Note.objects.filter(Q(extrainfo__author=a1)|Q(extrainfo=xx)) 950 [<Note: n1>, <Note: n3>] 951 >>> xx.delete() 952 >>> q = Note.objects.filter(Q(extrainfo__author=a1)|Q(extrainfo=xx)).query 953 >>> len([x[2] for x in q.alias_map.values() if x[2] == q.LOUTER and q.alias_refcount[x[1]]]) 954 1 955 938 956 """} 939 957
