Opened 4 months ago

Closed 4 months ago

Last modified 4 months ago

#35613 closed Bug (duplicate)

SQL params mismatch when using ArrayAgg with timezone override

Reported by: Claudia Onorato Owned by:
Component: contrib.postgres Version: 5.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hi! When updating from Django 4.0 to Django 5.0., I encountered an issue related to the use of django.contrib.postgres.aggregates's ArrayAgg. I also checked and this issue also happens on Django 4.1 and 4.2.

Given the following models:

from django.db import models


class Publisher(models.Model):
    name = models.CharField(max_length=300)


class Book(models.Model):
    name = models.CharField(max_length=300)
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
    published_on = models.DateTimeField(null=True)

If I run the following in a shell

import zoneinfo
from django.utils import timezone
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Q
from library.models import Publisher

with timezone.override(zoneinfo.ZoneInfo('America/Toronto')):
    Publisher.objects.annotate(books_date=ArrayAgg(
        'book__published_on__date',
        filter=Q(id=100),
        ordering=('book__published_on__date',),
    )).all()

I get an error saying there's an invalid input syntax. Looking at the generated SQL, I see there's indeed an error, where the argument for the filter was instead use to localize the field in the order by, and vice-versa.

SELECT
    "library_publisher"."id",
    "library_publisher"."name",
    ARRAY_AGG(
        (
            "library_book"."published_on" AT TIME ZONE 'America/Toronto'
        ) :: date
        ORDER BY
            ("library_book"."published_on" AT TIME ZONE 100) :: date
    ) FILTER (
        WHERE
            "library_publisher"."id" = 'America/Toronto'
    ) AS "books_date"
FROM
    "library_publisher"
    LEFT OUTER JOIN "library_book" ON (
        "library_publisher"."id" = "library_book"."publisher_id"
    )
GROUP BY
    "library_publisher"."id";

Let me know if you need any more information. I created a small django project for this that I can share.

Change History (2)

comment:1 by Simon Charette, 4 months ago

Hey Claudia, thank you for your report I'm pretty sure this is a duplicate of #35339 which was fixed by c8df2f994130d74ec35d32a36e30aad7d6ea8e3a which will be part of the upcoming 5.1 release (expected August 2024). It wasn't backported as when it was discovered, 4 months ago, the issue had existed since the introduction of ArrayAgg as you've noticed.

I've confirmed with the following test

  • tests/postgres_tests/test_aggregates.py

    diff --git a/tests/postgres_tests/test_aggregates.py b/tests/postgres_tests/test_aggregates.py
    index bb694dae63..3bf7c2cafe 100644
    a b def test_string_agg_filter_in_subquery_with_exclude(self):  
    704704            [self.aggs[0]],
    705705        )
    706706
     707    def test_foo_bar(self):
     708        import zoneinfo
     709        from django.utils import timezone
     710        from django.contrib.postgres.aggregates import ArrayAgg
     711        from django.db.models import Q
     712
     713        with (
     714            self.settings(USE_TZ=True),
     715            timezone.override(zoneinfo.ZoneInfo("America/Toronto")),
     716        ):
     717            list(
     718                Room.objects.annotate(
     719                    books_date=ArrayAgg(
     720                        "hotelreservation__start__date",
     721                        filter=Q(id=100),
     722                        ordering=("hotelreservation__start__date",),
     723                    )
     724                )
     725            )
     726
    707727    def test_ordering_isnt_cleared_for_array_subquery(self):
    708728        inner_qs = AggregateTestModel.objects.order_by("-integer_field")
    709729        qs = AggregateTestModel.objects.annotate(

Please re-open if you can reproduce against Django==5.1b1.

Last edited 4 months ago by Simon Charette (previous) (diff)

comment:2 by Simon Charette, 4 months ago

Resolution: duplicate
Status: newclosed
Note: See TracTickets for help on using tickets.
Back to Top