Fixed #11535: Corrected SQL generated for queries involving generic relations and ORed Q objects. Thanks to brianglass for report, tobias for fix and test, and Alex for review.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12405 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Karen Tracey 2010-02-10 19:21:52 +00:00
parent 225c413b08
commit bb6b9aa472
3 changed files with 53 additions and 3 deletions

View File

@ -1100,13 +1100,13 @@ class Query(object):
for child in q_object.children:
if connector == OR:
refcounts_before = self.alias_refcount.copy()
self.where.start_subtree(connector)
if isinstance(child, Node):
self.where.start_subtree(connector)
self.add_q(child, used_aliases)
self.where.end_subtree()
else:
self.add_filter(child, connector, q_object.negated,
can_reuse=used_aliases)
self.where.end_subtree()
if connector == OR:
# Aliases that were newly added or not used at all need to
# be promoted to outer joins if they are nullable relations.

View File

@ -2,6 +2,10 @@ from django.db import models
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
__all__ = ('Link', 'Place', 'Restaurant', 'Person', 'Address',
'CharLink', 'TextLink', 'OddRelation1', 'OddRelation2',
'Contact', 'Organization', 'Note')
class Link(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
@ -59,3 +63,17 @@ class OddRelation2(models.Model):
name = models.CharField(max_length=100)
tlinks = generic.GenericRelation(TextLink)
# models for test_q_object_or:
class Note(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
note = models.TextField()
class Contact(models.Model):
notes = generic.GenericRelation(Note)
class Organization(models.Model):
name = models.CharField(max_length=255)
contacts = models.ManyToManyField(Contact, related_name='organizations')

View File

@ -1,6 +1,7 @@
from django.test import TestCase
from django.contrib.contenttypes.models import ContentType
from models import Link, Place, Restaurant, Person, Address, CharLink, TextLink, OddRelation1, OddRelation2
from django.db.models import Q
from models import *
class GenericRelationTests(TestCase):
@ -40,3 +41,34 @@ class GenericRelationTests(TestCase):
oddrel = OddRelation2.objects.create(name='tlink')
tl = TextLink.objects.create(content_object=oddrel)
oddrel.delete()
def test_q_object_or(self):
"""
Tests that SQL query parameters for generic relations are properly
grouped when OR is used.
Test for bug http://code.djangoproject.com/ticket/11535
In this bug the first query (below) works while the second, with the
query parameters the same but in reverse order, does not.
The issue is that the generic relation conditions do not get properly
grouped in parentheses.
"""
note_contact = Contact.objects.create()
org_contact = Contact.objects.create()
note = Note.objects.create(note='note', content_object=note_contact)
org = Organization.objects.create(name='org name')
org.contacts.add(org_contact)
# search with a non-matching note and a matching org name
qs = Contact.objects.filter(Q(notes__note__icontains=r'other note') |
Q(organizations__name__icontains=r'org name'))
self.assertTrue(org_contact in qs)
# search again, with the same query parameters, in reverse order
qs = Contact.objects.filter(
Q(organizations__name__icontains=r'org name') |
Q(notes__note__icontains=r'other note'))
self.assertTrue(org_contact in qs)