#8439: Q objects still incorrectly choosing inner join over outer join
------------------------------+---------------------------------------------
Reporter: mikemintz | Owner: nobody
Status: new | Milestone:
Component: Database wrapper | Version: SVN
Keywords: | Stage: Unreviewed
Has_patch: 0 |
------------------------------+---------------------------------------------
I am basically reopening #3592 with an example that is broken in the
latest SVN. I am using SVN r8445.
Here are my test models:
{{{
class Enemy(models.Model):
pass
class Troop(models.Model):
pass
class Soldier(models.Model):
troop = models.ForeignKey(Troop)
class TroopKill(models.Model):
enemy = models.ForeignKey(Enemy)
troop = models.ForeignKey(Troop)
class SoldierKill(models.Model):
enemy = models.ForeignKey(Enemy)
soldier = models.ForeignKey(Soldier)
grenade = models.BooleanField()
}}}
I want to find all enemies that were killed either by my soldier, or by
the troop my soldier is in. So I execute the following query:
{{{
direct_kills = Q(soldierkill__soldier__pk=1)
troop_kills = Q(troopkill__troop__soldier__pk=1)
all_kills = direct_kills | troop_kills
print Enemy.objects.filter(all_kills).all()
}}}
And I get the correct SQL:
{{{
SELECT "enemy"."id" FROM "enemy"
LEFT OUTER JOIN "soldierkill" ON ("enemy"."id" = "soldierkill"."enemy_id")
LEFT OUTER JOIN "troopkill" ON ("enemy"."id" = "troopkill"."enemy_id")
LEFT OUTER JOIN "troop" ON ("troopkill"."troop_id" = "troop"."id")
LEFT OUTER JOIN "soldier" T6 ON ("troop"."id" = T6."troop_id")
WHERE ("soldierkill"."soldier_id" = 1 OR T6."id" = 1 )
}}}
But when I try to add just one more condition (the direct kill had to have
grenade=True):
{{{
direct_kills = Q(soldierkill__soldier__pk=1,soldierkill__grenade=True)
troop_kills = Q(troopkill__troop__soldier__pk=1)
all_kills = direct_kills | troop_kills
print Enemy.objects.filter(all_kills).all()
}}}
It switches incorrectly to inner joins.
{{{
SELECT "enemy"."id" FROM "enemy"
INNER JOIN "soldierkill" ON ("enemy"."id" = "soldierkill"."enemy_id")
INNER JOIN "troopkill" ON ("enemy"."id" = "troopkill"."enemy_id")
INNER JOIN "troop" ON ("troopkill"."troop_id" = "troop"."id")
INNER JOIN "soldier" T6 ON ("troop"."id" = T6."troop_id")
WHERE (("soldierkill"."grenade" = true AND "soldierkill"."soldier_id" = 1
) OR T6."id" = 1 )
}}}
Am I doing something wrong, or is this broken?
Thanks,
Mike
--
Ticket URL: <http://code.djangoproject.com/ticket/8439>
Django Code <http://code.djangoproject.com/>
The web framework for perfectionists with deadlines
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---