[#362] cli/object: Change query language of search filters

Make `--filters` flag to be repeated. Define new filter expression format:
 * `<key> <binary_op> <value>` for binary filters. Supported binary ops: `EQ` (`STRING_EQUAL`), `NE` (`STRING_NOT_EQUAL`).
 * `<key> <unary_op>` for unary filters. Supported unary ops: `NOPRESENT` (`NOT_PRESENT`).
Any other string expressions are considered invalid.

Additionally support shorthand flag `-f`.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2021-02-11 01:03:46 +03:00 committed by Leonard Lyubich
parent 3b9d4b4df1
commit 6039cd119c

View file

@ -64,6 +64,8 @@ var (
RunE: deleteObject,
}
searchFilters []string
objectSearchCmd = &cobra.Command{
Use: "search",
Short: "Search object",
@ -138,7 +140,8 @@ func init() {
objectCmd.AddCommand(objectSearchCmd)
objectSearchCmd.Flags().String("cid", "", "Container ID")
_ = objectSearchCmd.MarkFlagRequired("cid")
objectSearchCmd.Flags().String("filters", "", "Filters in the form hdrName=value,...")
objectSearchCmd.Flags().StringSliceVarP(&searchFilters, "filters", "f", nil,
"Repeated filter expressions")
objectSearchCmd.Flags().Bool("root", false, "Search for user objects")
objectSearchCmd.Flags().Bool("phy", false, "Search physically stored objects")
objectSearchCmd.Flags().String(searchOIDFlag, "", "Search object by identifier")
@ -520,16 +523,38 @@ func getOwnerID() (*owner.ID, error) {
return ownerID, nil
}
var searchUnaryOpVocabulary = map[string]object.SearchMatchType{
"NOPRESENT": object.MatchNotPresent,
}
var searchBinaryOpVocabulary = map[string]object.SearchMatchType{
"EQ": object.MatchStringEqual,
"NE": object.MatchStringNotEqual,
}
func parseSearchFilters(cmd *cobra.Command) (object.SearchFilters, error) {
var fs object.SearchFilters
if raw := cmd.Flag("filters").Value.String(); len(raw) != 0 {
rawFs := strings.Split(raw, ",")
for i := range rawFs {
kv := strings.SplitN(rawFs[i], "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("invalid filter format: %s", rawFs[i])
for i := range searchFilters {
words := strings.Fields(searchFilters[i])
switch len(words) {
default:
return nil, fmt.Errorf("invalid field number: %d", len(words))
case 2:
m, ok := searchUnaryOpVocabulary[words[1]]
if !ok {
return nil, fmt.Errorf("unsupported unary op: %s", words[1])
}
fs.AddFilter(kv[0], kv[1], object.MatchStringEqual)
fs.AddFilter(words[0], "", m)
case 3:
m, ok := searchBinaryOpVocabulary[words[1]]
if !ok {
return nil, fmt.Errorf("unsupported binary op: %s", words[1])
}
fs.AddFilter(words[0], words[2], m)
}
}