[#46] Make SELECT attribute optional

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2020-10-14 18:25:21 +03:00 committed by Alex Vanin
parent 719075ca97
commit d7c53debb5
4 changed files with 55 additions and 14 deletions

View file

@ -15,7 +15,7 @@ CbtStmt ::= 'CBF', Number1 (* container backup factor *)
SelectStmt ::=
'SELECT', Number1, (* number of nodes to select without container backup factor *)
'IN', Clause?, Ident, (* bucket name *)
('IN', Clause?, Ident)?, (* bucket name *)
FROM, (Ident | '*'), (* filter reference or whole netmap *)
('AS', Ident)? (* optional selector name *)
;

View file

@ -27,11 +27,10 @@ type replicaStmt struct {
}
type selectorStmt struct {
Count uint32 `"SELECT" @Int`
Clause string `"IN" @("SAME" | "DISTINCT")?`
Bucket string `@Ident`
Filter string `"FROM" @(Ident | "*")`
Name string `("AS" @Ident)?`
Count uint32 `"SELECT" @Int`
Bucket []string `("IN" @(("SAME" | "DISTINCT")? Ident))?`
Filter string `"FROM" @(Ident | "*")`
Name string `("AS" @Ident)?`
}
type filterStmt struct {

View file

@ -52,18 +52,16 @@ func Parse(s string) (*netmap.PlacementPolicy, error) {
return nil, fmt.Errorf("%w: '%s'", ErrUnknownFilter, qs.Filter)
}
s := new(netmap.Selector)
switch qs.Clause {
case "SAME":
s.SetClause(netmap.Same)
case "DISTINCT":
s.SetClause(netmap.Distinct)
default:
s.SetClause(netmap.UnspecifiedClause)
switch len(qs.Bucket) {
case 1: // only bucket
s.SetAttribute(qs.Bucket[0])
case 2: // clause + bucket
s.SetClause(clauseFromString(qs.Bucket[0]))
s.SetAttribute(qs.Bucket[1])
}
s.SetName(qs.Name)
seenSelectors[qs.Name] = true
s.SetFilter(qs.Filter)
s.SetAttribute(qs.Bucket)
if qs.Count == 0 {
return nil, fmt.Errorf("%w: SELECT", ErrInvalidNumber)
}
@ -95,6 +93,17 @@ func Parse(s string) (*netmap.PlacementPolicy, error) {
return p, nil
}
func clauseFromString(s string) netmap.Clause {
switch strings.ToUpper(s) {
case "SAME":
return netmap.Same
case "DISTINCT":
return netmap.Distinct
default:
return netmap.UnspecifiedClause
}
}
func filterFromOrChain(expr *orChain, seen map[string]bool) (*netmap.Filter, error) {
var fs []*netmap.Filter
for _, ac := range expr.Clauses {

View file

@ -48,6 +48,39 @@ SELECT 1 IN City FROM * AS SPB`
require.Equal(t, expected, r)
}
// https://github.com/nspcc-dev/neofs-node/issues/46
func TestFromSelectNoAttribute(t *testing.T) {
t.Run("Simple", func(t *testing.T) {
q := `REP 2
SELECT 6 FROM *`
expected := new(netmap.PlacementPolicy)
expected.SetFilters([]*netmap.Filter{})
expected.SetSelectors([]*netmap.Selector{newSelector(6, netmap.UnspecifiedClause, "", "*", "")})
expected.SetReplicas([]*netmap.Replica{newReplica("", 2)})
r, err := Parse(q)
require.NoError(t, err)
require.Equal(t, expected, r)
})
t.Run("with filter", func(t *testing.T) {
q := `REP 2
SELECT 6 FROM F
FILTER StorageType EQ SSD AS F`
expected := new(netmap.PlacementPolicy)
expected.SetFilters([]*netmap.Filter{newFilter("F", "StorageType", "SSD", netmap.EQ)})
expected.SetSelectors([]*netmap.Selector{newSelector(6, netmap.UnspecifiedClause, "", "F", "")})
expected.SetReplicas([]*netmap.Replica{newReplica("", 2)})
r, err := Parse(q)
require.NoError(t, err)
require.Equal(t, expected, r)
})
}
func TestFromSelectClause(t *testing.T) {
q := `REP 4
SELECT 3 IN Country FROM *