From 90817b6dae088ad9b60d9d7047cda281d720cc33 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sat, 19 Dec 2020 13:56:55 +0100 Subject: [PATCH] Add "like" filter comparator --- pkg/models/error.go | 4 ++-- pkg/models/task_collection.go | 2 +- pkg/models/task_collection_filter.go | 6 +++++- pkg/models/task_collection_test.go | 21 +++++++++++++++++++++ pkg/models/tasks.go | 11 +++++++++++ pkg/swagger/docs.go | 2 +- pkg/swagger/swagger.json | 2 +- pkg/swagger/swagger.yaml | 2 +- 8 files changed, 43 insertions(+), 7 deletions(-) diff --git a/pkg/models/error.go b/pkg/models/error.go index 7e9ac9f96f9..a2081488e69 100644 --- a/pkg/models/error.go +++ b/pkg/models/error.go @@ -737,7 +737,7 @@ func (err ErrInvalidTaskFilterConcatinator) HTTPError() web.HTTPError { // ErrInvalidTaskFilterValue represents an error where the provided task filter value is invalid type ErrInvalidTaskFilterValue struct { - Value string + Value interface{} Field string } @@ -748,7 +748,7 @@ func IsErrInvalidTaskFilterValue(err error) bool { } func (err ErrInvalidTaskFilterValue) Error() string { - return fmt.Sprintf("Task filter value is invalid [Value: %s, Field: %s]", err.Value, err.Field) + return fmt.Sprintf("Task filter value is invalid [Value: %v, Field: %s]", err.Value, err.Field) } // ErrCodeInvalidTaskFilterValue holds the unique world-error code of this error diff --git a/pkg/models/task_collection.go b/pkg/models/task_collection.go index e1b7652343c..46d4408690b 100644 --- a/pkg/models/task_collection.go +++ b/pkg/models/task_collection.go @@ -93,7 +93,7 @@ func validateTaskField(fieldName string) error { // @Param order_by query string false "The ordering parameter. Possible values to order by are `asc` or `desc`. Default is `asc`." // @Param filter_by query string false "The name of the field to filter by. Accepts an array for multiple filters which will be chanied together, all supplied filter must match." // @Param filter_value query string false "The value to filter for." -// @Param filter_comparator query string false "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less` and `less_equals`. Defaults to `equals`" +// @Param filter_comparator query string false "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals` and `like`. Defaults to `equals`" // @Param filter_concat query string false "The concatinator to use for filters. Available values are `and` or `or`. Defaults to `or`." // @Param filter_include_nulls query string false "If set to true the result will include filtered fields whose value is set to `null`. Available values are `true` or `false`. Defaults to `false`." // @Security JWTKeyAuth diff --git a/pkg/models/task_collection_filter.go b/pkg/models/task_collection_filter.go index 1284e806922..5cb738f288c 100644 --- a/pkg/models/task_collection_filter.go +++ b/pkg/models/task_collection_filter.go @@ -39,6 +39,7 @@ const ( taskFilterComparatorLess taskFilterComparator = "<" taskFilterComparatorLessEquals taskFilterComparator = "<=" taskFilterComparatorNotEquals taskFilterComparator = "!=" + taskFilterComparatorLike taskFilterComparator = "like" ) type taskFilter struct { @@ -111,7 +112,8 @@ func validateTaskFieldComparator(comparator taskFilterComparator) error { taskFilterComparatorGreateEquals, taskFilterComparatorLess, taskFilterComparatorLessEquals, - taskFilterComparatorNotEquals: + taskFilterComparatorNotEquals, + taskFilterComparatorLike: return nil case taskFilterComparatorInvalid: fallthrough @@ -134,6 +136,8 @@ func getFilterComparatorFromString(comparator string) (taskFilterComparator, err return taskFilterComparatorLessEquals, nil case "not_equals": return taskFilterComparatorNotEquals, nil + case "like": + return taskFilterComparatorLike, nil default: return taskFilterComparatorInvalid, ErrInvalidTaskFilterComparator{Comparator: taskFilterComparator(comparator)} } diff --git a/pkg/models/task_collection_test.go b/pkg/models/task_collection_test.go index 6a06b6fe4e2..071640d7820 100644 --- a/pkg/models/task_collection_test.go +++ b/pkg/models/task_collection_test.go @@ -858,6 +858,27 @@ func TestTaskCollection_ReadAll(t *testing.T) { // Task 34 is also a favorite, but on a list user 1 has no access to. }, }, + { + name: "filtered with like", + fields: fields{ + FilterBy: []string{"title"}, + FilterValue: []string{"with"}, + FilterComparator: []string{"like"}, + }, + args: defaultArgs, + want: []*Task{ + task7, + task8, + task9, + task27, + task28, + task29, + task30, + task31, + task33, + }, + wantErr: false, + }, } for _, tt := range tests { diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 97959ecbd08..fb3bdfd5ef8 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -247,6 +247,17 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] } else { filters = append(filters, &builder.Lte{f.field: f.value}) } + case taskFilterComparatorLike: + val, is := f.value.(string) + if !is { + return nil, 0, 0, ErrInvalidTaskFilterValue{Field: f.field, Value: f.value} + } + c := &builder.Like{f.field, "%" + val + "%"} + if opts.filterIncludeNulls { + filters = append(filters, builder.Or(c, &builder.IsNull{f.field})) + } else { + filters = append(filters, c) + } case taskFilterComparatorInvalid: // Nothing to do } diff --git a/pkg/swagger/docs.go b/pkg/swagger/docs.go index 548fad20db3..0c5c0ddd1ff 100644 --- a/pkg/swagger/docs.go +++ b/pkg/swagger/docs.go @@ -1904,7 +1904,7 @@ var doc = `{ }, { "type": "string", - "description": "The comparator to use for a filter. Available values are ` + "`" + `equals` + "`" + `, ` + "`" + `greater` + "`" + `, ` + "`" + `greater_equals` + "`" + `, ` + "`" + `less` + "`" + ` and ` + "`" + `less_equals` + "`" + `. Defaults to ` + "`" + `equals` + "`" + `", + "description": "The comparator to use for a filter. Available values are ` + "`" + `equals` + "`" + `, ` + "`" + `greater` + "`" + `, ` + "`" + `greater_equals` + "`" + `, ` + "`" + `less` + "`" + `, ` + "`" + `less_equals` + "`" + ` and ` + "`" + `like` + "`" + `. Defaults to ` + "`" + `equals` + "`" + `", "name": "filter_comparator", "in": "query" }, diff --git a/pkg/swagger/swagger.json b/pkg/swagger/swagger.json index d78f6b27c49..45a6af5836b 100644 --- a/pkg/swagger/swagger.json +++ b/pkg/swagger/swagger.json @@ -1887,7 +1887,7 @@ }, { "type": "string", - "description": "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less` and `less_equals`. Defaults to `equals`", + "description": "The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals` and `like`. Defaults to `equals`", "name": "filter_comparator", "in": "query" }, diff --git a/pkg/swagger/swagger.yaml b/pkg/swagger/swagger.yaml index 0ab9ba81cf3..a206f963dc5 100644 --- a/pkg/swagger/swagger.yaml +++ b/pkg/swagger/swagger.yaml @@ -2451,7 +2451,7 @@ paths: in: query name: filter_value type: string - - description: The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less` and `less_equals`. Defaults to `equals` + - description: The comparator to use for a filter. Available values are `equals`, `greater`, `greater_equals`, `less`, `less_equals` and `like`. Defaults to `equals` in: query name: filter_comparator type: string