mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	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:
		| @@ -679,12 +679,16 @@ class Query(object): | ||||
|         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 | ||||
|         always promoted. | ||||
|  | ||||
|         Returns True if the join was promoted. | ||||
|         """ | ||||
|         if ((unconditional or self.alias_map[alias][NULLABLE]) and | ||||
|                 self.alias_map[alias] != self.LOUTER): | ||||
|             data = list(self.alias_map[alias]) | ||||
|             data[JOIN_TYPE] = self.LOUTER | ||||
|             self.alias_map[alias] = tuple(data) | ||||
|             return True | ||||
|         return False | ||||
|  | ||||
|     def change_aliases(self, change_map): | ||||
|         """ | ||||
| @@ -1294,10 +1298,12 @@ class Query(object): | ||||
|                         final_alias = join[LHS_ALIAS] | ||||
|                         col = join[LHS_JOIN_COL] | ||||
|                         joins = joins[:-1] | ||||
|                 promote = False | ||||
|                 for join in joins[1:]: | ||||
|                     # Only nullable aliases are promoted, so we don't end up | ||||
|                     # 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_fields.append(field) | ||||
|         except MultiJoin: | ||||
|   | ||||
| @@ -58,7 +58,7 @@ class Item(models.Model): | ||||
|  | ||||
| class Report(models.Model): | ||||
|     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): | ||||
|         return self.name | ||||
| @@ -191,6 +191,8 @@ by 'info'. Helps detect some problems later. | ||||
| >>> r1.save() | ||||
| >>> r2 = Report(name='r2', creator=a3) | ||||
| >>> r2.save() | ||||
| >>> r3 = Report(name='r3') | ||||
| >>> r3.save() | ||||
|  | ||||
| Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering | ||||
| 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) | ||||
| >>> 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] | ||||
|  | ||||
| """} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user