Skip to content

crud: allow interface{} as values for *ManyRequest #375

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

Merged
merged 1 commit into from
Jan 29, 2024
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
- Tests with crud 1.4.0 (#336)
- Tests with case sensitive SQL (#341)
- Splice update operation accepts 3 arguments instead of 5 (#348)
- Unable to use a slice of custom types as a slice of tuples or objects for
`crud.*ManyRequest/crud.*ObjectManyRequest` (#365)

## [1.12.0] - 2023-06-07

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ The subpackage has been deleted. You could use `pool` instead.

* `crud` operations `Timeout` option has `crud.OptFloat64` type
instead of `crud.OptUint`.
* A slice of a custom type could be used as tuples for `ReplaceManyRequest` and
`InsertManyRequest`, `ReplaceObjectManyRequest`.
* A slice of a custom type could be used as objects for `ReplaceObjectManyRequest`
and `InsertObjectManyRequest`.

#### test_helpers package

Expand Down
83 changes: 83 additions & 0 deletions crud/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,89 @@ func ExampleResult_rowsCustomType() {
// [{{} 2010 45 bla}]
}

// ExampleTuples_customType demonstrates how to use a slice of objects of a
// custom type as Tuples to make a ReplaceManyRequest.
func ExampleTuples_customType() {
conn := exampleConnect()

// The type will be encoded/decoded as an array.
type Tuple struct {
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
Id uint64
BucketId *uint64
Name string
}
req := crud.MakeReplaceManyRequest(exampleSpace).Tuples([]Tuple{
Tuple{
Id: 2010,
BucketId: nil,
Name: "bla",
},
})

ret := crud.MakeResult(reflect.TypeOf(Tuple{}))
if err := conn.Do(req).GetTyped(&ret); err != nil {
fmt.Printf("Failed to execute request: %s", err)
return
}

fmt.Println(ret.Metadata)
rows := ret.Rows.([]Tuple)
if len(rows) == 1 {
fmt.Println(rows[0].Id)
fmt.Println(*rows[0].BucketId)
fmt.Println(rows[0].Name)
} else {
fmt.Printf("Unexpected result tuples count: %d", len(rows))
}
// Output:
// [{id unsigned false} {bucket_id unsigned true} {name string false}]
// 2010
// 45
// bla
}

// ExampleObjects_customType demonstrates how to use a slice of objects of
// a custom type as Objects to make a ReplaceObjectManyRequest.
func ExampleObjects_customType() {
conn := exampleConnect()

// The type will be encoded/decoded as a map.
type Tuple struct {
Id uint64 `msgpack:"id,omitempty"`
BucketId *uint64 `msgpack:"bucket_id,omitempty"`
Name string `msgpack:"name,omitempty"`
}
req := crud.MakeReplaceObjectManyRequest(exampleSpace).Objects([]Tuple{
Tuple{
Id: 2010,
BucketId: nil,
Name: "bla",
},
})

ret := crud.MakeResult(reflect.TypeOf(Tuple{}))
if err := conn.Do(req).GetTyped(&ret); err != nil {
fmt.Printf("Failed to execute request: %s", err)
return
}

fmt.Println(ret.Metadata)
rows := ret.Rows.([]Tuple)
if len(rows) == 1 {
fmt.Println(rows[0].Id)
fmt.Println(*rows[0].BucketId)
fmt.Println(rows[0].Name)
} else {
fmt.Printf("Unexpected result tuples count: %d", len(rows))
}
// Output:
// [{id unsigned false} {bucket_id unsigned true} {name string false}]
// 2010
// 45
// bla
}

// ExampleResult_operationData demonstrates how to obtain information
// about erroneous objects from crud.Error using `OperationData` field.
func ExampleResult_operationData() {
Expand Down
12 changes: 6 additions & 6 deletions crud/insert_many.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ type InsertManyOpts = OperationManyOpts
// `crud.insert_many` for execution by a Connection.
type InsertManyRequest struct {
spaceRequest
tuples []Tuple
tuples Tuples
opts InsertManyOpts
}

type insertManyArgs struct {
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
Space string
Tuples []Tuple
Tuples Tuples
Opts InsertManyOpts
}

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

// Tuples sets the tuples for the InsertManyRequest request.
// Note: default value is nil.
func (req InsertManyRequest) Tuples(tuples []Tuple) InsertManyRequest {
func (req InsertManyRequest) Tuples(tuples Tuples) InsertManyRequest {
req.tuples = tuples
return req
}
Expand Down Expand Up @@ -73,14 +73,14 @@ type InsertObjectManyOpts = OperationObjectManyOpts
// `crud.insert_object_many` for execution by a Connection.
type InsertObjectManyRequest struct {
spaceRequest
objects []Object
objects Objects
opts InsertObjectManyOpts
}

type insertObjectManyArgs struct {
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
Space string
Objects []Object
Objects Objects
Opts InsertObjectManyOpts
}

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

// Objects sets the objects for the InsertObjectManyRequest request.
// Note: default value is nil.
func (req InsertObjectManyRequest) Objects(objects []Object) InsertObjectManyRequest {
func (req InsertObjectManyRequest) Objects(objects Objects) InsertObjectManyRequest {
req.objects = objects
return req
}
Expand Down
15 changes: 11 additions & 4 deletions crud/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ import (
"github.com/vmihailenco/msgpack/v5"
)

// Object is an interface to describe object for CRUD methods.
type Object interface {
EncodeMsgpack(enc *msgpack.Encoder)
}
// Object is an interface to describe object for CRUD methods. It can be any
// type that msgpack can encode as a map.
type Object = interface{}

// Objects is a type to describe an array of object for CRUD methods. It can be
// any type that msgpack can encode, but encoded data must be an array of
// objects.
//
// See the reason why not just []Object:
// https://github.com/tarantool/go-tarantool/issues/365
type Objects = interface{}

// MapObject is a type to describe object as a map.
type MapObject map[string]interface{}
Expand Down
12 changes: 6 additions & 6 deletions crud/replace_many.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ type ReplaceManyOpts = OperationManyOpts
// `crud.replace_many` for execution by a Connection.
type ReplaceManyRequest struct {
spaceRequest
tuples []Tuple
tuples Tuples
opts ReplaceManyOpts
}

type replaceManyArgs struct {
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
Space string
Tuples []Tuple
Tuples Tuples
Opts ReplaceManyOpts
}

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

// Tuples sets the tuples for the ReplaceManyRequest request.
// Note: default value is nil.
func (req ReplaceManyRequest) Tuples(tuples []Tuple) ReplaceManyRequest {
func (req ReplaceManyRequest) Tuples(tuples Tuples) ReplaceManyRequest {
req.tuples = tuples
return req
}
Expand Down Expand Up @@ -73,14 +73,14 @@ type ReplaceObjectManyOpts = OperationObjectManyOpts
// `crud.replace_object_many` for execution by a Connection.
type ReplaceObjectManyRequest struct {
spaceRequest
objects []Object
objects Objects
opts ReplaceObjectManyOpts
}

type replaceObjectManyArgs struct {
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
Space string
Objects []Object
Objects Objects
Opts ReplaceObjectManyOpts
}

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

// Objects sets the tuple for the ReplaceObjectManyRequest request.
// Note: default value is nil.
func (req ReplaceObjectManyRequest) Objects(objects []Object) ReplaceObjectManyRequest {
func (req ReplaceObjectManyRequest) Objects(objects Objects) ReplaceObjectManyRequest {
req.objects = objects
return req
}
Expand Down
10 changes: 9 additions & 1 deletion crud/tuple.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package crud

// Tuple is a type to describe tuple for CRUD methods. It can be any type that
// msgpask can encode.
// msgpask can encode as an array.
type Tuple = interface{}

// Tuples is a type to describe an array of tuples for CRUD methods. It can be
// any type that msgpack can encode, but encoded data must be an array of
// tuples.
//
// See the reason why not just []Tuple:
// https://github.com/tarantool/go-tarantool/issues/365
type Tuples = interface{}