#34975: Getting refs is not work properly with models.Window and aggregation
-------------------------------------+-------------------------------------
     Reporter:  Zwergpro             |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  4.2
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  QuerySet, Window,    |             Triage Stage:
  Aggregate, F                       |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Zwergpro:

Old description:

> I found out that getting refs in QuerySet doesn't work with models.Window
> when I try to use aggregate method. It happened when I tried to update
> Django to 4.2.7.
>
> For example:
> {{{
> MyModel.objects.annotate(
>         new_ordering=Window(RowNumber(),  order_by=[F('ordering')])
> ).aggregate(
>         wrong_count=Count('id', filter=Q(ordering=F('new_ordering')))
> )
> }}}
>
> And as a result, it fails with:
> {{{
> Traceback (most recent call last):
>   File "/main.py", line 38, in <module>
>     result = ordering_query.aggregate(
>   File "/python3.10/site-packages/django/db/models/query.py", line 592,
> in aggregate
>     return self.query.chain().get_aggregation(self.db, kwargs)
>   File "/python3.10/site-packages/django/db/models/sql/query.py", line
> 398, in get_aggregation
>     aggregate = aggregate_expr.resolve_expression(
>   File "/python3.10/site-packages/django/db/models/aggregates.py", line
> 70, in resolve_expression
>     for ref in c.get_refs():
>   File "/python3.10/site-packages/django/db/models/expressions.py", line
> 418, in get_refs
>     refs |= expr.get_refs()
>   File "/python3.10/site-packages/django/db/models/sql/where.py", line
> 233, in get_refs
>     refs |= child.get_refs()
>   File "/python3.10/site-packages/django/db/models/expressions.py", line
> 418, in get_refs
>     refs |= expr.get_refs()
>   File "/python3.10/site-packages/django/db/models/expressions.py", line
> 418, in get_refs
>     refs |= expr.get_refs()
> AttributeError: 'NoneType' object has no attribute 'get_refs'
> }}}
>
> It happens because of Window.get_source_expressions return:
> {{{
> def get_source_expressions(self):
>         return [self.source_expression, self.partition_by, self.order_by,
> self.frame]
> }}}
> and if we don't specify 'frame' (for example) it will be None in the
> list.
>
> And in models.aggregates.Aggregate.resolve_expression when we try to find
> all refs
> https://github.com/django/django/blob/47f9b8dca16b1fdc054b338d81eb080eabad0edf/django/db/models/aggregates.py#L70C30-L70C30
> it fails because of we have None in Window.get_source_expressions
> {{{
> def get_refs(self):
>         refs = set()
>         for expr in self.get_source_expressions():
>                 refs |= expr.get_refs()
>         return refs
> }}}

New description:

 I found out that getting refs in QuerySet doesn't work with models.Window
 when I try to use aggregate method. It happened when I tried to update
 Django to 4.2.7.

 For example:
 {{{
 MyModel.objects.annotate(
         new_ordering=Window(RowNumber(),  order_by=[F('ordering')])
 ).aggregate(
         new_count=Count('id', filter=Q(ordering=F('new_ordering')))
 )
 }}}

 And as a result, it fails with:
 {{{
 Traceback (most recent call last):
   File "/main.py", line 38, in <module>
     result = ordering_query.aggregate(
   File "/python3.10/site-packages/django/db/models/query.py", line 592, in
 aggregate
     return self.query.chain().get_aggregation(self.db, kwargs)
   File "/python3.10/site-packages/django/db/models/sql/query.py", line
 398, in get_aggregation
     aggregate = aggregate_expr.resolve_expression(
   File "/python3.10/site-packages/django/db/models/aggregates.py", line
 70, in resolve_expression
     for ref in c.get_refs():
   File "/python3.10/site-packages/django/db/models/expressions.py", line
 418, in get_refs
     refs |= expr.get_refs()
   File "/python3.10/site-packages/django/db/models/sql/where.py", line
 233, in get_refs
     refs |= child.get_refs()
   File "/python3.10/site-packages/django/db/models/expressions.py", line
 418, in get_refs
     refs |= expr.get_refs()
   File "/python3.10/site-packages/django/db/models/expressions.py", line
 418, in get_refs
     refs |= expr.get_refs()
 AttributeError: 'NoneType' object has no attribute 'get_refs'
 }}}

 It happens because of Window.get_source_expressions return:
 {{{
 def get_source_expressions(self):
         return [self.source_expression, self.partition_by, self.order_by,
 self.frame]
 }}}
 and if we don't specify 'frame' (for example) it will be None in the list.

 And in models.aggregates.Aggregate.resolve_expression when we try to find
 all refs
 
https://github.com/django/django/blob/47f9b8dca16b1fdc054b338d81eb080eabad0edf/django/db/models/aggregates.py#L70C30-L70C30
 it fails because of we have None in Window.get_source_expressions
 {{{
 def get_refs(self):
         refs = set()
         for expr in self.get_source_expressions():
                 refs |= expr.get_refs()
         return refs
 }}}

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34975#comment:1>
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/0107018bdde666fc-19dda3af-7108-499d-b23b-9e71ecce6c01-000000%40eu-central-1.amazonses.com.

Reply via email to