Skip to content

Commit 7ecc243

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 7ecc243

35 files changed

+3419
-64
lines changed

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

+9-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/testdata/.rocks crud/testdata/.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/testdata; $(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/testdata && 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

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Package crud with support of API of Tarantool's CRUD module.
2+
//
3+
// Supported CRUD methods:
4+
//
5+
// - insert
6+
//
7+
// - insert_object
8+
//
9+
// - insert_many
10+
//
11+
// - insert_object_many
12+
//
13+
// - get
14+
//
15+
// - update
16+
//
17+
// - delete
18+
//
19+
// - replace
20+
//
21+
// - replace_object
22+
//
23+
// - replace_many
24+
//
25+
// - replace_object_many
26+
//
27+
// - upsert
28+
//
29+
// - upsert_object
30+
//
31+
// - upsert_many
32+
//
33+
// - upsert_object_many
34+
//
35+
// - select
36+
//
37+
// - min
38+
//
39+
// - max
40+
//
41+
// - truncate
42+
//
43+
// - len
44+
//
45+
// - storage_info
46+
//
47+
// - count
48+
//
49+
// - stats
50+
//
51+
// - unflatten_rows
52+
//
53+
// Since: 1.11.0.
54+
package crud
55+
56+
import (
57+
"context"
58+
59+
"github.com/tarantool/go-tarantool"
60+
)
61+
62+
// Tuple is a type to describe tuple for CRUD methods.
63+
type Tuple = []interface{}
64+
65+
type baseRequest struct {
66+
impl *tarantool.CallRequest
67+
}
68+
69+
func (req *baseRequest) initImpl(methodName string) {
70+
req.impl = tarantool.NewCall17Request(methodName)
71+
}
72+
73+
// Code returns IPROTO code for CRUD request.
74+
func (req *baseRequest) Code() int32 {
75+
return req.impl.Code()
76+
}
77+
78+
// Ctx returns a context of CRUD request.
79+
func (req *baseRequest) Ctx() context.Context {
80+
return req.impl.Ctx()
81+
}
82+
83+
// Async returns is CRUD request expects a response.
84+
func (req *baseRequest) Async() bool {
85+
return req.impl.Async()
86+
}
87+
88+
type spaceRequest struct {
89+
baseRequest
90+
space string
91+
}
92+
93+
func (req *spaceRequest) setSpace(space string) {
94+
req.space = space
95+
}

crud/conditions.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package crud
2+
3+
// Operator is a type to describe operator of operation.
4+
type Operator string
5+
6+
const (
7+
// Eq - comparison operator for "equal".
8+
Eq Operator = "="
9+
// Lt - comparison operator for "less than".
10+
Lt Operator = "<"
11+
// Le - comparison operator for "less than or equal".
12+
Le Operator = "<="
13+
// Gt - comparison operator for "greater than".
14+
Gt Operator = ">"
15+
// Ge - comparison operator for "greater than or equal".
16+
Ge Operator = ">="
17+
)
18+
19+
// Condition describes CRUD condition as a table
20+
// {operator, field-identifier, value}.
21+
type Condition struct {
22+
// Instruct msgpack to pack this struct as array, so no custom packer
23+
// is needed.
24+
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
25+
Operator Operator
26+
KeyName string
27+
KeyValue interface{}
28+
}

crud/count.go

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package crud
2+
3+
import (
4+
"context"
5+
6+
"github.com/tarantool/go-tarantool"
7+
)
8+
9+
// CountOpts describes options for `crud.count` method.
10+
type CountOpts struct {
11+
// Timeout is a `vshard.call` timeout and vshard
12+
// master discovery timeout (in seconds).
13+
Timeout OptUint
14+
// VshardRouter is cartridge vshard group name or
15+
// vshard router instance.
16+
VshardRouter OptString
17+
// Mode is a parameter with `write`/`read` possible values,
18+
// if `write` is specified then operation is performed on master.
19+
Mode OptString
20+
// PreferReplica is a parameter to specify preferred target
21+
// as one of the replicas.
22+
PreferReplica OptBool
23+
// Balance is a parameter to use replica according to vshard
24+
// load balancing policy.
25+
Balance OptBool
26+
// YieldEvery describes number of tuples processed to yield after.
27+
YieldEvery OptUint
28+
// BucketId is a bucket ID.
29+
BucketId OptUint
30+
// ForceMapCall describes the map call is performed without any
31+
// optimizations even if full primary key equal condition is specified.
32+
ForceMapCall OptBool
33+
// Fullscan describes if a critical log entry will be skipped on
34+
// potentially long count.
35+
Fullscan OptBool
36+
}
37+
38+
// EncodeMsgpack provides custom msgpack encoder.
39+
func (opts CountOpts) EncodeMsgpack(enc *encoder) error {
40+
const optsCnt = 9
41+
42+
options := [optsCnt]option{opts.Timeout, opts.VshardRouter,
43+
opts.Mode, opts.PreferReplica, opts.Balance,
44+
opts.YieldEvery, opts.BucketId, opts.ForceMapCall,
45+
opts.Fullscan}
46+
names := [optsCnt]string{timeoutOptName, vshardRouterOptName,
47+
modeOptName, preferReplicaOptName, balanceOptName,
48+
yieldEveryOptName, bucketIdOptName, forceMapCallOptName,
49+
fullscanOptName}
50+
values := [optsCnt]interface{}{}
51+
52+
return encodeOptions(enc, options[:], names[:], values[:])
53+
}
54+
55+
// CountRequest helps you to create request object to call `crud.count`
56+
// for execution by a Connection.
57+
type CountRequest struct {
58+
spaceRequest
59+
conditions []Condition
60+
opts CountOpts
61+
}
62+
63+
type countArgs struct {
64+
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
65+
Space string
66+
Conditions []Condition
67+
Opts CountOpts
68+
}
69+
70+
// NewCountRequest returns a new empty CountRequest.
71+
func NewCountRequest(space string) *CountRequest {
72+
req := new(CountRequest)
73+
req.initImpl("crud.count")
74+
req.setSpace(space)
75+
req.conditions = nil
76+
req.opts = CountOpts{}
77+
return req
78+
}
79+
80+
// Conditions sets the conditions for the CountRequest request.
81+
// Note: default value is nil.
82+
func (req *CountRequest) Conditions(conditions []Condition) *CountRequest {
83+
req.conditions = conditions
84+
return req
85+
}
86+
87+
// Opts sets the options for the CountRequest request.
88+
// Note: default value is nil.
89+
func (req *CountRequest) Opts(opts CountOpts) *CountRequest {
90+
req.opts = opts
91+
return req
92+
}
93+
94+
// Body fills an encoder with the call request body.
95+
func (req *CountRequest) Body(res tarantool.SchemaResolver, enc *encoder) error {
96+
args := countArgs{Space: req.space, Conditions: req.conditions, Opts: req.opts}
97+
req.impl = req.impl.Args(args)
98+
return req.impl.Body(res, enc)
99+
}
100+
101+
// Context sets a passed context to CRUD request.
102+
func (req *CountRequest) Context(ctx context.Context) *CountRequest {
103+
req.impl = req.impl.Context(ctx)
104+
105+
return req
106+
}

crud/delete.go

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

0 commit comments

Comments
 (0)