1
0
mirror of https://github.com/django/django.git synced 2025-07-06 18:59:13 +00:00

queryset-refactor: Fixed query disjunctions.

git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6867 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-12-03 21:10:51 +00:00
parent cc0078494e
commit 57a4b882ae
2 changed files with 38 additions and 1 deletions

View File

@ -8,6 +8,7 @@ all about the internals of models in order to get the information it needs.
""" """
import copy import copy
import operator
import re import re
from django.utils.tree import Node from django.utils.tree import Node
@ -465,7 +466,7 @@ class Query(object):
result = [] result = []
for field in ordering: for field in ordering:
if field == '?': if field == '?':
result.append(self.connector.ops.random_function_sql()) result.append(self.connection.ops.random_function_sql())
continue continue
if isinstance(field, int): if isinstance(field, int):
if field < 0: if field < 0:
@ -724,7 +725,32 @@ class Query(object):
# efficient at the database level. # efficient at the database level.
self.promote_alias(join_list[-1][0]) self.promote_alias(join_list[-1][0])
if connector == OR:
# Some joins may need to be promoted when adding a new filter to a
# disjunction. We walk the list of new joins and where it diverges
# from any previous joins (ref count is 1 in the table list), we
# make the new additions (and any existing ones not used in the new
# join list) an outer join.
join_it = nested_iter(join_list)
table_it = iter(self.tables)
join_it.next(), table_it.next()
for join in join_it:
table = table_it.next()
if join == table and self.alias_map[join][ALIAS_REFCOUNT] > 1:
continue
self.promote_alias(join)
if table != join:
self.promote_alias(table)
break
for join in join_it:
self.promote_alias(join)
for table in table_it:
# Some of these will have been promoted from the join_list, but
# that's harmless.
self.promote_alias(table)
self.where.add([alias, col, field, lookup_type, value], connector) self.where.add([alias, col, field, lookup_type, value], connector)
if negate: if negate:
flag = False flag = False
for pos, null in enumerate(nullable): for pos, null in enumerate(nullable):
@ -1198,6 +1224,15 @@ def results_iter(cursor):
raise StopIteration raise StopIteration
yield rows yield rows
def nested_iter(nested):
"""
An iterator over a sequence of sequences. Each element is returned in turn.
Only handles one level of nesting, since that's all we need here.
"""
for seq in nested:
for elt in seq:
yield elt
def setup_join_cache(sender): def setup_join_cache(sender):
""" """
The information needed to join between model fields is something that is The information needed to join between model fields is something that is

View File

@ -196,6 +196,8 @@ Bug #2080, #3592
[<Author: a1>, <Author: a3>] [<Author: a1>, <Author: a3>]
>>> Author.objects.filter(Q(name='a3') | Q(item__name='one')) >>> Author.objects.filter(Q(name='a3') | Q(item__name='one'))
[<Author: a1>, <Author: a3>] [<Author: a1>, <Author: a3>]
>>> Author.objects.filter(Q(item__name='three') | Q(report__name='r3'))
[<Author: a2>]
Bug #6074 Bug #6074
Merging two empty result sets shouldn't leave a queryset with no constraints Merging two empty result sets shouldn't leave a queryset with no constraints