lmdb 0.7.5 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +22 -0
- data/ext/lmdb_ext/extconf.rb +2 -0
- data/ext/lmdb_ext/lmdb_ext.c +1379 -912
- data/ext/lmdb_ext/lmdb_ext.h +36 -19
- data/lib/lmdb/database.rb +50 -52
- data/lib/lmdb/version.rb +1 -1
- data/spec/gc_torture_spec.rb +162 -0
- data/spec/helper.rb +3 -3
- data/spec/lmdb_spec.rb +154 -137
- data/spec/pseudo_transactions_spec.rb +237 -0
- metadata +6 -2
data/spec/lmdb_spec.rb
CHANGED
|
@@ -8,107 +8,108 @@ describe LMDB do
|
|
|
8
8
|
let(:db) { env.database }
|
|
9
9
|
|
|
10
10
|
it 'has version constants' do
|
|
11
|
-
LMDB::LIB_VERSION_MAJOR.
|
|
12
|
-
LMDB::LIB_VERSION_MINOR.
|
|
13
|
-
LMDB::LIB_VERSION_PATCH.
|
|
14
|
-
LMDB::LIB_VERSION.
|
|
15
|
-
LMDB::VERSION.
|
|
11
|
+
expect(LMDB::LIB_VERSION_MAJOR).to be_instance_of(Integer)
|
|
12
|
+
expect(LMDB::LIB_VERSION_MINOR).to be_instance_of(Integer)
|
|
13
|
+
expect(LMDB::LIB_VERSION_PATCH).to be_instance_of(Integer)
|
|
14
|
+
expect(LMDB::LIB_VERSION).to be_instance_of(String)
|
|
15
|
+
expect(LMDB::VERSION).to be_instance_of(String)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
describe LMDB::Environment do
|
|
19
19
|
subject { env }
|
|
20
20
|
|
|
21
21
|
it 'should return flags' do
|
|
22
|
-
subject.flags.
|
|
22
|
+
expect(subject.flags).to be_instance_of(Array)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
describe 'new' do
|
|
26
26
|
it 'returns environment' do
|
|
27
27
|
env = LMDB::Environment.new(path)
|
|
28
|
-
env.
|
|
28
|
+
expect(env).to be_instance_of(described_class)
|
|
29
29
|
env.close
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it 'accepts block' do
|
|
33
|
-
LMDB::Environment.new(path) do |env|
|
|
34
|
-
env.
|
|
33
|
+
out = LMDB::Environment.new(path) do |env|
|
|
34
|
+
expect(env).to be_instance_of(described_class)
|
|
35
35
|
42
|
|
36
|
-
end
|
|
36
|
+
end
|
|
37
|
+
expect(out).to eq(42)
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
it 'accepts options' do
|
|
40
41
|
env = LMDB::Environment.new(path, nosync: true, mode: 0777,
|
|
41
42
|
maxreaders: 777, mapsize: 111111, maxdbs: 666)
|
|
42
|
-
env.
|
|
43
|
-
env.info[:maxreaders].
|
|
44
|
-
env.info[:mapsize].
|
|
45
|
-
env.flags.
|
|
43
|
+
expect(env).to be_instance_of(described_class)
|
|
44
|
+
expect(env.info[:maxreaders]).to eq(777)
|
|
45
|
+
expect(env.info[:mapsize]).to eq(111111)
|
|
46
|
+
expect(env.flags.include? :nosync).to be_truthy
|
|
46
47
|
env.close
|
|
47
48
|
|
|
48
|
-
env = LMDB::Environment.new(path, :
|
|
49
|
-
env.flags.
|
|
49
|
+
env = LMDB::Environment.new(path, nosync: false)
|
|
50
|
+
expect(env.flags.include? :nosync).to be_falsy
|
|
50
51
|
env.close
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
it 'should return stat' do
|
|
55
56
|
stat = env.stat
|
|
56
|
-
stat[:psize].
|
|
57
|
-
stat[:depth].
|
|
58
|
-
stat[:branch_pages].
|
|
59
|
-
stat[:leaf_pages].
|
|
60
|
-
stat[:overflow_pages].
|
|
61
|
-
stat[:entries].
|
|
57
|
+
expect(stat[:psize]).to be_instance_of(Integer)
|
|
58
|
+
expect(stat[:depth]).to be_instance_of(Integer)
|
|
59
|
+
expect(stat[:branch_pages]).to be_instance_of(Integer)
|
|
60
|
+
expect(stat[:leaf_pages]).to be_instance_of(Integer)
|
|
61
|
+
expect(stat[:overflow_pages]).to be_instance_of(Integer)
|
|
62
|
+
expect(stat[:entries]).to be_instance_of(Integer)
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
it 'should return info' do
|
|
65
66
|
info = env.info
|
|
66
|
-
info[:mapaddr].
|
|
67
|
-
info[:mapsize].
|
|
68
|
-
info[:last_pgno].
|
|
69
|
-
info[:last_txnid].
|
|
70
|
-
info[:maxreaders].
|
|
71
|
-
info[:numreaders].
|
|
67
|
+
expect(info[:mapaddr]).to be_instance_of(Integer)
|
|
68
|
+
expect(info[:mapsize]).to be_instance_of(Integer)
|
|
69
|
+
expect(info[:last_pgno]).to be_instance_of(Integer)
|
|
70
|
+
expect(info[:last_txnid]).to be_instance_of(Integer)
|
|
71
|
+
expect(info[:maxreaders]).to be_instance_of(Integer)
|
|
72
|
+
expect(info[:numreaders]).to be_instance_of(Integer)
|
|
72
73
|
end
|
|
73
74
|
|
|
74
75
|
it 'should set mapsize' do
|
|
75
76
|
size_before = env.info[:mapsize]
|
|
76
77
|
env.mapsize = size_before * 2
|
|
77
|
-
env.info[:mapsize].
|
|
78
|
+
expect(env.info[:mapsize]).to eq(size_before * 2)
|
|
78
79
|
end
|
|
79
80
|
|
|
80
81
|
it 'should copy' do
|
|
81
82
|
target = mkpath('copy')
|
|
82
|
-
subject.copy(target).
|
|
83
|
+
expect(subject.copy(target)).to be_nil
|
|
83
84
|
end
|
|
84
85
|
|
|
85
86
|
it 'should sync' do
|
|
86
|
-
subject.sync.
|
|
87
|
+
expect(subject.sync).to be_nil
|
|
87
88
|
end
|
|
88
89
|
|
|
89
90
|
it 'should force-sync' do
|
|
90
|
-
subject.sync(true).
|
|
91
|
+
expect(subject.sync(true)).to be_nil
|
|
91
92
|
end
|
|
92
93
|
|
|
93
94
|
it 'should accept custom flags' do
|
|
94
|
-
subject.flags.
|
|
95
|
+
expect(subject.flags.include? :nosync).to be_falsy
|
|
95
96
|
|
|
96
97
|
subject.set_flags :nosync
|
|
97
|
-
subject.flags.
|
|
98
|
+
expect(subject.flags.include? :nosync).to be_truthy
|
|
98
99
|
|
|
99
100
|
subject.clear_flags :nosync
|
|
100
|
-
subject.flags.
|
|
101
|
+
expect(subject.flags.include? :nosync).to be_falsy
|
|
101
102
|
end
|
|
102
103
|
|
|
103
104
|
describe 'databases' do
|
|
104
105
|
it 'returns empty list when there are no named databases' do
|
|
105
|
-
subject.databases.
|
|
106
|
+
expect(subject.databases).to eq([])
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
it 'returns list of named databases' do
|
|
109
110
|
db1 = subject.database 'db1', create: true
|
|
110
111
|
db2 = subject.database 'db2', create: true
|
|
111
|
-
subject.databases.
|
|
112
|
+
expect(subject.databases).to eq(['db1', 'db2'])
|
|
112
113
|
end
|
|
113
114
|
|
|
114
115
|
it 'returns list of named databases when there are non-database kes in the main db' do
|
|
@@ -117,7 +118,7 @@ describe LMDB do
|
|
|
117
118
|
subject.database 'db1', create: true
|
|
118
119
|
subject.database 'db2', create: true
|
|
119
120
|
|
|
120
|
-
subject.databases.
|
|
121
|
+
expect(subject.databases).to eq(['db1', 'db2'])
|
|
121
122
|
end
|
|
122
123
|
end
|
|
123
124
|
|
|
@@ -125,71 +126,71 @@ describe LMDB do
|
|
|
125
126
|
subject { env }
|
|
126
127
|
|
|
127
128
|
it 'should create transactions' do
|
|
128
|
-
subject.active_txn.
|
|
129
|
+
expect(subject.active_txn).to be_nil
|
|
129
130
|
subject.transaction do |txn|
|
|
130
|
-
subject.active_txn.
|
|
131
|
-
txn.
|
|
131
|
+
expect(subject.active_txn).to eq(txn)
|
|
132
|
+
expect(txn).to be_instance_of(described_class)
|
|
132
133
|
txn.abort
|
|
133
|
-
subject.active_txn.
|
|
134
|
+
expect(subject.active_txn).to be_nil
|
|
134
135
|
end
|
|
135
|
-
subject.active_txn.
|
|
136
|
+
expect(subject.active_txn).to be_nil
|
|
136
137
|
end
|
|
137
138
|
|
|
138
139
|
it 'should create read-only transactions' do
|
|
139
|
-
subject.active_txn.
|
|
140
|
+
expect(subject.active_txn).to be_nil
|
|
140
141
|
subject.transaction(true) do |txn|
|
|
141
|
-
subject.active_txn.
|
|
142
|
-
txn.
|
|
142
|
+
expect(subject.active_txn).to eq(txn)
|
|
143
|
+
expect(txn).to be_instance_of(described_class)
|
|
143
144
|
txn.abort
|
|
144
|
-
subject.active_txn.
|
|
145
|
+
expect(subject.active_txn).to be_nil
|
|
145
146
|
end
|
|
146
|
-
subject.active_txn.
|
|
147
|
+
expect(subject.active_txn).to be_nil
|
|
147
148
|
end
|
|
148
149
|
|
|
149
150
|
it 'can create child transactions' do
|
|
150
|
-
subject.active_txn.
|
|
151
|
+
expect(subject.active_txn).to be_nil
|
|
151
152
|
env.transaction do |txn|
|
|
152
|
-
subject.active_txn.
|
|
153
|
+
expect(subject.active_txn).to eq(txn)
|
|
153
154
|
env.transaction do |ctxn|
|
|
154
|
-
subject.active_txn.
|
|
155
|
+
expect(subject.active_txn).to eq(ctxn)
|
|
155
156
|
ctxn.abort
|
|
156
|
-
subject.active_txn.
|
|
157
|
+
expect(subject.active_txn).to eq(txn)
|
|
157
158
|
end
|
|
158
|
-
subject.active_txn.
|
|
159
|
+
expect(subject.active_txn).to eq(txn)
|
|
159
160
|
end
|
|
160
|
-
subject.active_txn.
|
|
161
|
+
expect(subject.active_txn).to be_nil
|
|
161
162
|
end
|
|
162
163
|
|
|
163
164
|
it 'should support aborting parent transaction' do
|
|
164
|
-
subject.active_txn.
|
|
165
|
+
expect(subject.active_txn).to be_nil
|
|
165
166
|
env.transaction do |txn|
|
|
166
|
-
subject.active_txn.
|
|
167
|
+
expect(subject.active_txn).to eq(txn)
|
|
167
168
|
env.transaction do |ctxn|
|
|
168
|
-
subject.active_txn.
|
|
169
|
+
expect(subject.active_txn).to eq(ctxn)
|
|
169
170
|
db['key'] = 'value'
|
|
170
171
|
txn.abort
|
|
171
|
-
subject.active_txn.
|
|
172
|
+
expect(subject.active_txn).to be_nil
|
|
172
173
|
end
|
|
173
|
-
subject.active_txn.
|
|
174
|
+
expect(subject.active_txn).to be_nil
|
|
174
175
|
end
|
|
175
|
-
db['key'].
|
|
176
|
-
subject.active_txn.
|
|
176
|
+
expect(db['key']).to be_nil
|
|
177
|
+
expect(subject.active_txn).to be_nil
|
|
177
178
|
end
|
|
178
179
|
|
|
179
180
|
it 'should support comitting parent transaction' do
|
|
180
|
-
subject.active_txn.
|
|
181
|
+
expect(subject.active_txn).to be_nil
|
|
181
182
|
env.transaction do |txn|
|
|
182
|
-
subject.active_txn.
|
|
183
|
+
expect(subject.active_txn).to eq(txn)
|
|
183
184
|
env.transaction do |ctxn|
|
|
184
|
-
subject.active_txn.
|
|
185
|
+
expect(subject.active_txn).to eq(ctxn)
|
|
185
186
|
db['key'] = 'value'
|
|
186
187
|
txn.commit
|
|
187
|
-
subject.active_txn.
|
|
188
|
+
expect(subject.active_txn).to be_nil
|
|
188
189
|
end
|
|
189
|
-
subject.active_txn.
|
|
190
|
+
expect(subject.active_txn).to be_nil
|
|
190
191
|
end
|
|
191
|
-
db['key'].
|
|
192
|
-
subject.active_txn.
|
|
192
|
+
expect(db['key']).to eq('value')
|
|
193
|
+
expect(subject.active_txn).to be_nil
|
|
193
194
|
end
|
|
194
195
|
|
|
195
196
|
it 'should get environment' do
|
|
@@ -197,7 +198,17 @@ describe LMDB do
|
|
|
197
198
|
env.transaction do |txn|
|
|
198
199
|
env2 = txn.env
|
|
199
200
|
end
|
|
200
|
-
env2.
|
|
201
|
+
expect(env2).to eq(env)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'should do conditional transactions' do
|
|
205
|
+
subject.transaction? true do |t1|
|
|
206
|
+
# note this second one is not readonly which would be
|
|
207
|
+
# illegal if it was opening a transaction for real
|
|
208
|
+
subject.transaction? do |t2|
|
|
209
|
+
expect(t2).to eq(t1)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
201
212
|
end
|
|
202
213
|
end
|
|
203
214
|
end
|
|
@@ -206,9 +217,9 @@ describe LMDB do
|
|
|
206
217
|
subject { db }
|
|
207
218
|
|
|
208
219
|
it 'should return flags' do
|
|
209
|
-
subject.flags.
|
|
210
|
-
subject.dupsort
|
|
211
|
-
subject.dupfixed
|
|
220
|
+
expect(subject.flags).to be_instance_of(Hash)
|
|
221
|
+
expect(subject.dupsort?).to be_falsy
|
|
222
|
+
expect(subject.dupfixed?).to be_falsy
|
|
212
223
|
end
|
|
213
224
|
|
|
214
225
|
it 'should support named databases' do
|
|
@@ -218,63 +229,69 @@ describe LMDB do
|
|
|
218
229
|
db1 = env.database 'db1', create: true # actually no it doesn't wtf
|
|
219
230
|
db2 = env.database 'db2', **dbopts
|
|
220
231
|
|
|
232
|
+
# this should not crash
|
|
233
|
+
expect(env[:db1].size).to eq(0)
|
|
234
|
+
|
|
221
235
|
main['key'] = '1'
|
|
222
236
|
db1['key'] = '2'
|
|
223
237
|
db2['key'] = '3'
|
|
224
238
|
|
|
225
|
-
main['key'].
|
|
226
|
-
db1['key'].
|
|
227
|
-
db2['key'].
|
|
239
|
+
expect(main['key']).to eq(?1)
|
|
240
|
+
expect(db1['key']).to eq(?2)
|
|
241
|
+
expect(db2['key']).to eq(?3)
|
|
228
242
|
end
|
|
229
243
|
|
|
230
244
|
it 'should get/put data' do
|
|
231
|
-
subject.get
|
|
232
|
-
subject.put
|
|
233
|
-
subject.get
|
|
245
|
+
expect(subject.get 'cat').to be_nil
|
|
246
|
+
expect(subject.put 'cat', 'garfield').to be_nil
|
|
247
|
+
expect(subject.get 'cat').to eq('garfield')
|
|
234
248
|
|
|
235
249
|
# check for key-value pairs on non-dupsort database
|
|
236
|
-
subject.has?
|
|
237
|
-
subject.has?
|
|
250
|
+
expect(subject.has? 'cat', 'garfield').to be_truthy
|
|
251
|
+
expect(subject.has? 'cat', 'heathcliff').to be_falsy
|
|
238
252
|
|
|
239
253
|
subject.put?('dog', 'odie')
|
|
240
|
-
subject.has?
|
|
254
|
+
expect(subject.has? 'dog', 'odie').to be_truthy
|
|
241
255
|
end
|
|
242
256
|
|
|
243
257
|
it 'should delete by key' do
|
|
244
|
-
|
|
245
|
-
|
|
258
|
+
expect { subject.delete('cat') }.to raise_error(LMDB::Error::NOTFOUND)
|
|
259
|
+
expect {
|
|
260
|
+
subject.delete 'cat', 'garfield'
|
|
261
|
+
}.to raise_error(LMDB::Error::NOTFOUND)
|
|
246
262
|
|
|
247
263
|
subject.put('cat', 'garfield')
|
|
248
|
-
subject.delete
|
|
249
|
-
|
|
264
|
+
expect(subject.delete 'cat').to be_nil
|
|
265
|
+
expect { subject.delete 'cat' }.to raise_error(LMDB::Error::NOTFOUND)
|
|
250
266
|
|
|
251
267
|
subject.put('cat', 'garfield')
|
|
252
|
-
subject.delete
|
|
253
|
-
|
|
268
|
+
expect(subject.delete 'cat', 'garfield').to be_nil
|
|
269
|
+
expect {
|
|
270
|
+
subject.delete 'cat', 'garfield' }.to raise_error(LMDB::Error::NOTFOUND)
|
|
254
271
|
|
|
255
272
|
# soft delete
|
|
256
|
-
subject.delete?
|
|
273
|
+
expect(subject.delete? 'cat', 'heathcliff').to be_nil
|
|
257
274
|
end
|
|
258
275
|
|
|
259
276
|
it 'stores key/values in same transaction' do
|
|
260
|
-
db.put
|
|
261
|
-
db.get
|
|
277
|
+
expect(db.put 'key', 'value').to be_nil
|
|
278
|
+
expect(db.get 'key').to eq('value')
|
|
262
279
|
end
|
|
263
280
|
|
|
264
281
|
it 'stores key/values in different transactions' do
|
|
265
282
|
env.transaction do
|
|
266
|
-
db.put
|
|
267
|
-
db.put
|
|
283
|
+
expect(db.put 'key', 'value').to be_nil
|
|
284
|
+
expect(db.put 'key2', 'value2').to be_nil
|
|
268
285
|
env.transaction do
|
|
269
|
-
db.put
|
|
286
|
+
expect(db.put 'key3', 'value3').to be_nil
|
|
270
287
|
end
|
|
271
288
|
end
|
|
272
289
|
|
|
273
290
|
env.transaction do
|
|
274
|
-
db.get
|
|
275
|
-
db.get
|
|
291
|
+
expect(db.get 'key').to eq('value')
|
|
292
|
+
expect(db.get 'key2').to eq('value2')
|
|
276
293
|
env.transaction do
|
|
277
|
-
db.get
|
|
294
|
+
expect(db.get 'key3').to eq('value3')
|
|
278
295
|
end
|
|
279
296
|
end
|
|
280
297
|
end
|
|
@@ -285,30 +302,30 @@ describe LMDB do
|
|
|
285
302
|
break
|
|
286
303
|
end
|
|
287
304
|
|
|
288
|
-
db.get
|
|
305
|
+
expect(db.get 'key4').to eq('value4')
|
|
289
306
|
end
|
|
290
307
|
|
|
291
308
|
it 'should return stat' do
|
|
292
|
-
db.stat.
|
|
309
|
+
expect(db.stat).to be_instance_of(Hash)
|
|
293
310
|
end
|
|
294
311
|
|
|
295
312
|
it 'should return size' do
|
|
296
|
-
db.size.
|
|
313
|
+
expect(db.size).to eq(0)
|
|
297
314
|
db.put('key', 'value')
|
|
298
|
-
db.size.
|
|
315
|
+
expect(db.size).to eq(1)
|
|
299
316
|
db.put('key2', 'value2')
|
|
300
|
-
db.size.
|
|
317
|
+
expect(db.size).to eq(2)
|
|
301
318
|
end
|
|
302
319
|
|
|
303
320
|
it 'should be enumerable' do
|
|
304
321
|
db['k1'] = 'v1'
|
|
305
322
|
db['k2'] = 'v2'
|
|
306
|
-
db.to_a.
|
|
323
|
+
expect(db.to_a).to eq([['k1', 'v1'], ['k2', 'v2']])
|
|
307
324
|
end
|
|
308
325
|
|
|
309
326
|
it 'should have shortcuts' do
|
|
310
327
|
db['key'] = 'value'
|
|
311
|
-
db['key'].
|
|
328
|
+
expect(db['key']).to eq('value')
|
|
312
329
|
end
|
|
313
330
|
|
|
314
331
|
it 'should store binary' do
|
|
@@ -316,21 +333,21 @@ describe LMDB do
|
|
|
316
333
|
bin2 = "\xAAx\BB\xCC2"
|
|
317
334
|
db[bin1] = bin2
|
|
318
335
|
db['key'] = bin2
|
|
319
|
-
db[bin1].
|
|
320
|
-
db['key'].
|
|
336
|
+
expect(db[bin1]).to eq(bin2)
|
|
337
|
+
expect(db['key']).to eq(bin2)
|
|
321
338
|
end
|
|
322
339
|
|
|
323
340
|
it 'should get environment' do
|
|
324
341
|
main = env.database
|
|
325
342
|
db1 = env.database('db1', create: true)
|
|
326
|
-
main.env.
|
|
327
|
-
db1.env.
|
|
343
|
+
expect(main.env).to eq(env)
|
|
344
|
+
expect(db1.env).to eq(env)
|
|
328
345
|
end
|
|
329
346
|
|
|
330
347
|
it 'should iterate over/list keys' do
|
|
331
348
|
db['k1'] = 'v1'
|
|
332
349
|
db['k2'] = 'v2'
|
|
333
|
-
db.keys.sort.
|
|
350
|
+
expect(db.keys.sort).to eq(%w[k1 k2])
|
|
334
351
|
end
|
|
335
352
|
end
|
|
336
353
|
|
|
@@ -342,38 +359,38 @@ describe LMDB do
|
|
|
342
359
|
|
|
343
360
|
it 'should get first key/value' do
|
|
344
361
|
db.cursor do |c|
|
|
345
|
-
c.first.
|
|
362
|
+
expect(c.first).to eq(['key1', 'value1'])
|
|
346
363
|
end
|
|
347
364
|
end
|
|
348
365
|
|
|
349
366
|
it 'should get last key/value' do
|
|
350
367
|
db.cursor do |c|
|
|
351
|
-
c.last.
|
|
368
|
+
expect(c.last).to eq(['key2', 'value2'])
|
|
352
369
|
end
|
|
353
370
|
end
|
|
354
371
|
|
|
355
372
|
it 'should get next key/value' do
|
|
356
373
|
db.cursor do |c|
|
|
357
374
|
c.first
|
|
358
|
-
c.next.
|
|
375
|
+
expect(c.next).to eq(['key2', 'value2'])
|
|
359
376
|
end
|
|
360
377
|
end
|
|
361
378
|
|
|
362
379
|
it 'should seek to key' do
|
|
363
380
|
db.cursor do |c|
|
|
364
|
-
c.set
|
|
381
|
+
expect(c.set 'key1').to eq(['key1', 'value1'])
|
|
365
382
|
end
|
|
366
383
|
end
|
|
367
384
|
|
|
368
385
|
it 'should seek to closest key' do
|
|
369
386
|
db.cursor do |c|
|
|
370
|
-
c.set_range
|
|
387
|
+
expect(c.set_range 'key0').to eq(['key1', 'value1'])
|
|
371
388
|
end
|
|
372
389
|
end
|
|
373
390
|
|
|
374
391
|
it 'should seek to key with nuls' do
|
|
375
392
|
db.cursor do |c|
|
|
376
|
-
c.set_range
|
|
393
|
+
expect(c.set_range '\x00').to eq(['key1', 'value1'])
|
|
377
394
|
end
|
|
378
395
|
end
|
|
379
396
|
|
|
@@ -381,8 +398,8 @@ describe LMDB do
|
|
|
381
398
|
db.cursor do |c|
|
|
382
399
|
db.put('key0', 'value0')
|
|
383
400
|
c.first
|
|
384
|
-
c.next_range
|
|
385
|
-
c.next_range
|
|
401
|
+
expect(c.next_range 'key1').to eq(['key1', 'value1'])
|
|
402
|
+
expect(c.next_range 'key1').to be_nil
|
|
386
403
|
end
|
|
387
404
|
end
|
|
388
405
|
|
|
@@ -390,35 +407,35 @@ describe LMDB do
|
|
|
390
407
|
dupdb = env.database 'dupsort', create: true, dupsort: true
|
|
391
408
|
|
|
392
409
|
# check flag while we're at it
|
|
393
|
-
dupdb.flags[:dupsort].
|
|
394
|
-
dupdb.dupsort
|
|
395
|
-
dupdb.dupfixed
|
|
410
|
+
expect(dupdb.flags[:dupsort]).to be_truthy
|
|
411
|
+
expect(dupdb.dupsort?).to be_truthy
|
|
412
|
+
expect(dupdb.dupfixed?).to be_falsy
|
|
396
413
|
|
|
397
414
|
# add the no-op keyword to trigger a complaint from ruby 2.7
|
|
398
415
|
dupdb.put 'key1', 'value1', nodupdata: false
|
|
399
416
|
dupdb.put 'key1', 'value2'
|
|
400
417
|
dupdb.put 'key2', 'value3'
|
|
401
418
|
dupdb.cursor do |c|
|
|
402
|
-
c.set
|
|
403
|
-
c.set
|
|
404
|
-
c.set
|
|
419
|
+
expect(c.set 'key1', 'value2').to eq(['key1', 'value2'])
|
|
420
|
+
expect(c.set 'key1', 'value1').to eq(['key1', 'value1'])
|
|
421
|
+
expect(c.set 'key1', 'value3').to be_nil
|
|
405
422
|
end
|
|
406
423
|
|
|
407
424
|
# this should do nothing
|
|
408
|
-
dupdb.put?
|
|
425
|
+
expect(dupdb.put? 'key1', 'value1', nodupdata: true).to be_nil
|
|
409
426
|
|
|
410
427
|
# this is basically an extended test of `cursor.set key, val`
|
|
411
|
-
dupdb.has?
|
|
412
|
-
dupdb.has?
|
|
413
|
-
dupdb.has?
|
|
428
|
+
expect(dupdb.has? 'key1', 'value1').to be_truthy
|
|
429
|
+
expect(dupdb.has? 'key1', 'value2').to be_truthy
|
|
430
|
+
expect(dupdb.has? 'key1', 'value0').to be_falsy
|
|
414
431
|
|
|
415
432
|
# match the contents of key1
|
|
416
|
-
dupdb.each_value('key1').to_a.sort.
|
|
433
|
+
expect(dupdb.each_value('key1').to_a.sort).to eq(['value1', 'value2'])
|
|
417
434
|
|
|
418
435
|
# we should have two entries for key1
|
|
419
|
-
dupdb.cardinality
|
|
436
|
+
expect(dupdb.cardinality 'key1').to eq(2)
|
|
420
437
|
|
|
421
|
-
dupdb.each_key.to_a.sort.
|
|
438
|
+
expect(dupdb.each_key.to_a.sort).to eq(['key1', 'key2'])
|
|
422
439
|
|
|
423
440
|
# XXX move this or whatever
|
|
424
441
|
env.transaction do |t|
|
|
@@ -428,24 +445,24 @@ describe LMDB do
|
|
|
428
445
|
|
|
429
446
|
it 'should complain setting a key-value pair without dupsort' do
|
|
430
447
|
db.cursor do |c|
|
|
431
|
-
|
|
448
|
+
expect { c.set('key1', 'value1') }.to raise_error(LMDB::Error)
|
|
432
449
|
end
|
|
433
450
|
end
|
|
434
451
|
|
|
435
452
|
it 'should raise without block or txn' do
|
|
436
|
-
|
|
453
|
+
expect { db.cursor.next }.to raise_error(LMDB::Error)
|
|
437
454
|
end
|
|
438
455
|
|
|
439
456
|
it 'should raise outside txn' do
|
|
440
457
|
c = nil
|
|
441
458
|
env.transaction { c = db.cursor }
|
|
442
|
-
|
|
459
|
+
expect { c.next }.to raise_error(LMDB::Error)
|
|
443
460
|
end
|
|
444
461
|
|
|
445
462
|
it 'should get database' do
|
|
446
463
|
db2 = nil
|
|
447
464
|
env.transaction { c = db.cursor; db2 = c.database }
|
|
448
|
-
db2.
|
|
465
|
+
expect(db2).to eq(db)
|
|
449
466
|
end
|
|
450
467
|
|
|
451
468
|
it 'should nest a read-only txn in a read-write' do
|
|
@@ -456,19 +473,19 @@ describe LMDB do
|
|
|
456
473
|
end
|
|
457
474
|
|
|
458
475
|
it 'should croak when cursor key is not given a string' do
|
|
459
|
-
|
|
476
|
+
expect do
|
|
460
477
|
db.cursor do |c|
|
|
461
478
|
c.set 1
|
|
462
479
|
end
|
|
463
|
-
end.
|
|
480
|
+
end.to raise_error(ArgumentError)
|
|
464
481
|
end
|
|
465
482
|
|
|
466
483
|
it 'should croak when cursor value is not given a string' do
|
|
467
|
-
|
|
484
|
+
expect do
|
|
468
485
|
db.cursor do |c|
|
|
469
486
|
c.set 'hi', 1
|
|
470
487
|
end
|
|
471
|
-
end.
|
|
488
|
+
end.to raise_error(ArgumentError)
|
|
472
489
|
end
|
|
473
490
|
end
|
|
474
491
|
end
|