#34285 closed Bug (fixed)
Index transforms on filtered array aggregates produces incorrect SQL query
| Reported by: | Nils Van Zuijlen | Owned by: | Nils Van Zuijlen |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 3.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
For example, with the following models:
class MembershipKind(models.TextChoices):
MEMBER = "member", _("Member")
DIRECTOR = "director", _("Director")
MANAGER = "manager", _("Manager")
class Project(models.Model):
name = models.CharField(max_length=255)
members = models.ManyToManyField(User, related_name="projects", blank=True, through="ProjectMember")
class ProjectMember(models.Model):
project = models.ForeignKey(
Project, related_name="memberships", on_delete=models.CASCADE, verbose_name=_("project")
)
user = models.ForeignKey(User, related_name="project_memberships", on_delete=models.CASCADE, verbose_name=_("user"))
kind = models.CharField(choices=MembershipKind.choices, max_length=10)
class Meta:
constraints = [models.UniqueConstraint(fields=("project", "user"), name="project_user_unique_link")]
The following query has missing parenthesis around the annotated field first_director_id.
>>> Project.objects.all().annotate(
... director_ids=ArrayAgg('memberships__user_id', filter=Q(memberships__kind=MembershipKind.DIRECTOR))
... ).annotate(
... first_director_id=F('director_ids__0')
... ).query.sql_with_params()
(
'''SELECT "imputations_project"."id", "imputations_project"."name",
ARRAY_AGG("imputations_projectmember"."user_id" ) FILTER (WHERE "imputations_projectmember"."kind" = %s) AS "director_ids",
ARRAY_AGG("imputations_projectmember"."user_id" ) FILTER (WHERE "imputations_projectmember"."kind" = %s)[%s] AS "first_director_id"
FROM "imputations_project"
LEFT OUTER JOIN "imputations_projectmember" ON ("imputations_project"."id" = "imputations_projectmember"."project_id")
GROUP BY "imputations_project"."id"''',
(<MembershipKind.DIRECTOR: 'director'>, <MembershipKind.DIRECTOR: 'director'>, 1)
)
It should be
(ARRAY_AGG("imputations_projectmember"."user_id" ) FILTER (WHERE "imputations_projectmember"."kind" = %s))[%s] AS "first_director_id"
Change History (8)
comment:1 by , 3 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:2 by , 3 years ago
| Component: | Uncategorized → Database layer (models, ORM) |
|---|
comment:3 by , 3 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
I tried to write unit tests on main, but they failed with another error.
The proposed solution makes another test on integer nested indexation fail, but I don't know how to fix that.
comment:4 by , 3 years ago
| Has patch: | set |
|---|---|
| Patch needs improvement: | set |
Version 0, edited 3 years ago by (next)
comment:6 by , 3 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Note:
See TracTickets
for help on using tickets.
Thanks for the report, it seems the issue lies in
IndexTransform.as_sqlwhere me might want to dodjango/contrib/postgres/fields/array.py
%s[%%s]" % lhs, params + [self.index]It seems that slicing is suffering from the same issue (e.g.
director_ids__0_2)Would you be interested in submitting a PR with this patch that includes a regression test?