#33282: django.db.utils.ProgrammingError: more than one row returned by a
subquery
used as an expression
-------------------------------------+-------------------------------------
Reporter: Antonio Terceiro | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: 3.2
(models, ORM) |
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Antonio Terceiro):
Hi, I spent some time debugging this today. This seems to be caused by
`get_group_by_cols()` returning an incorrect value for a `Query` object.
In a pdb session against the main branch of the git repository, I get
this:
{{{
$ pdb3 ./manage.py runscript test
> /home/terceiro/src/linaro/lava/manage.py(22)<module>()
-> import argparse
(Pdb) break /home/terceiro/src/django/django/db/models/lookups.py:434
Breakpoint 1 at /home/terceiro/src/django/django/db/models/lookups.py:434
(Pdb) c
>
/home/terceiro/src/django/django/db/models/lookups.py(434)get_group_by_cols()
-> cols.extend(self.rhs.get_group_by_cols())
(Pdb) p self.rhs
<django.db.models.sql.query.Query object at 0x7f6ddb7bd580>
(Pdb) p self.rhs.get_group_by_cols()
[<django.db.models.sql.query.Query object at 0x7f6ddb7bd580>]
}}}
In commit 35431298226165986ad07e91f9d3aca721ff38ec, which caused this,
{{{django.db.models.sql.query.Query}}} is made a subclass of
{{{django.db.models.expressions.BaseExpression}}}.
BaseExpression.get_group_by_calls is implemented like this:
{{{
def get_group_by_cols(self, alias=None):
if not self.contains_aggregate:
return [self]
cols = []
for source in self.get_source_expressions():
cols.extend(source.get_group_by_cols())
return cols
}}}
Since BaseExpression also hardcodes {{{contains_aggregate}}} to False,
that first if statement always applies. Providing an appropriate
implementation of contains_aggregate to Query fixes things for me here:
{{{
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 2c5f11cbbf..f7c43ff622 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -414,6 +414,11 @@ class Query(BaseExpression):
annotation.set_source_expressions(new_exprs)
return annotation, col_cnt
+ @cached_property
+ def contains_aggregate(self):
+ annotations = self.annotations.values()
+ return any(getattr(ann, 'contains_aggregate', True) for ann in
annotations)
+
def get_aggregation(self, using, added_aggregate_names):
"""
Return the dictionary with the values of the existing
aggregations.
}}}
I wasn't able to write an unit tests for this so far, though.
--
Ticket URL: <https://code.djangoproject.com/ticket/33282#comment:4>
Django <https://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 unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/066.654d0f66c5e1dfd4383575f65de66776%40djangoproject.com.