Author: mtredinnick
Date: 2009-03-24 00:54:35 -0500 (Tue, 24 Mar 2009)
New Revision: 10138

Modified:
   django/branches/releases/1.0.X/django/db/models/sql/query.py
   django/branches/releases/1.0.X/tests/regressiontests/queries/models.py
   
django/branches/releases/1.0.X/tests/regressiontests/select_related_regress/models.py
Log:
[1.0.X] Fixed #9926 -- Fixes for some select_related() situations.

Using select_related(...) across a nullable relation to a multi-table
model inheritance situation no longer excludes results. Thanks to AdamG
for a test demonstrating part of the problem.

Backport of r10136 from trunk.

Modified: django/branches/releases/1.0.X/django/db/models/sql/query.py
===================================================================
--- django/branches/releases/1.0.X/django/db/models/sql/query.py        
2009-03-24 04:26:56 UTC (rev 10137)
+++ django/branches/releases/1.0.X/django/db/models/sql/query.py        
2009-03-24 05:54:35 UTC (rev 10138)
@@ -510,6 +510,7 @@
                 alias = self.included_inherited_models[model]
             if as_pairs:
                 result.append((alias, field.column))
+                aliases.add(alias)
                 continue
             if with_aliases and field.column in col_aliases:
                 c_alias = 'Col%d' % len(col_aliases)
@@ -524,7 +525,7 @@
                 if with_aliases:
                     col_aliases.add(field.column)
         if as_pairs:
-            return result, None
+            return result, aliases
         return result, aliases
 
     def get_from_clause(self):
@@ -1076,6 +1077,7 @@
             if model:
                 int_opts = opts
                 alias = root_alias
+                alias_chain = []
                 for int_model in opts.get_base_chain(model):
                     lhs_col = int_opts.parents[int_model].column
                     dedupe = lhs_col in opts.duplicate_targets
@@ -1087,8 +1089,11 @@
                     alias = self.join((alias, int_opts.db_table, lhs_col,
                             int_opts.pk.column), exclusions=used,
                             promote=promote)
+                    alias_chain.append(alias)
                     for (dupe_opts, dupe_col) in dupe_set:
                         self.update_dupe_avoidance(dupe_opts, dupe_col, alias)
+                if self.alias_map[root_alias][JOIN_TYPE] == self.LOUTER:
+                    self.promote_alias_chain(alias_chain, True)
             else:
                 alias = root_alias
 
@@ -1102,8 +1107,11 @@
                     f.rel.get_related_field().column),
                     exclusions=used.union(avoid), promote=promote)
             used.add(alias)
-            self.related_select_cols.extend(self.get_default_columns(
-                start_alias=alias, opts=f.rel.to._meta, as_pairs=True)[0])
+            columns, aliases = self.get_default_columns(start_alias=alias,
+                    opts=f.rel.to._meta, as_pairs=True)
+            self.related_select_cols.extend(columns)
+            if self.alias_map[alias][JOIN_TYPE] == self.LOUTER:
+                self.promote_alias_chain(aliases, True)
             self.related_select_fields.extend(f.rel.to._meta.fields)
             if restricted:
                 next = requested.get(f.name, {})

Modified: django/branches/releases/1.0.X/tests/regressiontests/queries/models.py
===================================================================
--- django/branches/releases/1.0.X/tests/regressiontests/queries/models.py      
2009-03-24 04:26:56 UTC (rev 10137)
+++ django/branches/releases/1.0.X/tests/regressiontests/queries/models.py      
2009-03-24 05:54:35 UTC (rev 10138)
@@ -16,10 +16,17 @@
 except NameError:
     from django.utils.itercompat import sorted
 
+class DumbCategory(models.Model):
+    pass
+
+class NamedCategory(DumbCategory):
+    name = models.CharField(max_length=10)
+
 class Tag(models.Model):
     name = models.CharField(max_length=10)
     parent = models.ForeignKey('self', blank=True, null=True,
             related_name='children')
+    category = models.ForeignKey(NamedCategory, null=True, default=None)
 
     class Meta:
         ordering = ['name']
@@ -266,8 +273,9 @@
 
 
 __test__ = {'API_TESTS':"""
->>> t1 = Tag.objects.create(name='t1')
->>> t2 = Tag.objects.create(name='t2', parent=t1)
+>>> generic = NamedCategory.objects.create(name="Generic")
+>>> t1 = Tag.objects.create(name='t1', category=generic)
+>>> t2 = Tag.objects.create(name='t2', parent=t1, category=generic)
 >>> t3 = Tag.objects.create(name='t3', parent=t1)
 >>> t4 = Tag.objects.create(name='t4', parent=t3)
 >>> t5 = Tag.objects.create(name='t5', parent=t3)
@@ -726,6 +734,12 @@
 >>> Tag.objects.select_related('parent').order_by('name')
 [<Tag: t1>, <Tag: t2>, <Tag: t3>, <Tag: t4>, <Tag: t5>]
 
+Bug #9926
+>>> Tag.objects.select_related("parent", "category").order_by('name')
+[<Tag: t1>, <Tag: t2>, <Tag: t3>, <Tag: t4>, <Tag: t5>]
+>>> Tag.objects.select_related('parent', "parent__category").order_by('name')
+[<Tag: t1>, <Tag: t2>, <Tag: t3>, <Tag: t4>, <Tag: t5>]
+
 Bug #6180, #6203 -- dates with limits and/or counts
 >>> Item.objects.count()
 4

Modified: 
django/branches/releases/1.0.X/tests/regressiontests/select_related_regress/models.py
===================================================================
--- 
django/branches/releases/1.0.X/tests/regressiontests/select_related_regress/models.py
       2009-03-24 04:26:56 UTC (rev 10137)
+++ 
django/branches/releases/1.0.X/tests/regressiontests/select_related_regress/models.py
       2009-03-24 05:54:35 UTC (rev 10138)
@@ -65,6 +65,23 @@
     state = models.ForeignKey(State, null=True)
     status = models.ForeignKey(ClientStatus)
 
+# Some model inheritance exercises
+class Parent(models.Model):
+    name = models.CharField(max_length=10)
+
+    def __unicode__(self):
+        return self.name
+
+class Child(Parent):
+    value = models.IntegerField()
+
+class Item(models.Model):
+    name = models.CharField(max_length=10)
+    child = models.ForeignKey(Child, null=True)
+
+    def __unicode__(self):
+        return self.name
+
 __test__ = {'API_TESTS': """
 Regression test for bug #7110. When using select_related(), we must query the
 Device and Building tables using two different aliases (each) in order to
@@ -140,4 +157,12 @@
 <ClientStatus: ClientStatus object>
 >>> Client.objects.select_related('status')[0].status
 <ClientStatus: ClientStatus object>
+
+Exercising select_related() with multi-table model inheritance.
+>>> c1 = Child.objects.create(name="child1", value=42)
+>>> _ = Item.objects.create(name="item1", child=c1)
+>>> _ = Item.objects.create(name="item2")
+>>> Item.objects.select_related("child").order_by("name")
+[<Item: item1>, <Item: item2>]
+
 """}


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to