Skip to content

Commit 6ba01ff

Browse files
committed
crud: allow interface{} as values for *ManyRequest
It was a mistake to use `[]interface{}` or `[]msgpack.CustomEncoder` as types for an array of tuples or an array of objects. Users were unable to use slices of custom types as incoming values. The patch now allows the use of `interface{}` as incoming values. It makes it easier to use the API, but users need to be more careful. Therefore, we have also added examples. Closes #365
1 parent b8d9914 commit 6ba01ff

File tree

7 files changed

+121
-17
lines changed

7 files changed

+121
-17
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
131131
- Tests with crud 1.4.0 (#336)
132132
- Tests with case sensitive SQL (#341)
133133
- Splice update operation accepts 3 arguments instead of 5 (#348)
134+
- Unable to use a slice of custom types as a slice of tuples or objects for
135+
`crud.*ManyRequest/crud.*ObjectManyRequest` (#365)
134136

135137
## [1.12.0] - 2023-06-07
136138

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ The subpackage has been deleted. You could use `pool` instead.
213213

214214
* `crud` operations `Timeout` option has `crud.OptFloat64` type
215215
instead of `crud.OptUint`.
216+
* A slice of a custom type could be used as tuples for `ReplaceManyRequest` and
217+
`InsertManyRequest`, `ReplaceObjectManyRequest`.
218+
* A slice of a custom type could be used as objects for `ReplaceObjectManyRequest`
219+
and `InsertObjectManyRequest`.
216220

217221
#### test_helpers package
218222

crud/example_test.go

+83
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,89 @@ func ExampleResult_rowsCustomType() {
8585
// [{{} 2010 45 bla}]
8686
}
8787

88+
// ExampleTuples_customType demonstrates how to use a slice of objects of a
89+
// custom type as Tuples to make a ReplaceManyRequest.
90+
func ExampleTuples_customType() {
91+
conn := exampleConnect()
92+
93+
// The type will be encoded/decoded as an array.
94+
type Tuple struct {
95+
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
96+
Id uint64
97+
BucketId *uint64
98+
Name string
99+
}
100+
req := crud.MakeReplaceManyRequest(exampleSpace).Tuples([]Tuple{
101+
Tuple{
102+
Id: 2010,
103+
BucketId: nil,
104+
Name: "bla",
105+
},
106+
})
107+
108+
ret := crud.MakeResult(reflect.TypeOf(Tuple{}))
109+
if err := conn.Do(req).GetTyped(&ret); err != nil {
110+
fmt.Printf("Failed to execute request: %s", err)
111+
return
112+
}
113+
114+
fmt.Println(ret.Metadata)
115+
rows := ret.Rows.([]Tuple)
116+
if len(rows) == 1 {
117+
fmt.Println(rows[0].Id)
118+
fmt.Println(*rows[0].BucketId)
119+
fmt.Println(rows[0].Name)
120+
} else {
121+
fmt.Printf("Unexpected result tuples count: %d", len(rows))
122+
}
123+
// Output:
124+
// [{id unsigned false} {bucket_id unsigned true} {name string false}]
125+
// 2010
126+
// 45
127+
// bla
128+
}
129+
130+
// ExampleObjects_customType demonstrates how to use a slice of objects of
131+
// a custom type as Objects to make a ReplaceObjectManyRequest.
132+
func ExampleObjects_customType() {
133+
conn := exampleConnect()
134+
135+
// The type will be encoded/decoded as a map.
136+
type Tuple struct {
137+
Id uint64 `msgpack:"id,omitempty"`
138+
BucketId *uint64 `msgpack:"bucket_id,omitempty"`
139+
Name string `msgpack:"name,omitempty"`
140+
}
141+
req := crud.MakeReplaceObjectManyRequest(exampleSpace).Objects([]Tuple{
142+
Tuple{
143+
Id: 2010,
144+
BucketId: nil,
145+
Name: "bla",
146+
},
147+
})
148+
149+
ret := crud.MakeResult(reflect.TypeOf(Tuple{}))
150+
if err := conn.Do(req).GetTyped(&ret); err != nil {
151+
fmt.Printf("Failed to execute request: %s", err)
152+
return
153+
}
154+
155+
fmt.Println(ret.Metadata)
156+
rows := ret.Rows.([]Tuple)
157+
if len(rows) == 1 {
158+
fmt.Println(rows[0].Id)
159+
fmt.Println(*rows[0].BucketId)
160+
fmt.Println(rows[0].Name)
161+
} else {
162+
fmt.Printf("Unexpected result tuples count: %d", len(rows))
163+
}
164+
// Output:
165+
// [{id unsigned false} {bucket_id unsigned true} {name string false}]
166+
// 2010
167+
// 45
168+
// bla
169+
}
170+
88171
// ExampleResult_operationData demonstrates how to obtain information
89172
// about erroneous objects from crud.Error using `OperationData` field.
90173
func ExampleResult_operationData() {

crud/insert_many.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ type InsertManyOpts = OperationManyOpts
1515
// `crud.insert_many` for execution by a Connection.
1616
type InsertManyRequest struct {
1717
spaceRequest
18-
tuples []Tuple
18+
tuples Tuples
1919
opts InsertManyOpts
2020
}
2121

2222
type insertManyArgs struct {
2323
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
2424
Space string
25-
Tuples []Tuple
25+
Tuples Tuples
2626
Opts InsertManyOpts
2727
}
2828

@@ -37,7 +37,7 @@ func MakeInsertManyRequest(space string) InsertManyRequest {
3737

3838
// Tuples sets the tuples for the InsertManyRequest request.
3939
// Note: default value is nil.
40-
func (req InsertManyRequest) Tuples(tuples []Tuple) InsertManyRequest {
40+
func (req InsertManyRequest) Tuples(tuples Tuples) InsertManyRequest {
4141
req.tuples = tuples
4242
return req
4343
}
@@ -73,14 +73,14 @@ type InsertObjectManyOpts = OperationObjectManyOpts
7373
// `crud.insert_object_many` for execution by a Connection.
7474
type InsertObjectManyRequest struct {
7575
spaceRequest
76-
objects []Object
76+
objects Objects
7777
opts InsertObjectManyOpts
7878
}
7979

8080
type insertObjectManyArgs struct {
8181
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
8282
Space string
83-
Objects []Object
83+
Objects Objects
8484
Opts InsertObjectManyOpts
8585
}
8686

@@ -95,7 +95,7 @@ func MakeInsertObjectManyRequest(space string) InsertObjectManyRequest {
9595

9696
// Objects sets the objects for the InsertObjectManyRequest request.
9797
// Note: default value is nil.
98-
func (req InsertObjectManyRequest) Objects(objects []Object) InsertObjectManyRequest {
98+
func (req InsertObjectManyRequest) Objects(objects Objects) InsertObjectManyRequest {
9999
req.objects = objects
100100
return req
101101
}

crud/object.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ import (
44
"github.com/vmihailenco/msgpack/v5"
55
)
66

7-
// Object is an interface to describe object for CRUD methods.
8-
type Object interface {
9-
EncodeMsgpack(enc *msgpack.Encoder)
10-
}
7+
// Object is an interface to describe object for CRUD methods. It can be any
8+
// type that msgpack can encode as a map.
9+
type Object = interface{}
10+
11+
// Objects is a type to describe an array of object for CRUD methods. It can be
12+
// any type that msgpack can encode, but encoded data must be an array of
13+
// objects.
14+
//
15+
// See the reason why not just []Object:
16+
// https://github.com/tarantool/go-tarantool/issues/365
17+
type Objects = interface{}
1118

1219
// MapObject is a type to describe object as a map.
1320
type MapObject map[string]interface{}

crud/replace_many.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ type ReplaceManyOpts = OperationManyOpts
1515
// `crud.replace_many` for execution by a Connection.
1616
type ReplaceManyRequest struct {
1717
spaceRequest
18-
tuples []Tuple
18+
tuples Tuples
1919
opts ReplaceManyOpts
2020
}
2121

2222
type replaceManyArgs struct {
2323
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
2424
Space string
25-
Tuples []Tuple
25+
Tuples Tuples
2626
Opts ReplaceManyOpts
2727
}
2828

@@ -37,7 +37,7 @@ func MakeReplaceManyRequest(space string) ReplaceManyRequest {
3737

3838
// Tuples sets the tuples for the ReplaceManyRequest request.
3939
// Note: default value is nil.
40-
func (req ReplaceManyRequest) Tuples(tuples []Tuple) ReplaceManyRequest {
40+
func (req ReplaceManyRequest) Tuples(tuples Tuples) ReplaceManyRequest {
4141
req.tuples = tuples
4242
return req
4343
}
@@ -73,14 +73,14 @@ type ReplaceObjectManyOpts = OperationObjectManyOpts
7373
// `crud.replace_object_many` for execution by a Connection.
7474
type ReplaceObjectManyRequest struct {
7575
spaceRequest
76-
objects []Object
76+
objects Objects
7777
opts ReplaceObjectManyOpts
7878
}
7979

8080
type replaceObjectManyArgs struct {
8181
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
8282
Space string
83-
Objects []Object
83+
Objects Objects
8484
Opts ReplaceObjectManyOpts
8585
}
8686

@@ -95,7 +95,7 @@ func MakeReplaceObjectManyRequest(space string) ReplaceObjectManyRequest {
9595

9696
// Objects sets the tuple for the ReplaceObjectManyRequest request.
9797
// Note: default value is nil.
98-
func (req ReplaceObjectManyRequest) Objects(objects []Object) ReplaceObjectManyRequest {
98+
func (req ReplaceObjectManyRequest) Objects(objects Objects) ReplaceObjectManyRequest {
9999
req.objects = objects
100100
return req
101101
}

crud/tuple.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
package crud
22

33
// Tuple is a type to describe tuple for CRUD methods. It can be any type that
4-
// msgpask can encode.
4+
// msgpask can encode as an array.
55
type Tuple = interface{}
6+
7+
// Tuples is a type to describe an array of tuples for CRUD methods. It can be
8+
// any type that msgpack can encode, but encoded data must be an array of
9+
// tuples.
10+
//
11+
// See the reason why not just []Tuple:
12+
// https://github.com/tarantool/go-tarantool/issues/365
13+
type Tuples = interface{}

0 commit comments

Comments
 (0)