Opened 7 hours ago
Last modified 7 hours ago
#36860 new Bug
Annotate after Union using django-cte breaks with django 5.2
| Reported by: | benjfield | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 5.2 |
| Severity: | Normal | Keywords: | union |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
I'm not sure whether the fault here lies with django-cte or django, but django 5.2 has broken a feature in django-cte.
I was using a cte to create a union and then use annotation to aggregate a value. An example is here:
from django.db.models import F, Sum
from django_cte import CTE, with_cte
class UnderlyingDemo(models.Model):
pass
class Demo(models.Model):
name = models.CharField()
underlying = models.ForeignKey(
UnderlyingDemo,
on_delete=models.CASCADE,
)
positive = models.BooleanField()
number = models.IntegerField()
def __str__(self):
return self.name
#Doesn't work natively in django - cannot run annotate after union
def query_no_cte():
return Demo.objects.filter(
positive=True,
).values(
"underlying_id",
signed_number=F("number")
).union(
Demo.objects.filter(
positive=False,
).values(
"underlying_id",
signed_number=F("number") * -1
),
all=True,
).values(
"underlying_id"
).annotate(
summed_total_number=Sum("signed_number")
)
#Breaks between django 5.1 and django 5.2
def query_with_cte():
demo_cte = CTE(
Demo.objects.all().filter(
positive=True,
).values(
"underlying_id",
signed_number=F("number")
).union(
Demo.objects.all().filter(
positive=False,
).values(
"underlying_id",
signed_number=F("number") * -1
),
all=True,
),
name="union"
)
return with_cte(
demo_cte,
select=demo_cte.queryset(),
).values(
"underlying_id"
).annotate(
summed_total_number=Sum("signed_number")
)
This previously worked but now returns "django.core.exceptions.FieldError: Cannot select the 'underlying_id' alias. Use annotate() to promote it.". The problem seems to continue with 6.0
I should note that while I appreciate this may well be "Won't Fix" if the problem lies with django-cte, it would be very helpful to know what the error means - the documentation does not seem to use "promote" in concert with "annotate()" at any point I could find.
Change History (2)
comment:2 by , 7 hours ago
If it helps, I can quickly answer the question about "promote" -- it means somewhere (maybe in django-cte?) an .alias() call should be replaced with .annotate(). Agree that the error wording is not so helpful. When doing more fulsome triage later today I'll look into whether this is expected.
I should note that while I appreciate this may well be "Won't Fix", it would be very helpful to know what the error means - the documentation does not seem to use "promote" in concert with "annotate()" at any point I could find.