#33073: AttributeError when annotating with Exists(none()) and aggregation
-------------------------------------+-------------------------------------
               Reporter:  Matthijs   |          Owner:  nobody
  Kooijman                           |
                   Type:             |         Status:  new
  Uncategorized                      |
              Component:  Database   |        Version:  dev
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I ran into a problem with annotating a field with an Exists subquery,
 passing {{{MyModel.objects.none()}}} to Exists. On Django main branch,
 this throws an AttributeError, on 2.2.24 this returns an empty queryset
 (and printing the query attribute of the queryset raises EmptyResultSet).

 Strangely enough this only seems to occur when I add a second annotation
 using an aggregation (I tried Sum, Max and Count). Adding a second
 aggregation using a plain field (e.g. {{{F('id')}}}) does not seem to
 trigger the problem. Each of the annotations individually also work, but
 not together.

 It seems this already fails on the most basic (empty) model definition, no
 options or specific fields required.

 I have not really investigated the details, I'm not too familiar with the
 query generating code.

 Below is a testcase (ready to be included as a regression test).

 {{{
 --- a/tests/model_regress/tests.py
 +++ b/tests/model_regress/tests.py
 @@ -236,6 +236,18 @@ class Horse(models.Model, metaclass=HorseBase):

          self.assertEqual(Horse.horns, 1)

 +    def test_exists_none_with_aggregate(self):
 +        Party.objects.create()
 +        qs = Party.objects.all().annotate(
 +            foo=models.Count('id'),
 +            bar=models.Exists(Party.objects.none()),
 +        )
 +        # Throws EmptyResultSet on 2.2.24, or AttributeError:
 'NothingNode' object has no attribute
 +        # 'get_source_expressions' on 3.2.6
 +        qs.query
 +        # Returns empty result on 2.2.24 or throws on 3.2.6
 +        self.assertEqual(len(qs), 1)
 +

 ./runtests.py
 model_regress.tests.ModelTests.test_exists_none_with_aggregate
 (... snip some stuff ...)
 Traceback (most recent call last):
   File "django/tests/model_regress/tests.py", line 249, in
 test_exists_empty_with_aggregate
     self.assertEqual(len(qs), 1)
   File "django/db/models/query.py", line 262, in __len__
     self._fetch_all()
   File "django/db/models/query.py", line 1352, in _fetch_all
     self._result_cache = list(self._iterable_class(self))
   File "django/db/models/query.py", line 51, in __iter__
     results = compiler.execute_sql(chunked_fetch=self.chunked_fetch,
 chunk_size=self.chunk_size)
   File "django/db/models/sql/compiler.py", line 1185, in execute_sql
     sql, params = self.as_sql()
   File "django/db/models/sql/compiler.py", line 527, in as_sql
     extra_select, order_by, group_by = self.pre_sql_setup()
   File "django/db/models/sql/compiler.py", line 64, in pre_sql_setup
     group_by = self.get_group_by(self.select + extra_select, order_by)
   File "django/db/models/sql/compiler.py", line 129, in get_group_by
     cols = expr.get_group_by_cols()
   File "django/db/models/expressions.py", line 1159, in get_group_by_cols
     external_cols = self.get_external_cols()
   File "django/db/models/expressions.py", line 1143, in get_external_cols
     return self.query.get_external_cols()
   File "django/db/models/sql/query.py", line 1057, in get_external_cols
     return [
   File "django/db/models/sql/query.py", line 1057, in <listcomp>
     return [
   File "django/db/models/sql/query.py", line 1697, in _gen_cols
     expr.get_source_expressions(),
 AttributeError: 'NothingNode' object has no attribute
 'get_source_expressions'
 }}}

 (Can be pulled from https://github.com/matthijskooijman/django/blob
 /testcase-exists-none/tests/model_regress/tests.py#L239)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33073>
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 django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/059.59f71e0eba515ba081bdb635119ec4b5%40djangoproject.com.

Reply via email to