Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api: support IPROTO_FEATURE_SPACE_AND_INDEX_NAMES #345

Merged
merged 3 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,20 @@ jobs:
strategy:
DifferentialOrange marked this conversation as resolved.
Show resolved Hide resolved
DifferentialOrange marked this conversation as resolved.
Show resolved Hide resolved
fail-fast: false
matrix:
sdk-path:
- 'release/linux/x86_64/1.10/'
sdk-version:
- 'bundle-1.10.11-0-gf0b0e7ecf-r470'
- 'sdk-1.10.15-0-r598'
coveralls: [false]
fuzzing: [false]
ssl: [false]
include:
- sdk-version: 'bundle-2.10.0-1-gfa775b383-r486-linux-x86_64'
- sdk-path: 'release/linux/x86_64/2.10/'
sdk-version: 'sdk-gc64-2.10.8-0-r598.linux.x86_64'
coveralls: false
ssl: true
- sdk-path: 'release/linux/x86_64/2.11/'
DifferentialOrange marked this conversation as resolved.
Show resolved Hide resolved
sdk-version: 'sdk-gc64-2.11.0-0-r577.linux.x86_64'
sdk-version: 'sdk-gc64-2.11.1-0-r598.linux.x86_64'
coveralls: true
ssl: true

Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
DifferentialOrange marked this conversation as resolved.
Show resolved Hide resolved
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

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
DifferentialOrange marked this conversation as resolved.
Show resolved Hide resolved

* `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.
oleg-jukovec marked this conversation as resolved.
Show resolved Hide resolved
* `Schema` structure no longer implements `SchemaResolver` interface.

## Contributing

See [the contributing guide](CONTRIBUTING.md) for detailed instructions on how
Expand Down
12 changes: 11 additions & 1 deletion connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -528,6 +530,14 @@ func (conn *Connection) dial(ctx context.Context) error {
conn.Greeting.Version = c.Greeting().Version
conn.serverProtocolInfo = c.ProtocolInfo()

spaceAndIndexNamesSupported :=
isFeatureInSlice(iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES,
conn.serverProtocolInfo.Features)

conn.schemaResolver = &noSchemaResolver{
SpaceAndIndexNamesSupported: spaceAndIndexNamesSupported,
}

// Watchers.
conn.watchMap.Range(func(key, value interface{}) bool {
st := value.(chan watchState)
Expand Down Expand Up @@ -1102,7 +1112,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 {
Expand Down
43 changes: 4 additions & 39 deletions crud/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package crud_test
import (
"bytes"
"context"
"errors"
"fmt"
"testing"

Expand All @@ -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

Expand Down Expand Up @@ -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())
}
Expand All @@ -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())
}
Expand Down
88 changes: 88 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
}

Expand Down
67 changes: 54 additions & 13 deletions export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
}
Expand Down
Loading
Loading