Skip to content

Commit 3a4f315

Browse files
committed
api: add CRUD module support
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
1 parent a22527a commit 3a4f315

35 files changed

+3158
-64
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
1212

1313
- Support pagination (#246)
1414
- A Makefile target to test with race detector (#218)
15+
- Support CRUD API (#108)
1516

1617
### Changed
1718

Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ endif
2121

2222
.PHONY: clean
2323
clean:
24-
( cd ./queue; rm -rf .rocks )
24+
( rm -rf queue/.rocks crud/.rocks )
2525
rm -f $(COVERAGE_FILE)
2626

2727
.PHONY: deps
2828
deps: clean
2929
( cd ./queue/testdata; $(TTCTL) rocks install queue 1.2.1 )
30+
( cd ./crud; $(TTCTL) rocks install crud 0.14.1 )
3031

3132
.PHONY: datetime-timezones
3233
datetime-timezones:
@@ -99,6 +100,13 @@ test-settings:
99100
go clean -testcache
100101
go test -tags "$(TAGS)" ./settings/ -v -p 1
101102

103+
.PHONY: test-crud
104+
test-crud:
105+
@echo "Running tests in crud package"
106+
cd ./crud/ && tarantool -e "require('crud')"
107+
go clean -testcache
108+
go test -tags "$(TAGS)" ./crud/ -v -p 1
109+
102110
.PHONY: test-main
103111
test-main:
104112
@echo "Running tests in main package"

crud/common.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package crud
2+
3+
import (
4+
"context"
5+
6+
"github.com/tarantool/go-tarantool"
7+
)
8+
9+
type Tuple = []interface{}
10+
type Object = map[string]interface{}
11+
12+
type baseRequest struct {
13+
impl *tarantool.CallRequest
14+
}
15+
16+
func (req *baseRequest) initImpl(methodName string) {
17+
req.impl = tarantool.NewCall17Request(methodName)
18+
}
19+
20+
// Code returns IPROTO code for CRUD request.
21+
func (req *baseRequest) Code() int32 {
22+
return req.impl.Code()
23+
}
24+
25+
// Ctx returns a context of CRUD request.
26+
func (req *baseRequest) Ctx() context.Context {
27+
return req.impl.Ctx()
28+
}
29+
30+
// Async returns is CRUD request expects a response.
31+
func (req *baseRequest) Async() bool {
32+
return req.impl.Async()
33+
}
34+
35+
type spaceRequest struct {
36+
baseRequest
37+
space string
38+
}
39+
40+
func (req *spaceRequest) setSpace(space string) {
41+
req.space = space
42+
}

crud/conditions.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package crud
2+
3+
type Operator string
4+
5+
const (
6+
EQ Operator = "="
7+
LT Operator = "<"
8+
LE Operator = "<="
9+
GT Operator = ">"
10+
GE Operator = ">="
11+
)
12+
13+
type Condition struct {
14+
// Instruct msgpack to pack this struct as array, so no custom packer
15+
// is needed.
16+
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
17+
Operator Operator
18+
KeyName string
19+
KeyValue interface{}
20+
}

crud/count.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package crud
2+
3+
import (
4+
"context"
5+
6+
"github.com/tarantool/go-tarantool"
7+
)
8+
9+
type CountOpts struct {
10+
Timeout OptUint
11+
VshardRouter OptString
12+
Mode OptString
13+
PreferReplica OptBool
14+
Balance OptBool
15+
YieldEvery OptUint
16+
BucketId OptUint
17+
ForceMapCall OptBool
18+
Fullscan OptBool
19+
}
20+
21+
func (opts CountOpts) EncodeMsgpack(enc *encoder) error {
22+
const optsCnt = 9
23+
24+
options := []option{opts.Timeout, opts.VshardRouter,
25+
opts.Mode, opts.PreferReplica, opts.Balance,
26+
opts.YieldEvery, opts.BucketId, opts.ForceMapCall,
27+
opts.Fullscan}
28+
names := []string{timeoutOptName, vshardRouterOptName,
29+
modeOptName, preferReplicaOptName, balanceOptName,
30+
yieldEveryOptName, bucketIdOptName, forceMapCallOptName,
31+
fullscanOptName}
32+
values := make([]interface{}, optsCnt)
33+
34+
return encodeOptions(enc, options, names, values)
35+
}
36+
37+
// CountRequest helps you to create request object to call `crud.count`
38+
// for execution by a Connection.
39+
type CountRequest struct {
40+
spaceRequest
41+
conditions []Condition
42+
opts CountOpts
43+
}
44+
45+
type countArgs struct {
46+
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
47+
Space string
48+
Conditions []Condition
49+
Opts CountOpts
50+
}
51+
52+
// NewCountRequest returns a new empty CountRequest.
53+
func NewCountRequest(space string) *CountRequest {
54+
req := new(CountRequest)
55+
req.initImpl("crud.count")
56+
req.setSpace(space)
57+
req.conditions = []Condition{}
58+
req.opts = CountOpts{}
59+
return req
60+
}
61+
62+
// Conditions sets the conditions for the CountRequest request.
63+
// Note: default value is nil.
64+
func (req *CountRequest) Conditions(conditions []Condition) *CountRequest {
65+
req.conditions = conditions
66+
return req
67+
}
68+
69+
// Opts sets the options for the CountRequest request.
70+
// Note: default value is nil.
71+
func (req *CountRequest) Opts(opts CountOpts) *CountRequest {
72+
req.opts = opts
73+
return req
74+
}
75+
76+
// Body fills an encoder with the call request body.
77+
func (req *CountRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
78+
args := countArgs{Space: req.space, Conditions: req.conditions, Opts: req.opts}
79+
req.impl = req.impl.Args(args)
80+
return req.impl.Body(res, enc)
81+
}
82+
83+
// Context sets a passed context to CRUD request.
84+
func (req *CountRequest) Context(ctx context.Context) *CountRequest {
85+
req.impl = req.impl.Context(ctx)
86+
87+
return req
88+
}

crud/delete.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package crud
2+
3+
import (
4+
"context"
5+
6+
"github.com/tarantool/go-tarantool"
7+
)
8+
9+
type DeleteOpts = SimpleOperationOpts
10+
11+
// DeleteRequest helps you to create request object to call `crud.delete`
12+
// for execution by a Connection.
13+
type DeleteRequest struct {
14+
spaceRequest
15+
key Tuple
16+
opts DeleteOpts
17+
}
18+
19+
type deleteArgs struct {
20+
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
21+
Space string
22+
Key Tuple
23+
Opts DeleteOpts
24+
}
25+
26+
// NewDeleteRequest returns a new empty DeleteRequest.
27+
func NewDeleteRequest(space string) *DeleteRequest {
28+
req := new(DeleteRequest)
29+
req.initImpl("crud.delete")
30+
req.setSpace(space)
31+
req.key = Tuple{}
32+
req.opts = DeleteOpts{}
33+
return req
34+
}
35+
36+
// Key sets the key for the DeleteRequest request.
37+
// Note: default value is nil.
38+
func (req *DeleteRequest) Key(key Tuple) *DeleteRequest {
39+
req.key = key
40+
return req
41+
}
42+
43+
// Opts sets the options for the DeleteRequest request.
44+
// Note: default value is nil.
45+
func (req *DeleteRequest) Opts(opts DeleteOpts) *DeleteRequest {
46+
req.opts = opts
47+
return req
48+
}
49+
50+
// Body fills an encoder with the call request body.
51+
func (req *DeleteRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
52+
args := deleteArgs{Space: req.space, Key: req.key, Opts: req.opts}
53+
req.impl = req.impl.Args(args)
54+
return req.impl.Body(res, enc)
55+
}
56+
57+
// Context sets a passed context to CRUD request.
58+
func (req *DeleteRequest) Context(ctx context.Context) *DeleteRequest {
59+
req.impl = req.impl.Context(ctx)
60+
61+
return req
62+
}

crud/get.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package crud
2+
3+
import (
4+
"context"
5+
6+
"github.com/tarantool/go-tarantool"
7+
)
8+
9+
type GetOpts struct {
10+
Timeout OptUint
11+
VshardRouter OptString
12+
Fields OptTuple
13+
BucketId OptUint
14+
Mode OptString
15+
PreferReplica OptBool
16+
Balance OptBool
17+
}
18+
19+
func (opts GetOpts) EncodeMsgpack(enc *encoder) error {
20+
const optsCnt = 7
21+
22+
options := []option{opts.Timeout, opts.VshardRouter,
23+
opts.Fields, opts.BucketId, opts.Mode,
24+
opts.PreferReplica, opts.Balance}
25+
names := []string{timeoutOptName, vshardRouterOptName,
26+
fieldsOptName, bucketIdOptName, modeOptName,
27+
preferReplicaOptName, balanceOptName}
28+
values := make([]interface{}, optsCnt)
29+
30+
return encodeOptions(enc, options, names, values)
31+
}
32+
33+
// GetRequest helps you to create request object to call `crud.get`
34+
// for execution by a Connection.
35+
type GetRequest struct {
36+
spaceRequest
37+
key Tuple
38+
opts GetOpts
39+
}
40+
41+
type getArgs struct {
42+
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
43+
Space string
44+
Key Tuple
45+
Opts GetOpts
46+
}
47+
48+
// NewGetRequest returns a new empty GetRequest.
49+
func NewGetRequest(space string) *GetRequest {
50+
req := new(GetRequest)
51+
req.initImpl("crud.get")
52+
req.setSpace(space)
53+
req.key = Tuple{}
54+
req.opts = GetOpts{}
55+
return req
56+
}
57+
58+
// Key sets the key for the GetRequest request.
59+
// Note: default value is nil.
60+
func (req *GetRequest) Key(key Tuple) *GetRequest {
61+
req.key = key
62+
return req
63+
}
64+
65+
// Opts sets the options for the GetRequest request.
66+
// Note: default value is nil.
67+
func (req *GetRequest) Opts(opts GetOpts) *GetRequest {
68+
req.opts = opts
69+
return req
70+
}
71+
72+
// Body fills an encoder with the call request body.
73+
func (req *GetRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
74+
args := getArgs{Space: req.space, Key: req.key, Opts: req.opts}
75+
req.impl = req.impl.Args(args)
76+
return req.impl.Body(res, enc)
77+
}
78+
79+
// Context sets a passed context to CRUD request.
80+
func (req *GetRequest) Context(ctx context.Context) *GetRequest {
81+
req.impl = req.impl.Context(ctx)
82+
83+
return req
84+
}

0 commit comments

Comments
 (0)