Skip to content

Commit 375dad1

Browse files
committed
introduce internal API for raw tuples
This patch introduces internal API for insert, replace and upsert raw tuples. To reduce amonut of changes this methods will be exposed in next patches. Hovewer this patch already tries to support naming convenstion: we internally use module.object for operations on objects and module.tuple for operations on tuples. Also some kind of optimization is introduced. Before this patch we call unflatten for object twice. This patch removes one of them. This way reduce amount of Lua garbage. Part of #6
1 parent b42e022 commit 375dad1

File tree

5 files changed

+177
-52
lines changed

5 files changed

+177
-52
lines changed

crud.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,25 @@ crud.register = registry.add
2525
--- CRUD operations.
2626
-- @section crud
2727

28-
-- @refer insert.call
28+
-- @refer insert.object
2929
-- @function insert
30-
crud.insert = insert.call
30+
crud.insert = insert.object
3131

3232
-- @refer get.call
3333
-- @function get
3434
crud.get = get.call
3535

36-
-- @refer replace.call
36+
-- @refer replace.object
3737
-- @function replace
38-
crud.replace = replace.call
38+
crud.replace = replace.object
3939

4040
-- @refer update.call
4141
-- @function update
4242
crud.update = update.call
4343

44-
-- @refer upsert.call
44+
-- @refer upsert.object
4545
-- @function upsert
46-
crud.upsert = upsert.call
46+
crud.upsert = upsert.object
4747

4848
-- @refer delete.call
4949
-- @function delete

crud/common/utils.lua

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local dev_checks = require('crud.common.dev_checks')
55
local FlattenError = errors.new_class("FlattenError", {capture_stack = false})
66
local UnflattenError = errors.new_class("UnflattenError", {capture_stack = false})
77
local ParseOperationsError = errors.new_class('ParseOperationsError', {capture_stack = false})
8+
local ShardingError = errors.new_class('ShardingError', {capture_stack = false})
89

910
local utils = {}
1011

@@ -195,4 +196,14 @@ function utils.reverse_inplace(t)
195196
return t
196197
end
197198

199+
function utils.get_bucket_id_fieldno(space, shard_index_name)
200+
shard_index_name = shard_index_name or 'bucket_id'
201+
local bucket_id_index = space.index[shard_index_name]
202+
if bucket_id_index == nil then
203+
return nil, ShardingError:new('%q index is not found', shard_index_name)
204+
end
205+
206+
return bucket_id_index.parts[1].fieldno
207+
end
208+
198209
return utils

crud/insert.lua

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,24 @@ function insert.init()
3030
})
3131
end
3232

33-
--- Inserts tuple to the specified space
33+
--- Inserts a tuple to the specified space
3434
--
35-
-- @function call
35+
-- @function tuple
3636
--
3737
-- @param string space_name
3838
-- A space name
3939
--
40-
-- @param table key_parts
41-
-- Primary key fields' names array
42-
--
43-
-- @param table obj
44-
-- Tuple object (according to space format)
40+
-- @param table tuple
41+
-- Tuple
4542
--
4643
-- @tparam ?number opts.timeout
4744
-- Function call timeout
4845
--
49-
-- @return[1] object
46+
-- @return[1] tuple
5047
-- @treturn[2] nil
5148
-- @treturn[2] table Error description
5249
--
53-
function insert.call(space_name, obj, opts)
50+
function insert.tuple(space_name, tuple, opts)
5451
checks('string', 'table', {
5552
timeout = '?number',
5653
})
@@ -63,25 +60,24 @@ function insert.call(space_name, obj, opts)
6360
end
6461
local space_format = space:format()
6562

66-
-- compute default bucket_id
67-
local tuple, err = utils.flatten(obj, space_format)
68-
if err ~= nil then
69-
return nil, InsertError:new("Object is specified in bad format: %s", err)
70-
end
71-
7263
local key = utils.extract_key(tuple, space.index[0].parts)
73-
7464
local bucket_id = vshard.router.bucket_id_strcrc32(key)
7565
local replicaset, err = vshard.router.route(bucket_id)
7666
if replicaset == nil then
7767
return nil, InsertError:new("Failed to get replicaset for bucket_id %s: %s", bucket_id, err.err)
7868
end
7969

80-
local tuple, err = utils.flatten(obj, space_format, bucket_id)
70+
local bucket_id_fieldno, err = utils.get_bucket_id_fieldno(space)
8171
if err ~= nil then
82-
return nil, InsertError:new("Object is specified in bad format: %s", err)
72+
return nil, err
73+
end
74+
75+
if tuple[bucket_id_fieldno] ~= nil then
76+
return nil, InsertError:new("Unexpected value (%s) at field %s (sharding key)",
77+
tuple[bucket_id_fieldno], bucket_id_fieldno)
8378
end
8479

80+
tuple[bucket_id_fieldno] = bucket_id
8581
local results, err = call.rw(INSERT_FUNC_NAME, {space_name, tuple}, {
8682
replicasets = {replicaset},
8783
timeout = opts.timeout,
@@ -98,4 +94,42 @@ function insert.call(space_name, obj, opts)
9894
}
9995
end
10096

97+
--- Inserts an object to the specified space
98+
--
99+
-- @function object
100+
--
101+
-- @param string space_name
102+
-- A space name
103+
--
104+
-- @param table obj
105+
-- Object
106+
--
107+
-- @tparam ?number opts.timeout
108+
-- Function call timeout
109+
--
110+
-- @return[1] object
111+
-- @treturn[2] nil
112+
-- @treturn[2] table Error description
113+
--
114+
function insert.object(space_name, obj, opts)
115+
checks('string', 'table', {
116+
timeout = '?number',
117+
})
118+
119+
opts = opts or {}
120+
121+
local space = utils.get_space(space_name, vshard.router.routeall())
122+
if space == nil then
123+
return nil, InsertError:new("Space %q doesn't exists", space_name)
124+
end
125+
local space_format = space:format()
126+
127+
local tuple, err = utils.flatten(obj, space_format)
128+
if err ~= nil then
129+
return nil, InsertError:new("Object is specified in bad format: %s", err)
130+
end
131+
132+
return insert.tuple(space_name, tuple, opts)
133+
end
134+
101135
return insert

crud/replace.lua

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ end
3232

3333
--- Insert or replace a tuple in the specified space
3434
--
35-
-- @function call
35+
-- @function tuple
3636
--
3737
-- @param string space_name
3838
-- A space name
3939
--
40-
-- @param table obj
41-
-- Tuple object (according to space format)
40+
-- @param table tuple
41+
-- Tuple
4242
--
4343
-- @tparam ?number opts.timeout
4444
-- Function call timeout
@@ -47,7 +47,7 @@ end
4747
-- @treturn[2] nil
4848
-- @treturn[2] table Error description
4949
--
50-
function replace.call(space_name, obj, opts)
50+
function replace.tuple(space_name, tuple, opts)
5151
checks('string', 'table', {
5252
timeout = '?number',
5353
})
@@ -59,13 +59,6 @@ function replace.call(space_name, obj, opts)
5959
return nil, ReplaceError:new("Space %q doesn't exist", space_name)
6060
end
6161

62-
local space_format = space:format()
63-
-- compute default bucket_id
64-
local tuple, err = utils.flatten(obj, space_format)
65-
if err ~= nil then
66-
return nil, ReplaceError:new("Object is specified in bad format: %s", err)
67-
end
68-
6962
local key = utils.extract_key(tuple, space.index[0].parts)
7063

7164
local bucket_id = vshard.router.bucket_id_strcrc32(key)
@@ -74,11 +67,17 @@ function replace.call(space_name, obj, opts)
7467
return nil, ReplaceError:new("Failed to get replicaset for bucket_id %s: %s", bucket_id, err.err)
7568
end
7669

77-
local tuple, err = utils.flatten(obj, space_format, bucket_id)
70+
local bucket_id_fieldno, err = utils.get_bucket_id_fieldno(space)
7871
if err ~= nil then
79-
return nil, ReplaceError:new("Object is specified in bad format: %s", err)
72+
return nil, err
8073
end
8174

75+
if tuple[bucket_id_fieldno] ~= nil then
76+
return nil, ReplaceError:new("Unexpected value (%s) at field %s (sharding key)",
77+
tuple[bucket_id_fieldno], bucket_id_fieldno)
78+
end
79+
80+
tuple[bucket_id_fieldno] = bucket_id
8281
local results, err = call.rw(REPLACE_FUNC_NAME, {space_name, tuple}, {
8382
replicasets = {replicaset},
8483
timeout = opts.timeout,
@@ -90,9 +89,47 @@ function replace.call(space_name, obj, opts)
9089

9190
local tuple = results[replicaset.uuid]
9291
return {
93-
metadata = table.copy(space_format),
92+
metadata = table.copy(space:format()),
9493
rows = {tuple},
9594
}
9695
end
9796

97+
--- Insert or replace an object in the specified space
98+
--
99+
-- @function object
100+
--
101+
-- @param string space_name
102+
-- A space name
103+
--
104+
-- @param table obj
105+
-- Object
106+
--
107+
-- @tparam ?number opts.timeout
108+
-- Function call timeout
109+
--
110+
-- @return[1] object
111+
-- @treturn[2] nil
112+
-- @treturn[2] table Error description
113+
--
114+
function replace.object(space_name, obj, opts)
115+
checks('string', 'table', {
116+
timeout = '?number',
117+
})
118+
119+
opts = opts or {}
120+
121+
local space = utils.get_space(space_name, vshard.router.routeall())
122+
if space == nil then
123+
return nil, ReplaceError:new("Space %q doesn't exists", space_name)
124+
end
125+
126+
local space_format = space:format()
127+
local tuple, err = utils.flatten(obj, space_format)
128+
if err ~= nil then
129+
return nil, ReplaceError:new("Object is specified in bad format: %s", err)
130+
end
131+
132+
return replace.tuple(space_name, tuple, opts)
133+
end
134+
98135
return replace

crud/upsert.lua

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,26 @@ end
3232

3333
--- Update or insert a tuple in the specified space
3434
--
35-
-- @function call
35+
-- @function tuple
3636
--
3737
-- @param string space_name
3838
-- A space name
3939
--
40-
-- @param table obj
41-
-- Tuple object (according to space format)
40+
-- @param table tuple
41+
-- Tuple
4242
--
4343
-- @param table user_operations
4444
-- user_operations to be performed.
45-
-- See `space:update` operations in Tarantool doc
45+
-- See `space:upsert()` operations in Tarantool doc
4646
--
4747
-- @tparam ?number opts.timeout
4848
-- Function call timeout
4949
--
50-
-- @return[1] object
50+
-- @return[1] tuple
5151
-- @treturn[2] nil
5252
-- @treturn[2] table Error description
5353
--
54-
function upsert.call(space_name, obj, user_operations, opts)
54+
function upsert.tuple(space_name, tuple, user_operations, opts)
5555
checks('string', '?', 'table', {
5656
timeout = '?number',
5757
})
@@ -69,12 +69,6 @@ function upsert.call(space_name, obj, user_operations, opts)
6969
return nil, UpsertError:new("Wrong operations are specified: %s", err)
7070
end
7171

72-
-- compute default bucket_id
73-
local tuple, err = utils.flatten(obj, space_format)
74-
if err ~= nil then
75-
return nil, UpsertError:new("Object is specified in bad format: %s", err)
76-
end
77-
7872
local key = utils.extract_key(tuple, space.index[0].parts)
7973

8074
local bucket_id = vshard.router.bucket_id_strcrc32(key)
@@ -83,11 +77,17 @@ function upsert.call(space_name, obj, user_operations, opts)
8377
return nil, UpsertError:new("Failed to get replicaset for bucket_id %s: %s", bucket_id, err.err)
8478
end
8579

86-
local tuple, err = utils.flatten(obj, space_format, bucket_id)
80+
local bucket_id_fieldno, err = utils.get_bucket_id_fieldno(space)
8781
if err ~= nil then
88-
return nil, UpsertError:new("Object is specified in bad format: %s", err)
82+
return nil, err
83+
end
84+
85+
if tuple[bucket_id_fieldno] ~= nil then
86+
return nil, UpsertError:new("Unexpected value (%s) at field %s (sharding key)",
87+
tuple[bucket_id_fieldno], bucket_id_fieldno)
8988
end
9089

90+
tuple[bucket_id_fieldno] = bucket_id
9191
local _, err = call.rw(UPSERT_FUNC_NAME, {space_name, tuple, operations}, {
9292
replicasets = {replicaset},
9393
timeout = opts.timeout,
@@ -104,4 +104,47 @@ function upsert.call(space_name, obj, user_operations, opts)
104104
}
105105
end
106106

107+
--- Update or insert an object in the specified space
108+
--
109+
-- @function object
110+
--
111+
-- @param string space_name
112+
-- A space name
113+
--
114+
-- @param table obj
115+
-- Object
116+
--
117+
-- @param table user_operations
118+
-- user_operations to be performed.
119+
-- See `space:upsert()` operations in Tarantool doc
120+
--
121+
-- @tparam ?number opts.timeout
122+
-- Function call timeout
123+
--
124+
-- @return[1] object
125+
-- @treturn[2] nil
126+
-- @treturn[2] table Error description
127+
--
128+
function upsert.object(space_name, obj, user_operations, opts)
129+
checks('string', '?', 'table', {
130+
timeout = '?number',
131+
})
132+
133+
opts = opts or {}
134+
135+
local space = utils.get_space(space_name, vshard.router.routeall())
136+
if space == nil then
137+
return nil, UpsertError:new("Space %q doesn't exists", space_name)
138+
end
139+
140+
local space_format = space:format()
141+
142+
local tuple, err = utils.flatten(obj, space_format)
143+
if err ~= nil then
144+
return nil, UpsertError:new("Object is specified in bad format: %s", err)
145+
end
146+
147+
return upsert.tuple(space_name, tuple, user_operations, opts)
148+
end
149+
107150
return upsert

0 commit comments

Comments
 (0)