forked from TrueCloudLab/frostfs-sdk-go
Compare commits
10 commits
3e455777fd
...
3063b525d5
Author | SHA1 | Date | |
---|---|---|---|
3063b525d5 | |||
99d5bf913b | |||
e50838a33d | |||
97cf56ba41 | |||
07625e3bd1 | |||
da2f0e7532 | |||
114b4c14b5 | |||
e580ee991d | |||
6821fe6fb2 | |||
6009d089fc |
26 changed files with 187 additions and 70 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -23,7 +23,7 @@ coverage.txt
|
|||
coverage.html
|
||||
|
||||
# antlr tool jar
|
||||
antlr-*.jar
|
||||
antlr*.jar
|
||||
|
||||
# tempfiles
|
||||
.cache
|
||||
|
|
5
Makefile
5
Makefile
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
ANTLR_VERSION="4.13.0"
|
||||
ANTLR_VERSION=4.13.1
|
||||
TMP_DIR := .cache
|
||||
LINT_VERSION ?= 1.60.1
|
||||
TRUECLOUDLAB_LINT_VERSION ?= 0.0.6
|
||||
|
@ -53,7 +53,8 @@ format:
|
|||
|
||||
policy:
|
||||
@wget -q https://www.antlr.org/download/antlr-${ANTLR_VERSION}-complete.jar -O antlr4-tool.jar
|
||||
@java -Xmx500M -cp "`pwd`/antlr4-tool.jar" "org.antlr.v4.Tool" -o `pwd`/netmap/parser/ -Dlanguage=Go -no-listener -visitor `pwd`/netmap/parser/Query.g4 `pwd`/netmap/parser/QueryLexer.g4
|
||||
@java -Xmx500M -cp antlr4-tool.jar org.antlr.v4.Tool -Dlanguage=Go \
|
||||
-no-listener -visitor netmap/parser/Query.g4 netmap/parser/QueryLexer.g4
|
||||
|
||||
# Run `make %` in truecloudlab/frostfs-sdk-go container(Golang+Java)
|
||||
docker/%:
|
||||
|
|
|
@ -65,7 +65,7 @@ func (c *Client) APEManagerListChains(ctx context.Context, prm PrmAPEManagerList
|
|||
var res ResAPEManagerListChains
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil || !apistatus.IsSuccessful(res.st) {
|
||||
return nil, err
|
||||
return &res, err
|
||||
}
|
||||
|
||||
for _, ch := range resp.GetBody().GetChains() {
|
||||
|
|
|
@ -11,6 +11,8 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Client represents virtual connection to the FrostFS network to communicate
|
||||
|
@ -98,13 +100,21 @@ func (c *Client) Dial(ctx context.Context, prm PrmDial) error {
|
|||
|
||||
c.setFrostFSAPIServer((*coreServer)(&c.c))
|
||||
|
||||
// TODO: (neofs-api-go#382) perform generic dial stage of the client.Client
|
||||
_, err := rpc.Balance(&c.c, new(v2accounting.BalanceRequest),
|
||||
client.WithContext(ctx),
|
||||
)
|
||||
// return context errors since they signal about dial problem
|
||||
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
||||
return err
|
||||
if err != nil {
|
||||
// return context errors since they signal about dial problem
|
||||
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
||||
return err
|
||||
}
|
||||
st, ok := status.FromError(err)
|
||||
if ok && st.Code() == codes.Canceled {
|
||||
return context.Canceled
|
||||
}
|
||||
if ok && st.Code() == codes.DeadlineExceeded {
|
||||
return context.DeadlineExceeded
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -240,7 +240,7 @@ func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResN
|
|||
var res ResNetMapSnapshot
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &res, err
|
||||
}
|
||||
|
||||
if !apistatus.IsSuccessful(res.st) {
|
||||
|
|
|
@ -149,7 +149,7 @@ func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObj
|
|||
var res ResObjectDelete
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &res, err
|
||||
}
|
||||
|
||||
if !apistatus.IsSuccessful(res.st) {
|
||||
|
|
|
@ -493,7 +493,7 @@ func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectH
|
|||
var res ResObjectHead
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &res, err
|
||||
}
|
||||
|
||||
if !apistatus.IsSuccessful(res.st) {
|
||||
|
|
|
@ -190,7 +190,7 @@ func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectH
|
|||
var res ResObjectHash
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &res, err
|
||||
}
|
||||
|
||||
if !apistatus.IsSuccessful(res.st) {
|
||||
|
|
|
@ -247,7 +247,7 @@ func (x *objectPatcher) Close(_ context.Context) (*ResObjectPatch, error) {
|
|||
|
||||
x.res.st, x.err = x.client.processResponse(&x.respV2)
|
||||
if x.err != nil {
|
||||
return nil, x.err
|
||||
return &x.res, x.err
|
||||
}
|
||||
|
||||
if !apistatus.IsSuccessful(x.res.st) {
|
||||
|
|
|
@ -157,7 +157,7 @@ func (x *objectWriterRaw) Close(_ context.Context) (*ResObjectPut, error) {
|
|||
|
||||
x.res.st, x.err = x.client.processResponse(&x.respV2)
|
||||
if x.err != nil {
|
||||
return nil, x.err
|
||||
return &x.res, x.err
|
||||
}
|
||||
|
||||
if !apistatus.IsSuccessful(x.res.st) {
|
||||
|
|
|
@ -167,7 +167,7 @@ func (c *Client) ObjectPutSingle(ctx context.Context, prm PrmObjectPutSingle) (*
|
|||
var res ResObjectPutSingle
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &res, err
|
||||
}
|
||||
res.epoch = resp.GetMetaHeader().GetEpoch()
|
||||
|
||||
|
|
|
@ -356,8 +356,7 @@ func (x Container) IterateUserAttributes(f func(key, val string)) {
|
|||
attrs := x.v2.GetAttributes()
|
||||
for _, attr := range attrs {
|
||||
key := attr.GetKey()
|
||||
if !strings.HasPrefix(key, container.SysAttributePrefix) &&
|
||||
!strings.HasPrefix(key, container.SysAttributePrefixNeoFS) {
|
||||
if !strings.HasPrefix(key, container.SysAttributePrefix) {
|
||||
f(key, attr.GetValue())
|
||||
}
|
||||
}
|
||||
|
@ -417,8 +416,7 @@ func DisableHomomorphicHashing(cnr *Container) {
|
|||
//
|
||||
// Zero Container has enabled hashing.
|
||||
func IsHomomorphicHashingDisabled(cnr Container) bool {
|
||||
return cnr.Attribute(container.SysAttributeHomomorphicHashing) == attributeHomoHashEnabled ||
|
||||
cnr.Attribute(container.SysAttributeHomomorphicHashingNeoFS) == attributeHomoHashEnabled
|
||||
return cnr.Attribute(container.SysAttributeHomomorphicHashing) == attributeHomoHashEnabled
|
||||
}
|
||||
|
||||
// Domain represents information about container domain registered in the NNS
|
||||
|
@ -467,9 +465,6 @@ func ReadDomain(cnr Container) (res Domain) {
|
|||
if name := cnr.Attribute(container.SysAttributeName); name != "" {
|
||||
res.SetName(name)
|
||||
res.SetZone(cnr.Attribute(container.SysAttributeZone))
|
||||
} else if name = cnr.Attribute(container.SysAttributeNameNeoFS); name != "" {
|
||||
res.SetName(name)
|
||||
res.SetZone(cnr.Attribute(container.SysAttributeZoneNeoFS))
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -150,7 +150,7 @@ func assertContainsAttribute(t *testing.T, m v2container.Container, key, val str
|
|||
}
|
||||
|
||||
func TestContainer_Attribute(t *testing.T) {
|
||||
const attrKey1, attrKey2 = v2container.SysAttributePrefix + "key1", v2container.SysAttributePrefixNeoFS + "key2"
|
||||
const attrKey1, attrKey2 = v2container.SysAttributePrefix + "key1", v2container.SysAttributePrefix + "key2"
|
||||
const attrVal1, attrVal2 = "val1", "val2"
|
||||
|
||||
val := containertest.Container()
|
||||
|
|
4
go.mod
4
go.mod
|
@ -7,7 +7,7 @@ require (
|
|||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e
|
||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1
|
||||
git.frostfs.info/TrueCloudLab/tzhash v1.8.0
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
github.com/klauspost/reedsolomon v1.12.1
|
||||
|
@ -40,7 +40,7 @@ require (
|
|||
go.etcd.io/bbolt v1.3.9 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
golang.org/x/net v0.26.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
|
|
8
go.sum
8
go.sum
|
@ -12,8 +12,8 @@ git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjq
|
|||
git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3GYvaX1a8GQZQHvlF8=
|
||||
github.com/VictoriaMetrics/easyproto v0.1.4 h1:r8cNvo8o6sR4QShBXQd1bKw/VVLSQma/V2KhTBPf+Sc=
|
||||
github.com/VictoriaMetrics/easyproto v0.1.4/go.mod h1:QlGlzaJnDfFd8Lk6Ci/fuLxfTo3/GThPs2KH23mv710=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c=
|
||||
|
@ -124,8 +124,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
|
@ -19,10 +19,10 @@ repStmt:
|
|||
cbfStmt: CBF BackupFactor = NUMBER1; // container backup factor
|
||||
|
||||
selectStmt:
|
||||
SELECT Count = NUMBER1 // number of nodes to select without container backup factor *)
|
||||
(IN clause? Bucket = ident)? // bucket name
|
||||
FROM Filter = identWC // filter reference or whole netmap
|
||||
(AS Name = ident)? // optional selector name
|
||||
SELECT Count = NUMBER1 // number of nodes to select without container backup factor *)
|
||||
(IN clause? Bucket = filterKey)? // bucket name
|
||||
FROM Filter = identWC // filter reference or whole netmap
|
||||
(AS Name = ident)? // optional selector name
|
||||
;
|
||||
|
||||
clause: CLAUSE_SAME | CLAUSE_DISTINCT; // nodes from distinct buckets
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,5 @@
|
|||
package parser
|
||||
|
||||
// ANTLR can be downloaded from https://www.antlr.org/download/antlr-4.13.0-complete.jar
|
||||
//go:generate java -Xmx500M -cp "./antlr-4.13.0-complete.jar:$CLASSPATH" org.antlr.v4.Tool -Dlanguage=Go -no-listener -visitor QueryLexer.g4 Query.g4
|
||||
// You can download ANTLR from https://www.antlr.org/download/antlr-4.13.1-complete.jar,
|
||||
// then run generate or simply run the dedicated Makefile target like this `make policy`.
|
||||
//go:generate java -Xmx500M -cp "./antlr-4.13.1-complete.jar:$CLASSPATH" org.antlr.v4.Tool -Dlanguage=Go -no-listener -visitor QueryLexer.g4 Query.g4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated from /repo/frostfs/sdk-go/netmap/parser/Query.g4 by ANTLR 4.13.0. DO NOT EDIT.
|
||||
// Code generated from netmap/parser/Query.g4 by ANTLR 4.13.1. DO NOT EDIT.
|
||||
|
||||
package parser // Query
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated from /repo/frostfs/sdk-go/netmap/parser/QueryLexer.g4 by ANTLR 4.13.0. DO NOT EDIT.
|
||||
// Code generated from netmap/parser/QueryLexer.g4 by ANTLR 4.13.1. DO NOT EDIT.
|
||||
|
||||
package parser
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated from /repo/frostfs/sdk-go/netmap/parser/Query.g4 by ANTLR 4.13.0. DO NOT EDIT.
|
||||
// Code generated from netmap/parser/Query.g4 by ANTLR 4.13.1. DO NOT EDIT.
|
||||
|
||||
package parser // Query
|
||||
|
||||
|
@ -93,7 +93,7 @@ func queryParserInit() {
|
|||
85, 1, 0, 0, 0, 85, 7, 1, 0, 0, 0, 86, 87, 5, 10, 0, 0, 87, 88, 5, 22,
|
||||
0, 0, 88, 9, 1, 0, 0, 0, 89, 90, 5, 11, 0, 0, 90, 96, 5, 22, 0, 0, 91,
|
||||
93, 5, 8, 0, 0, 92, 94, 3, 12, 6, 0, 93, 92, 1, 0, 0, 0, 93, 94, 1, 0,
|
||||
0, 0, 94, 95, 1, 0, 0, 0, 95, 97, 3, 28, 14, 0, 96, 91, 1, 0, 0, 0, 96,
|
||||
0, 0, 94, 95, 1, 0, 0, 0, 95, 97, 3, 20, 10, 0, 96, 91, 1, 0, 0, 0, 96,
|
||||
97, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 99, 5, 12, 0, 0, 99, 102, 3, 30,
|
||||
15, 0, 100, 101, 5, 9, 0, 0, 101, 103, 3, 28, 14, 0, 102, 100, 1, 0, 0,
|
||||
0, 102, 103, 1, 0, 0, 0, 103, 11, 1, 0, 0, 0, 104, 105, 7, 0, 0, 0, 105,
|
||||
|
@ -1364,7 +1364,7 @@ type ISelectStmtContext interface {
|
|||
SetCount(antlr.Token)
|
||||
|
||||
// GetBucket returns the Bucket rule contexts.
|
||||
GetBucket() IIdentContext
|
||||
GetBucket() IFilterKeyContext
|
||||
|
||||
// GetFilter returns the Filter rule contexts.
|
||||
GetFilter() IIdentWCContext
|
||||
|
@ -1373,7 +1373,7 @@ type ISelectStmtContext interface {
|
|||
GetName() IIdentContext
|
||||
|
||||
// SetBucket sets the Bucket rule contexts.
|
||||
SetBucket(IIdentContext)
|
||||
SetBucket(IFilterKeyContext)
|
||||
|
||||
// SetFilter sets the Filter rule contexts.
|
||||
SetFilter(IIdentWCContext)
|
||||
|
@ -1388,8 +1388,8 @@ type ISelectStmtContext interface {
|
|||
IdentWC() IIdentWCContext
|
||||
IN() antlr.TerminalNode
|
||||
AS() antlr.TerminalNode
|
||||
AllIdent() []IIdentContext
|
||||
Ident(i int) IIdentContext
|
||||
FilterKey() IFilterKeyContext
|
||||
Ident() IIdentContext
|
||||
Clause() IClauseContext
|
||||
|
||||
// IsSelectStmtContext differentiates from other interfaces.
|
||||
|
@ -1400,7 +1400,7 @@ type SelectStmtContext struct {
|
|||
antlr.BaseParserRuleContext
|
||||
parser antlr.Parser
|
||||
Count antlr.Token
|
||||
Bucket IIdentContext
|
||||
Bucket IFilterKeyContext
|
||||
Filter IIdentWCContext
|
||||
Name IIdentContext
|
||||
}
|
||||
|
@ -1436,13 +1436,13 @@ func (s *SelectStmtContext) GetCount() antlr.Token { return s.Count }
|
|||
|
||||
func (s *SelectStmtContext) SetCount(v antlr.Token) { s.Count = v }
|
||||
|
||||
func (s *SelectStmtContext) GetBucket() IIdentContext { return s.Bucket }
|
||||
func (s *SelectStmtContext) GetBucket() IFilterKeyContext { return s.Bucket }
|
||||
|
||||
func (s *SelectStmtContext) GetFilter() IIdentWCContext { return s.Filter }
|
||||
|
||||
func (s *SelectStmtContext) GetName() IIdentContext { return s.Name }
|
||||
|
||||
func (s *SelectStmtContext) SetBucket(v IIdentContext) { s.Bucket = v }
|
||||
func (s *SelectStmtContext) SetBucket(v IFilterKeyContext) { s.Bucket = v }
|
||||
|
||||
func (s *SelectStmtContext) SetFilter(v IIdentWCContext) { s.Filter = v }
|
||||
|
||||
|
@ -1484,37 +1484,28 @@ func (s *SelectStmtContext) AS() antlr.TerminalNode {
|
|||
return s.GetToken(QueryAS, 0)
|
||||
}
|
||||
|
||||
func (s *SelectStmtContext) AllIdent() []IIdentContext {
|
||||
children := s.GetChildren()
|
||||
len := 0
|
||||
for _, ctx := range children {
|
||||
if _, ok := ctx.(IIdentContext); ok {
|
||||
len++
|
||||
func (s *SelectStmtContext) FilterKey() IFilterKeyContext {
|
||||
var t antlr.RuleContext
|
||||
for _, ctx := range s.GetChildren() {
|
||||
if _, ok := ctx.(IFilterKeyContext); ok {
|
||||
t = ctx.(antlr.RuleContext)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
tst := make([]IIdentContext, len)
|
||||
i := 0
|
||||
for _, ctx := range children {
|
||||
if t, ok := ctx.(IIdentContext); ok {
|
||||
tst[i] = t.(IIdentContext)
|
||||
i++
|
||||
}
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return tst
|
||||
return t.(IFilterKeyContext)
|
||||
}
|
||||
|
||||
func (s *SelectStmtContext) Ident(i int) IIdentContext {
|
||||
func (s *SelectStmtContext) Ident() IIdentContext {
|
||||
var t antlr.RuleContext
|
||||
j := 0
|
||||
for _, ctx := range s.GetChildren() {
|
||||
if _, ok := ctx.(IIdentContext); ok {
|
||||
if j == i {
|
||||
t = ctx.(antlr.RuleContext)
|
||||
break
|
||||
}
|
||||
j++
|
||||
t = ctx.(antlr.RuleContext)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1617,7 +1608,7 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) {
|
|||
{
|
||||
p.SetState(95)
|
||||
|
||||
var _x = p.Ident()
|
||||
var _x = p.FilterKey()
|
||||
|
||||
localctx.(*SelectStmtContext).Bucket = _x
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated from /repo/frostfs/sdk-go/netmap/parser/Query.g4 by ANTLR 4.13.0. DO NOT EDIT.
|
||||
// Code generated from netmap/parser/Query.g4 by ANTLR 4.13.1. DO NOT EDIT.
|
||||
|
||||
package parser // Query
|
||||
|
||||
|
|
|
@ -82,6 +82,13 @@ CBF 1
|
|||
SELECT 1 FROM Color
|
||||
FILTER (Color EQ Red OR Color EQ Blue OR Color EQ Yellow) AND Color NE Green AS Color`,
|
||||
},
|
||||
{
|
||||
name: "non-ascii attributes in SELECT IN",
|
||||
input: `REP 1
|
||||
CBF 1
|
||||
SELECT 1 IN SAME 'Цвет' FROM Colorful
|
||||
FILTER 'Цвет' EQ 'Красный' OR 'Цвет' EQ 'Синий' AS Colorful`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
@ -127,6 +134,11 @@ func TestDecodeSelectFilterExpr(t *testing.T) {
|
|||
SELECT 1 FROM R
|
||||
FILTER Color LIKE 'R' AS R
|
||||
`,
|
||||
`
|
||||
CBF 1
|
||||
SELECT 1 IN SAME 'Цвет' FROM Colorful
|
||||
FILTER 'Цвет' EQ 'Красный' OR 'Цвет' EQ 'Синий' AS Colorful
|
||||
`,
|
||||
} {
|
||||
_, err := DecodeSelectFilterString(s)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
mrand "math/rand"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -13,6 +14,7 @@ import (
|
|||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/hrw"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -542,6 +544,66 @@ func TestPlacementPolicy_ProcessSelectorsExceptForNodes(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPlacementPolicy_NonAsciiAttributes(t *testing.T) {
|
||||
p := newPlacementPolicy(
|
||||
1,
|
||||
[]ReplicaDescriptor{
|
||||
newReplica(2, "Nodes"),
|
||||
newReplica(2, "Nodes"),
|
||||
},
|
||||
[]Selector{
|
||||
newSelector("Nodes", "Цвет", 2, "Colorful", (*Selector).SelectSame),
|
||||
},
|
||||
[]Filter{
|
||||
newFilter("Colorful", "", "", netmap.OR,
|
||||
newFilter("", "Цвет", "Красный", netmap.EQ),
|
||||
newFilter("", "Цвет", "Синий", netmap.EQ),
|
||||
),
|
||||
},
|
||||
)
|
||||
p.SetUnique(true)
|
||||
|
||||
nodes := []NodeInfo{
|
||||
nodeInfoFromAttributes("Цвет", "Красный", "Форма", "Треугольник"),
|
||||
nodeInfoFromAttributes("Цвет", "Красный", "Форма", "Круг"),
|
||||
nodeInfoFromAttributes("Цвет", "Синий", "Форма", "Треугольник"),
|
||||
nodeInfoFromAttributes("Цвет", "Синий", "Форма", "Круг"),
|
||||
nodeInfoFromAttributes("Свойство", "Мягкий", "Форма", "Треугольник"),
|
||||
nodeInfoFromAttributes("Свойство", "Теплый", "Форма", "Круг"),
|
||||
}
|
||||
for i := range nodes {
|
||||
nodes[i].SetPublicKey([]byte{byte(i)})
|
||||
}
|
||||
|
||||
redNodes := nodes[:2]
|
||||
blueNodes := nodes[2:4]
|
||||
|
||||
var nm NetMap
|
||||
nm.SetNodes(nodes)
|
||||
|
||||
pivot := make([]byte, 42)
|
||||
_, _ = rand.Read(pivot)
|
||||
|
||||
nodesPerReplica, err := nm.ContainerNodes(p, pivot)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, nodesPerReplica, 2)
|
||||
|
||||
for i := range nodesPerReplica {
|
||||
slices.SortFunc(nodesPerReplica[i], func(n1, n2 NodeInfo) int {
|
||||
pk1, pk2 := string(n1.PublicKey()), string(n2.PublicKey())
|
||||
return cmp.Compare(pk1, pk2)
|
||||
})
|
||||
}
|
||||
|
||||
redMatchFirst := reflect.DeepEqual(redNodes, nodesPerReplica[0])
|
||||
blueMatchFirst := reflect.DeepEqual(blueNodes, nodesPerReplica[0])
|
||||
|
||||
redMatchSecond := reflect.DeepEqual(redNodes, nodesPerReplica[1])
|
||||
blueMatchSecond := reflect.DeepEqual(blueNodes, nodesPerReplica[1])
|
||||
|
||||
assert.True(t, redMatchFirst && blueMatchSecond || blueMatchFirst && redMatchSecond)
|
||||
}
|
||||
|
||||
func TestSelector_SetName(t *testing.T) {
|
||||
const name = "some name"
|
||||
var s Selector
|
||||
|
|
|
@ -3,7 +3,10 @@ package object
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
|
@ -312,6 +315,23 @@ func (o *Object) Attributes() []Attribute {
|
|||
return res
|
||||
}
|
||||
|
||||
// UserAttributes returns object user attributes.
|
||||
func (o *Object) UserAttributes() []Attribute {
|
||||
attrs := (*object.Object)(o).
|
||||
GetHeader().
|
||||
GetAttributes()
|
||||
|
||||
res := make([]Attribute, 0, len(attrs))
|
||||
|
||||
for _, attr := range attrs {
|
||||
if !strings.HasPrefix(attr.GetKey(), container.SysAttributePrefix) {
|
||||
res = append(res, *NewAttributeFromV2(&attr))
|
||||
}
|
||||
}
|
||||
|
||||
return slices.Clip(res)
|
||||
}
|
||||
|
||||
// SetAttributes sets object attributes.
|
||||
func (o *Object) SetAttributes(v ...Attribute) {
|
||||
attrs := make([]object.Attribute, len(v))
|
||||
|
|
|
@ -3,8 +3,10 @@ package object_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/test"
|
||||
usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -24,3 +26,26 @@ func TestInitCreation(t *testing.T) {
|
|||
require.Equal(t, cnr, cID)
|
||||
require.Equal(t, own, o.OwnerID())
|
||||
}
|
||||
|
||||
func Test_Attributes(t *testing.T) {
|
||||
obj := objecttest.Object()
|
||||
|
||||
t.Run("get user attributes", func(t *testing.T) {
|
||||
// See how we create a test object. It's created with two attributes.
|
||||
require.Len(t, obj.UserAttributes(), 2)
|
||||
})
|
||||
|
||||
userAttrs := obj.UserAttributes()
|
||||
|
||||
sysAttr := *object.NewAttribute()
|
||||
sysAttr.SetKey(v2container.SysAttributePrefix + "key")
|
||||
sysAttr.SetValue("value")
|
||||
|
||||
attr := append(userAttrs, sysAttr)
|
||||
obj.SetAttributes(attr...)
|
||||
|
||||
t.Run("get attributes", func(t *testing.T) {
|
||||
require.ElementsMatch(t, obj.UserAttributes(), userAttrs)
|
||||
require.ElementsMatch(t, obj.Attributes(), attr)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue