tarantool 0.2.5 → 0.3.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +14 -12
- data/LICENSE +4 -4
- data/README.md +15 -9
- data/Rakefile +5 -129
- data/lib/tarantool/base_record.rb +288 -0
- data/lib/tarantool/block_db.rb +135 -0
- data/lib/tarantool/callback_db.rb +47 -0
- data/lib/tarantool/core-ext.rb +12 -0
- data/lib/tarantool/em_db.rb +37 -0
- data/lib/tarantool/exceptions.rb +52 -7
- data/lib/tarantool/fiber_db.rb +152 -0
- data/lib/tarantool/light_record.rb +68 -0
- data/lib/tarantool/query.rb +127 -0
- data/lib/tarantool/record/select.rb +59 -0
- data/lib/tarantool/record.rb +93 -282
- data/lib/tarantool/request.rb +351 -52
- data/lib/tarantool/response.rb +108 -45
- data/lib/tarantool/serializers/bson.rb +2 -2
- data/lib/tarantool/serializers.rb +32 -4
- data/lib/tarantool/space_array.rb +153 -0
- data/lib/tarantool/space_hash.rb +262 -0
- data/lib/tarantool/util.rb +182 -0
- data/lib/tarantool/version.rb +3 -0
- data/lib/tarantool.rb +79 -29
- data/test/box.pid +1 -0
- data/test/helper.rb +164 -0
- data/test/run_all.rb +3 -0
- data/test/shared_query.rb +73 -0
- data/test/shared_record.rb +474 -0
- data/test/shared_space_array.rb +284 -0
- data/test/shared_space_hash.rb +239 -0
- data/test/tarant/init.lua +22 -0
- data/test/tarantool.cfg +62 -0
- data/test/tarantool.log +6 -0
- data/{spec/tarantool.cfg → test/tarantool_repl.cfg} +11 -5
- data/test/test_light_record.rb +48 -0
- data/test/test_query_block.rb +6 -0
- data/test/test_query_fiber.rb +7 -0
- data/test/test_record.rb +88 -0
- data/{spec/tarantool/composite_primary_key_spec.rb → test/test_record_composite_pk.rb} +5 -7
- data/test/test_space_array_block.rb +6 -0
- data/test/test_space_array_callback.rb +255 -0
- data/test/test_space_array_callback_nodef.rb +190 -0
- data/test/test_space_array_fiber.rb +7 -0
- data/test/test_space_hash_block.rb +6 -0
- data/test/test_space_hash_fiber.rb +7 -0
- metadata +78 -55
- data/Gemfile.lock +0 -54
- data/examples/em_simple.rb +0 -16
- data/examples/record.rb +0 -68
- data/examples/simple.rb +0 -13
- data/lib/tarantool/requests/call.rb +0 -20
- data/lib/tarantool/requests/delete.rb +0 -18
- data/lib/tarantool/requests/insert.rb +0 -19
- data/lib/tarantool/requests/ping.rb +0 -16
- data/lib/tarantool/requests/select.rb +0 -22
- data/lib/tarantool/requests/update.rb +0 -35
- data/lib/tarantool/requests.rb +0 -19
- data/lib/tarantool/serializers/integer.rb +0 -14
- data/lib/tarantool/serializers/string.rb +0 -14
- data/lib/tarantool/space.rb +0 -39
- data/spec/helpers/let.rb +0 -11
- data/spec/helpers/truncate.rb +0 -12
- data/spec/spec_helper.rb +0 -21
- data/spec/tarantool/em_spec.rb +0 -22
- data/spec/tarantool/record_spec.rb +0 -316
- data/spec/tarantool/request_spec.rb +0 -103
- data/tarantool.gemspec +0 -69
@@ -0,0 +1,284 @@
|
|
1
|
+
require File.expand_path('../helper.rb', __FILE__)
|
2
|
+
|
3
|
+
shared_examples_for :blocking_array_space do
|
4
|
+
before { clear_db }
|
5
|
+
|
6
|
+
let(:space0) { tarantool.space_array(0, SPACE0[:types], keys: SPACE0[:keys])}
|
7
|
+
let(:space1) { tarantool.space_array(1, SPACE1[:types], keys: SPACE1[:keys])}
|
8
|
+
let(:space2) { tarantool.space_array(2, SPACE2[:types], keys: SPACE2[:keys])}
|
9
|
+
let(:space3) { tarantool.space_array(3, SPACE3[:types], keys: SPACE3[:keys])}
|
10
|
+
|
11
|
+
describe "with definition" do
|
12
|
+
let(:vasya){ ['vasya', 'petrov', 'eb@lo.com', 5] }
|
13
|
+
let(:ilya) { ['ilya', 'zimov', 'il@zi.bot', 13] }
|
14
|
+
let(:fedor){ ['fedor', 'kuklin', 'ku@kl.in', 13] }
|
15
|
+
it "should be selectable" do
|
16
|
+
results = blockrun { [
|
17
|
+
space0.select(0, 'vasya'),
|
18
|
+
space0.select(0, ['vasya']),
|
19
|
+
space0.select(0, ['vasya', 'ilya']),
|
20
|
+
space0.select(0, [['vasya'], ['ilya']]),
|
21
|
+
space0.select(0, [['ilya'], ['vasya']]),
|
22
|
+
space0.select(0, [['ilya'], ['vasya']], 0, 1),
|
23
|
+
space0.select(0, [['ilya'], ['vasya']], 1, 1),
|
24
|
+
space0.select(2, 13, 0, 2),
|
25
|
+
space0.select(1, [['zimov','il@zi.bot']])
|
26
|
+
] }
|
27
|
+
results[0].must_equal [vasya]
|
28
|
+
results[1].must_equal [vasya]
|
29
|
+
results[2].must_equal [vasya, ilya]
|
30
|
+
results[3].must_equal [vasya, ilya]
|
31
|
+
results[4].must_equal [ilya, vasya]
|
32
|
+
results[5].must_equal [ilya]
|
33
|
+
results[6].must_equal [vasya]
|
34
|
+
(results[7] - [ilya, fedor]).must_be_empty
|
35
|
+
([ilya, fedor] - results[7]).must_be_empty
|
36
|
+
results[8].must_equal [ilya]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be able to all_by_keys" do
|
40
|
+
results = blockrun { [
|
41
|
+
space0.all_by_keys(0, 'vasya'),
|
42
|
+
space0.all_by_keys(0, ['vasya']),
|
43
|
+
space0.all_by_keys(0, ['vasya', 'ilya']),
|
44
|
+
space0.all_by_keys(0, [['vasya'], ['ilya']]),
|
45
|
+
space0.all_by_keys(0, [['ilya'], ['vasya']]),
|
46
|
+
space0.all_by_keys(0, [['ilya'], ['vasya']], limit: 1),
|
47
|
+
space0.all_by_keys(0, [['ilya'], ['vasya']], limit: 1, offset: 1),
|
48
|
+
space0.all_by_keys(2, 13),
|
49
|
+
space0.all_by_keys(1, [['zimov','il@zi.bot']]),
|
50
|
+
] }
|
51
|
+
results[0].must_equal [vasya]
|
52
|
+
results[1].must_equal [vasya]
|
53
|
+
results[2].must_equal [vasya, ilya]
|
54
|
+
results[3].must_equal [vasya, ilya]
|
55
|
+
results[4].must_equal [ilya, vasya]
|
56
|
+
results[5].must_equal [ilya]
|
57
|
+
results[6].must_equal [vasya]
|
58
|
+
(results[7] - [ilya, fedor]).must_be_empty
|
59
|
+
results[8].must_equal [ilya]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be able to all_by_key" do
|
63
|
+
results = blockrun { [
|
64
|
+
space0.all_by_key(0, 'vasya'),
|
65
|
+
space0.all_by_key(0, ['vasya']),
|
66
|
+
space0.all_by_key(2, 13),
|
67
|
+
space0.all_by_key(1, ['zimov','il@zi.bot']),
|
68
|
+
] }
|
69
|
+
results[0].must_equal [vasya]
|
70
|
+
results[1].must_equal [vasya]
|
71
|
+
(results[2] - [ilya, fedor]).must_be_empty
|
72
|
+
results[3].must_equal [ilya]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should be able to first_by_key" do
|
76
|
+
results = blockrun { [
|
77
|
+
space0.first_by_key(0, 'vasya'),
|
78
|
+
space0.first_by_key(0, ['ilya']),
|
79
|
+
space0.first_by_key(2, 13),
|
80
|
+
space0.first_by_key(1, ['petrov','eb@lo.com']),
|
81
|
+
] }
|
82
|
+
results[0].must_equal vasya
|
83
|
+
results[1].must_equal ilya
|
84
|
+
[ilya, fedor].must_include results[2]
|
85
|
+
results[3].must_equal vasya
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should be able to by_pk" do
|
89
|
+
results = blockrun { [
|
90
|
+
space0.by_pk('vasya'),
|
91
|
+
space0.by_pk(['ilya']),
|
92
|
+
space2.by_pk(['hi zo', 'ho zo']),
|
93
|
+
] }
|
94
|
+
results[0].must_equal vasya
|
95
|
+
results[1].must_equal ilya
|
96
|
+
results[2].must_equal ['hi zo', 'ho zo', 1]
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should raise on not matched pk" do
|
100
|
+
proc {
|
101
|
+
space0.by_pk(['il','ya'])
|
102
|
+
}.must_raise Tarantool::ArgumentError
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should fetch longer records" do
|
106
|
+
results = blockrun { [
|
107
|
+
space2.by_pk(['hi zo', 'pidas']),
|
108
|
+
space1.by_pk(2),
|
109
|
+
]}
|
110
|
+
results[0].must_equal ['hi zo', 'pidas', 1, 3, 5]
|
111
|
+
results[1].must_equal [2, 'medium', 6, 'common', 7]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should be able to insert" do
|
115
|
+
asdf = ['asdf', 'asdf', 'asdf', 4, 5]
|
116
|
+
qwer = ['qwer', 'qwer', 'qwer', 4, 20, 19]
|
117
|
+
zxcv = [4, 'zxcv', 7, 'zxcv', 8]
|
118
|
+
xcvb = [5, 'xcvb', 7, 'xcvb', 8]
|
119
|
+
results = blockrun {[
|
120
|
+
space0.insert(asdf),
|
121
|
+
space0.insert(qwer, return_tuple: true),
|
122
|
+
space1.insert(zxcv),
|
123
|
+
space1.by_pk(4),
|
124
|
+
space1.insert(xcvb, return_tuple: true),
|
125
|
+
]}
|
126
|
+
results[0].must_equal 1
|
127
|
+
results[1].must_equal qwer
|
128
|
+
results[2].must_equal 1
|
129
|
+
results[3].must_equal zxcv
|
130
|
+
results[4].must_equal xcvb
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should be able to update" do
|
134
|
+
results = blockrun {[
|
135
|
+
space0.update('vasya', {1 => 'holodov', 3 => [:+, 2]}, return_tuple: true),
|
136
|
+
space0.update('ilya', {[2, :set] => 'we@al.hero', 3 => [:&, 7]}, return_tuple: true),
|
137
|
+
space1.update(2, [[2, :^, 3], [4, :|, 20]]),
|
138
|
+
space1.by_pk(2),
|
139
|
+
space1.update(1, [1, :splice, 2, 2, 'nd'], return_tuple: true),
|
140
|
+
space2.update(['hi zo', 'pidas'], [[2, :delete], [3, :delete]], return_tuple: true),
|
141
|
+
space2.update(['coma', 'peredoma'], [2, :insert, 1]),
|
142
|
+
space2.all_by_key(1, 1),
|
143
|
+
]}
|
144
|
+
results[0].must_equal ['vasya', 'holodov', 'eb@lo.com', 7]
|
145
|
+
results[1].must_equal ['ilya', 'zimov', 'we@al.hero', 5]
|
146
|
+
results[2].must_equal 1
|
147
|
+
results[3].must_equal [2, 'medium', 5, 'common', 23]
|
148
|
+
results[4].must_equal [1, 'condon', 4]
|
149
|
+
results[5].must_equal ['hi zo', 'pidas', 5]
|
150
|
+
results[6].must_equal 1
|
151
|
+
res = [['hi zo', 'ho zo', 1], ['coma', 'peredoma', 1, 2]]
|
152
|
+
results[7].sort.must_equal res.sort
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should be able to update (2)" do
|
156
|
+
results = blockrun {[
|
157
|
+
space2.update(['hi zo', 'pidas'], [[3, [:+, 1]], [4, [:+, -1]]], return_tuple: true)
|
158
|
+
]}
|
159
|
+
results[0].must_equal ['hi zo', 'pidas', 1, 4, 4]
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should be able to delete" do
|
163
|
+
results = blockrun {[
|
164
|
+
space0.delete('vasya', return_tuple: true),
|
165
|
+
space1.delete([1], return_tuple: true),
|
166
|
+
space2.delete(['hi zo', 'pidas'], return_tuple: true),
|
167
|
+
]}
|
168
|
+
results[0].must_equal vasya
|
169
|
+
results[1].must_equal [1, 'common', 4]
|
170
|
+
results[2].must_equal ['hi zo', 'pidas', 1, 3, 5]
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should be able to choose index by field numbers" do
|
174
|
+
results = blockrun {[
|
175
|
+
space0.first_by_key([0], 'vasya'),
|
176
|
+
space0.first_by_key([1,2], ['zimov', 'il@zi.bot']),
|
177
|
+
space0.all_by_key([3], 13),
|
178
|
+
space2.first_by_key([1,0], ['peredoma', 'coma']),
|
179
|
+
]}
|
180
|
+
results[0].must_equal vasya
|
181
|
+
results[1].must_equal ilya
|
182
|
+
(results[2] - [ilya, fedor]).must_be_empty
|
183
|
+
([ilya, fedor] - results[2]).must_be_empty
|
184
|
+
results[3].must_equal ['coma', 'peredoma', 2]
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should be able to invoke" do
|
188
|
+
results = blockrun {[
|
189
|
+
space0.invoke('truncate'),
|
190
|
+
space0.by_pk('vasya'),
|
191
|
+
space0.by_pk('ilya')
|
192
|
+
]}
|
193
|
+
results.must_equal [0, nil, nil]
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should be able to call" do
|
197
|
+
results = blockrun {[
|
198
|
+
space0.call('truncate'),
|
199
|
+
space0.by_pk('vasya'),
|
200
|
+
space0.by_pk('ilya')
|
201
|
+
]}
|
202
|
+
results.must_equal [[], nil, nil]
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should be able to call (1)" do
|
206
|
+
results = blockrun {[
|
207
|
+
space0.call('func1'),
|
208
|
+
space0.call('func1', [1, 2]),
|
209
|
+
space0.call('func1', ['1', '2']),
|
210
|
+
space0.call('func1', [1, 2], types: [:int, :int]),
|
211
|
+
space0.call('func2', [1, 2], types: [:int, :int], returns: [:str, :int])
|
212
|
+
]}
|
213
|
+
results.must_equal [
|
214
|
+
[['string', '0'], ['nil'], ['nil']],
|
215
|
+
[['string', '0'], ['string', '1'], ['string', '2']],
|
216
|
+
[['string', '0'], ['string', '1'], ['string', '2']],
|
217
|
+
[['string', '0'], ['string', "\x01\x00\x00\x00"], ['string', "\x02\x00\x00\x00"]],
|
218
|
+
[['string', 1], ['string', 2]],
|
219
|
+
]
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should be able to call (2)" do
|
223
|
+
results = blockrun {[
|
224
|
+
space0.call('box.select_range', [0, 2]),
|
225
|
+
space0.call('box.select_range', [0, 1000000, 'ilya'])
|
226
|
+
]}
|
227
|
+
results[0].must_equal [fedor, ilya]
|
228
|
+
results[1].must_equal [ilya, vasya]
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "Array Serializer" do
|
232
|
+
it "should be able to save" do
|
233
|
+
results = blockrun {[
|
234
|
+
space3.insert([1, [1,2,3,4]], return_tuple: true),
|
235
|
+
space3.insert([2, []], return_tuple: true),
|
236
|
+
space3.insert([3, nil], return_tuple: true),
|
237
|
+
space3.all_by_pks([1,2,3])
|
238
|
+
]}
|
239
|
+
results[0].must_equal [1, [1,2,3,4]]
|
240
|
+
results[1].must_equal [2, nil]
|
241
|
+
results[2].must_equal [3, nil]
|
242
|
+
results[3].sort.must_equal [[1, [1,2,3,4]], [2, nil], [3, nil]]
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should be able to update" do
|
246
|
+
results = blockrun {[
|
247
|
+
space3.insert([1, [1,2,3,4]], return_tuple: true),
|
248
|
+
space3.update(1, [1, :set, [4,3,2,1]], return_tuple: true)
|
249
|
+
]}
|
250
|
+
results.must_equal [[1, [1,2,3,4]], [1,[4,3,2,1]]]
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should be able to save tail with same type" do
|
254
|
+
results = blockrun {[
|
255
|
+
space3.insert([1, [1,2,3,4], [4,3,2,1], [2,1]], return_tuple: true),
|
256
|
+
space3.by_pk(1)
|
257
|
+
]}
|
258
|
+
results[0].must_equal [1, [1,2,3,4], [4,3,2,1], [2,1]]
|
259
|
+
results[1].must_equal [1, [1,2,3,4], [4,3,2,1], [2,1]]
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should be able to update tail with same type" do
|
263
|
+
results = blockrun {[
|
264
|
+
space3.insert([1, [1,2,3,4], [4,3,2,1], [2,1]], return_tuple: true),
|
265
|
+
space3.update(1, [3, :set, [3,2,1]], return_tuple: true)
|
266
|
+
]}
|
267
|
+
results[0].must_equal [1, [1,2,3,4], [4,3,2,1], [2,1]]
|
268
|
+
results[1].must_equal [1, [1,2,3,4], [4,3,2,1], [3,2,1]]
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should be able to search by serialized value" do
|
272
|
+
results = blockrun {[
|
273
|
+
space3.insert([5, [1,2,3]]),
|
274
|
+
space3.insert([6, [3,2,1]]),
|
275
|
+
space3.first_by_key(1, [[1,2,3]]),
|
276
|
+
space3.first_by_key(1, [[3,2,1]]),
|
277
|
+
]}
|
278
|
+
results[0..1].must_equal [1,1]
|
279
|
+
results[2].must_equal [5, [1,2,3]]
|
280
|
+
results[3].must_equal [6, [3,2,1]]
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
require File.expand_path('../helper.rb', __FILE__)
|
2
|
+
|
3
|
+
shared_examples_for :blocking_hash_space do
|
4
|
+
before { clear_db }
|
5
|
+
|
6
|
+
let(:space0) { tarantool.space_hash(0, HSPACE0[:fields], keys: HSPACE0[:keys])}
|
7
|
+
let(:space1) { tarantool.space_hash(1, HSPACE1[:fields], keys: HSPACE1[:keys])}
|
8
|
+
let(:space2) { tarantool.space_hash(2, HSPACE2[:fields], keys: HSPACE2[:keys])}
|
9
|
+
let(:space3) { tarantool.space_hash(3, HSPACE3[:fields], keys: HSPACE3[:keys])}
|
10
|
+
|
11
|
+
let(:vasya) { {name: 'vasya', surname: 'petrov', email: 'eb@lo.com', score: 5} }
|
12
|
+
let(:ilya) { {name: 'ilya', surname: 'zimov', email: 'il@zi.bot', score: 13} }
|
13
|
+
let(:fedor) { {name: 'fedor', surname: 'kuklin', email: 'ku@kl.in', score: 13} }
|
14
|
+
let(:hozo) { {first: 'hi zo', second: 'ho zo', third: 1} }
|
15
|
+
let(:pidas) { {first: 'hi zo', second: 'pidas', third: 1, _tail: [3, 5]} }
|
16
|
+
let(:peredoma) { {first: 'coma', second: 'peredoma', third: 2} }
|
17
|
+
|
18
|
+
it "should be selectable" do
|
19
|
+
results = blockrun { [
|
20
|
+
space0.select({name: 'vasya'}, 0, -1),
|
21
|
+
space0.select([{name: 'vasya'}], 0, -1),
|
22
|
+
space0.select([{name: 'vasya'}, {name: 'ilya'}], 0, -1),
|
23
|
+
space0.select([{name: 'ilya'}, {name: 'vasya'}], 0, -1),
|
24
|
+
space0.select([{name: 'ilya'}, {name: 'vasya'}], 0, 1),
|
25
|
+
space0.select([{name: 'ilya'}, {name: 'vasya'}], 1, 1),
|
26
|
+
space0.select({score: 13}, 0, 2),
|
27
|
+
space0.select({surname: 'zimov', email: 'il@zi.bot'}, 0, -1),
|
28
|
+
] }
|
29
|
+
results[0].must_equal [vasya]
|
30
|
+
results[1].must_equal [vasya]
|
31
|
+
results[2].must_equal [vasya, ilya]
|
32
|
+
results[3].must_equal [ilya, vasya]
|
33
|
+
results[4].must_equal [ilya]
|
34
|
+
results[5].must_equal [vasya]
|
35
|
+
(results[6] - [ilya, fedor]).must_be_empty
|
36
|
+
([ilya, fedor] - results[6]).must_be_empty
|
37
|
+
results[7].must_equal [ilya]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should select tail (and have #all)" do
|
41
|
+
results = blockrun{ [
|
42
|
+
space1.all({id: 2}),
|
43
|
+
space2.all({third: 1})
|
44
|
+
] }
|
45
|
+
results[0].must_equal [{id: 2, _tail: [['medium', 6], ['common', 7]]}]
|
46
|
+
(results[1] - [hozo, pidas]).must_be_empty
|
47
|
+
([hozo, pidas] - results[1]).must_be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should react on #by_pk" do
|
51
|
+
results = blockrun{ [
|
52
|
+
space0.by_pk('vasya'),
|
53
|
+
space1.by_pk([1]),
|
54
|
+
space1.by_pk({id: 2}),
|
55
|
+
space2.by_pk(['hi zo', 'ho zo']),
|
56
|
+
space2.by_pk({first: 'hi zo', second: 'pidas'})
|
57
|
+
] }
|
58
|
+
results[0].must_equal vasya
|
59
|
+
results[1].must_equal({id: 1, _tail: [['common', 4]]})
|
60
|
+
results[2].must_equal({id: 2, _tail: [['medium', 6], ['common', 7]]})
|
61
|
+
results[3].must_equal hozo
|
62
|
+
results[4].must_equal pidas
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should react on #first" do
|
66
|
+
results = blockrun{ [
|
67
|
+
space0.first({surname: 'petrov', email: 'eb@lo.com'}),
|
68
|
+
space2.first({third: 1})
|
69
|
+
] }
|
70
|
+
results[0].must_equal vasya
|
71
|
+
[hozo, pidas].must_include results[1]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should insert" do
|
75
|
+
petr = {name: 'petr', surname: 'kuprin', email: 'zo@na.ru', score: 1000}
|
76
|
+
sp1id3 = {id: 3, _tail: [['no', 8], ['more', 9], ['turtles', 10]]}
|
77
|
+
results = blockrun{ [
|
78
|
+
space0.insert(petr),
|
79
|
+
space0.first(score: 1000),
|
80
|
+
space1.insert(sp1id3, return_tuple: true)
|
81
|
+
] }
|
82
|
+
results[0].must_equal 1
|
83
|
+
results[1].must_equal petr
|
84
|
+
results[2].must_equal sp1id3
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should replace" do
|
88
|
+
huzo = {first: 'hi zo', second: 'ho zo', third: 6, _tail: [5, 4]}
|
89
|
+
results = blockrun{ [
|
90
|
+
space2.replace(huzo),
|
91
|
+
space2.by_pk(['hi zo', 'ho zo']),
|
92
|
+
space1.replace({id: 2, _tail: []}, return_tuple: true)
|
93
|
+
] }
|
94
|
+
results[0].must_equal 1
|
95
|
+
results[1].must_equal huzo
|
96
|
+
results[2].must_equal({id: 2})
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should update" do
|
100
|
+
results = blockrun{ [
|
101
|
+
space0.update('vasya', {score: 6}),
|
102
|
+
space0.by_pk('vasya'),
|
103
|
+
space0.update(['ilya'], {email: 'x@y.z', score: [:+, 2]}, return_tuple: true),
|
104
|
+
space1.update({id: 1}, {2 => 'more', 3 => 8}, return_tuple: true),
|
105
|
+
space1.update(2, [[2, :insert, 'high'], [2, :ins, 20]], return_tuple: true),
|
106
|
+
space2.update(['hi zo', 'pidas'], {_tail: [[:+, 1], [:+, -1]]}, return_tuple: true),
|
107
|
+
] }
|
108
|
+
results[0].must_equal 1
|
109
|
+
results[1].must_equal vasya.merge(score: 6)
|
110
|
+
results[2].must_equal ilya.merge(score: 15, email: 'x@y.z')
|
111
|
+
results[3].must_equal({id: 1, _tail: [['common', 4], ['more', 8]]})
|
112
|
+
results[4].must_equal({id: 2, _tail: [['medium', 6], ['high', 20], ['common', 7]]})
|
113
|
+
results[5].must_equal({first: 'hi zo', second: 'pidas', third: 1, _tail: [4, 4]})
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should delete" do
|
117
|
+
results = blockrun {[
|
118
|
+
space0.delete('vasya', return_tuple: true),
|
119
|
+
space0.delete(['ilya'], return_tuple: true),
|
120
|
+
space0.delete({name: 'fedor'}, return_tuple: true),
|
121
|
+
space1.delete({id: 1}),
|
122
|
+
space2.delete(['hi zo', 'ho zo']),
|
123
|
+
space2.delete({first: 'hi zo', second: 'pidas'}),
|
124
|
+
space2.delete(['unknown', 'man'])
|
125
|
+
]}
|
126
|
+
results[0].must_equal vasya
|
127
|
+
results[1].must_equal ilya
|
128
|
+
results[2].must_equal fedor
|
129
|
+
results[3..6].must_equal [1, 1, 1, 0]
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should be able to call" do
|
133
|
+
results = blockrun {[
|
134
|
+
space0.call('box.select_range', [0, 2]),
|
135
|
+
space0.call('box.select_range', [0, 1000000, 'ilya']),
|
136
|
+
space0.call('func2', [1,2], types: [:int, :int], returns: [:str, :int]),
|
137
|
+
space0.call('func2', [1,2], types: [:int, :int], returns: {type: :str, val: :int})
|
138
|
+
]}
|
139
|
+
results[0].must_equal [fedor, ilya]
|
140
|
+
results[1].must_equal [ilya, vasya]
|
141
|
+
results[2].must_equal [['string', 1], ['string', 2]]
|
142
|
+
results[3].must_equal [{type: 'string', val: 1}, {type: 'string', val: 2}]
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should raise error on wrong key" do
|
146
|
+
blockrun {
|
147
|
+
proc {
|
148
|
+
space2.insert(name: 1)
|
149
|
+
}.must_raise Tarantool::ArgumentError
|
150
|
+
proc {
|
151
|
+
space2.by_pk(third: 1)
|
152
|
+
}.must_raise Tarantool::ArgumentError
|
153
|
+
proc {
|
154
|
+
space2.first(name: 1)
|
155
|
+
}.must_raise Tarantool::ArgumentError
|
156
|
+
proc {
|
157
|
+
space2.all(name: 1)
|
158
|
+
}.must_raise Tarantool::ArgumentError
|
159
|
+
proc {
|
160
|
+
space2.select([name: 1], 0, 1)
|
161
|
+
}.must_raise Tarantool::ArgumentError
|
162
|
+
proc {
|
163
|
+
space2.update({third: 1}, {first: 'haha'})
|
164
|
+
}.must_raise Tarantool::ArgumentError
|
165
|
+
proc {
|
166
|
+
space2.update({first: 'haha'}, {first: 'haha'})
|
167
|
+
}.must_raise Tarantool::ArgumentError
|
168
|
+
proc {
|
169
|
+
space2.update({first: 'haha', second: 'hoho'}, {name: 'haha'})
|
170
|
+
}.must_raise Tarantool::ArgumentError
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "Array Serializer" do
|
175
|
+
it "should be able to save" do
|
176
|
+
results = blockrun {[
|
177
|
+
space3.insert({id: 1, scores: [1,2,3,4]}, return_tuple: true),
|
178
|
+
space3.insert({id: 2, scores: []}, return_tuple: true),
|
179
|
+
space3.insert({id: 3}, return_tuple: true),
|
180
|
+
space3.all_by_pks([1,2,3])
|
181
|
+
]}
|
182
|
+
results[0].must_equal({id: 1, scores: [1,2,3,4]})
|
183
|
+
results[1].must_equal({id: 2, scores: nil})
|
184
|
+
results[2].must_equal({id: 3, scores: nil})
|
185
|
+
results[3].sort_by{|h| h[:id]}.must_equal [
|
186
|
+
{id:1, scores:[1,2,3,4]},
|
187
|
+
{id:2, scores:nil},
|
188
|
+
{id:3, scores:nil}
|
189
|
+
]
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should be able to update" do
|
193
|
+
results = blockrun {[
|
194
|
+
space3.insert({id:1, scores:[1,2,3,4]}, return_tuple: true),
|
195
|
+
space3.update(1, [[:scores, :set, [4,3,2,1]]], return_tuple: true)
|
196
|
+
]}
|
197
|
+
results.must_equal [{id:1, scores:[1,2,3,4]}, {id:1, scores:[4,3,2,1]}]
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should be able to save tail with same type" do
|
201
|
+
results = blockrun {[
|
202
|
+
space3.insert({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [2,1]]}, return_tuple: true),
|
203
|
+
space3.by_pk(1)
|
204
|
+
]}
|
205
|
+
results[0].must_equal({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [2,1]]})
|
206
|
+
results[1].must_equal({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [2,1]]})
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should be able to update tail with same type" do
|
210
|
+
results = blockrun {[
|
211
|
+
space3.insert({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [2,1]]}, return_tuple: true),
|
212
|
+
space3.update(1, {1 => [:set, [3,2,1]]}, return_tuple: true)
|
213
|
+
]}
|
214
|
+
results[0].must_equal({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [2,1]]})
|
215
|
+
results[1].must_equal({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [3,2,1]]})
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should be able to update tail with same type(2)" do
|
219
|
+
results = blockrun {[
|
220
|
+
space3.insert({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [2,1]]}, return_tuple: true),
|
221
|
+
space3.update(1, {:_tail => [:set, [[1,2,3],[3,2,1]]]}, return_tuple: true)
|
222
|
+
]}
|
223
|
+
results[0].must_equal({id:1, scores:[1,2,3,4], _tail:[[4,3,2,1], [2,1]]})
|
224
|
+
results[1].must_equal({id:1, scores:[1,2,3,4], _tail:[[1,2,3], [3,2,1]]})
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should be able to search by serialized value" do
|
228
|
+
results = blockrun {[
|
229
|
+
space3.insert({id:5, scores:[1,2,3]}),
|
230
|
+
space3.insert({id:6, scores:[3,2,1]}),
|
231
|
+
space3.first(scores: [1,2,3]),
|
232
|
+
space3.first(scores: [3,2,1]),
|
233
|
+
]}
|
234
|
+
results[0..1].must_equal [1,1]
|
235
|
+
results[2].must_equal({id:5, scores:[1,2,3]})
|
236
|
+
results[3].must_equal({id:6, scores:[3,2,1]})
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
function truncate(space_no)
|
2
|
+
box.space[0+space_no]:truncate()
|
3
|
+
end
|
4
|
+
|
5
|
+
function func1(space_no, arg1, arg2)
|
6
|
+
return
|
7
|
+
{type(space_no), space_no},
|
8
|
+
{type(arg1), arg1},
|
9
|
+
{type(arg2), arg2}
|
10
|
+
end
|
11
|
+
|
12
|
+
function func2(space_no, arg1, arg2)
|
13
|
+
return
|
14
|
+
{type(arg1), arg1},
|
15
|
+
{type(arg2), arg2}
|
16
|
+
end
|
17
|
+
|
18
|
+
function func3(arg1, arg2)
|
19
|
+
return
|
20
|
+
{type(arg1), arg1},
|
21
|
+
{type(arg2), arg2}
|
22
|
+
end
|
data/test/tarantool.cfg
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
slab_alloc_arena = 0.1
|
2
|
+
pid_file = "box.pid"
|
3
|
+
|
4
|
+
logger="cat - >> tarantool.log"
|
5
|
+
work_dir="tarant"
|
6
|
+
|
7
|
+
primary_port = 33013
|
8
|
+
secondary_port = 33014
|
9
|
+
admin_port = 33015
|
10
|
+
|
11
|
+
rows_per_wal = 50000
|
12
|
+
|
13
|
+
space[0].enabled = 1
|
14
|
+
|
15
|
+
space[0].index[0].type = "TREE"
|
16
|
+
space[0].index[0].unique = 1
|
17
|
+
space[0].index[0].key_field[0].fieldno = 0
|
18
|
+
space[0].index[0].key_field[0].type = "STR"
|
19
|
+
|
20
|
+
space[0].index[1].type = "TREE"
|
21
|
+
space[0].index[1].unique = 0
|
22
|
+
space[0].index[1].key_field[0].fieldno = 1
|
23
|
+
space[0].index[1].key_field[0].type = "STR"
|
24
|
+
space[0].index[1].key_field[1].fieldno = 2
|
25
|
+
space[0].index[1].key_field[1].type = "STR"
|
26
|
+
|
27
|
+
space[0].index[2].type = "TREE"
|
28
|
+
space[0].index[2].unique = 0
|
29
|
+
space[0].index[2].key_field[0].fieldno = 3
|
30
|
+
space[0].index[2].key_field[0].type = "NUM"
|
31
|
+
|
32
|
+
space[1].enabled = 1
|
33
|
+
|
34
|
+
space[1].index[0].type = "HASH"
|
35
|
+
space[1].index[0].unique = 1
|
36
|
+
space[1].index[0].key_field[0].fieldno = 0
|
37
|
+
space[1].index[0].key_field[0].type = "NUM"
|
38
|
+
|
39
|
+
|
40
|
+
space[2].enabled = 1
|
41
|
+
|
42
|
+
space[2].index[0].type = "TREE"
|
43
|
+
space[2].index[0].unique = 1
|
44
|
+
space[2].index[0].key_field[0].fieldno = 0
|
45
|
+
space[2].index[0].key_field[0].type = "STR"
|
46
|
+
space[2].index[0].key_field[1].fieldno = 1
|
47
|
+
space[2].index[0].key_field[1].type = "STR"
|
48
|
+
|
49
|
+
space[2].index[1].type = "TREE"
|
50
|
+
space[2].index[1].unique = 0
|
51
|
+
space[2].index[1].key_field[0].fieldno = 2
|
52
|
+
space[2].index[1].key_field[0].type = "NUM"
|
53
|
+
|
54
|
+
space[3].enabled = 1
|
55
|
+
space[3].index[0].type = "HASH"
|
56
|
+
space[3].index[0].unique = 1
|
57
|
+
space[3].index[0].key_field[0].fieldno = 0
|
58
|
+
space[3].index[0].key_field[0].type = "NUM"
|
59
|
+
space[3].index[1].type = "TREE"
|
60
|
+
space[3].index[1].unique = 0
|
61
|
+
space[3].index[1].key_field[0].fieldno = 1
|
62
|
+
space[3].index[1].key_field[0].type = "STR"
|
data/test/tarantool.log
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
1341840795.677 2887 1/sched _ I> space 0 successfully configured
|
2
|
+
1341840795.677 2887 1/sched _ I> space 1 successfully configured
|
3
|
+
1341840795.677 2887 1/sched _ I> space 2 successfully configured
|
4
|
+
1341840795.677 2887 1/sched _ I> recovery start
|
5
|
+
1341840795.677 2887 1/sched _ recovery.m:274 E> can't find snapshot
|
6
|
+
1341840795.677 2887 1/sched _ C> didn't you forget to initialize storage with --init-storage switch?
|
@@ -2,12 +2,14 @@ slab_alloc_arena = 0.1
|
|
2
2
|
pid_file = "box.pid"
|
3
3
|
|
4
4
|
logger="cat - >> tarantool.log"
|
5
|
+
work_dir="tarant_repl"
|
5
6
|
|
6
|
-
primary_port =
|
7
|
-
secondary_port =
|
8
|
-
admin_port =
|
7
|
+
primary_port = 34013
|
8
|
+
secondary_port = 34014
|
9
|
+
admin_port = 34015
|
10
|
+
replication_source = "127.0.0.1:33012"
|
9
11
|
|
10
|
-
rows_per_wal =
|
12
|
+
rows_per_wal = 50000
|
11
13
|
|
12
14
|
space[0].enabled = 1
|
13
15
|
|
@@ -23,6 +25,10 @@ space[0].index[1].key_field[0].type = "STR"
|
|
23
25
|
space[0].index[1].key_field[1].fieldno = 2
|
24
26
|
space[0].index[1].key_field[1].type = "STR"
|
25
27
|
|
28
|
+
space[0].index[2].type = "TREE"
|
29
|
+
space[0].index[2].unique = 0
|
30
|
+
space[0].index[2].key_field[0].fieldno = 3
|
31
|
+
space[0].index[2].key_field[0].type = "NUM"
|
26
32
|
|
27
33
|
space[1].enabled = 1
|
28
34
|
|
@@ -44,4 +50,4 @@ space[2].index[0].key_field[1].type = "STR"
|
|
44
50
|
space[2].index[1].type = "TREE"
|
45
51
|
space[2].index[1].unique = 0
|
46
52
|
space[2].index[1].key_field[0].fieldno = 2
|
47
|
-
space[2].index[1].key_field[0].type = "NUM"
|
53
|
+
space[2].index[1].key_field[0].type = "NUM"
|