#9132 closed (invalid)
QuerySet. count() doesn't do a Join if tables are inherited
| Reported by: | Owned by: | cazzerson | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.0 |
| Severity: | Keywords: | count() QuerySet | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
the sql-query for result with correct joins:
SELECT "springshop_spring"."id", "springshop_spring"."material", "springshop_spring"."articelnumber", "springshop_spring"."wiresize", "springshop_spring"."outerdiameter", "springshop_spring"."windingcount", "springshop_spring"."weight", "springshop_pressurespring"."spring_ptr_id", "springshop_pressurespring"."freelengthLo", "springshop_pressurespring"."springconstant", "springshop_pressurespring"."blocklength" FROM "springshop_pressurespring" INNER JOIN "springshop_spring" ON ("springshop_pressurespring"."spring_ptr_id" = "springshop_spring"."id") WHERE wiresize=2
the sql-query for count with incorrect joins:
'SELECT COUNT(*) FROM "springshop_pressurespring" WHERE wiresize=2'
so the join is missing
Change History (7)
comment:1 by , 17 years ago
comment:2 by , 17 years ago
==django model==
class Spring(models.Model):
"""This class represents a spring"""
class Meta:
verbose_name = _(u"Feder")
#material
MATERIAL_CHOICES = ( [
( 'sh', _("Federstahl SH") ),
( 'r', _("Federstahl 1.4310") ),
])
material = models.CharField(max_length=4, choices=MATERIAL_CHOICES, verbose_name=_(u"Material") )
#artikelnumber
articelnumber = models.CharField(max_length=16, unique=True, verbose_name=_(u"Artikelnummer") )
#drahtduchrmesser
wiresize = models.DecimalField(max_digits=10,decimal_places=5)
#außendurchmesser
outerdiameter = models.DecimalField(max_digits=10,decimal_places=5)
#windungszahl
windingcount = models.IntegerField(verbose_name=_(u"Gesamtwindungszahl"))
#gewicht
weight = models.DecimalField(max_digits=10,decimal_places=5)
class PressureSpring(Spring):
"""This class represents a pressure spring"""
class Meta:
verbose_name = _(u"Druckfeder")
verbose_name_plural = _(u"Druckfedern")
#einhängelänge Lo
freelengthLo = models.DecimalField(max_digits=10,decimal_places=5)
#federrate#
springconstant = models.DecimalField(max_digits=10,decimal_places=5, verbose_name=_(u"Federrate") )
blocklength = models.DecimalField(max_digits=10,decimal_places=5, verbose_name=_(u"Blocklänge") )
class PullSpring(Spring):
#class Zugfeder(Feder):
"""This class represents a pull-spring"""
class Meta:
verbose_name = _(u"Zugfeder")
verbose_name_plural = _(u"Zugfedern")
#Einhängelänge lo
replacementlengthLo = models.DecimalField(max_digits=10,decimal_places=5)
#federrate
springconstant = models.DecimalField(max_digits=10,decimal_places=5)
class TorsionSpring(Spring):
"""This class represents a torsion spring"""
class Meta:
verbose_name = _(u"Torsionsfeder")
verbose_name = _(u"Torsionsfedern")
#schängellänge1
leglength1 = models.DecimalField(max_digits=10,decimal_places=5)
#schänkellänge2
leglength2 = models.DecimalField(max_digits=10,decimal_places=5)
==the sql code for creating these models ( output from python manage.py sqlall springshop )==
BEGIN;
CREATE TABLE "springshop_spring" (
"id" integer NOT NULL PRIMARY KEY,
"material" varchar(4) NOT NULL,
"articelnumber" varchar(16) NOT NULL UNIQUE,
"wiresize" decimal NOT NULL,
"outerdiameter" decimal NOT NULL,
"windingcount" integer NOT NULL,
"weight" decimal NOT NULL
)
;
CREATE TABLE "springshop_pressurespring" (
"spring_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "springshop_spring" ("id"),
"freelengthLo" decimal NOT NULL,
"springconstant" decimal NOT NULL,
"blocklength" decimal NOT NULL
)
;
CREATE TABLE "springshop_pullspring" (
"spring_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "springshop_spring" ("id"),
"replacementlengthLo" decimal NOT NULL,
"springconstant" decimal NOT NULL
)
;
CREATE TABLE "springshop_torsionspring" (
"spring_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "springshop_spring" ("id"),
"leglength1" decimal NOT NULL,
"leglength2" decimal NOT NULL
)
;
COMMIT;
===python code===
result = models.PressureSpring.extra(where=['wiresize=%s'], params=[wiresize] )
func_count = result.count()
count = 0
for i in result:
count = count + 1
after this code func_count != count and I think the problem is the missing join between the Spring-table and the PressureSpring-table
comment:3 by , 17 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:4 by , 17 years ago
| Owner: | changed from to |
|---|---|
| Status: | assigned → new |
comment:5 by , 17 years ago
| milestone: | → 1.1 |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:6 by , 17 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
Your issue here is that you're using extra, and Django doesn't know the extra field is on a different table. This works fine if you use normal Django QuerySet operations.
If you're counting the inherited model and the attribute wiresize is on that inherited model, there's maybe no need to do a join here and it was optimized away for a faster query.
Could you provide the model definitions and the ORM call that led to these SQL queries please?