#14055: Wrong query generated when using reverse foreign key
------------------------------------------+---------------------------------
Reporter: premalshah | Owner: nobody
Status: new | Milestone: 1.3
Component: Database layer (models, ORM) | Version: 0.96
Keywords: foreign key | Stage: Unreviewed
Has_patch: 0 |
------------------------------------------+---------------------------------
Here is the model setup
{{{
from django.db import models
class Base(models.Model):
id = models.AutoField(primary_key=True)
field1 = models.CharField(max_length=11)
class Child(models.Model):
id = models.AutoField(primary_key=True)
obj = models.ForeignKey(Base)
field1 = models.CharField(max_length=11)
field2 = models.IntegerField()
}}}
Here are some sample queries and the corresponding sql statements
generated and sql statements expected
{{{
'''Query 1'''
Base.objects.filter(child__obj=1).query
''Generated SQL''
SELECT `apptest_base`.`id`, `apptest_base`.`field1` FROM `apptest_base`
WHERE `apptest_base`.`id` = 1;
''Expected SQL''
SELECT `apptest_base`.`id`, `apptest_base`.`field1` FROM `apptest_base`
INNER JOIN `apptest_child`
ON (`apptest_base`.`id` = `apptest_child`.`obj_id`) WHERE
`apptest_child`.`obj_id` = 1;
}}}
{{{
'''Query 2'''
Base.objects.filter(child__obj=1, child__field1='a').query
''Generated SQL''
SELECT `apptest_base`.`id`, `apptest_base`.`field1` FROM `apptest_base`
INNER JOIN `apptest_child` T4
ON (`apptest_base`.`id` = T4.`obj_id`) WHERE (`apptest_base`.`id` = 1 AND
T4.`field1` = a );
''Expected SQL''
SELECT `apptest_base`.`id`, `apptest_base`.`field1` FROM `apptest_base`
INNER JOIN `apptest_child`
ON (`apptest_base`.`id` = `apptest_child`.`obj_id`) WHERE
(`apptest_child`.`obj_id` = 1 AND `apptest_child`.`field1` = a );
}}}
{{{
'''Query 3'''
Base.objects.filter(child__obj=1,
child__field1='a').order_by('child__field2', 'child__obj').query
''Generated SQL''
SELECT `apptest_base`.`id`, `apptest_base`.`field1` FROM `apptest_base`
LEFT OUTER JOIN `apptest_child`
ON (`apptest_base`.`id` = `apptest_child`.`obj_id`) INNER JOIN
`apptest_child` T4
ON (`apptest_base`.`id` = T4.`obj_id`) WHERE (`apptest_base`.`id` = 1 AND
T4.`field1` = a )
ORDER BY `apptest_child`.`field2` ASC, `apptest_base`.`id` ASC;
''Expected SQL''
SELECT `apptest_base`.`id`, `apptest_base`.`field1` FROM `apptest_base`
LEFT OUTER JOIN `apptest_child`
ON (`apptest_base`.`id` = `apptest_child`.`obj_id`) WHERE
(`apptest_child`.`obj_id` = 1 AND
`apptest_child`.`field1` = a ) ORDER BY `apptest_child`.`field2` ASC,
`apptest_child`.`obj_id` ASC;
}}}
Problems:
1) Query 1 is missing a join.
2) Query 2 is using apptest_base.id in the where clause instead of
apptest_child.obj_id. The results from the generated sql and expected sql
would be the same. However, indexes created on the apptest_child table to
optimize the query cannot be used hence leading to a slow query.
3) Query 3 has the same problem as query 2 in the where clause as well as
the order by clause. In addition to that, it also performs an extra join
on the apptest_child table which gives different results from the
generated sql and the expected sql statements.
I believe that this happens because of the reverse foreign key field
{{obj}}. When {{child__obj}} is used, the query generation logic does not
know that we are referencing the {{obj}} field on the Child table and not
the {{id}} field on the Base table. If we could explicitly specify
{{child__obj_id}}, it would help, but thats not an options with the
current database model api code.
--
Ticket URL: <http://code.djangoproject.com/ticket/14055>
Django <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.