#31109 closed Bug (fixed)
Multiple annotation with Subquery generates wrong SQL.
| Reported by: | Thierry Bastian | Owned by: | Simon Charette |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 3.0 |
| Severity: | Release blocker | Keywords: | |
| Cc: | Simon Charette | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I have 2 models Item and ItemInfo.
class Item(models.Model):
name = TextField()
...
class ItemInfo(models.Model):
id = models.OneToOneField(Item, models.CASCADE, db_column='id', primary_key=True)
size = models.BigIntegerField(blank=True, null=True)
...
If I do a QuerySet like this:
Item.objects \
.annotate(
size=Subquery(
ItemInfo.objects.filter(id=OuterRef('id')).values_list(
'size', flat=True
)[:1]
),
depends_on=StringAgg('name', ', ' )
)
If I simply execute it, it works. Please don't look at the QuerySet, I really tried to make it the simplest example ever
But if I do a .exists() I'm getting
django.db.utils.ProgrammingError: column "size" does not exist
LINE 1...
Obviously that used to work with any 2.x version.
Change History (7)
comment:1 by , 6 years ago
comment:2 by , 6 years ago
| Severity: | Normal → Release blocker |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
I reproduced the issue in the current master (abeb4599af5ea7a384e18ec6201a95c9e419b44a).
This regression seems to have been caused by fb3f034f1c63160c0ff13c609acd01c18be12f80 (found using git bisect).
I'll bump the severity to "release blocker" because of the regression.
Thanks!
comment:3 by , 6 years ago
| Cc: | added |
|---|---|
| Summary: | multiple annotation with SubQuery generates wrong SQL → Multiple annotation with Subquery generates wrong SQL. |
comment:4 by , 6 years ago
So here's what happens here.
- Since
StringAggis an aggregate it setsqueryset.query.group_by = Trueon annotation. QuerySet.exists()relies onQuery.has_resultsQuery.has_resultsdoes the following whendistinct=Falseandgroup_by=True.- It adds all the the concrete fields of the model to address #24835
- Calls
set_group_bywhich happens to add aRefreferring to the selectedSubqueryannotation togroup_bysince fb3f034f1c63160c0ff13c609acd01c18be12f80 . - It then calls
clear_select_clausewhich orphans theRefsince it now points to column that isn't selected to anymore.
The solutions is either to:
- Add a parameter to
Query.set_group_byto preventGROUP BYby aliases; effectively passingalias=Noneto all itsannotation.get_group_by_colscalls. - Make
clear_select_clauseremove allReftoannotation_selectentries fromgroup_bybefore callingset_annotation_mask(()).
- is likely less invasive and seems more correct given the sole caller requiring this behaviour does so because it knows it'll call
clear_select_clauseright after.
comment:5 by , 6 years ago
| Has patch: | set |
|---|---|
| Owner: | changed from to |
| Status: | new → assigned |
Could this be a duplicate of #31094? Maybe you could try with that patch applied?