diff --git a/CHANGELOG.md b/CHANGELOG.md index b4cdf0012..549eb4349 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release. - Support `IPROTO_WATCH_ONCE` request type for Tarantool version >= 3.0.0-alpha1 (#337) - Support `yield_every` option for crud select requests (#350) +- Support `IPROTO_FEATURE_SPACE_AND_INDEX_NAMES` for Tarantool + version >= 3.0.0-alpha1 (#338). It allows to use space and index names + in requests instead of their IDs ### Changed diff --git a/README.md b/README.md index eae6f92ab..f8483dc34 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,14 @@ and user may cancel it in process. * `iproto.Feature` type used instead of `ProtocolFeature`. * `iproto.IPROTO_FEATURE_` constants used instead of local ones. +#### Schema changes + +* `ResolveSpaceIndex` function for `SchemaResolver` interface split into two: +`ResolveSpace` and `ResolveIndex`. `NamesUseSupported` function added into the +interface to get information if the usage of space and index names in requests +is supported. +* `Schema` structure no longer implements `SchemaResolver` interface. + ## Contributing See [the contributing guide](CONTRIBUTING.md) for detailed instructions on how diff --git a/connection.go b/connection.go index 018df6caa..e7071d3e3 100644 --- a/connection.go +++ b/connection.go @@ -162,6 +162,8 @@ type Connection struct { cond *sync.Cond // Schema contains schema loaded on connection. Schema *Schema + // schemaResolver contains a SchemaResolver implementation. + schemaResolver SchemaResolver // requestId contains the last request ID for requests with nil context. requestId uint32 // contextRequestId contains the last request ID for requests with context. @@ -384,6 +386,10 @@ func Connect(ctx context.Context, addr string, opts Opts) (conn *Connection, err control: make(chan struct{}), opts: opts.Clone(), dec: msgpack.NewDecoder(&smallBuf{}), + schemaResolver: &noSchemaResolver{ + isFeatureInSlice(iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES, + opts.RequiredProtocolInfo.Features), + }, } maxprocs := uint32(runtime.GOMAXPROCS(-1)) if conn.opts.Concurrency == 0 || conn.opts.Concurrency > maxprocs*128 { @@ -1102,7 +1108,7 @@ func (conn *Connection) putFuture(fut *Future, req Request, streamId uint64) { } blen := shard.buf.Len() reqid := fut.requestId - if err := pack(&shard.buf, shard.enc, reqid, req, streamId, conn.Schema); err != nil { + if err := pack(&shard.buf, shard.enc, reqid, req, streamId, conn.schemaResolver); err != nil { shard.buf.Trunc(blen) shard.bufmut.Unlock() if f := conn.fetchFuture(reqid); f == fut { diff --git a/crud/request_test.go b/crud/request_test.go index 8a64ab427..0b728162e 100644 --- a/crud/request_test.go +++ b/crud/request_test.go @@ -3,7 +3,6 @@ package crud_test import ( "bytes" "context" - "errors" "fmt" "testing" @@ -14,14 +13,7 @@ import ( "github.com/tarantool/go-tarantool/v2/crud" ) -const invalidSpaceMsg = "invalid space" -const invalidIndexMsg = "invalid index" - -const invalidSpace = 2 -const invalidIndex = 2 const validSpace = "test" // Any valid value != default. -const defaultSpace = 0 // And valid too. -const defaultIndex = 0 // And valid too. const CrudRequestType = iproto.IPROTO_CALL @@ -69,38 +61,11 @@ var expectedOpts = map[string]interface{}{ "timeout": timeout, } -type ValidSchemeResolver struct { -} - -func (*ValidSchemeResolver) ResolveSpaceIndex(s, i interface{}) (uint32, uint32, error) { - var spaceNo, indexNo uint32 - if s != nil { - spaceNo = uint32(s.(int)) - } else { - spaceNo = defaultSpace - } - if i != nil { - indexNo = uint32(i.(int)) - } else { - indexNo = defaultIndex - } - if spaceNo == invalidSpace { - return 0, 0, errors.New(invalidSpaceMsg) - } - if indexNo == invalidIndex { - return 0, 0, errors.New(invalidIndexMsg) - } - return spaceNo, indexNo, nil -} - -var resolver ValidSchemeResolver - -func extractRequestBody(req tarantool.Request, - resolver tarantool.SchemaResolver) ([]byte, error) { +func extractRequestBody(req tarantool.Request) ([]byte, error) { var reqBuf bytes.Buffer reqEnc := msgpack.NewEncoder(&reqBuf) - err := req.Body(resolver, reqEnc) + err := req.Body(nil, reqEnc) if err != nil { return nil, fmt.Errorf("An unexpected Response.Body() error: %q", err.Error()) } @@ -111,12 +76,12 @@ func extractRequestBody(req tarantool.Request, func assertBodyEqual(t testing.TB, reference tarantool.Request, req tarantool.Request) { t.Helper() - reqBody, err := extractRequestBody(req, &resolver) + reqBody, err := extractRequestBody(req) if err != nil { t.Fatalf("An unexpected Response.Body() error: %q", err.Error()) } - refBody, err := extractRequestBody(reference, &resolver) + refBody, err := extractRequestBody(reference) if err != nil { t.Fatalf("An unexpected Response.Body() error: %q", err.Error()) } diff --git a/example_test.go b/example_test.go index f85f532d0..9b66ea29b 100644 --- a/example_test.go +++ b/example_test.go @@ -231,6 +231,21 @@ func ExampleSelectRequest() { // response is [{{} 1111 hello world}] } +func ExampleSelectRequest_spaceAndIndexNames() { + conn := exampleConnect(opts) + defer conn.Close() + + req := tarantool.NewSelectRequest(spaceName) + req.Index(indexName) + resp, err := conn.Do(req).Get() + + if err != nil { + fmt.Printf("Failed to execute the request: %s\n", err) + } else { + fmt.Println(resp.Data) + } +} + func ExampleInsertRequest() { conn := exampleConnect(opts) defer conn.Close() @@ -273,6 +288,20 @@ func ExampleInsertRequest() { // Data [[32 test one]] } +func ExampleInsertRequest_spaceAndIndexNames() { + conn := exampleConnect(opts) + defer conn.Close() + + req := tarantool.NewInsertRequest(spaceName) + resp, err := conn.Do(req).Get() + + if err != nil { + fmt.Printf("Failed to execute the request: %s\n", err) + } else { + fmt.Println(resp.Data) + } +} + func ExampleDeleteRequest() { conn := exampleConnect(opts) defer conn.Close() @@ -316,6 +345,21 @@ func ExampleDeleteRequest() { // Data [[36 test one]] } +func ExampleDeleteRequest_spaceAndIndexNames() { + conn := exampleConnect(opts) + defer conn.Close() + + req := tarantool.NewDeleteRequest(spaceName) + req.Index(indexName) + resp, err := conn.Do(req).Get() + + if err != nil { + fmt.Printf("Failed to execute the request: %s\n", err) + } else { + fmt.Println(resp.Data) + } +} + func ExampleReplaceRequest() { conn := exampleConnect(opts) defer conn.Close() @@ -375,6 +419,20 @@ func ExampleReplaceRequest() { // Data [[13 test twelve]] } +func ExampleReplaceRequest_spaceAndIndexNames() { + conn := exampleConnect(opts) + defer conn.Close() + + req := tarantool.NewReplaceRequest(spaceName) + resp, err := conn.Do(req).Get() + + if err != nil { + fmt.Printf("Failed to execute the request: %s\n", err) + } else { + fmt.Println(resp.Data) + } +} + func ExampleUpdateRequest() { conn := exampleConnect(opts) defer conn.Close() @@ -411,6 +469,21 @@ func ExampleUpdateRequest() { // response is []interface {}{[]interface {}{0x457, "hello", "world"}} } +func ExampleUpdateRequest_spaceAndIndexNames() { + conn := exampleConnect(opts) + defer conn.Close() + + req := tarantool.NewUpdateRequest(spaceName) + req.Index(indexName) + resp, err := conn.Do(req).Get() + + if err != nil { + fmt.Printf("Failed to execute the request: %s\n", err) + } else { + fmt.Println(resp.Data) + } +} + func ExampleUpsertRequest() { conn := exampleConnect(opts) defer conn.Close() @@ -452,6 +525,20 @@ func ExampleUpsertRequest() { // response is []interface {}{[]interface {}{0x459, "first", "updated"}} } +func ExampleUpsertRequest_spaceAndIndexNames() { + conn := exampleConnect(opts) + defer conn.Close() + + req := tarantool.NewUpsertRequest(spaceName) + resp, err := conn.Do(req).Get() + + if err != nil { + fmt.Printf("Failed to execute the request: %s\n", err) + } else { + fmt.Println(resp.Data) + } +} + func ExampleCallRequest() { conn := exampleConnect(opts) defer conn.Close() @@ -634,6 +721,7 @@ func ExampleProtocolVersion() { // Connector client protocol feature: IPROTO_FEATURE_ERROR_EXTENSION // Connector client protocol feature: IPROTO_FEATURE_WATCHERS // Connector client protocol feature: IPROTO_FEATURE_PAGINATION + // Connector client protocol feature: IPROTO_FEATURE_SPACE_AND_INDEX_NAMES // Connector client protocol feature: IPROTO_FEATURE_WATCH_ONCE } diff --git a/export_test.go b/export_test.go index 38211a4fc..a52ef5b26 100644 --- a/export_test.go +++ b/export_test.go @@ -25,39 +25,80 @@ func RefImplPingBody(enc *msgpack.Encoder) error { // RefImplSelectBody is reference implementation for filling of a select // request's body. -func RefImplSelectBody(enc *msgpack.Encoder, space, index, offset, limit uint32, iterator Iter, - key, after interface{}, fetchPos bool) error { - return fillSelect(enc, space, index, offset, limit, iterator, key, after, fetchPos) +func RefImplSelectBody(enc *msgpack.Encoder, res SchemaResolver, space, index interface{}, + offset, limit uint32, iterator Iter, key, after interface{}, fetchPos bool) error { + spaceEnc, err := newSpaceEncoder(res, space) + if err != nil { + return err + } + indexEnc, err := newIndexEncoder(res, index, spaceEnc.Id) + if err != nil { + return err + } + return fillSelect(enc, spaceEnc, indexEnc, offset, limit, iterator, key, after, fetchPos) } // RefImplInsertBody is reference implementation for filling of an insert // request's body. -func RefImplInsertBody(enc *msgpack.Encoder, space uint32, tuple interface{}) error { - return fillInsert(enc, space, tuple) +func RefImplInsertBody(enc *msgpack.Encoder, res SchemaResolver, space, + tuple interface{}) error { + spaceEnc, err := newSpaceEncoder(res, space) + if err != nil { + return err + } + return fillInsert(enc, spaceEnc, tuple) } // RefImplReplaceBody is reference implementation for filling of a replace // request's body. -func RefImplReplaceBody(enc *msgpack.Encoder, space uint32, tuple interface{}) error { - return fillInsert(enc, space, tuple) +func RefImplReplaceBody(enc *msgpack.Encoder, res SchemaResolver, space, + tuple interface{}) error { + spaceEnc, err := newSpaceEncoder(res, space) + if err != nil { + return err + } + return fillInsert(enc, spaceEnc, tuple) } // RefImplDeleteBody is reference implementation for filling of a delete // request's body. -func RefImplDeleteBody(enc *msgpack.Encoder, space, index uint32, key interface{}) error { - return fillDelete(enc, space, index, key) +func RefImplDeleteBody(enc *msgpack.Encoder, res SchemaResolver, space, index, + key interface{}) error { + spaceEnc, err := newSpaceEncoder(res, space) + if err != nil { + return err + } + indexEnc, err := newIndexEncoder(res, index, spaceEnc.Id) + if err != nil { + return err + } + return fillDelete(enc, spaceEnc, indexEnc, key) } // RefImplUpdateBody is reference implementation for filling of an update // request's body. -func RefImplUpdateBody(enc *msgpack.Encoder, space, index uint32, key, ops interface{}) error { - return fillUpdate(enc, space, index, key, ops) +func RefImplUpdateBody(enc *msgpack.Encoder, res SchemaResolver, space, index, + key, ops interface{}) error { + spaceEnc, err := newSpaceEncoder(res, space) + if err != nil { + return err + } + indexEnc, err := newIndexEncoder(res, index, spaceEnc.Id) + if err != nil { + return err + } + return fillUpdate(enc, spaceEnc, indexEnc, key, ops) } // RefImplUpsertBody is reference implementation for filling of an upsert // request's body. -func RefImplUpsertBody(enc *msgpack.Encoder, space uint32, tuple, ops interface{}) error { - return fillUpsert(enc, space, tuple, ops) +func RefImplUpsertBody(enc *msgpack.Encoder, res SchemaResolver, space, + tuple, ops interface{}) error { + spaceEnc, err := newSpaceEncoder(res, space) + if err != nil { + return err + } + return fillUpsert(enc, spaceEnc, tuple, ops) } // RefImplCallBody is reference implementation for filling of a call or call17 diff --git a/protocol.go b/protocol.go index 7de8b197e..9296943ce 100644 --- a/protocol.go +++ b/protocol.go @@ -56,6 +56,7 @@ var clientProtocolInfo ProtocolInfo = ProtocolInfo{ iproto.IPROTO_FEATURE_ERROR_EXTENSION, iproto.IPROTO_FEATURE_WATCHERS, iproto.IPROTO_FEATURE_PAGINATION, + iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES, iproto.IPROTO_FEATURE_WATCH_ONCE, }, } diff --git a/request.go b/request.go index 3332486f4..c2e7cf96d 100644 --- a/request.go +++ b/request.go @@ -12,19 +12,90 @@ import ( "github.com/vmihailenco/msgpack/v5" ) -func fillSearch(enc *msgpack.Encoder, spaceNo, indexNo uint32, key interface{}) error { - if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil { +type spaceEncoder struct { + Id uint32 + Name string + IsId bool +} + +func newSpaceEncoder(res SchemaResolver, spaceInfo interface{}) (spaceEncoder, error) { + if res.NamesUseSupported() { + if spaceName, ok := spaceInfo.(string); ok { + return spaceEncoder{ + Id: 0, + Name: spaceName, + IsId: false, + }, nil + } + } + + spaceId, err := res.ResolveSpace(spaceInfo) + return spaceEncoder{ + Id: spaceId, + IsId: true, + }, err +} + +func (e spaceEncoder) Encode(enc *msgpack.Encoder) error { + if e.IsId { + if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil { + return err + } + return enc.EncodeUint(uint64(e.Id)) + } + if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_NAME)); err != nil { return err } - if err := enc.EncodeUint(uint64(spaceNo)); err != nil { + return enc.EncodeString(e.Name) +} + +type indexEncoder struct { + Id uint32 + Name string + IsId bool +} + +func newIndexEncoder(res SchemaResolver, indexInfo interface{}, + spaceNo uint32) (indexEncoder, error) { + if res.NamesUseSupported() { + if indexName, ok := indexInfo.(string); ok { + return indexEncoder{ + Name: indexName, + IsId: false, + }, nil + } + } + + indexId, err := res.ResolveIndex(indexInfo, spaceNo) + return indexEncoder{ + Id: indexId, + IsId: true, + }, err +} + +func (e indexEncoder) Encode(enc *msgpack.Encoder) error { + if e.IsId { + if err := enc.EncodeUint(uint64(iproto.IPROTO_INDEX_ID)); err != nil { + return err + } + return enc.EncodeUint(uint64(e.Id)) + } + if err := enc.EncodeUint(uint64(iproto.IPROTO_INDEX_NAME)); err != nil { return err } - if err := enc.EncodeUint(uint64(iproto.IPROTO_INDEX_ID)); err != nil { + return enc.EncodeString(e.Name) +} + +func fillSearch(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder, + key interface{}) error { + if err := spaceEnc.Encode(enc); err != nil { return err } - if err := enc.EncodeUint(uint64(indexNo)); err != nil { + + if err := indexEnc.Encode(enc); err != nil { return err } + if err := enc.EncodeUint(uint64(iproto.IPROTO_KEY)); err != nil { return err } @@ -50,24 +121,22 @@ func fillIterator(enc *msgpack.Encoder, offset, limit uint32, iterator Iter) err return enc.EncodeUint(uint64(limit)) } -func fillInsert(enc *msgpack.Encoder, spaceNo uint32, tuple interface{}) error { +func fillInsert(enc *msgpack.Encoder, spaceEnc spaceEncoder, tuple interface{}) error { if err := enc.EncodeMapLen(2); err != nil { return err } - if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil { - return err - } - if err := enc.EncodeUint(uint64(spaceNo)); err != nil { + if err := spaceEnc.Encode(enc); err != nil { return err } + if err := enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)); err != nil { return err } return enc.Encode(tuple) } -func fillSelect(enc *msgpack.Encoder, spaceNo, indexNo, offset, limit uint32, iterator Iter, - key, after interface{}, fetchPos bool) error { +func fillSelect(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder, + offset, limit uint32, iterator Iter, key, after interface{}, fetchPos bool) error { mapLen := 6 if fetchPos { mapLen += 1 @@ -81,7 +150,7 @@ func fillSelect(enc *msgpack.Encoder, spaceNo, indexNo, offset, limit uint32, it if err := fillIterator(enc, offset, limit, iterator); err != nil { return err } - if err := fillSearch(enc, spaceNo, indexNo, key); err != nil { + if err := fillSearch(enc, spaceEnc, indexEnc, key); err != nil { return err } if fetchPos { @@ -112,19 +181,22 @@ func fillSelect(enc *msgpack.Encoder, spaceNo, indexNo, offset, limit uint32, it return nil } -func fillUpdate(enc *msgpack.Encoder, spaceNo, indexNo uint32, key, ops interface{}) error { +func fillUpdate(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder, + key, ops interface{}) error { enc.EncodeMapLen(4) - if err := fillSearch(enc, spaceNo, indexNo, key); err != nil { + if err := fillSearch(enc, spaceEnc, indexEnc, key); err != nil { return err } enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)) return enc.Encode(ops) } -func fillUpsert(enc *msgpack.Encoder, spaceNo uint32, tuple, ops interface{}) error { +func fillUpsert(enc *msgpack.Encoder, spaceEnc spaceEncoder, tuple, ops interface{}) error { enc.EncodeMapLen(3) - enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)) - enc.EncodeUint(uint64(spaceNo)) + if err := spaceEnc.Encode(enc); err != nil { + return err + } + enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)) if err := enc.Encode(tuple); err != nil { return err @@ -133,9 +205,10 @@ func fillUpsert(enc *msgpack.Encoder, spaceNo uint32, tuple, ops interface{}) er return enc.Encode(ops) } -func fillDelete(enc *msgpack.Encoder, spaceNo, indexNo uint32, key interface{}) error { +func fillDelete(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder, + key interface{}) error { enc.EncodeMapLen(3) - return fillSearch(enc, spaceNo, indexNo, key) + return fillSearch(enc, spaceEnc, indexEnc, key) } func fillCall(enc *msgpack.Encoder, functionName string, args interface{}) error { @@ -948,12 +1021,16 @@ func (req *SelectRequest) After(after interface{}) *SelectRequest { // Body fills an encoder with the select request body. func (req *SelectRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { - spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index) + spaceEnc, err := newSpaceEncoder(res, req.space) + if err != nil { + return err + } + indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id) if err != nil { return err } - return fillSelect(enc, spaceNo, indexNo, req.offset, req.limit, req.iterator, + return fillSelect(enc, spaceEnc, indexEnc, req.offset, req.limit, req.iterator, req.key, req.after, req.fetchPos) } @@ -993,12 +1070,12 @@ func (req *InsertRequest) Tuple(tuple interface{}) *InsertRequest { // Body fills an msgpack.Encoder with the insert request body. func (req *InsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { - spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil) + spaceEnc, err := newSpaceEncoder(res, req.space) if err != nil { return err } - return fillInsert(enc, spaceNo, req.tuple) + return fillInsert(enc, spaceEnc, req.tuple) } // Context sets a passed context to the request. @@ -1037,12 +1114,12 @@ func (req *ReplaceRequest) Tuple(tuple interface{}) *ReplaceRequest { // Body fills an msgpack.Encoder with the replace request body. func (req *ReplaceRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { - spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil) + spaceEnc, err := newSpaceEncoder(res, req.space) if err != nil { return err } - return fillInsert(enc, spaceNo, req.tuple) + return fillInsert(enc, spaceEnc, req.tuple) } // Context sets a passed context to the request. @@ -1088,12 +1165,16 @@ func (req *DeleteRequest) Key(key interface{}) *DeleteRequest { // Body fills an msgpack.Encoder with the delete request body. func (req *DeleteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { - spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index) + spaceEnc, err := newSpaceEncoder(res, req.space) + if err != nil { + return err + } + indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id) if err != nil { return err } - return fillDelete(enc, spaceNo, indexNo, req.key) + return fillDelete(enc, spaceEnc, indexEnc, req.key) } // Context sets a passed context to the request. @@ -1150,12 +1231,16 @@ func (req *UpdateRequest) Operations(ops *Operations) *UpdateRequest { // Body fills an msgpack.Encoder with the update request body. func (req *UpdateRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { - spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index) + spaceEnc, err := newSpaceEncoder(res, req.space) + if err != nil { + return err + } + indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id) if err != nil { return err } - return fillUpdate(enc, spaceNo, indexNo, req.key, req.ops) + return fillUpdate(enc, spaceEnc, indexEnc, req.key, req.ops) } // Context sets a passed context to the request. @@ -1205,12 +1290,12 @@ func (req *UpsertRequest) Operations(ops *Operations) *UpsertRequest { // Body fills an msgpack.Encoder with the upsert request body. func (req *UpsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { - spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil) + spaceEnc, err := newSpaceEncoder(res, req.space) if err != nil { return err } - return fillUpsert(enc, spaceNo, req.tuple, req.ops) + return fillUpsert(enc, spaceEnc, req.tuple, req.ops) } // Context sets a passed context to the request. diff --git a/request_test.go b/request_test.go index 6d08533d3..3829b082c 100644 --- a/request_test.go +++ b/request_test.go @@ -17,14 +17,14 @@ import ( const invalidSpaceMsg = "invalid space" const invalidIndexMsg = "invalid index" -const invalidSpace = 2 -const invalidIndex = 2 -const validSpace = 1 // Any valid value != default. -const validIndex = 3 // Any valid value != default. +const invalidSpace uint32 = 2 +const invalidIndex uint32 = 2 +const validSpace uint32 = 1 // Any valid value != default. +const validIndex uint32 = 3 // Any valid value != default. const validExpr = "any string" // We don't check the value here. const validKey = "foo" // Any string. -const defaultSpace = 0 // And valid too. -const defaultIndex = 0 // And valid too. +const defaultSpace uint32 = 0 // And valid too. +const defaultIndex uint32 = 0 // And valid too. const defaultIsolationLevel = DefaultIsolationLevel const defaultTimeout = 0 @@ -39,27 +39,43 @@ var validProtocolInfo ProtocolInfo = ProtocolInfo{ } type ValidSchemeResolver struct { + nameUseSupported bool + spaceResolverCalls int + indexResolverCalls int } -func (*ValidSchemeResolver) ResolveSpaceIndex(s, i interface{}) (uint32, uint32, error) { - var spaceNo, indexNo uint32 - if s != nil { - spaceNo = uint32(s.(int)) +func (r *ValidSchemeResolver) ResolveSpace(s interface{}) (uint32, error) { + r.spaceResolverCalls++ + + var spaceNo uint32 + if no, ok := s.(uint32); ok { + spaceNo = no } else { spaceNo = defaultSpace } - if i != nil { - indexNo = uint32(i.(int)) + if spaceNo == invalidSpace { + return 0, errors.New(invalidSpaceMsg) + } + return spaceNo, nil +} + +func (r *ValidSchemeResolver) ResolveIndex(i interface{}, spaceNo uint32) (uint32, error) { + r.indexResolverCalls++ + + var indexNo uint32 + if no, ok := i.(uint32); ok { + indexNo = no } else { indexNo = defaultIndex } - if spaceNo == invalidSpace { - return 0, 0, errors.New(invalidSpaceMsg) - } if indexNo == invalidIndex { - return 0, 0, errors.New(invalidIndexMsg) + return 0, errors.New(invalidIndexMsg) } - return spaceNo, indexNo, nil + return indexNo, nil +} + +func (r *ValidSchemeResolver) NamesUseSupported() bool { + return r.nameUseSupported } var resolver ValidSchemeResolver @@ -313,6 +329,58 @@ func TestRequestsCtx_setter(t *testing.T) { } } +func TestResolverCalledWithoutNameSupport(t *testing.T) { + resolver.nameUseSupported = false + resolver.spaceResolverCalls = 0 + resolver.indexResolverCalls = 0 + + req := NewSelectRequest("valid") + req.Index("valid") + + var reqBuf bytes.Buffer + reqEnc := msgpack.NewEncoder(&reqBuf) + + err := req.Body(&resolver, reqEnc) + if err != nil { + t.Errorf("An unexpected Response.Body() error: %q", err.Error()) + } + + if resolver.spaceResolverCalls != 1 { + t.Errorf("ResolveSpace was called %d times instead of 1.", + resolver.spaceResolverCalls) + } + if resolver.indexResolverCalls != 1 { + t.Errorf("ResolveIndex was called %d times instead of 1.", + resolver.indexResolverCalls) + } +} + +func TestResolverNotCalledWithNameSupport(t *testing.T) { + resolver.nameUseSupported = true + resolver.spaceResolverCalls = 0 + resolver.indexResolverCalls = 0 + + req := NewSelectRequest("valid") + req.Index("valid") + + var reqBuf bytes.Buffer + reqEnc := msgpack.NewEncoder(&reqBuf) + + err := req.Body(&resolver, reqEnc) + if err != nil { + t.Errorf("An unexpected Response.Body() error: %q", err.Error()) + } + + if resolver.spaceResolverCalls != 0 { + t.Errorf("ResolveSpace was called %d times instead of 0.", + resolver.spaceResolverCalls) + } + if resolver.indexResolverCalls != 0 { + t.Errorf("ResolveIndex was called %d times instead of 0.", + resolver.indexResolverCalls) + } +} + func TestPingRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer @@ -331,7 +399,7 @@ func TestSelectRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplSelectBody(refEnc, validSpace, defaultIndex, 0, 0xFFFFFFFF, + err := RefImplSelectBody(refEnc, &resolver, validSpace, defaultIndex, 0, 0xFFFFFFFF, IterAll, []interface{}{}, nil, false) if err != nil { t.Errorf("An unexpected RefImplSelectBody() error %q", err.Error()) @@ -342,12 +410,47 @@ func TestSelectRequestDefaultValues(t *testing.T) { assertBodyEqual(t, refBuf.Bytes(), req) } +func TestSelectRequestSpaceByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplSelectBody(refEnc, &resolver, "valid", defaultIndex, 0, 0xFFFFFFFF, + IterAll, []interface{}{}, nil, false) + if err != nil { + t.Errorf("An unexpected RefImplSelectBody() error %q", err.Error()) + return + } + + req := NewSelectRequest("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + +func TestSelectRequestIndexByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplSelectBody(refEnc, &resolver, defaultSpace, "valid", 0, 0xFFFFFFFF, + IterAll, []interface{}{}, nil, false) + if err != nil { + t.Errorf("An unexpected RefImplSelectBody() error %q", err.Error()) + return + } + + req := NewSelectRequest(defaultSpace) + req.Index("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + func TestSelectRequestDefaultIteratorEqIfKey(t *testing.T) { var refBuf bytes.Buffer key := []interface{}{uint(18)} refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplSelectBody(refEnc, validSpace, defaultIndex, 0, 0xFFFFFFFF, + err := RefImplSelectBody(refEnc, &resolver, validSpace, defaultIndex, 0, 0xFFFFFFFF, IterEq, key, nil, false) if err != nil { t.Errorf("An unexpected RefImplSelectBody() error %q", err.Error()) @@ -365,7 +468,7 @@ func TestSelectRequestIteratorNotChangedIfKey(t *testing.T) { const iter = IterGe refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplSelectBody(refEnc, validSpace, defaultIndex, 0, 0xFFFFFFFF, + err := RefImplSelectBody(refEnc, &resolver, validSpace, defaultIndex, 0, 0xFFFFFFFF, iter, key, nil, false) if err != nil { t.Errorf("An unexpected RefImplSelectBody() error %q", err.Error()) @@ -388,7 +491,7 @@ func TestSelectRequestSetters(t *testing.T) { var refBufAfterBytes, refBufAfterKey bytes.Buffer refEncAfterBytes := msgpack.NewEncoder(&refBufAfterBytes) - err := RefImplSelectBody(refEncAfterBytes, validSpace, validIndex, offset, + err := RefImplSelectBody(refEncAfterBytes, &resolver, validSpace, validIndex, offset, limit, iter, key, afterBytes, true) if err != nil { t.Errorf("An unexpected RefImplSelectBody() error %s", err) @@ -396,7 +499,7 @@ func TestSelectRequestSetters(t *testing.T) { } refEncAfterKey := msgpack.NewEncoder(&refBufAfterKey) - err = RefImplSelectBody(refEncAfterKey, validSpace, validIndex, offset, + err = RefImplSelectBody(refEncAfterKey, &resolver, validSpace, validIndex, offset, limit, iter, key, afterKey, true) if err != nil { t.Errorf("An unexpected RefImplSelectBody() error %s", err) @@ -428,7 +531,7 @@ func TestInsertRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplInsertBody(refEnc, validSpace, []interface{}{}) + err := RefImplInsertBody(refEnc, &resolver, validSpace, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplInsertBody() error: %q", err.Error()) return @@ -438,12 +541,28 @@ func TestInsertRequestDefaultValues(t *testing.T) { assertBodyEqual(t, refBuf.Bytes(), req) } +func TestInsertRequestSpaceByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplInsertBody(refEnc, &resolver, "valid", []interface{}{}) + if err != nil { + t.Errorf("An unexpected RefImplInsertBody() error: %q", err.Error()) + return + } + + req := NewInsertRequest("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + func TestInsertRequestSetters(t *testing.T) { tuple := []interface{}{uint(24)} var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplInsertBody(refEnc, validSpace, tuple) + err := RefImplInsertBody(refEnc, &resolver, validSpace, tuple) if err != nil { t.Errorf("An unexpected RefImplInsertBody() error: %q", err.Error()) return @@ -458,7 +577,7 @@ func TestReplaceRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplReplaceBody(refEnc, validSpace, []interface{}{}) + err := RefImplReplaceBody(refEnc, &resolver, validSpace, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplReplaceBody() error: %q", err.Error()) return @@ -468,12 +587,28 @@ func TestReplaceRequestDefaultValues(t *testing.T) { assertBodyEqual(t, refBuf.Bytes(), req) } +func TestReplaceRequestSpaceByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplReplaceBody(refEnc, &resolver, "valid", []interface{}{}) + if err != nil { + t.Errorf("An unexpected RefImplReplaceBody() error: %q", err.Error()) + return + } + + req := NewReplaceRequest("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + func TestReplaceRequestSetters(t *testing.T) { tuple := []interface{}{uint(99)} var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplReplaceBody(refEnc, validSpace, tuple) + err := RefImplReplaceBody(refEnc, &resolver, validSpace, tuple) if err != nil { t.Errorf("An unexpected RefImplReplaceBody() error: %q", err.Error()) return @@ -488,7 +623,7 @@ func TestDeleteRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplDeleteBody(refEnc, validSpace, defaultIndex, []interface{}{}) + err := RefImplDeleteBody(refEnc, &resolver, validSpace, defaultIndex, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplDeleteBody() error: %q", err.Error()) return @@ -498,12 +633,45 @@ func TestDeleteRequestDefaultValues(t *testing.T) { assertBodyEqual(t, refBuf.Bytes(), req) } +func TestDeleteRequestSpaceByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplDeleteBody(refEnc, &resolver, "valid", defaultIndex, []interface{}{}) + if err != nil { + t.Errorf("An unexpected RefImplDeleteBody() error: %q", err.Error()) + return + } + + req := NewDeleteRequest("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + +func TestDeleteRequestIndexByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplDeleteBody(refEnc, &resolver, defaultSpace, "valid", []interface{}{}) + if err != nil { + t.Errorf("An unexpected RefImplDeleteBody() error: %q", err.Error()) + return + } + + req := NewDeleteRequest(defaultSpace) + req.Index("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + func TestDeleteRequestSetters(t *testing.T) { key := []interface{}{uint(923)} var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplDeleteBody(refEnc, validSpace, validIndex, key) + err := RefImplDeleteBody(refEnc, &resolver, validSpace, validIndex, key) if err != nil { t.Errorf("An unexpected RefImplDeleteBody() error: %q", err.Error()) return @@ -519,7 +687,8 @@ func TestUpdateRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplUpdateBody(refEnc, validSpace, defaultIndex, []interface{}{}, []Op{}) + err := RefImplUpdateBody(refEnc, &resolver, validSpace, defaultIndex, + []interface{}{}, []Op{}) if err != nil { t.Errorf("An unexpected RefImplUpdateBody() error: %q", err.Error()) return @@ -529,13 +698,48 @@ func TestUpdateRequestDefaultValues(t *testing.T) { assertBodyEqual(t, refBuf.Bytes(), req) } +func TestUpdateRequestSpaceByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplUpdateBody(refEnc, &resolver, "valid", defaultIndex, + []interface{}{}, []Op{}) + if err != nil { + t.Errorf("An unexpected RefImplUpdateBody() error: %q", err.Error()) + return + } + + req := NewUpdateRequest("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + +func TestUpdateRequestIndexByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplUpdateBody(refEnc, &resolver, defaultSpace, "valid", + []interface{}{}, []Op{}) + if err != nil { + t.Errorf("An unexpected RefImplUpdateBody() error: %q", err.Error()) + return + } + + req := NewUpdateRequest(defaultSpace) + req.Index("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + func TestUpdateRequestSetters(t *testing.T) { key := []interface{}{uint(44)} refOps, reqOps := getTestOps() var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplUpdateBody(refEnc, validSpace, validIndex, key, refOps) + err := RefImplUpdateBody(refEnc, &resolver, validSpace, validIndex, key, refOps) if err != nil { t.Errorf("An unexpected RefImplUpdateBody() error: %q", err.Error()) return @@ -552,7 +756,7 @@ func TestUpsertRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplUpsertBody(refEnc, validSpace, []interface{}{}, []Op{}) + err := RefImplUpsertBody(refEnc, &resolver, validSpace, []interface{}{}, []Op{}) if err != nil { t.Errorf("An unexpected RefImplUpsertBody() error: %q", err.Error()) return @@ -562,13 +766,29 @@ func TestUpsertRequestDefaultValues(t *testing.T) { assertBodyEqual(t, refBuf.Bytes(), req) } +func TestUpsertRequestSpaceByName(t *testing.T) { + var refBuf bytes.Buffer + + resolver.nameUseSupported = true + + refEnc := msgpack.NewEncoder(&refBuf) + err := RefImplUpsertBody(refEnc, &resolver, "valid", []interface{}{}, []Op{}) + if err != nil { + t.Errorf("An unexpected RefImplUpsertBody() error: %q", err.Error()) + return + } + + req := NewUpsertRequest("valid") + assertBodyEqual(t, refBuf.Bytes(), req) +} + func TestUpsertRequestSetters(t *testing.T) { tuple := []interface{}{uint(64)} refOps, reqOps := getTestOps() var refBuf bytes.Buffer refEnc := msgpack.NewEncoder(&refBuf) - err := RefImplUpsertBody(refEnc, validSpace, tuple, refOps) + err := RefImplUpsertBody(refEnc, &resolver, validSpace, tuple, refOps) if err != nil { t.Errorf("An unexpected RefImplUpsertBody() error: %q", err.Error()) return diff --git a/schema.go b/schema.go index 714f51c5b..37afb72de 100644 --- a/schema.go +++ b/schema.go @@ -41,9 +41,16 @@ func msgpackIsString(code byte) bool { // SchemaResolver is an interface for resolving schema details. type SchemaResolver interface { - // ResolveSpaceIndex returns resolved space and index numbers or an - // error if it cannot be resolved. - ResolveSpaceIndex(s interface{}, i interface{}) (spaceNo, indexNo uint32, err error) + // ResolveSpace returns resolved space number or an error + // if it cannot be resolved. + ResolveSpace(s interface{}) (spaceNo uint32, err error) + // ResolveIndex returns resolved index number or an error + // if it cannot be resolved. + ResolveIndex(i interface{}, spaceNo uint32) (indexNo uint32, err error) + // NamesUseSupported shows if usage of space and index names, instead of + // IDs, is supported. It must return true if + // iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES is supported. + NamesUseSupported() bool } // Schema contains information about spaces and indexes. @@ -366,31 +373,21 @@ func (conn *Connection) loadSchema() (err error) { conn.lockShards() conn.Schema = schema + conn.schemaResolver = &loadedSchemaResolver{ + schema, + conn.schemaResolver.NamesUseSupported(), + } conn.unlockShards() return nil } -// ResolveSpaceIndex tries to resolve space and index numbers. -// Note: s can be a number, string, or an object of Space type. -// Note: i can be a number, string, or an object of Index type. -func (schema *Schema) ResolveSpaceIndex(s interface{}, i interface{}) (uint32, uint32, error) { - var ( - spaceNo, indexNo uint32 - space *Space - index *Index - ok bool - ) +// resolveSpaceNumber tries to resolve a space number. +// Note: at this point, s can be a number, or an object of Space type. +func resolveSpaceNumber(s interface{}) (uint32, error) { + var spaceNo uint32 switch s := s.(type) { - case string: - if schema == nil { - return spaceNo, indexNo, fmt.Errorf("Schema is not loaded") - } - if space, ok = schema.Spaces[s]; !ok { - return spaceNo, indexNo, fmt.Errorf("there is no space with name %s", s) - } - spaceNo = space.Id case uint: spaceNo = uint32(s) case uint64: @@ -419,50 +416,107 @@ func (schema *Schema) ResolveSpaceIndex(s interface{}, i interface{}) (uint32, u panic("unexpected type of space param") } - if i != nil { - switch i := i.(type) { - case string: - if schema == nil { - return spaceNo, indexNo, fmt.Errorf("schema is not loaded") - } - if space == nil { - if space, ok = schema.SpacesById[spaceNo]; !ok { - return spaceNo, indexNo, fmt.Errorf("there is no space with id %d", spaceNo) - } - } - if index, ok = space.Indexes[i]; !ok { - err := fmt.Errorf("space %s has not index with name %s", space.Name, i) - return spaceNo, indexNo, err - } - indexNo = index.Id - case uint: - indexNo = uint32(i) - case uint64: - indexNo = uint32(i) - case uint32: - indexNo = i - case uint16: - indexNo = uint32(i) - case uint8: - indexNo = uint32(i) - case int: - indexNo = uint32(i) - case int64: - indexNo = uint32(i) - case int32: - indexNo = uint32(i) - case int16: - indexNo = uint32(i) - case int8: - indexNo = uint32(i) - case Index: - indexNo = i.Id - case *Index: - indexNo = i.Id - default: - panic("unexpected type of index param") + return spaceNo, nil +} + +// resolveIndexNumber tries to resolve an index number. +// Note: at this point, i can be a number, or an object of Index type. +func resolveIndexNumber(i interface{}) (uint32, error) { + var indexNo uint32 + + switch i := i.(type) { + case uint: + indexNo = uint32(i) + case uint64: + indexNo = uint32(i) + case uint32: + indexNo = i + case uint16: + indexNo = uint32(i) + case uint8: + indexNo = uint32(i) + case int: + indexNo = uint32(i) + case int64: + indexNo = uint32(i) + case int32: + indexNo = uint32(i) + case int16: + indexNo = uint32(i) + case int8: + indexNo = uint32(i) + case Index: + indexNo = i.Id + case *Index: + indexNo = i.Id + default: + panic("unexpected type of index param") + } + + return indexNo, nil +} + +type loadedSchemaResolver struct { + Schema *Schema + // spaceAndIndexNamesSupported shows if a current Tarantool version supports + // iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES. + spaceAndIndexNamesSupported bool +} + +func (r *loadedSchemaResolver) ResolveSpace(s interface{}) (uint32, error) { + if str, ok := s.(string); ok { + space, ok := r.Schema.Spaces[str] + if !ok { + return 0, fmt.Errorf("there is no space with name %s", s) + } + return space.Id, nil + } + return resolveSpaceNumber(s) +} + +func (r *loadedSchemaResolver) ResolveIndex(i interface{}, spaceNo uint32) (uint32, error) { + if i == nil { + return 0, nil + } + if str, ok := i.(string); ok { + space, ok := r.Schema.SpacesById[spaceNo] + if !ok { + return 0, fmt.Errorf("there is no space with id %d", spaceNo) + } + index, ok := space.Indexes[str] + if !ok { + err := fmt.Errorf("space %s has not index with name %s", space.Name, i) + return 0, err } + return index.Id, nil } + return resolveIndexNumber(i) +} + +func (r *loadedSchemaResolver) NamesUseSupported() bool { + return r.spaceAndIndexNamesSupported +} + +type noSchemaResolver struct { + // spaceAndIndexNamesSupported shows if a current Tarantool version supports + // iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES. + spaceAndIndexNamesSupported bool +} + +func (*noSchemaResolver) ResolveSpace(s interface{}) (uint32, error) { + if _, ok := s.(string); ok { + return 0, fmt.Errorf("schema is not loaded") + } + return resolveSpaceNumber(s) +} + +func (*noSchemaResolver) ResolveIndex(i interface{}, spaceNo uint32) (uint32, error) { + if _, ok := i.(string); ok { + return 0, fmt.Errorf("schema is not loaded") + } + return resolveIndexNumber(i) +} - return spaceNo, indexNo, nil +func (r *noSchemaResolver) NamesUseSupported() bool { + return r.spaceAndIndexNamesSupported } diff --git a/settings/request_test.go b/settings/request_test.go index 2438f81cc..ea0dc185a 100644 --- a/settings/request_test.go +++ b/settings/request_test.go @@ -14,29 +14,25 @@ import ( ) type ValidSchemeResolver struct { + nameUseSupported bool } -func (*ValidSchemeResolver) ResolveSpaceIndex(s, i interface{}) (uint32, uint32, error) { - var spaceNo, indexNo uint32 - if s == nil { - if s == "_session_settings" { - spaceNo = 380 - } else { - spaceNo = uint32(s.(int)) - } - } else { - spaceNo = 0 - } - if i != nil { - indexNo = uint32(i.(int)) - } else { - indexNo = 0 - } +func (*ValidSchemeResolver) ResolveSpace(s interface{}) (uint32, error) { + return 0, nil +} - return spaceNo, indexNo, nil +func (*ValidSchemeResolver) ResolveIndex(i interface{}, spaceNo uint32) (uint32, error) { + return 0, nil } -var resolver ValidSchemeResolver +func (r *ValidSchemeResolver) NamesUseSupported() bool { + return r.nameUseSupported +} + +var ( + resolverNames = ValidSchemeResolver{true} + resolverNoNames = ValidSchemeResolver{false} +) func TestRequestsAPI(t *testing.T) { tests := []struct { @@ -76,7 +72,10 @@ func TestRequestsAPI(t *testing.T) { var reqBuf bytes.Buffer enc := msgpack.NewEncoder(&reqBuf) - require.Nilf(t, test.req.Body(&resolver, enc), "No errors on fill") + require.Nilf(t, test.req.Body(&resolverNames, enc), + "No errors on fill, names supported") + require.Nilf(t, test.req.Body(&resolverNoNames, enc), + "No errors on fill, names unsupported") } } diff --git a/tarantool_test.go b/tarantool_test.go index 0ad365286..8be963474 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -585,15 +585,10 @@ func BenchmarkClientReplaceParallel(b *testing.B) { conn := test_helpers.ConnectWithValidation(b, server, opts) defer conn.Close() - rSpaceNo, _, err := conn.Schema.ResolveSpaceIndex("test_perf", "secondary") - if err != nil { - b.Fatalf("Space is not resolved: %s", err.Error()) - } - b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { - _, err := conn.Replace(rSpaceNo, []interface{}{uint(1), "hello", []interface{}{}}) + _, err := conn.Replace("test_perf", []interface{}{uint(1), "hello", []interface{}{}}) if err != nil { b.Error(err) } @@ -605,17 +600,11 @@ func BenchmarkClientLargeSelectParallel(b *testing.B) { conn := test_helpers.ConnectWithValidation(b, server, opts) defer conn.Close() - schema := conn.Schema - rSpaceNo, rIndexNo, err := schema.ResolveSpaceIndex("test_perf", "secondary") - if err != nil { - b.Fatalf("symbolic space and index params not resolved") - } - offset, limit := uint32(0), uint32(1000) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { - _, err := conn.Select(rSpaceNo, rIndexNo, offset, limit, IterEq, + _, err := conn.Select("test_perf", "secondary", offset, limit, IterEq, []interface{}{"test_name"}) if err != nil { b.Fatal(err) @@ -1889,8 +1878,6 @@ func TestNewPreparedFromResponse(t *testing.T) { } func TestSchema(t *testing.T) { - var err error - conn := test_helpers.ConnectWithValidation(t, server, opts) defer conn.Close() @@ -2035,32 +2022,6 @@ func TestSchema(t *testing.T) { (ifield2.Type != "STR" && ifield2.Type != "string") { t.Errorf("index field has incorrect Type '%s'", ifield2.Type) } - - var rSpaceNo, rIndexNo uint32 - rSpaceNo, rIndexNo, err = schema.ResolveSpaceIndex(616, 3) - if err != nil || rSpaceNo != 616 || rIndexNo != 3 { - t.Errorf("numeric space and index params not resolved as-is") - } - rSpaceNo, _, err = schema.ResolveSpaceIndex(616, nil) - if err != nil || rSpaceNo != 616 { - t.Errorf("numeric space param not resolved as-is") - } - rSpaceNo, rIndexNo, err = schema.ResolveSpaceIndex("schematest", "secondary") - if err != nil || rSpaceNo != 616 || rIndexNo != 3 { - t.Errorf("symbolic space and index params not resolved") - } - rSpaceNo, _, err = schema.ResolveSpaceIndex("schematest", nil) - if err != nil || rSpaceNo != 616 { - t.Errorf("symbolic space param not resolved") - } - _, _, err = schema.ResolveSpaceIndex("schematest22", "secondary") - if err == nil { - t.Errorf("ResolveSpaceIndex didn't returned error with not existing space name") - } - _, _, err = schema.ResolveSpaceIndex("schematest", "secondary22") - if err == nil { - t.Errorf("ResolveSpaceIndex didn't returned error with not existing index name") - } } func TestSchema_IsNullable(t *testing.T) { @@ -3302,6 +3263,7 @@ func TestConnectionProtocolInfoSupported(t *testing.T) { iproto.IPROTO_FEATURE_ERROR_EXTENSION, iproto.IPROTO_FEATURE_WATCHERS, iproto.IPROTO_FEATURE_PAGINATION, + iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES, iproto.IPROTO_FEATURE_WATCH_ONCE, }, }) @@ -3420,6 +3382,7 @@ func TestConnectionProtocolInfoUnsupported(t *testing.T) { iproto.IPROTO_FEATURE_ERROR_EXTENSION, iproto.IPROTO_FEATURE_WATCHERS, iproto.IPROTO_FEATURE_PAGINATION, + iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES, iproto.IPROTO_FEATURE_WATCH_ONCE, }, })