From 26c067cc3899ac77ea4bc3ba2250b71d4a5cb864 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 8 Jun 2026 15:10:55 +0200 Subject: [PATCH] refactor: extract preprocessFilterString from task filter parsing --- pkg/models/task_collection_filter.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pkg/models/task_collection_filter.go b/pkg/models/task_collection_filter.go index 7d2970277..6828b0e07 100644 --- a/pkg/models/task_collection_filter.go +++ b/pkg/models/task_collection_filter.go @@ -170,20 +170,16 @@ func parseFilterFromExpression(f fexpr.ExprGroup, loc *time.Location) (filter *t return filter, nil } -func getTaskFiltersFromFilterString(filter string, filterTimezone string) (filters []*taskFilter, err error) { - - if filter == "" { - return - } - +// preprocessFilterString rewrites the human filter syntax (in / not in / like) +// into fexpr sigils and quotes bare values so fexpr.Parse accepts them. Shared +// by every entity that filters with the task grammar. +func preprocessFilterString(filter string) string { filter = strings.ReplaceAll(filter, " not in ", " "+string(fexpr.SignAnyNeq)+" ") filter = strings.ReplaceAll(filter, " in ", " ?= ") filter = strings.ReplaceAll(filter, " like ", " ~ ") - // Regex pattern to match filter expressions re := regexp.MustCompile(`(\w+)\s*(>=|<=|!=|~|\?=|\?!=|=|>|<)\s*([^&|()]+)`) - - filter = re.ReplaceAllStringFunc(filter, func(match string) string { + return re.ReplaceAllStringFunc(filter, func(match string) string { parts := re.FindStringSubmatch(match) if len(parts) != 4 { return match @@ -193,16 +189,24 @@ func getTaskFiltersFromFilterString(filter string, filterTimezone string) (filte comparator := parts[2] value := strings.TrimSpace(parts[3]) - // Check if the value is already quoted + // Already quoted — leave as-is if (strings.HasPrefix(value, "'") && strings.HasSuffix(value, "'")) || (strings.HasPrefix(value, "\"") && strings.HasSuffix(value, "\"")) { return field + " " + comparator + " " + value } - // Quote the value quotedValue := "'" + strings.ReplaceAll(value, "'", "\\'") + "'" return field + " " + comparator + " " + quotedValue }) +} + +func getTaskFiltersFromFilterString(filter string, filterTimezone string) (filters []*taskFilter, err error) { + + if filter == "" { + return + } + + filter = preprocessFilterString(filter) parsedFilter, err := fexpr.Parse(filter) if err != nil {