[#46] Make SELECT attribute optional
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
719075ca97
commit
d7c53debb5
4 changed files with 55 additions and 14 deletions
|
@ -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 *)
|
||||
;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 *
|
||||
|
|
Loading…
Reference in a new issue