Skip to content

Commit

Permalink
api: add CRUD module support
Browse files Browse the repository at this point in the history
This patch provides crud [1] methods as request objects to support CRUD API.
The following methods are supported:

* `insert`
* `insert_object`
* `insert_many`
* `insert_object_many`
* `get`
* `update`
* `delete`
* `replace`
* `replace_object`
* `replace_many`
* `replace_object_many`
* `upsert`
* `upsert_object`
* `upsert_many`
* `upsert_object_many`
* `select`
* `min`
* `max`
* `truncate`
* `len`
* `storage_info`
* `count`
* `stats`
* `unflatten_rows`

1. https://github.com/tarantool/crud

Closes #108
  • Loading branch information
AnaNek committed Feb 9, 2023
1 parent a22527a commit 8b40f0d
Show file tree
Hide file tree
Showing 33 changed files with 2,687 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.

- Support pagination (#246)
- A Makefile target to test with race detector (#218)
- Support CRUD API (#108)

### Changed

Expand Down
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ endif

.PHONY: clean
clean:
( cd ./queue; rm -rf .rocks )
( rm -rf queue/.rocks crud/.rocks )
rm -f $(COVERAGE_FILE)

.PHONY: deps
deps: clean
( cd ./queue/testdata; $(TTCTL) rocks install queue 1.2.1 )
( cd ./crud; $(TTCTL) rocks install crud 0.14.1 )

.PHONY: datetime-timezones
datetime-timezones:
Expand Down Expand Up @@ -99,6 +100,13 @@ test-settings:
go clean -testcache
go test -tags "$(TAGS)" ./settings/ -v -p 1

.PHONY: test-crud
test-crud:
@echo "Running tests in crud package"
cd ./crud/ && tarantool -e "require('crud')"
go clean -testcache
go test -tags "$(TAGS)" ./crud/ -v -p 1

.PHONY: test-main
test-main:
@echo "Running tests in main package"
Expand Down
42 changes: 42 additions & 0 deletions crud/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package crud

import (
"context"

"github.com/tarantool/go-tarantool"
)

type Tuple = []interface{}
type Object = map[string]interface{}

type baseRequest struct {
impl *tarantool.CallRequest
}

func (req *baseRequest) initImpl(methodName string) {
req.impl = tarantool.NewCall17Request(methodName)
}

// Code returns IPROTO code for CRUD request.
func (req *baseRequest) Code() int32 {
return req.impl.Code()
}

// Ctx returns a context of CRUD request.
func (req *baseRequest) Ctx() context.Context {
return req.impl.Ctx()
}

// Async returns is CRUD request expects a response.
func (req *baseRequest) Async() bool {
return req.impl.Async()
}

type spaceRequest struct {
baseRequest
space interface{}
}

func (req *spaceRequest) setSpace(space interface{}) {
req.space = space
}
20 changes: 20 additions & 0 deletions crud/conditions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package crud

type Operator string

const (
EQ Operator = "="
LT Operator = "<"
LE Operator = "<="
Gt Operator = ">"
GE Operator = ">="
)

type Condition struct {
// Instruct msgpack to pack this struct as array, so no custom packer
// is needed.
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
Operator Operator
KeyName string
KeyValue interface{}
}
64 changes: 64 additions & 0 deletions crud/count.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package crud

import (
"context"

"github.com/tarantool/go-tarantool"
)

type CountOpts struct {
Timeout OptUint `crud:"timeout"`
VshardRouter OptString `crud:"vshard_router"`
Mode OptString `crud:"mode"`
PreferReplica OptBool `crud:"prefer_replica"`
Balance OptBool `crud:"balance"`
YieldEvery OptUint `crud:"yield_every"`
BucketId OptUint `crud:"bucket_id"`
ForceMapCall OptBool `crud:"force_map_call"`
Fullscan OptBool `crud:"fullscan"`
}

// CountRequest helps you to create request object to call `crud.count`
// for execution by a Connection.
type CountRequest struct {
spaceRequest
conditions []Condition
opts CountOpts
}

// NewCountRequest returns a new empty CountRequest.
func NewCountRequest(space interface{}) *CountRequest {
req := new(CountRequest)
req.initImpl("crud.count")
req.setSpace(space)
req.conditions = []Condition{}
req.opts = CountOpts{}
return req
}

// Conditions sets the conditions for the CountRequest request.
// Note: default value is nil.
func (req *CountRequest) Conditions(conditions []Condition) *CountRequest {
req.conditions = conditions
return req
}

// Opts sets the options for the CountRequest request.
// Note: default value is nil.
func (req *CountRequest) Opts(opts CountOpts) *CountRequest {
req.opts = opts
return req
}

// Body fills an encoder with the call request body.
func (req *CountRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
req.impl.Args([]interface{}{req.space, req.conditions, convertToMap(req.opts)})
return req.impl.Body(res, enc)
}

// Context sets a passed context to CRUD request.
func (req *CountRequest) Context(ctx context.Context) *CountRequest {
req.impl = req.impl.Context(ctx)

return req
}
54 changes: 54 additions & 0 deletions crud/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package crud

import (
"context"

"github.com/tarantool/go-tarantool"
)

type DeleteOpts = SimpleOperationOpts

// DeleteRequest helps you to create request object to call `crud.delete`
// for execution by a Connection.
type DeleteRequest struct {
spaceRequest
key Tuple
opts DeleteOpts
}

// NewDeleteRequest returns a new empty DeleteRequest.
func NewDeleteRequest(space interface{}) *DeleteRequest {
req := new(DeleteRequest)
req.initImpl("crud.delete")
req.setSpace(space)
req.key = Tuple{}
req.opts = DeleteOpts{}
return req
}

// Key sets the key for the DeleteRequest request.
// Note: default value is nil.
func (req *DeleteRequest) Key(key Tuple) *DeleteRequest {
req.key = key
return req
}

// Opts sets the options for the DeleteRequest request.
// Note: default value is nil.
func (req *DeleteRequest) Opts(opts DeleteOpts) *DeleteRequest {
req.opts = opts
return req
}

// Body fills an encoder with the call request body.
func (req *DeleteRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
req.impl.Args([]interface{}{req.space, req.key, convertToMap(req.opts)})
return req.impl.Body(res, enc)
}

// Context sets a passed context to CRUD request.
func (req *DeleteRequest) Context(ctx context.Context) *DeleteRequest {
req.impl = req.impl.Context(ctx)

return req
}
62 changes: 62 additions & 0 deletions crud/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package crud

import (
"context"

"github.com/tarantool/go-tarantool"
)

type GetOpts struct {
Timeout OptUint `crud:"timeout"`
VshardRouter OptString `crud:"vshard_router"`
Fields OptTuple `crud:"fields"`
BucketId OptUint `crud:"bucket_id"`
Mode OptString `crud:"mode"`
PreferReplica OptBool `crud:"prefer_replica"`
Balance OptBool `crud:"balance"`
}

// GetRequest helps you to create request object to call `crud.get`
// for execution by a Connection.
type GetRequest struct {
spaceRequest
key Tuple
opts GetOpts
}

// NewGetRequest returns a new empty GetRequest.
func NewGetRequest(space interface{}) *GetRequest {
req := new(GetRequest)
req.initImpl("crud.get")
req.setSpace(space)
req.key = Tuple{}
req.opts = GetOpts{}
return req
}

// Key sets the key for the GetRequest request.
// Note: default value is nil.
func (req *GetRequest) Key(key Tuple) *GetRequest {
req.key = key
return req
}

// Opts sets the options for the GetRequest request.
// Note: default value is nil.
func (req *GetRequest) Opts(opts GetOpts) *GetRequest {
req.opts = opts
return req
}

// Body fills an encoder with the call request body.
func (req *GetRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
req.impl.Args([]interface{}{req.space, req.key, convertToMap(req.opts)})
return req.impl.Body(res, enc)
}

// Context sets a passed context to CRUD request.
func (req *GetRequest) Context(ctx context.Context) *GetRequest {
req.impl = req.impl.Context(ctx)

return req
}
101 changes: 101 additions & 0 deletions crud/insert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package crud

import (
"context"

"github.com/tarantool/go-tarantool"
)

type InsertOpts = SimpleOperationOpts

// InsertRequest helps you to create request object to call `crud.insert`
// for execution by a Connection.
type InsertRequest struct {
spaceRequest
tuple Tuple
opts InsertOpts
}

// NewInsertRequest returns a new empty InsertRequest.
func NewInsertRequest(space interface{}) *InsertRequest {
req := new(InsertRequest)
req.initImpl("crud.insert")
req.setSpace(space)
req.tuple = Tuple{}
req.opts = InsertOpts{}
return req
}

// Tuple sets the tuple for the InsertRequest request.
// Note: default value is nil.
func (req *InsertRequest) Tuple(tuple Tuple) *InsertRequest {
req.tuple = tuple
return req
}

// Opts sets the options for the insert request.
// Note: default value is nil.
func (req *InsertRequest) Opts(opts InsertOpts) *InsertRequest {
req.opts = opts
return req
}

// Body fills an encoder with the call request body.
func (req *InsertRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
req.impl.Args([]interface{}{req.space, req.tuple, convertToMap(req.opts)})
return req.impl.Body(res, enc)
}

// Context sets a passed context to CRUD request.
func (req *InsertRequest) Context(ctx context.Context) *InsertRequest {
req.impl = req.impl.Context(ctx)

return req
}

type InsertObjectOpts = SimpleOperationObjectOpts

// InsertObjectRequest helps you to create request object to call
// `crud.insert_object` for execution by a Connection.
type InsertObjectRequest struct {
spaceRequest
object Object
opts InsertObjectOpts
}

// NewInsertObjectRequest returns a new empty InsertObjectRequest.
func NewInsertObjectRequest(space interface{}) *InsertObjectRequest {
req := new(InsertObjectRequest)
req.initImpl("crud.insert_object")
req.setSpace(space)
req.object = Object{}
req.opts = InsertObjectOpts{}
return req
}

// Object sets the tuple for the InsertObjectRequest request.
// Note: default value is nil.
func (req *InsertObjectRequest) Object(object Object) *InsertObjectRequest {
req.object = object
return req
}

// Opts sets the options for the InsertObjectRequest request.
// Note: default value is nil.
func (req *InsertObjectRequest) Opts(opts InsertObjectOpts) *InsertObjectRequest {
req.opts = opts
return req
}

// Body fills an encoder with the call request body.
func (req *InsertObjectRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
req.impl.Args([]interface{}{req.space, req.object, convertToMap(req.opts)})
return req.impl.Body(res, enc)
}

// Context sets a passed context to CRUD request.
func (req *InsertObjectRequest) Context(ctx context.Context) *InsertObjectRequest {
req.impl = req.impl.Context(ctx)

return req
}
Loading

0 comments on commit 8b40f0d

Please sign in to comment.