From 7260f68bca6bff0a624801694e1b6b0053c0fbd2 Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Wed, 1 Sep 2021 14:22:59 -0400 Subject: [PATCH] 17995: Accept boolean expressions as strings without ["...",=,true]. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- doc/api/methods.html.textile.liquid | 30 ++++++------ lib/controller/router/router_test.go | 43 ++++++++++++++--- sdk/go/arvados/resource_list.go | 45 ++++++++++------- sdk/go/arvados/resource_list_test.go | 72 ++++++++++++---------------- 4 files changed, 110 insertions(+), 80 deletions(-) diff --git a/doc/api/methods.html.textile.liquid b/doc/api/methods.html.textile.liquid index 87ff621b8b..fd52917928 100644 --- a/doc/api/methods.html.textile.liquid +++ b/doc/api/methods.html.textile.liquid @@ -111,20 +111,6 @@ table(table table-bordered table-condensed). |@contains@|string, array of strings|Presence of one or more keys or array elements|@["storage_classes_desired", "contains", ["foo", "bar"]]@ (matches both @["foo", "bar"]@ and @["foo", "bar", "baz"]@) (note @[..., "contains", "foo"]@ is also accepted, and is equivalent to @[..., "contains", ["foo"]]@)| -h4(#filterexpression). Filtering using boolean expressions - -In place of an attribute, the first element of the three-element filter array can be a boolean expression. The following restrictions apply: -* The expression must contain exactly one operator. -* The operator must be @=@, @<@, @<=@, @>@, or @>=@. -* There must be exactly one pair of parentheses, surrounding the entire expression. -* Each operand must be the name of a numeric attribute like @replication_desired@ (literal values like @3@ and non-numeric attributes like @uuid@ are not accepted). -* The expression must not contain whitespace other than an ASCII space (newline and tab characters are not accepted). -* The second and third elements of the filter array must be @"="@ and @true@ respectively. - -Examples: -* @["(replication_desired < replication_confirmed)", "=", true]@ -* @["(replication_desired = replication_confirmed)", "=", true]@ - h4(#substringsearchfilter). Filtering using substring search Resources can also be filtered by searching for a substring in attributes of type @string@, @array of strings@, @text@, and @hash@, which are indexed in the database specifically for search. To use substring search, the filter must: @@ -150,6 +136,22 @@ table(table table-bordered table-condensed). Note that exclusion filters @!=@ and @not in@ will return records for which the property is not defined at all. To restrict filtering to records on which the subproperty is defined, combine with an @exists@ filter. +h4(#filterexpression). Filtering using boolean expressions + +In addition to the three-element array form described above, a string containing a boolean expression is also accepted. The following restrictions apply: +* The expression must contain exactly one operator. +* The operator must be @=@, @<@, @<=@, @>@, or @>=@. +* There must be exactly one pair of parentheses, surrounding the entire expression. +* Each operand must be the name of a numeric attribute like @replication_desired@ (literal values like @3@ and non-numeric attributes like @uuid@ are not accepted). +* The expression must not contain whitespace other than an ASCII space (newline and tab characters are not accepted). + +Examples: +* @(replication_desired > replication_confirmed)@ +* @(replication_desired = replication_confirmed)@ + +Both types of filter (boolean expressions and @[attribute, operator, operand]@ filters) can be combined in the same API call. Example: +* @{"filters": ["(replication_desired > replication_confirmed)", ["replication_desired", "<", 2]]}@ + h4. Federated listing Federated listing forwards a request to multiple clusters and combines the results. Currently only a very restricted form of the "list" method is supported. diff --git a/lib/controller/router/router_test.go b/lib/controller/router/router_test.go index 0330ec4252..639d2a28b4 100644 --- a/lib/controller/router/router_test.go +++ b/lib/controller/router/router_test.go @@ -47,6 +47,7 @@ func (s *RouterSuite) SetUpTest(c *check.C) { func (s *RouterSuite) TestOptions(c *check.C) { token := arvadostest.ActiveToken for _, trial := range []struct { + comment string // unparsed -- only used to help match test failures to trials method string path string header http.Header @@ -120,6 +121,32 @@ func (s *RouterSuite) TestOptions(c *check.C) { shouldCall: "CollectionList", withOptions: arvados.ListOptions{Limit: 123, Offset: 456, IncludeTrash: true, IncludeOldVersions: true}, }, + { + comment: "form-encoded expression filter in query string", + method: "GET", + path: "/arvados/v1/collections?filters=[%22(foo