Fixed a problem with values() and values_list() queries and nullable joins.
Previously, if we were querying across a nullable join and then a non-nullable one, the second join would not be a LEFT OUTER join, which would exclude certain valid results from the result set. This is the same problem as [7597] but for values() field specifications, so this covers the second case where Django adds extra stuff to the select-clause. git-svn-id: http://code.djangoproject.com/svn/django/trunk@7740 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
b8f7b39ccc
commit
1834428648
|
@ -679,12 +679,16 @@ class Query(object):
|
||||||
for the join to contain NULL values on the left. If 'unconditional' is
|
for the join to contain NULL values on the left. If 'unconditional' is
|
||||||
False, the join is only promoted if it is nullable, otherwise it is
|
False, the join is only promoted if it is nullable, otherwise it is
|
||||||
always promoted.
|
always promoted.
|
||||||
|
|
||||||
|
Returns True if the join was promoted.
|
||||||
"""
|
"""
|
||||||
if ((unconditional or self.alias_map[alias][NULLABLE]) and
|
if ((unconditional or self.alias_map[alias][NULLABLE]) and
|
||||||
self.alias_map[alias] != self.LOUTER):
|
self.alias_map[alias] != self.LOUTER):
|
||||||
data = list(self.alias_map[alias])
|
data = list(self.alias_map[alias])
|
||||||
data[JOIN_TYPE] = self.LOUTER
|
data[JOIN_TYPE] = self.LOUTER
|
||||||
self.alias_map[alias] = tuple(data)
|
self.alias_map[alias] = tuple(data)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def change_aliases(self, change_map):
|
def change_aliases(self, change_map):
|
||||||
"""
|
"""
|
||||||
|
@ -1294,10 +1298,12 @@ class Query(object):
|
||||||
final_alias = join[LHS_ALIAS]
|
final_alias = join[LHS_ALIAS]
|
||||||
col = join[LHS_JOIN_COL]
|
col = join[LHS_JOIN_COL]
|
||||||
joins = joins[:-1]
|
joins = joins[:-1]
|
||||||
|
promote = False
|
||||||
for join in joins[1:]:
|
for join in joins[1:]:
|
||||||
# Only nullable aliases are promoted, so we don't end up
|
# Only nullable aliases are promoted, so we don't end up
|
||||||
# doing unnecessary left outer joins here.
|
# doing unnecessary left outer joins here.
|
||||||
self.promote_alias(join)
|
if self.promote_alias(join, promote):
|
||||||
|
promote = True
|
||||||
self.select.append((final_alias, col))
|
self.select.append((final_alias, col))
|
||||||
self.select_fields.append(field)
|
self.select_fields.append(field)
|
||||||
except MultiJoin:
|
except MultiJoin:
|
||||||
|
|
|
@ -58,7 +58,7 @@ class Item(models.Model):
|
||||||
|
|
||||||
class Report(models.Model):
|
class Report(models.Model):
|
||||||
name = models.CharField(max_length=10)
|
name = models.CharField(max_length=10)
|
||||||
creator = models.ForeignKey(Author, to_field='num')
|
creator = models.ForeignKey(Author, to_field='num', null=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -191,6 +191,8 @@ by 'info'. Helps detect some problems later.
|
||||||
>>> r1.save()
|
>>> r1.save()
|
||||||
>>> r2 = Report(name='r2', creator=a3)
|
>>> r2 = Report(name='r2', creator=a3)
|
||||||
>>> r2.save()
|
>>> r2.save()
|
||||||
|
>>> r3 = Report(name='r3')
|
||||||
|
>>> r3.save()
|
||||||
|
|
||||||
Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
|
Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
|
||||||
will be rank3, rank2, rank1.
|
will be rank3, rank2, rank1.
|
||||||
|
@ -713,5 +715,10 @@ in MySQL. This exercises that case.
|
||||||
>>> mm = ManagedModel.objects.create(data='mm1', tag=t1, is_public=True)
|
>>> mm = ManagedModel.objects.create(data='mm1', tag=t1, is_public=True)
|
||||||
>>> ManagedModel.objects.update(data='mm')
|
>>> ManagedModel.objects.update(data='mm')
|
||||||
|
|
||||||
|
A values() or values_list() query across joined models must use outer joins
|
||||||
|
appropriately.
|
||||||
|
>>> Report.objects.values_list("creator__extra__info", flat=True).order_by("name")
|
||||||
|
[u'e1', u'e2', None]
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue