Skip to content

Commit

Permalink
crud: make *ManyRequest types less strict to tuples
Browse files Browse the repository at this point in the history
It was a mistake to use `[]interface{}` or `[]msgpack.CustomEncoder`
as types for an array of tuples and 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
  • Loading branch information
oleg-jukovec committed Jan 29, 2024
1 parent b8d9914 commit 77d65e8
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 17 deletions.
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)
- A slice of custom types could be used as a slice of tuples and objects for
`crud.*ManyRequest/crud.*ObjectManyRequest` (#365)

## [1.12.0] - 2023-06-07

Expand Down
75 changes: 75 additions & 0 deletions crud/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,81 @@ 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 {

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ee (release/linux/x86_64/1.10/, sdk-1.10.15-0-r598, false, false, false)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, 1.10, false, false)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (master, true, 1.13)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ee (release/linux/x86_64/2.11/, sdk-gc64-2.11.1-0-r598.linux.x86_64, true, true)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, master, false, false)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (master, true, 1.18, false)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, 2.10, false, false)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, 2.8, false, false)

undefined: _customType

Check failure on line 90 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ee (release/linux/x86_64/2.10/, sdk-gc64-2.10.8-0-r598.linux.x86_64, false, true)

undefined: _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

Check failure on line 111 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

not enough return values

Check failure on line 111 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (master, true, 1.18, false)

not enough return values
}

fmt.Println(ret.Metadata)
rows := ret.Rows.([]Tuple)
fmt.Println(rows[0].Id)
fmt.Println(*rows[0].BucketId)
fmt.Println(rows[0].Name)
// Output:
// [{id unsigned false} {bucket_id unsigned true} {name string false}]
// 2010
// 45
// bla
}

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

missing return (typecheck)

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ee (release/linux/x86_64/1.10/, sdk-1.10.15-0-r598, false, false, false)

missing return at end of function

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, 1.10, false, false)

missing return at end of function

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (master, true, 1.13)

missing return at end of function

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ee (release/linux/x86_64/2.11/, sdk-gc64-2.11.1-0-r598.linux.x86_64, true, true)

missing return at end of function

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, master, false, false)

missing return at end of function

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (master, true, 1.18, false)

missing return

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, 2.10, false, false)

missing return at end of function

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ce (1.13, 2.8, false, false)

missing return at end of function

Check failure on line 124 in crud/example_test.go

View workflow job for this annotation

GitHub Actions / run-tests-ee (release/linux/x86_64/2.10/, sdk-gc64-2.10.8-0-r598.linux.x86_64, false, true)

missing return at end of function

// 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)
fmt.Println(rows[0].Id)
fmt.Println(*rows[0].BucketId)
fmt.Println(rows[0].Name)
// 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
12 changes: 8 additions & 4 deletions crud/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ 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.
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
7 changes: 6 additions & 1 deletion crud/tuple.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
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.
type Tuples = interface{}

0 comments on commit 77d65e8

Please sign in to comment.