fix(filters): increase year value when using mysql and year < 1

Mysql cannot handle year values < 1. That means filtering for a date value like 0000-01-01 won't work with mysql. Additionally, dates like 0001-01-01 could under some circumstances not work either when the date in combination with the time zone would resolve to something like 0000-12-31 - for example when the server is located (and configured) in UTC, but the user running the query is in New York. This could be observed by setting the time zone manually using the filter_timezone query parameter.

Resolves https://vikunja.sentry.io/share/issue/42bce92c15354c109eb1e6488b6a542b/
Resolves https://vikunja.sentry.io/share/issue/ef81451b0c7b43f1bff2d3a86ba393bb/
This commit is contained in:
kolaente 2024-09-30 08:41:24 +02:00
parent d22bc79d3c
commit 754d56ca82
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
2 changed files with 11 additions and 8 deletions

View File

@ -25,10 +25,12 @@ import (
"time"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
"github.com/ganigeorgiev/fexpr"
"github.com/iancoleman/strcase"
"github.com/jszwedko/go-datemath"
"xorm.io/builder"
"xorm.io/xorm/schemas"
)
@ -270,21 +272,22 @@ func getValueForField(field reflect.StructField, rawValue string, loc *time.Loca
case reflect.Struct:
if field.Type == schemas.TimeType {
var t datemath.Expression
var tt time.Time
t, err = datemath.Parse(rawValue)
if err == nil {
value = t.Time(datemath.WithLocation(config.GetTimeZone())).In(loc)
tt = t.Time(datemath.WithLocation(config.GetTimeZone())).In(loc)
} else {
value, err = parseTimeFromUserInput(rawValue)
tt, err = parseTimeFromUserInput(rawValue)
}
if err != nil {
return
}
// Mariadb does not support date values where the year is 0. To make this edge-case work,
// Mysql/Mariadb does not support date values where the year < 1. To make this edge-case work,
// we're setting the year to 1 in that case.
tt := value.(time.Time)
if tt.Year() == 0 {
value = tt.AddDate(1, 0, 0)
if db.GetDialect() == builder.MYSQL && tt.Year() < 1 {
tt = tt.AddDate(1-tt.Year(), 0, 0)
}
value = tt
}
case reflect.Slice:
// If this is a slice of pointers we're dealing with some property which is a relation

View File

@ -302,7 +302,7 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo
Find(&tasks)
if err != nil {
sql, vals := query.LastSQL()
return nil, 0, fmt.Errorf("could not fetch task count, error was '%w', sql: '%v', vaues: %v", err, sql, vals)
return nil, 0, fmt.Errorf("could not fetch tasks, error was '%w', sql: '%v', values: %v", err, sql, vals)
}
// fetch subtasks when expanding
@ -367,7 +367,7 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo
Count(&Task{})
if err != nil {
sql, vals := queryCount.LastSQL()
return nil, 0, fmt.Errorf("could not fetch task count, error was '%w', sql: '%v', vaues: %v", err, sql, vals)
return nil, 0, fmt.Errorf("could not fetch task count, error was '%w', sql: '%v', values: %v", err, sql, vals)
}
return
}