diff --git a/doc/policy.md b/doc/policy.md index 28744ef..0b87079 100644 --- a/doc/policy.md +++ b/doc/policy.md @@ -428,6 +428,13 @@ Comparison operators (all binary): - `LE`: less or equal - `LT`: less than +Pattern operator: +- `LIKE`: specifies pattern for an attribute. Uses as a wildcard symbol `*`. + - `... ATTR LIKE "VAL"` - the behaviour is equal to `EQ` + - `... ATTR LIKE "VAL*"` - matches all which starts with `VAL` + - `... ATTR LIKE "*VAL"` - matches all which ends with `VAL` + - `... ATTR LIKE "*VAL*"` - matches all which contains `VAL` + Logical operators: - `NOT`: negation (unary) - `AND`: conjunction (binary) diff --git a/netmap/filter.go b/netmap/filter.go index 71e101d..ae25441 100644 --- a/netmap/filter.go +++ b/netmap/filter.go @@ -3,6 +3,7 @@ package netmap import ( "fmt" "strconv" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" ) @@ -53,7 +54,7 @@ func (c *context) processFilter(f netmap.Filter, top bool) error { } switch op { - case netmap.EQ, netmap.NE: + case netmap.EQ, netmap.NE, netmap.LIKE: case netmap.GT, netmap.GE, netmap.LT, netmap.LE: val := f.GetValue() n, err := strconv.ParseUint(val, 10, 64) @@ -110,6 +111,19 @@ func (c *context) matchKeyValue(f *netmap.Filter, b NodeInfo) bool { switch op := f.GetOp(); op { case netmap.EQ: return b.Attribute(f.GetKey()) == f.GetValue() + case netmap.LIKE: + str, prefix := strings.CutPrefix(f.GetValue(), netmap.LikeWildcard) + str, suffix := strings.CutSuffix(str, netmap.LikeWildcard) + if prefix && suffix { + return strings.Contains(b.Attribute(f.GetKey()), str) + } + if prefix && !suffix { + return strings.HasSuffix(b.Attribute(f.GetKey()), str) + } + if !prefix && suffix { + return strings.HasPrefix(b.Attribute(f.GetKey()), str) + } + return b.Attribute(f.GetKey()) == f.GetValue() case netmap.NE: return b.Attribute(f.GetKey()) != f.GetValue() default: diff --git a/netmap/parser/QueryLexer.g4 b/netmap/parser/QueryLexer.g4 index 3e4e924..200fbb6 100644 --- a/netmap/parser/QueryLexer.g4 +++ b/netmap/parser/QueryLexer.g4 @@ -3,7 +3,7 @@ lexer grammar QueryLexer; NOT_OP : 'NOT'; AND_OP : 'AND'; OR_OP : 'OR'; -SIMPLE_OP : 'EQ' | 'NE' | 'GE' | 'GT' | 'LT' | 'LE'; +SIMPLE_OP : 'EQ' | 'NE' | 'GE' | 'GT' | 'LT' | 'LE' | 'LIKE' ; UNIQUE : 'UNIQUE'; REP : 'REP'; diff --git a/netmap/parser/QueryLexer.interp b/netmap/parser/QueryLexer.interp index c4d6296..c339bdd 100644 Binary files a/netmap/parser/QueryLexer.interp and b/netmap/parser/QueryLexer.interp differ diff --git a/netmap/parser/query_lexer.go b/netmap/parser/query_lexer.go index 85a0336..43fc173 100644 --- a/netmap/parser/query_lexer.go +++ b/netmap/parser/query_lexer.go @@ -62,7 +62,7 @@ func querylexerLexerInit() { } staticData.PredictionContextCache = antlr.NewPredictionContextCache() staticData.serializedATN = []int32{ - 4, 0, 25, 222, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 0, 25, 226, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, @@ -70,96 +70,98 @@ func querylexerLexerInit() { 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 3, 3, 89, 8, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, - 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, - 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, - 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, - 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, - 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, - 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 5, 20, 161, 8, 20, 10, - 20, 12, 20, 164, 9, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 5, 23, - 172, 8, 23, 10, 23, 12, 23, 175, 9, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, - 25, 5, 25, 182, 8, 25, 10, 25, 12, 25, 185, 9, 25, 1, 25, 1, 25, 1, 25, - 1, 25, 5, 25, 191, 8, 25, 10, 25, 12, 25, 194, 9, 25, 1, 25, 3, 25, 197, - 8, 25, 1, 26, 1, 26, 1, 26, 3, 26, 202, 8, 26, 1, 27, 1, 27, 1, 27, 1, - 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 4, 31, - 217, 8, 31, 11, 31, 12, 31, 218, 1, 31, 1, 31, 0, 0, 32, 1, 1, 3, 2, 5, - 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, - 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, - 0, 45, 0, 47, 22, 49, 23, 51, 24, 53, 0, 55, 0, 57, 0, 59, 0, 61, 0, 63, - 25, 1, 0, 8, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 1, 0, 49, 57, - 9, 0, 34, 34, 39, 39, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, - 114, 116, 116, 3, 0, 48, 57, 65, 70, 97, 102, 3, 0, 0, 31, 39, 39, 92, - 92, 3, 0, 0, 31, 34, 34, 92, 92, 3, 0, 9, 10, 13, 13, 32, 32, 229, 0, 1, - 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, - 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, - 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, - 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, - 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, - 0, 0, 0, 41, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, - 0, 0, 0, 0, 63, 1, 0, 0, 0, 1, 65, 1, 0, 0, 0, 3, 69, 1, 0, 0, 0, 5, 73, - 1, 0, 0, 0, 7, 88, 1, 0, 0, 0, 9, 90, 1, 0, 0, 0, 11, 97, 1, 0, 0, 0, 13, - 101, 1, 0, 0, 0, 15, 104, 1, 0, 0, 0, 17, 107, 1, 0, 0, 0, 19, 110, 1, - 0, 0, 0, 21, 114, 1, 0, 0, 0, 23, 121, 1, 0, 0, 0, 25, 126, 1, 0, 0, 0, - 27, 133, 1, 0, 0, 0, 29, 135, 1, 0, 0, 0, 31, 137, 1, 0, 0, 0, 33, 142, - 1, 0, 0, 0, 35, 151, 1, 0, 0, 0, 37, 153, 1, 0, 0, 0, 39, 155, 1, 0, 0, - 0, 41, 157, 1, 0, 0, 0, 43, 165, 1, 0, 0, 0, 45, 167, 1, 0, 0, 0, 47, 169, - 1, 0, 0, 0, 49, 176, 1, 0, 0, 0, 51, 196, 1, 0, 0, 0, 53, 198, 1, 0, 0, - 0, 55, 203, 1, 0, 0, 0, 57, 209, 1, 0, 0, 0, 59, 211, 1, 0, 0, 0, 61, 213, - 1, 0, 0, 0, 63, 216, 1, 0, 0, 0, 65, 66, 5, 78, 0, 0, 66, 67, 5, 79, 0, - 0, 67, 68, 5, 84, 0, 0, 68, 2, 1, 0, 0, 0, 69, 70, 5, 65, 0, 0, 70, 71, - 5, 78, 0, 0, 71, 72, 5, 68, 0, 0, 72, 4, 1, 0, 0, 0, 73, 74, 5, 79, 0, - 0, 74, 75, 5, 82, 0, 0, 75, 6, 1, 0, 0, 0, 76, 77, 5, 69, 0, 0, 77, 89, - 5, 81, 0, 0, 78, 79, 5, 78, 0, 0, 79, 89, 5, 69, 0, 0, 80, 81, 5, 71, 0, - 0, 81, 89, 5, 69, 0, 0, 82, 83, 5, 71, 0, 0, 83, 89, 5, 84, 0, 0, 84, 85, - 5, 76, 0, 0, 85, 89, 5, 84, 0, 0, 86, 87, 5, 76, 0, 0, 87, 89, 5, 69, 0, - 0, 88, 76, 1, 0, 0, 0, 88, 78, 1, 0, 0, 0, 88, 80, 1, 0, 0, 0, 88, 82, - 1, 0, 0, 0, 88, 84, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, 89, 8, 1, 0, 0, 0, - 90, 91, 5, 85, 0, 0, 91, 92, 5, 78, 0, 0, 92, 93, 5, 73, 0, 0, 93, 94, - 5, 81, 0, 0, 94, 95, 5, 85, 0, 0, 95, 96, 5, 69, 0, 0, 96, 10, 1, 0, 0, - 0, 97, 98, 5, 82, 0, 0, 98, 99, 5, 69, 0, 0, 99, 100, 5, 80, 0, 0, 100, - 12, 1, 0, 0, 0, 101, 102, 5, 69, 0, 0, 102, 103, 5, 67, 0, 0, 103, 14, - 1, 0, 0, 0, 104, 105, 5, 73, 0, 0, 105, 106, 5, 78, 0, 0, 106, 16, 1, 0, - 0, 0, 107, 108, 5, 65, 0, 0, 108, 109, 5, 83, 0, 0, 109, 18, 1, 0, 0, 0, - 110, 111, 5, 67, 0, 0, 111, 112, 5, 66, 0, 0, 112, 113, 5, 70, 0, 0, 113, - 20, 1, 0, 0, 0, 114, 115, 5, 83, 0, 0, 115, 116, 5, 69, 0, 0, 116, 117, - 5, 76, 0, 0, 117, 118, 5, 69, 0, 0, 118, 119, 5, 67, 0, 0, 119, 120, 5, - 84, 0, 0, 120, 22, 1, 0, 0, 0, 121, 122, 5, 70, 0, 0, 122, 123, 5, 82, - 0, 0, 123, 124, 5, 79, 0, 0, 124, 125, 5, 77, 0, 0, 125, 24, 1, 0, 0, 0, - 126, 127, 5, 70, 0, 0, 127, 128, 5, 73, 0, 0, 128, 129, 5, 76, 0, 0, 129, - 130, 5, 84, 0, 0, 130, 131, 5, 69, 0, 0, 131, 132, 5, 82, 0, 0, 132, 26, - 1, 0, 0, 0, 133, 134, 5, 42, 0, 0, 134, 28, 1, 0, 0, 0, 135, 136, 5, 46, - 0, 0, 136, 30, 1, 0, 0, 0, 137, 138, 5, 83, 0, 0, 138, 139, 5, 65, 0, 0, - 139, 140, 5, 77, 0, 0, 140, 141, 5, 69, 0, 0, 141, 32, 1, 0, 0, 0, 142, - 143, 5, 68, 0, 0, 143, 144, 5, 73, 0, 0, 144, 145, 5, 83, 0, 0, 145, 146, - 5, 84, 0, 0, 146, 147, 5, 73, 0, 0, 147, 148, 5, 78, 0, 0, 148, 149, 5, - 67, 0, 0, 149, 150, 5, 84, 0, 0, 150, 34, 1, 0, 0, 0, 151, 152, 5, 40, - 0, 0, 152, 36, 1, 0, 0, 0, 153, 154, 5, 41, 0, 0, 154, 38, 1, 0, 0, 0, - 155, 156, 5, 64, 0, 0, 156, 40, 1, 0, 0, 0, 157, 162, 3, 45, 22, 0, 158, - 161, 3, 43, 21, 0, 159, 161, 3, 45, 22, 0, 160, 158, 1, 0, 0, 0, 160, 159, - 1, 0, 0, 0, 161, 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, - 0, 0, 163, 42, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 7, 0, 0, 0, - 166, 44, 1, 0, 0, 0, 167, 168, 7, 1, 0, 0, 168, 46, 1, 0, 0, 0, 169, 173, - 7, 2, 0, 0, 170, 172, 3, 43, 21, 0, 171, 170, 1, 0, 0, 0, 172, 175, 1, - 0, 0, 0, 173, 171, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 48, 1, 0, 0, - 0, 175, 173, 1, 0, 0, 0, 176, 177, 5, 48, 0, 0, 177, 50, 1, 0, 0, 0, 178, - 183, 5, 34, 0, 0, 179, 182, 3, 53, 26, 0, 180, 182, 3, 61, 30, 0, 181, - 179, 1, 0, 0, 0, 181, 180, 1, 0, 0, 0, 182, 185, 1, 0, 0, 0, 183, 181, - 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 186, 1, 0, 0, 0, 185, 183, 1, 0, - 0, 0, 186, 197, 5, 34, 0, 0, 187, 192, 5, 39, 0, 0, 188, 191, 3, 53, 26, - 0, 189, 191, 3, 59, 29, 0, 190, 188, 1, 0, 0, 0, 190, 189, 1, 0, 0, 0, - 191, 194, 1, 0, 0, 0, 192, 190, 1, 0, 0, 0, 192, 193, 1, 0, 0, 0, 193, - 195, 1, 0, 0, 0, 194, 192, 1, 0, 0, 0, 195, 197, 5, 39, 0, 0, 196, 178, - 1, 0, 0, 0, 196, 187, 1, 0, 0, 0, 197, 52, 1, 0, 0, 0, 198, 201, 5, 92, - 0, 0, 199, 202, 7, 3, 0, 0, 200, 202, 3, 55, 27, 0, 201, 199, 1, 0, 0, - 0, 201, 200, 1, 0, 0, 0, 202, 54, 1, 0, 0, 0, 203, 204, 5, 117, 0, 0, 204, - 205, 3, 57, 28, 0, 205, 206, 3, 57, 28, 0, 206, 207, 3, 57, 28, 0, 207, - 208, 3, 57, 28, 0, 208, 56, 1, 0, 0, 0, 209, 210, 7, 4, 0, 0, 210, 58, - 1, 0, 0, 0, 211, 212, 8, 5, 0, 0, 212, 60, 1, 0, 0, 0, 213, 214, 8, 6, - 0, 0, 214, 62, 1, 0, 0, 0, 215, 217, 7, 7, 0, 0, 216, 215, 1, 0, 0, 0, - 217, 218, 1, 0, 0, 0, 218, 216, 1, 0, 0, 0, 218, 219, 1, 0, 0, 0, 219, - 220, 1, 0, 0, 0, 220, 221, 6, 31, 0, 0, 221, 64, 1, 0, 0, 0, 12, 0, 88, - 160, 162, 173, 181, 183, 190, 192, 196, 201, 218, 1, 6, 0, 0, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 93, 8, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, + 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, + 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, + 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, + 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, + 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, + 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, + 5, 20, 165, 8, 20, 10, 20, 12, 20, 168, 9, 20, 1, 21, 1, 21, 1, 22, 1, + 22, 1, 23, 1, 23, 5, 23, 176, 8, 23, 10, 23, 12, 23, 179, 9, 23, 1, 24, + 1, 24, 1, 25, 1, 25, 1, 25, 5, 25, 186, 8, 25, 10, 25, 12, 25, 189, 9, + 25, 1, 25, 1, 25, 1, 25, 1, 25, 5, 25, 195, 8, 25, 10, 25, 12, 25, 198, + 9, 25, 1, 25, 3, 25, 201, 8, 25, 1, 26, 1, 26, 1, 26, 3, 26, 206, 8, 26, + 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, + 30, 1, 30, 1, 31, 4, 31, 221, 8, 31, 11, 31, 12, 31, 222, 1, 31, 1, 31, + 0, 0, 32, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, + 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, + 19, 39, 20, 41, 21, 43, 0, 45, 0, 47, 22, 49, 23, 51, 24, 53, 0, 55, 0, + 57, 0, 59, 0, 61, 0, 63, 25, 1, 0, 8, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, + 97, 122, 1, 0, 49, 57, 9, 0, 34, 34, 39, 39, 47, 47, 92, 92, 98, 98, 102, + 102, 110, 110, 114, 114, 116, 116, 3, 0, 48, 57, 65, 70, 97, 102, 3, 0, + 0, 31, 39, 39, 92, 92, 3, 0, 0, 31, 34, 34, 92, 92, 3, 0, 9, 10, 13, 13, + 32, 32, 234, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, + 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, + 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, + 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, + 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, + 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, + 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 1, 65, 1, 0, 0, 0, 3, 69, + 1, 0, 0, 0, 5, 73, 1, 0, 0, 0, 7, 92, 1, 0, 0, 0, 9, 94, 1, 0, 0, 0, 11, + 101, 1, 0, 0, 0, 13, 105, 1, 0, 0, 0, 15, 108, 1, 0, 0, 0, 17, 111, 1, + 0, 0, 0, 19, 114, 1, 0, 0, 0, 21, 118, 1, 0, 0, 0, 23, 125, 1, 0, 0, 0, + 25, 130, 1, 0, 0, 0, 27, 137, 1, 0, 0, 0, 29, 139, 1, 0, 0, 0, 31, 141, + 1, 0, 0, 0, 33, 146, 1, 0, 0, 0, 35, 155, 1, 0, 0, 0, 37, 157, 1, 0, 0, + 0, 39, 159, 1, 0, 0, 0, 41, 161, 1, 0, 0, 0, 43, 169, 1, 0, 0, 0, 45, 171, + 1, 0, 0, 0, 47, 173, 1, 0, 0, 0, 49, 180, 1, 0, 0, 0, 51, 200, 1, 0, 0, + 0, 53, 202, 1, 0, 0, 0, 55, 207, 1, 0, 0, 0, 57, 213, 1, 0, 0, 0, 59, 215, + 1, 0, 0, 0, 61, 217, 1, 0, 0, 0, 63, 220, 1, 0, 0, 0, 65, 66, 5, 78, 0, + 0, 66, 67, 5, 79, 0, 0, 67, 68, 5, 84, 0, 0, 68, 2, 1, 0, 0, 0, 69, 70, + 5, 65, 0, 0, 70, 71, 5, 78, 0, 0, 71, 72, 5, 68, 0, 0, 72, 4, 1, 0, 0, + 0, 73, 74, 5, 79, 0, 0, 74, 75, 5, 82, 0, 0, 75, 6, 1, 0, 0, 0, 76, 77, + 5, 69, 0, 0, 77, 93, 5, 81, 0, 0, 78, 79, 5, 78, 0, 0, 79, 93, 5, 69, 0, + 0, 80, 81, 5, 71, 0, 0, 81, 93, 5, 69, 0, 0, 82, 83, 5, 71, 0, 0, 83, 93, + 5, 84, 0, 0, 84, 85, 5, 76, 0, 0, 85, 93, 5, 84, 0, 0, 86, 87, 5, 76, 0, + 0, 87, 93, 5, 69, 0, 0, 88, 89, 5, 76, 0, 0, 89, 90, 5, 73, 0, 0, 90, 91, + 5, 75, 0, 0, 91, 93, 5, 69, 0, 0, 92, 76, 1, 0, 0, 0, 92, 78, 1, 0, 0, + 0, 92, 80, 1, 0, 0, 0, 92, 82, 1, 0, 0, 0, 92, 84, 1, 0, 0, 0, 92, 86, + 1, 0, 0, 0, 92, 88, 1, 0, 0, 0, 93, 8, 1, 0, 0, 0, 94, 95, 5, 85, 0, 0, + 95, 96, 5, 78, 0, 0, 96, 97, 5, 73, 0, 0, 97, 98, 5, 81, 0, 0, 98, 99, + 5, 85, 0, 0, 99, 100, 5, 69, 0, 0, 100, 10, 1, 0, 0, 0, 101, 102, 5, 82, + 0, 0, 102, 103, 5, 69, 0, 0, 103, 104, 5, 80, 0, 0, 104, 12, 1, 0, 0, 0, + 105, 106, 5, 69, 0, 0, 106, 107, 5, 67, 0, 0, 107, 14, 1, 0, 0, 0, 108, + 109, 5, 73, 0, 0, 109, 110, 5, 78, 0, 0, 110, 16, 1, 0, 0, 0, 111, 112, + 5, 65, 0, 0, 112, 113, 5, 83, 0, 0, 113, 18, 1, 0, 0, 0, 114, 115, 5, 67, + 0, 0, 115, 116, 5, 66, 0, 0, 116, 117, 5, 70, 0, 0, 117, 20, 1, 0, 0, 0, + 118, 119, 5, 83, 0, 0, 119, 120, 5, 69, 0, 0, 120, 121, 5, 76, 0, 0, 121, + 122, 5, 69, 0, 0, 122, 123, 5, 67, 0, 0, 123, 124, 5, 84, 0, 0, 124, 22, + 1, 0, 0, 0, 125, 126, 5, 70, 0, 0, 126, 127, 5, 82, 0, 0, 127, 128, 5, + 79, 0, 0, 128, 129, 5, 77, 0, 0, 129, 24, 1, 0, 0, 0, 130, 131, 5, 70, + 0, 0, 131, 132, 5, 73, 0, 0, 132, 133, 5, 76, 0, 0, 133, 134, 5, 84, 0, + 0, 134, 135, 5, 69, 0, 0, 135, 136, 5, 82, 0, 0, 136, 26, 1, 0, 0, 0, 137, + 138, 5, 42, 0, 0, 138, 28, 1, 0, 0, 0, 139, 140, 5, 46, 0, 0, 140, 30, + 1, 0, 0, 0, 141, 142, 5, 83, 0, 0, 142, 143, 5, 65, 0, 0, 143, 144, 5, + 77, 0, 0, 144, 145, 5, 69, 0, 0, 145, 32, 1, 0, 0, 0, 146, 147, 5, 68, + 0, 0, 147, 148, 5, 73, 0, 0, 148, 149, 5, 83, 0, 0, 149, 150, 5, 84, 0, + 0, 150, 151, 5, 73, 0, 0, 151, 152, 5, 78, 0, 0, 152, 153, 5, 67, 0, 0, + 153, 154, 5, 84, 0, 0, 154, 34, 1, 0, 0, 0, 155, 156, 5, 40, 0, 0, 156, + 36, 1, 0, 0, 0, 157, 158, 5, 41, 0, 0, 158, 38, 1, 0, 0, 0, 159, 160, 5, + 64, 0, 0, 160, 40, 1, 0, 0, 0, 161, 166, 3, 45, 22, 0, 162, 165, 3, 43, + 21, 0, 163, 165, 3, 45, 22, 0, 164, 162, 1, 0, 0, 0, 164, 163, 1, 0, 0, + 0, 165, 168, 1, 0, 0, 0, 166, 164, 1, 0, 0, 0, 166, 167, 1, 0, 0, 0, 167, + 42, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 169, 170, 7, 0, 0, 0, 170, 44, 1, + 0, 0, 0, 171, 172, 7, 1, 0, 0, 172, 46, 1, 0, 0, 0, 173, 177, 7, 2, 0, + 0, 174, 176, 3, 43, 21, 0, 175, 174, 1, 0, 0, 0, 176, 179, 1, 0, 0, 0, + 177, 175, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 48, 1, 0, 0, 0, 179, 177, + 1, 0, 0, 0, 180, 181, 5, 48, 0, 0, 181, 50, 1, 0, 0, 0, 182, 187, 5, 34, + 0, 0, 183, 186, 3, 53, 26, 0, 184, 186, 3, 61, 30, 0, 185, 183, 1, 0, 0, + 0, 185, 184, 1, 0, 0, 0, 186, 189, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 187, + 188, 1, 0, 0, 0, 188, 190, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 190, 201, + 5, 34, 0, 0, 191, 196, 5, 39, 0, 0, 192, 195, 3, 53, 26, 0, 193, 195, 3, + 59, 29, 0, 194, 192, 1, 0, 0, 0, 194, 193, 1, 0, 0, 0, 195, 198, 1, 0, + 0, 0, 196, 194, 1, 0, 0, 0, 196, 197, 1, 0, 0, 0, 197, 199, 1, 0, 0, 0, + 198, 196, 1, 0, 0, 0, 199, 201, 5, 39, 0, 0, 200, 182, 1, 0, 0, 0, 200, + 191, 1, 0, 0, 0, 201, 52, 1, 0, 0, 0, 202, 205, 5, 92, 0, 0, 203, 206, + 7, 3, 0, 0, 204, 206, 3, 55, 27, 0, 205, 203, 1, 0, 0, 0, 205, 204, 1, + 0, 0, 0, 206, 54, 1, 0, 0, 0, 207, 208, 5, 117, 0, 0, 208, 209, 3, 57, + 28, 0, 209, 210, 3, 57, 28, 0, 210, 211, 3, 57, 28, 0, 211, 212, 3, 57, + 28, 0, 212, 56, 1, 0, 0, 0, 213, 214, 7, 4, 0, 0, 214, 58, 1, 0, 0, 0, + 215, 216, 8, 5, 0, 0, 216, 60, 1, 0, 0, 0, 217, 218, 8, 6, 0, 0, 218, 62, + 1, 0, 0, 0, 219, 221, 7, 7, 0, 0, 220, 219, 1, 0, 0, 0, 221, 222, 1, 0, + 0, 0, 222, 220, 1, 0, 0, 0, 222, 223, 1, 0, 0, 0, 223, 224, 1, 0, 0, 0, + 224, 225, 6, 31, 0, 0, 225, 64, 1, 0, 0, 0, 12, 0, 92, 164, 166, 177, 185, + 187, 194, 196, 200, 205, 222, 1, 6, 0, 0, } deserializer := antlr.NewATNDeserializer(nil) staticData.atn = deserializer.Deserialize(staticData.serializedATN) diff --git a/netmap/policy.go b/netmap/policy.go index 545fb5c..48ca364 100644 --- a/netmap/policy.go +++ b/netmap/policy.go @@ -324,6 +324,13 @@ func (x *Filter) setAttribute(key string, op netmap.Operation, val string) { x.m.SetValue(val) } +// Like applies the rule to accept only nodes with attribute like value. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) Like(key, value string) { + x.setAttribute(key, netmap.LIKE, value) +} + // Equal applies the rule to accept only nodes with the same attribute value. // // Method SHOULD NOT be called along with other similar methods. diff --git a/netmap/policy_test.go b/netmap/policy_test.go index 1d5487b..7c639c6 100644 --- a/netmap/policy_test.go +++ b/netmap/policy_test.go @@ -122,6 +122,11 @@ func TestDecodeSelectFilterExpr(t *testing.T) { FILTER Color EQ 'Red' AS RedNode FILTER @RedNode AND Shape EQ 'Cirle' AS RedCircleNode `, + ` + CBF 1 + SELECT 1 FROM R + FILTER Color LIKE 'R' AS R + `, } { _, err := DecodeSelectFilterString(s) require.NoError(t, err) diff --git a/netmap/selector_test.go b/netmap/selector_test.go index 934ff7e..390da28 100644 --- a/netmap/selector_test.go +++ b/netmap/selector_test.go @@ -7,6 +7,7 @@ import ( mrand "math/rand" "sort" "strconv" + "strings" "testing" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" @@ -250,6 +251,92 @@ func TestPlacementPolicy_ProcessSelectors(t *testing.T) { } } +func TestPlacementPolicy_Like(t *testing.T) { + nodes := []NodeInfo{ + nodeInfoFromAttributes("Country", "Russia"), + nodeInfoFromAttributes("Country", "Germany"), + nodeInfoFromAttributes("Country", "Belarus"), + } + + var nm NetMap + nm.SetNodes(nodes) + + t.Run("LIKE all", func(t *testing.T) { + ssNamed := []Selector{newSelector("X", "Country", 4, "FromRU", (*Selector).SelectDistinct)} + fsNamed := []Filter{newFilter("FromRU", "Country", "*", netmap.LIKE)} + rsNamed := []ReplicaDescriptor{newReplica(4, "X")} + pNamed := newPlacementPolicy(0, rsNamed, ssNamed, fsNamed) + + n, err := nm.ContainerNodes(pNamed, []byte{1}) + require.NoError(t, err) + + require.Equal(t, 3, len(n[0])) + for _, n := range n[0] { + require.True(t, strings.Contains("GermanyRussiaBelarus", n.Attribute("Country"))) + } + }) + + t.Run("LIKE no wildcard", func(t *testing.T) { + ssNamed := []Selector{newSelector("X", "Country", 1, "FromRU", (*Selector).SelectDistinct)} + fsNamed := []Filter{newFilter("FromRU", "Country", "Russia", netmap.LIKE)} + rsNamed := []ReplicaDescriptor{newReplica(1, "X")} + pNamed := newPlacementPolicy(0, rsNamed, ssNamed, fsNamed) + + n, err := nm.ContainerNodes(pNamed, []byte{1}) + require.NoError(t, err) + + require.Equal(t, 1, len(n[0])) + for _, n := range n[0] { + require.True(t, n.Attribute("Country") == "Russia") + } + }) + + t.Run("LIKE prefix", func(t *testing.T) { + ssNamed := []Selector{newSelector("X", "Country", 1, "FromRU", (*Selector).SelectDistinct)} + fsNamed := []Filter{newFilter("FromRU", "Country", "Ge*", netmap.LIKE)} + rsNamed := []ReplicaDescriptor{newReplica(1, "X")} + pNamed := newPlacementPolicy(0, rsNamed, ssNamed, fsNamed) + + n, err := nm.ContainerNodes(pNamed, []byte{1}) + require.NoError(t, err) + + require.Equal(t, 1, len(n[0])) + for _, n := range n[0] { + require.True(t, n.Attribute("Country") == "Germany") + } + }) + + t.Run("LIKE suffix", func(t *testing.T) { + ssNamed := []Selector{newSelector("X", "Country", 1, "FromRU", (*Selector).SelectDistinct)} + fsNamed := []Filter{newFilter("FromRU", "Country", "*sia", netmap.LIKE)} + rsNamed := []ReplicaDescriptor{newReplica(1, "X")} + pNamed := newPlacementPolicy(0, rsNamed, ssNamed, fsNamed) + + n, err := nm.ContainerNodes(pNamed, []byte{1}) + require.NoError(t, err) + + require.Equal(t, 1, len(n[0])) + for _, n := range n[0] { + require.True(t, n.Attribute("Country") == "Russia") + } + }) + + t.Run("LIKE middle", func(t *testing.T) { + ssNamed := []Selector{newSelector("X", "Country", 2, "FromRU", (*Selector).SelectDistinct)} + fsNamed := []Filter{newFilter("FromRU", "Country", "*us*", netmap.LIKE)} + rsNamed := []ReplicaDescriptor{newReplica(2, "X")} + pNamed := newPlacementPolicy(0, rsNamed, ssNamed, fsNamed) + + n, err := nm.ContainerNodes(pNamed, []byte{1}) + require.NoError(t, err) + + require.Equal(t, 2, len(n[0])) + for _, n := range n[0] { + require.True(t, strings.Contains("RussiaBelarus", n.Attribute("Country"))) + } + }) +} + func TestPlacementPolicy_Unique(t *testing.T) { p := newPlacementPolicy(2, []ReplicaDescriptor{ diff --git a/netmap/yml_unmarshal.go b/netmap/yml_unmarshal.go index fa94586..7c38b2c 100644 --- a/netmap/yml_unmarshal.go +++ b/netmap/yml_unmarshal.go @@ -44,15 +44,16 @@ func convertNFilters(temp []tempFilter) []netmap.Filter { } var stringToOperationMap = map[string]netmap.Operation{ - "EQ": netmap.EQ, - "NE": netmap.NE, - "GT": netmap.GT, - "GE": netmap.GE, - "LT": netmap.LT, - "LE": netmap.LE, - "OR": netmap.OR, - "AND": netmap.AND, - "NOT": netmap.NOT, + "EQ": netmap.EQ, + "NE": netmap.NE, + "GT": netmap.GT, + "GE": netmap.GE, + "LT": netmap.LT, + "LE": netmap.LE, + "OR": netmap.OR, + "AND": netmap.AND, + "NOT": netmap.NOT, + "LIKE": netmap.LIKE, } func convertStringToOperation(opStr string) netmap.Operation {