[#xx] Add support for SELECT-FILTER expressions

Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
This commit is contained in:
Alejandro Lopez 2023-07-13 16:12:47 +03:00 committed by Evgenii Stratonikov
parent b9afe7a2f9
commit b91f9d8c79
8 changed files with 556 additions and 170 deletions

View file

@ -560,6 +560,44 @@ func (p *PlacementPolicy) DecodeString(s string) error {
return nil
}
// SelectFilterExpr is an expression containing only selectors and filters.
// It's useful to evaluate their effect before being used in a policy.
type SelectFilterExpr struct {
cbf uint32
selector *netmap.Selector
filters []netmap.Filter
}
// DecodeString decodes a string into a SelectFilterExpr.
// Returns an error if s is malformed.
func DecodeSelectFilterString(s string) (*SelectFilterExpr, error) {
var v policyVisitor
input := antlr.NewInputStream(s)
lexer := parser.NewQueryLexer(input)
lexer.RemoveErrorListeners()
lexer.AddErrorListener(&v)
stream := antlr.NewCommonTokenStream(lexer, 0)
pp := parser.NewQuery(stream)
pp.BuildParseTrees = true
pp.RemoveErrorListeners()
pp.AddErrorListener(&v)
sfExpr := pp.SelectFilterExpr().Accept(&v)
if len(v.errors) != 0 {
return nil, v.errors[0]
}
parsed, ok := sfExpr.(*SelectFilterExpr)
if !ok {
return nil, fmt.Errorf("unexpected parsed instance type %T", sfExpr)
}
return parsed, nil
}
var (
// errUnknownFilter is returned when a value of FROM in a query is unknown.
errUnknownFilter = errors.New("filter not found")
@ -636,6 +674,39 @@ func (p *policyVisitor) VisitPolicy(ctx *parser.PolicyContext) any {
return pl
}
func (p *policyVisitor) VisitSelectFilterExpr(ctx *parser.SelectFilterExprContext) any {
if len(p.errors) != 0 {
return nil
}
sfExpr := new(SelectFilterExpr)
if cbfStmt := ctx.CbfStmt(); cbfStmt != nil {
cbf, ok := cbfStmt.(*parser.CbfStmtContext).Accept(p).(uint32)
if !ok {
return nil
}
sfExpr.cbf = cbf
}
if selStmt := ctx.SelectStmt(); selStmt != nil {
sel, ok := selStmt.Accept(p).(*netmap.Selector)
if !ok {
return nil
}
sfExpr.selector = sel
}
filtStmts := ctx.AllFilterStmt()
sfExpr.filters = make([]netmap.Filter, 0, len(filtStmts))
for _, f := range filtStmts {
sfExpr.filters = append(sfExpr.filters, *f.Accept(p).(*netmap.Filter))
}
return sfExpr
}
func (p *policyVisitor) VisitCbfStmt(ctx *parser.CbfStmtContext) any {
cbf, err := strconv.ParseUint(ctx.GetBackupFactor().GetText(), 10, 32)
if err != nil {