Skip to content

Commit c86f41d

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 c86f41d

38 files changed

+4159
-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/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 1.0.0 )
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

Lines changed: 95 additions & 0 deletions
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

Lines changed: 28 additions & 0 deletions
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

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

crud/delete.go

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

0 commit comments

Comments
 (0)