Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30494 closed Bug (fixed)

Problem with ExtractYear()+1 in queries

Reported by: Alexey Chernov Owned by: Simon Charette
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

It looks like django doesn't create a correct MySQL query when having a simple arithmetics with ExtractYear().

I have a model with two data fields:

class Event(models.Model):
	start_date = models.DateField()
	finish_date = models.DateField()

If I want to find all rows such that the years of start_date and finish_date are equal, I can do it so:

from django.db.models import F
from django.db.models.functions import ExtractYear
>>> print Event.objects.annotate(year=ExtractYear(F('start_date'))).filter(finish_date__year=F('year')).only('pk').query
SELECT `event`.`id`, EXTRACT(YEAR FROM `event`.`start_date`) AS `year` FROM `event` WHERE EXTRACT(YEAR FROM `event`.`finish_date`) = (EXTRACT(YEAR FROM `event`.`start_date`))

But if I want to find events that start and finish in consequent years, I try the following filter, and it gives me an incorrect MySQL query:

>>> print Event.objects.annotate(year=ExtractYear(F('start_date'))).filter(finish_date__year=F('year')+1).only('pk').query
SELECT `event`.`id`, EXTRACT(YEAR FROM `event`.`start_date`) AS `year` FROM `event` WHERE `event`.`finish_date` BETWEEN 0001-01-01 AND 0001-12-31

I tried to replace F('year')+1 with F('year')+Value(1) but it didn't help.
Am I wrong somewhere, or does it look like a bug?

Change History (5)

comment:1 by Alexey Chernov, 5 years ago

Version: 2.21.11

comment:2 by Simon Charette, 5 years ago

Owner: changed from nobody to Simon Charette
Status: newassigned
Triage Stage: UnreviewedAccepted
Version: 1.11master

comment:3 by Simon Charette, 5 years ago

Has patch: set
Last edited 5 years ago by Mariusz Felisiak (previous) (diff)

comment:4 by Mariusz Felisiak <felisiak.mariusz@…>, 5 years ago

Resolution: fixed
Status: assignedclosed

In 4d142094:

Fixed #30494 -- Disabled year lookup optimization for indirect values.

The previous heuristics were naively enabling the BETWEEN optimization on
successful cast of the first rhs SQL params to an integer while it was
not appropriate for a lot of database resolved expressions.

Thanks Alexey Chernov for the report.

comment:5 by Mariusz Felisiak <felisiak.mariusz@…>, 5 years ago

In 514104cf:

Refs #29396, #30494 -- Reduced code duplication in year lookups.

Note: See TracTickets for help on using tickets.
Back to Top