Skip to content

Comments

fix: wrap windowed aggregates (swev-id: django__django-17084)#541

Open
casey-brooks wants to merge 1 commit intodjango__django-17084from
noa/issue-537
Open

fix: wrap windowed aggregates (swev-id: django__django-17084)#541
casey-brooks wants to merge 1 commit intodjango__django-17084from
noa/issue-537

Conversation

@casey-brooks
Copy link

@casey-brooks casey-brooks commented Dec 24, 2025

Summary

  • detect when aggregates reference window annotations and force subquery wrapping
  • add regression coverage ensuring the ORM emits a wrapped query for window aggregates
  • confirm aggregation over window annotations now succeeds on backends with OVER support

Observed failure

psycopg2.errors.GroupingError: aggregate function calls cannot contain window function calls

Stack trace

psycopg2.errors.GroupingError: aggregate function calls cannot contain window function calls
  File "django/db/backends/utils.py", line XXX, in _execute
    return self.cursor.execute(sql, params)
  File "django/db/models/sql/compiler.py", line XXX, in execute_sql
    cursor.execute(sql, params)
  File "django/db/models/query.py", line XXX, in aggregate
    return query.chain().get_aggregation(self.db, kwargs)
  ...

Reproduction steps

  1. Annotate a queryset with a window expression, e.g. Window(Sum("value"), order_by=F("date").asc()).
  2. Aggregate over both the original value and the window annotation.
  3. Run the query on PostgreSQL.
  4. Observe Django emits SUM(Window(...)) in a single SELECT and PostgreSQL raises psycopg2.errors.GroupingError.

Fix

  • track whether aggregates reference annotations whose expressions contain an OVER clause during resolution
  • include this flag when deciding whether to wrap the base query in an aggregate subquery
  • add a regression test confirming the ORM generates a subquery and the aggregate succeeds

Testing

  • PYTHONPATH=$PWD:$PWD/tests:$HOME/.nix-profile/lib/python3.11/site-packages DJANGO_SETTINGS_MODULE=tests.test_sqlite $HOME/.nix-profile/bin/python3.11 tests/runtests.py aggregation --parallel=1
  • $HOME/.nix-profile/bin/python3.11 -m flake8 django/db/models/sql/query.py tests/aggregation/tests.py

Fixes #537

@casey-brooks casey-brooks requested a review from a team December 24, 2025 18:19
@casey-brooks
Copy link
Author

Tests & Lint Summary:

  • PYTHONPATH=/workspace/django:/workspace/django/tests:/root/.nix-profile/lib/python3.11/site-packages DJANGO_SETTINGS_MODULE=tests.test_sqlite /root/.nix-profile/bin/python3.11 tests/runtests.py aggregation --parallel=1 → 125 passed, 0 failed, 0 skipped
  • /root/.nix-profile/bin/python3.11 -m flake8 django/db/models/sql/query.py tests/aggregation/tests.py → no lint issues

Copy link

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Verified subquery wrapping for aggregates on window annotations and the new test covers the regression.

@rowan-stein
Copy link
Collaborator

Validated locally:

  • Checked out branch noa/issue-537.
  • Ran tests for aggregation module (tests/aggregation/tests.py) using a Python 3.12 venv.
  • All 108 aggregation tests passed.
  • The new test AggregateTestCase.test_aggregate_over_window_annotation passes and confirms subquery wrapping when aggregating over window annotations.
    No further changes required.

@rowan-stein rowan-stein changed the base branch from django__django-17084 to main January 11, 2026 19:34
@rowan-stein rowan-stein changed the base branch from main to django__django-17084 January 12, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression: aggregate over Window() raises GroupingError in 4.2 — wrap via subquery (swev-id: django__django-17084)

3 participants