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 17, 2023
1 parent a22527a commit bfbe44f
Show file tree
Hide file tree
Showing 37 changed files with 2,997 additions and 64 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ jobs:
make test
make testrace
- name: Run CRUD tests with options v1
run: |
make bench-deps test-crud-bench
- name: Run CRUD tests with options v2
run: |
make bench-deps test-crud-bench TAGS="go_tarantool_crud_opts_v2"
- name: Run regression tests with call_17
run: |
make test TAGS="go_tarantool_call_17"
Expand Down
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
16 changes: 15 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,19 @@ 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-crud-bench
test-crud-bench:
@echo "Running bench tests in crud package"
cd ./crud/ && tarantool -e "require('crud')"
go test -v -tags "$(TAGS)" -bench=. -run=asdasdasd . -benchmem -memprofile=mem.out

.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 string
}

func (req *spaceRequest) setSpace(space string) {
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 string) *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 string) *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 string) *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
}
Loading

0 comments on commit bfbe44f

Please sign in to comment.