Dan Watson
unread,Oct 14, 2010, 5:07:59 PM10/14/10Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Django developers
There seems to be some inconsistent behavior when combining querysets
that use isnull on a ForeignKey. I'm not sure how to explain it well
in plain english, so here's a boiled-down example:
# Models
class Item (models.Model):
title = models.CharField( max_length=100 )
class PropertyValue (models.Model):
label = models.CharField( max_length=100 )
class Property (models.Model):
item = models.ForeignKey( Item, related_name='props' )
key = models.CharField( max_length=100 )
value = models.ForeignKey( PropertyValue, null=True )
# Example
item = Item.objects.create(title='Some Item')
pv = PropertyValue.objects.create(label='Some Value')
item.props.create(key='a', value=pv)
item.props.create(key='b')
q1 = Q(props__key='a', props__value=pv)
q2 = Q(props__key='b', props__value__isnull=True)
qs1 = Item.objects.filter(q1) & Item.objects.filter(q2)
qs2 = Item.objects.filter(q2) & Item.objects.filter(q1)
I would have expected qs1 and qs2 to yield the same result, but they
do not. They should both return the single item, but qs1 returns
nothing. The SQL for qs1 looks like:
SELECT "app_item"."id", "app_item"."title" FROM "app_item"
INNER JOIN "app_property" ON ("app_item"."id" =
"app_property"."item_id")
LEFT OUTER JOIN "app_property" T4 ON ("app_item"."id" = T4."item_id")
LEFT OUTER JOIN "app_propertyvalue" T5 ON ("app_property"."value_id" =
T5."id")
WHERE (("app_property"."value_id" = 1 AND "app_property"."key" =
'a' ) AND (T5."id" IS NULL AND T4."key" = 'b' ))
The first app_property join corresponds to q1, and the second
corresponds to q2. However, the app_propertyvalue join (corresponding
to the isnull from q2) refers to app_property.value_id (i.e. q1)
instead of T4.value_id (i.e. q2). I think fixing #10790 would fix
this, since removing the join to app_propertyvalue and simply checking
"T4.value_id IS NULL" works as expected, but I'm not sure if this is a
separate problem worthy of another ticket or not. Also (less
importantly), since both criteria (q1 and q2) are checking
props__key='something', I would imagine both joins could be INNER
JOINs, but the isnull seems to promote the second to a LEFT OUTER
JOIN.
I guess I was just wondering if I should open a separate ticket for
this, or is this simply a symptom of #10790? Or am I missing
something?
Regards,
Dan