Skip to content

Commit 76384ee

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 76384ee

35 files changed

+2825
-12
lines changed

.github/workflows/testing.yml

+8
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ jobs:
116116
make test TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17"
117117
make testrace TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17"
118118
119+
- name: Run CRUD tests with options v1
120+
run: |
121+
make bench-deps test-crud DURATION=1x COUNT=1
122+
123+
- name: Run CRUD tests with options v2
124+
run: |
125+
make bench-deps test-crud TAGS="go_tarantool_crud_opts_v2" DURATION=1x COUNT=1
126+
119127
- name: Run fuzzing tests
120128
if: ${{ matrix.fuzzing }}
121129
run: make fuzzing TAGS="go_tarantool_decimal_fuzzing"

CHANGELOG.md

+1
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

+12-1
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,16 @@ 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+
go test -tags "$(TAGS)" ./crud/ ${BENCH_OPTIONS} 2>&1 \
110+
| tee ${BENCH_FILE}
111+
benchstat ${BENCH_FILE}
112+
102113
.PHONY: test-main
103114
test-main:
104115
@echo "Running tests in main package"

crud/common.go

+42
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 interface{}
38+
}
39+
40+
func (req *spaceRequest) setSpace(space interface{}) {
41+
req.space = space
42+
}

crud/conditions.go

+20
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

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package crud
2+
3+
import (
4+
"context"
5+
6+
"github.com/tarantool/go-tarantool"
7+
)
8+
9+
type CountOpts struct {
10+
Timeout OptUint `crud:"timeout"`
11+
VshardRouter OptString `crud:"vshard_router"`
12+
Mode OptString `crud:"mode"`
13+
PreferReplica OptBool `crud:"prefer_replica"`
14+
Balance OptBool `crud:"balance"`
15+
YieldEvery OptUint `crud:"yield_every"`
16+
BucketId OptUint `crud:"bucket_id"`
17+
ForceMapCall OptBool `crud:"force_map_call"`
18+
Fullscan OptBool `crud:"fullscan"`
19+
}
20+
21+
// CountRequest helps you to create request object to call `crud.count`
22+
// for execution by a Connection.
23+
type CountRequest struct {
24+
spaceRequest
25+
conditions []Condition
26+
opts CountOpts
27+
}
28+
29+
// NewCountRequest returns a new empty CountRequest.
30+
func NewCountRequest(space interface{}) *CountRequest {
31+
req := new(CountRequest)
32+
req.initImpl("crud.count")
33+
req.setSpace(space)
34+
req.conditions = []Condition{}
35+
req.opts = CountOpts{}
36+
return req
37+
}
38+
39+
// Conditions sets the conditions for the CountRequest request.
40+
// Note: default value is nil.
41+
func (req *CountRequest) Conditions(conditions []Condition) *CountRequest {
42+
req.conditions = conditions
43+
return req
44+
}
45+
46+
// Opts sets the options for the CountRequest request.
47+
// Note: default value is nil.
48+
func (req *CountRequest) Opts(opts CountOpts) *CountRequest {
49+
req.opts = opts
50+
return req
51+
}
52+
53+
// Body fills an encoder with the call request body.
54+
func (req *CountRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
55+
req.impl.Args([]interface{}{req.space, req.conditions, convertToMap(req.opts)})
56+
return req.impl.Body(res, enc)
57+
}
58+
59+
// Context sets a passed context to CRUD request.
60+
func (req *CountRequest) Context(ctx context.Context) *CountRequest {
61+
req.impl = req.impl.Context(ctx)
62+
63+
return req
64+
}

crud/delete.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
// NewDeleteRequest returns a new empty DeleteRequest.
20+
func NewDeleteRequest(space interface{}) *DeleteRequest {
21+
req := new(DeleteRequest)
22+
req.initImpl("crud.delete")
23+
req.setSpace(space)
24+
req.key = Tuple{}
25+
req.opts = DeleteOpts{}
26+
return req
27+
}
28+
29+
// Key sets the key for the DeleteRequest request.
30+
// Note: default value is nil.
31+
func (req *DeleteRequest) Key(key Tuple) *DeleteRequest {
32+
req.key = key
33+
return req
34+
}
35+
36+
// Opts sets the options for the DeleteRequest request.
37+
// Note: default value is nil.
38+
func (req *DeleteRequest) Opts(opts DeleteOpts) *DeleteRequest {
39+
req.opts = opts
40+
return req
41+
}
42+
43+
// Body fills an encoder with the call request body.
44+
func (req *DeleteRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
45+
req.impl.Args([]interface{}{req.space, req.key, convertToMap(req.opts)})
46+
return req.impl.Body(res, enc)
47+
}
48+
49+
// Context sets a passed context to CRUD request.
50+
func (req *DeleteRequest) Context(ctx context.Context) *DeleteRequest {
51+
req.impl = req.impl.Context(ctx)
52+
53+
return req
54+
}

crud/get.go

+62
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 GetOpts struct {
10+
Timeout OptUint `crud:"timeout"`
11+
VshardRouter OptString `crud:"vshard_router"`
12+
Fields OptTuple `crud:"fields"`
13+
BucketId OptUint `crud:"bucket_id"`
14+
Mode OptString `crud:"mode"`
15+
PreferReplica OptBool `crud:"prefer_replica"`
16+
Balance OptBool `crud:"balance"`
17+
}
18+
19+
// GetRequest helps you to create request object to call `crud.get`
20+
// for execution by a Connection.
21+
type GetRequest struct {
22+
spaceRequest
23+
key Tuple
24+
opts GetOpts
25+
}
26+
27+
// NewGetRequest returns a new empty GetRequest.
28+
func NewGetRequest(space interface{}) *GetRequest {
29+
req := new(GetRequest)
30+
req.initImpl("crud.get")
31+
req.setSpace(space)
32+
req.key = Tuple{}
33+
req.opts = GetOpts{}
34+
return req
35+
}
36+
37+
// Key sets the key for the GetRequest request.
38+
// Note: default value is nil.
39+
func (req *GetRequest) Key(key Tuple) *GetRequest {
40+
req.key = key
41+
return req
42+
}
43+
44+
// Opts sets the options for the GetRequest request.
45+
// Note: default value is nil.
46+
func (req *GetRequest) Opts(opts GetOpts) *GetRequest {
47+
req.opts = opts
48+
return req
49+
}
50+
51+
// Body fills an encoder with the call request body.
52+
func (req *GetRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
53+
req.impl.Args([]interface{}{req.space, req.key, convertToMap(req.opts)})
54+
return req.impl.Body(res, enc)
55+
}
56+
57+
// Context sets a passed context to CRUD request.
58+
func (req *GetRequest) Context(ctx context.Context) *GetRequest {
59+
req.impl = req.impl.Context(ctx)
60+
61+
return req
62+
}

0 commit comments

Comments
 (0)