[#3] policy: allow to use brackets in filters

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2021-05-21 18:12:27 +03:00
parent 3aeeafe79e
commit 0f5ce2e8bb
6 changed files with 30 additions and 4 deletions

View file

@ -2,10 +2,7 @@
// ANTLRv4 grammar is provided in `parser/Query.g4` and `parser/QueryLexer.g4`.
//
// Current limitations:
// 1. Grouping filter expressions in parenthesis is not supported right now.
// Requiring this will make query too verbose, making it optional makes
// our grammar not LL(1). This can be supported in future.
// 2. Filters must be defined before they are used.
// 1. Filters must be defined before they are used.
// This requirement may be relaxed in future.
//
// Example query:

View file

@ -24,6 +24,7 @@ clause: CLAUSE_SAME | CLAUSE_DISTINCT; // nodes from distinct buckets
filterExpr:
F1 = filterExpr Op = AND_OP F2 = filterExpr
| F1 = filterExpr Op = OR_OP F2 = filterExpr
| '(' Inner = filterExpr ')'
| expr
;

Binary file not shown.

Binary file not shown.

View file

@ -186,6 +186,10 @@ func (p *policyVisitor) VisitFilterExpr(ctx *parser.FilterExprContext) interface
return eCtx.Accept(p)
}
if inner := ctx.GetInner(); inner != nil {
return inner.Accept(p)
}
f := new(netmap.Filter)
op := operationFromString(ctx.GetOp().GetText())
f.SetOperation(op)

View file

@ -215,6 +215,30 @@ FILTER City EQ "SPB" AND SSD EQ true OR City EQ "SPB" AND Rating GE 5 AS SPBSSD`
require.EqualValues(t, expected, r)
}
func TestBrackets(t *testing.T) {
q := `REP 7 IN SPB
SELECT 1 IN City FROM SPBSSD AS SPB
FILTER ( City EQ "SPB" OR SSD EQ true ) AND (City EQ "SPB" OR Rating GE 5) AS SPBSSD`
expected := new(netmap.PlacementPolicy)
expected.SetReplicas([]*netmap.Replica{newReplica("SPB", 7)})
expected.SetSelectors([]*netmap.Selector{
newSelector(1, netmap.UnspecifiedClause, "City", "SPBSSD", "SPB"),
})
expected.SetFilters([]*netmap.Filter{
newFilter("SPBSSD", "", "", netmap.AND,
newFilter("", "", "", netmap.OR,
newFilter("", "City", "SPB", netmap.EQ),
newFilter("", "SSD", "true", netmap.EQ)),
newFilter("", "", "", netmap.OR,
newFilter("", "City", "SPB", netmap.EQ),
newFilter("", "Rating", "5", netmap.GE)))})
r, err := Parse(q)
require.NoError(t, err)
require.EqualValues(t, expected, r)
}
func TestValidation(t *testing.T) {
t.Run("MissingSelector", func(t *testing.T) {
q := `REP 3 IN RU`