Skip to content

Commit 00fa43c

Browse files
committed
api: update all Update and Upsert requests
`Op` struct made private. Change all `Upsert` and `Update` requests to accept `*tarantool.Operations` as `ops` parameters instead of `interface{}`. Closes #348
1 parent c43db4d commit 00fa43c

16 files changed

+273
-101
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
4949
constants for `protocol` (#337)
5050
- Change `crud` operations `Timeout` option type to `crud.OptFloat64`
5151
instead of `crud.OptUint` (#342)
52+
- Change all `Upsert` and `Update` requests to accept `*tarantool.Operations`
53+
as `ops` parameters instead of `interface{}` (#348)
5254

5355
### Deprecated
5456

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ is supported.
255255

256256
#### Client tools changes
257257

258+
* `Op` struct made private.
258259
* Remove `OpSplice` struct.
259260
* `Operations.Splice` method now accepts 5 arguments instead of 3.
260261

client_tools.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ func (k IntIntKey) EncodeMsgpack(enc *msgpack.Encoder) error {
5454
return nil
5555
}
5656

57-
// Op - is update operation.
58-
type Op struct {
57+
// operation - is update operation.
58+
type operation struct {
5959
Op string
6060
Field int
6161
Arg interface{}
@@ -65,7 +65,7 @@ type Op struct {
6565
Replace string
6666
}
6767

68-
func (o Op) EncodeMsgpack(enc *msgpack.Encoder) error {
68+
func (o operation) EncodeMsgpack(enc *msgpack.Encoder) error {
6969
isSpliceOperation := o.Op == spliceOperator
7070
argsLen := 3
7171
if isSpliceOperation {
@@ -108,22 +108,26 @@ const (
108108

109109
// Operations is a collection of update operations.
110110
type Operations struct {
111-
ops []Op
111+
ops []operation
112+
}
113+
114+
// EncodeMsgpack encodes Operations as an array of operations.
115+
func (ops *Operations) EncodeMsgpack(enc *msgpack.Encoder) error {
116+
return enc.Encode(ops.ops)
112117
}
113118

114119
// NewOperations returns a new empty collection of update operations.
115120
func NewOperations() *Operations {
116-
ops := new(Operations)
117-
return ops
121+
return new(Operations)
118122
}
119123

120124
func (ops *Operations) append(op string, field int, arg interface{}) *Operations {
121-
ops.ops = append(ops.ops, Op{Op: op, Field: field, Arg: arg})
125+
ops.ops = append(ops.ops, operation{Op: op, Field: field, Arg: arg})
122126
return ops
123127
}
124128

125129
func (ops *Operations) appendSplice(op string, field, pos, len int, replace string) *Operations {
126-
ops.ops = append(ops.ops, Op{Op: op, Field: field, Pos: pos, Len: len, Replace: replace})
130+
ops.ops = append(ops.ops, operation{Op: op, Field: field, Pos: pos, Len: len, Replace: replace})
127131
return ops
128132
}
129133

client_tools_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package tarantool_test
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/vmihailenco/msgpack/v5"
8+
9+
"github.com/tarantool/go-tarantool/v2"
10+
)
11+
12+
func TestOperations_EncodeMsgpack(t *testing.T) {
13+
ops := tarantool.NewOperations().
14+
Add(1, 2).
15+
Subtract(1, 2).
16+
BitwiseAnd(1, 2).
17+
BitwiseOr(1, 2).
18+
BitwiseXor(1, 2).
19+
Splice(1, 2, 3, "a").
20+
Insert(1, 2).
21+
Delete(1, 2).
22+
Assign(1, 2)
23+
refOps := []interface{}{
24+
[]interface{}{"+", 1, 2},
25+
[]interface{}{"-", 1, 2},
26+
[]interface{}{"&", 1, 2},
27+
[]interface{}{"|", 1, 2},
28+
[]interface{}{"^", 1, 2},
29+
[]interface{}{":", 1, 2, 3, "a"},
30+
[]interface{}{"!", 1, 2},
31+
[]interface{}{"#", 1, 2},
32+
[]interface{}{"=", 1, 2},
33+
}
34+
35+
var refBuf bytes.Buffer
36+
encRef := msgpack.NewEncoder(&refBuf)
37+
if err := encRef.Encode(refOps); err != nil {
38+
t.Errorf("error while encoding: %v", err.Error())
39+
}
40+
41+
var buf bytes.Buffer
42+
enc := msgpack.NewEncoder(&buf)
43+
44+
if err := enc.Encode(ops); err != nil {
45+
t.Errorf("error while encoding: %v", err.Error())
46+
}
47+
if !bytes.Equal(refBuf.Bytes(), buf.Bytes()) {
48+
t.Errorf("encode response is wrong:\n expected %v\n got: %v",
49+
refBuf, buf.Bytes())
50+
}
51+
}

connector.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ type Connector interface {
2929
Delete(space, index interface{}, key interface{}) (*Response, error)
3030
// Deprecated: the method will be removed in the next major version,
3131
// use a UpdateRequest object + Do() instead.
32-
Update(space, index interface{}, key, ops interface{}) (*Response, error)
32+
Update(space, index interface{}, key interface{}, ops *Operations) (*Response, error)
3333
// Deprecated: the method will be removed in the next major version,
3434
// use a UpsertRequest object + Do() instead.
35-
Upsert(space interface{}, tuple, ops interface{}) (*Response, error)
35+
Upsert(space interface{}, tuple interface{}, ops *Operations) (*Response, error)
3636
// Deprecated: the method will be removed in the next major version,
3737
// use a CallRequest object + Do() instead.
3838
Call(functionName string, args interface{}) (*Response, error)
@@ -67,7 +67,8 @@ type Connector interface {
6767
DeleteTyped(space, index interface{}, key interface{}, result interface{}) error
6868
// Deprecated: the method will be removed in the next major version,
6969
// use a UpdateRequest object + Do() instead.
70-
UpdateTyped(space, index interface{}, key, ops interface{}, result interface{}) error
70+
UpdateTyped(space, index interface{}, key interface{}, ops *Operations,
71+
result interface{}) error
7172
// Deprecated: the method will be removed in the next major version,
7273
// use a CallRequest object + Do() instead.
7374
CallTyped(functionName string, args interface{}, result interface{}) error
@@ -100,10 +101,10 @@ type Connector interface {
100101
DeleteAsync(space, index interface{}, key interface{}) *Future
101102
// Deprecated: the method will be removed in the next major version,
102103
// use a UpdateRequest object + Do() instead.
103-
UpdateAsync(space, index interface{}, key, ops interface{}) *Future
104+
UpdateAsync(space, index interface{}, key interface{}, ops *Operations) *Future
104105
// Deprecated: the method will be removed in the next major version,
105106
// use a UpsertRequest object + Do() instead.
106-
UpsertAsync(space interface{}, tuple interface{}, ops interface{}) *Future
107+
UpsertAsync(space interface{}, tuple interface{}, ops *Operations) *Future
107108
// Deprecated: the method will be removed in the next major version,
108109
// use a CallRequest object + Do() instead.
109110
CallAsync(functionName string, args interface{}) *Future

crud/operations.go

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type Operation struct {
3939
Replace string
4040
}
4141

42+
// EncodeMsgpack encodes Operation.
4243
func (o Operation) EncodeMsgpack(enc *msgpack.Encoder) error {
4344
isSpliceOperation := o.Operator == Splice
4445
argsLen := 3

crud/operations_test.go

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package crud_test
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/vmihailenco/msgpack/v5"
8+
9+
"github.com/tarantool/go-tarantool/v2/crud"
10+
)
11+
12+
func TestOperation_EncodeMsgpack(t *testing.T) {
13+
testCases := []struct {
14+
name string
15+
op crud.Operation
16+
ref []interface{}
17+
}{
18+
{
19+
"Add",
20+
crud.Operation{
21+
Operator: crud.Add,
22+
Field: 1,
23+
Value: 2,
24+
},
25+
[]interface{}{"+", 1, 2},
26+
},
27+
{
28+
"Sub",
29+
crud.Operation{
30+
Operator: crud.Sub,
31+
Field: 1,
32+
Value: 2,
33+
},
34+
[]interface{}{"-", 1, 2},
35+
},
36+
{
37+
"And",
38+
crud.Operation{
39+
Operator: crud.And,
40+
Field: 1,
41+
Value: 2,
42+
},
43+
[]interface{}{"&", 1, 2},
44+
},
45+
{
46+
"Or",
47+
crud.Operation{
48+
Operator: crud.Or,
49+
Field: 1,
50+
Value: 2,
51+
},
52+
[]interface{}{"|", 1, 2},
53+
},
54+
{
55+
"Xor",
56+
crud.Operation{
57+
Operator: crud.Xor,
58+
Field: 1,
59+
Value: 2,
60+
},
61+
[]interface{}{"^", 1, 2},
62+
},
63+
{
64+
"Splice",
65+
crud.Operation{
66+
Operator: crud.Splice,
67+
Field: 1,
68+
Pos: 2,
69+
Len: 3,
70+
Replace: "a",
71+
},
72+
[]interface{}{":", 1, 2, 3, "a"},
73+
},
74+
{
75+
"Insert",
76+
crud.Operation{
77+
Operator: crud.Insert,
78+
Field: 1,
79+
Value: 2,
80+
},
81+
[]interface{}{"!", 1, 2},
82+
},
83+
{
84+
"Delete",
85+
crud.Operation{
86+
Operator: crud.Delete,
87+
Field: 1,
88+
Value: 2,
89+
},
90+
[]interface{}{"#", 1, 2},
91+
},
92+
{
93+
"Assign",
94+
crud.Operation{
95+
Operator: crud.Assign,
96+
Field: 1,
97+
Value: 2,
98+
},
99+
[]interface{}{"=", 1, 2},
100+
},
101+
}
102+
103+
for _, test := range testCases {
104+
t.Run(test.name, func(t *testing.T) {
105+
var refBuf bytes.Buffer
106+
encRef := msgpack.NewEncoder(&refBuf)
107+
if err := encRef.Encode(test.ref); err != nil {
108+
t.Errorf("error while encoding: %v", err.Error())
109+
}
110+
111+
var buf bytes.Buffer
112+
enc := msgpack.NewEncoder(&buf)
113+
114+
if err := enc.Encode(test.op); err != nil {
115+
t.Errorf("error while encoding: %v", err.Error())
116+
}
117+
if !bytes.Equal(refBuf.Bytes(), buf.Bytes()) {
118+
t.Errorf("encode response is wrong:\n expected %v\n got: %v",
119+
refBuf, buf.Bytes())
120+
}
121+
})
122+
}
123+
}

export_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func RefImplDeleteBody(enc *msgpack.Encoder, res SchemaResolver, space, index,
7878
// RefImplUpdateBody is reference implementation for filling of an update
7979
// request's body.
8080
func RefImplUpdateBody(enc *msgpack.Encoder, res SchemaResolver, space, index,
81-
key, ops interface{}) error {
81+
key interface{}, ops *Operations) error {
8282
spaceEnc, err := newSpaceEncoder(res, space)
8383
if err != nil {
8484
return err
@@ -93,7 +93,7 @@ func RefImplUpdateBody(enc *msgpack.Encoder, res SchemaResolver, space, index,
9393
// RefImplUpsertBody is reference implementation for filling of an upsert
9494
// request's body.
9595
func RefImplUpsertBody(enc *msgpack.Encoder, res SchemaResolver, space,
96-
tuple, ops interface{}) error {
96+
tuple interface{}, ops *Operations) error {
9797
spaceEnc, err := newSpaceEncoder(res, space)
9898
if err != nil {
9999
return err

pool/connection_pool.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,8 @@ func (p *ConnectionPool) Delete(space, index interface{}, key interface{},
462462
//
463463
// Deprecated: the method will be removed in the next major version,
464464
// use a UpdateRequest object + Do() instead.
465-
func (p *ConnectionPool) Update(space, index interface{}, key, ops interface{},
466-
userMode ...Mode) (*tarantool.Response, error) {
465+
func (p *ConnectionPool) Update(space, index interface{}, key interface{},
466+
ops *tarantool.Operations, userMode ...Mode) (*tarantool.Response, error) {
467467
conn, err := p.getConnByMode(RW, userMode)
468468
if err != nil {
469469
return nil, err
@@ -477,8 +477,8 @@ func (p *ConnectionPool) Update(space, index interface{}, key, ops interface{},
477477
//
478478
// Deprecated: the method will be removed in the next major version,
479479
// use a UpsertRequest object + Do() instead.
480-
func (p *ConnectionPool) Upsert(space interface{}, tuple, ops interface{},
481-
userMode ...Mode) (*tarantool.Response, error) {
480+
func (p *ConnectionPool) Upsert(space interface{}, tuple interface{},
481+
ops *tarantool.Operations, userMode ...Mode) (*tarantool.Response, error) {
482482
conn, err := p.getConnByMode(RW, userMode)
483483
if err != nil {
484484
return nil, err
@@ -639,8 +639,8 @@ func (p *ConnectionPool) DeleteTyped(space, index interface{}, key interface{},
639639
//
640640
// Deprecated: the method will be removed in the next major version,
641641
// use a UpdateRequest object + Do() instead.
642-
func (p *ConnectionPool) UpdateTyped(space, index interface{}, key, ops interface{},
643-
result interface{}, userMode ...Mode) error {
642+
func (p *ConnectionPool) UpdateTyped(space, index interface{}, key interface{},
643+
ops *tarantool.Operations, result interface{}, userMode ...Mode) error {
644644
conn, err := p.getConnByMode(RW, userMode)
645645
if err != nil {
646646
return err
@@ -788,8 +788,8 @@ func (p *ConnectionPool) DeleteAsync(space, index interface{}, key interface{},
788788
//
789789
// Deprecated: the method will be removed in the next major version,
790790
// use a UpdateRequest object + Do() instead.
791-
func (p *ConnectionPool) UpdateAsync(space, index interface{}, key, ops interface{},
792-
userMode ...Mode) *tarantool.Future {
791+
func (p *ConnectionPool) UpdateAsync(space, index interface{}, key interface{},
792+
ops *tarantool.Operations, userMode ...Mode) *tarantool.Future {
793793
conn, err := p.getConnByMode(RW, userMode)
794794
if err != nil {
795795
return newErrorFuture(err)
@@ -803,8 +803,8 @@ func (p *ConnectionPool) UpdateAsync(space, index interface{}, key, ops interfac
803803
//
804804
// Deprecated: the method will be removed in the next major version,
805805
// use a UpsertRequest object + Do() instead.
806-
func (p *ConnectionPool) UpsertAsync(space interface{}, tuple interface{}, ops interface{},
807-
userMode ...Mode) *tarantool.Future {
806+
func (p *ConnectionPool) UpsertAsync(space interface{}, tuple interface{},
807+
ops *tarantool.Operations, userMode ...Mode) *tarantool.Future {
808808
conn, err := p.getConnByMode(RW, userMode)
809809
if err != nil {
810810
return newErrorFuture(err)

pool/connection_pool_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -1964,7 +1964,7 @@ func TestUpsert(t *testing.T) {
19641964
// Mode is `RW` by default, we have only one RW instance (servers[2])
19651965
resp, err := connPool.Upsert(spaceName,
19661966
[]interface{}{"upsert_key", "upsert_value"},
1967-
[]interface{}{[]interface{}{"=", 1, "new_value"}})
1967+
tarantool.NewOperations().Assign(1, "new_value"))
19681968
require.Nilf(t, err, "failed to Upsert")
19691969
require.NotNilf(t, resp, "response is nil after Upsert")
19701970

@@ -1993,7 +1993,7 @@ func TestUpsert(t *testing.T) {
19931993
// PreferRW
19941994
resp, err = connPool.Upsert(
19951995
spaceName, []interface{}{"upsert_key", "upsert_value"},
1996-
[]interface{}{[]interface{}{"=", 1, "new_value"}}, pool.PreferRW)
1996+
tarantool.NewOperations().Assign(1, "new_value"), pool.PreferRW)
19971997

19981998
require.Nilf(t, err, "failed to Upsert")
19991999
require.NotNilf(t, resp, "response is nil after Upsert")
@@ -2056,7 +2056,7 @@ func TestUpdate(t *testing.T) {
20562056

20572057
// Mode is `RW` by default, we have only one RW instance (servers[2])
20582058
resp, err = connPool.Update(spaceName, indexNo,
2059-
[]interface{}{"update_key"}, []interface{}{[]interface{}{"=", 1, "new_value"}})
2059+
[]interface{}{"update_key"}, tarantool.NewOperations().Assign(1, "new_value"))
20602060
require.Nilf(t, err, "failed to Update")
20612061
require.NotNilf(t, resp, "response is nil after Update")
20622062

@@ -2085,7 +2085,7 @@ func TestUpdate(t *testing.T) {
20852085
// PreferRW
20862086
resp, err = connPool.Update(
20872087
spaceName, indexNo, []interface{}{"update_key"},
2088-
[]interface{}{[]interface{}{"=", 1, "another_value"}}, pool.PreferRW)
2088+
tarantool.NewOperations().Assign(1, "another_value"), pool.PreferRW)
20892089

20902090
require.Nilf(t, err, "failed to Update")
20912091
require.NotNilf(t, resp, "response is nil after Update")

0 commit comments

Comments
 (0)