In Django I'm creating a queryset with CASE and annotation. It looks like this:
days_diff_calc = Case(
When(Q(sent_date__isnull=True),
then=None),
When(Q(received_date__isnull=True),
then=(timezone.now().date() - F('sent_date'))),
default=(F('received_date') - F('sent_date')),
output_field=DurationField()
)
Item.objects.all().annotate(
days_diff=days_diff_calc
)
The important part of the query it creates looks something like this:
CASE
WHEN "item"."sent_date" IS NULL THEN NULL
WHEN "item"."received_date" IS NULL THEN ('2019-11-26' - "item"."sent_date")
ELSE (interval '1 day'* ("item"."received_date" - "item"."sent_date"))
END AS "days_diff"
When running it in Postgres I get this error:
CASE types interval and integer cannot be matched
LINE 3: ...item"."received_date" IS NULL THEN ('2019-11-2...
^
It seems like for some reason, Django ORM adds the interval 1 day *
after the ELSE, but doesn't do it after the second WHEN and I think that's the reason for this error. I don't understand - why does it add it only to one place and not to the other, and if I would want to add it to the other place (second WHEN) - I would I do it?
EDIT:
django version 2.1.5, psycopg2 version 2.6.2, Postgresql 9.6
all the 'date' fields are of type models.DateField(null=True, blank=True)
Tried also using ExpressionWrapper and got the same result:
days_diff_calc = Case(
When(Q(sent_date__isnull=True),
then=None),
When(Q(received_date__isnull=True),
then=ExpressionWrapper(timezone.now().date() - F('sent_date'),
output_field=DurationField())),
default=ExpressionWrapper(F('received_date') - F('sent_date'),
output_field=DurationField()),
)