rdf-lmdb 0.3.6 → 0.4.0
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/TODO.org +6 -4
- data/lib/rdf/lmdb/version.rb +1 -1
- data/lib/rdf/lmdb.rb +319 -276
- data/rdf-lmdb.gemspec +2 -2
- metadata +8 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '02085577cc4df2383a38f97e53f9f29cc75e94f5e2d8655be73d457737eabfa7'
|
|
4
|
+
data.tar.gz: a6eb270cb9297f16cb7e079f6f46710ef1b54ced75ae83db7cbe6cbaaba4ce84
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4c4daa84e4a59411d8ec197527a4571f48e56b5d54b911e572d5aae09c17d391be318f6cb519233bab468b641dcb9d2e2f07e6a767678235eab1afcbaa06db31
|
|
7
|
+
data.tar.gz: 5a132e61243460abf1819c5bd445a3a87b783aefe445b46b37af4abe0cd5327c03ba59095427459c02646eb802c2a139b38041e94dd8a07daa8da30502949e46
|
data/TODO.org
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
- "consensus graphs" which extend the idea of union graphs to a shared reality for multiple users
|
|
32
32
|
- "proxy graphs" that map to other systems (e.g. SQL)
|
|
33
33
|
- or even other RDF stores
|
|
34
|
+
- (include caching)
|
|
34
35
|
- statement-generating layers that do things we actually /do/ want statements in the graph for, but /generated/ rather than stored (or perhaps merely /cached/, and thus not subject to versioning)
|
|
35
36
|
- e.g. "soft" inferences, stuff written in vocab specs that had no way to formally express at the time
|
|
36
37
|
- I'm thinking specifically how ~?c a skos:OrderedCollection; skos:memberList (?m1 ?m2 ?mn)~ implies ~?c skos:member ?m1~ and so on.
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
- e.g. stateful or aggregate statements computed from other statements
|
|
39
40
|
- again this is totally doable with SHACL.
|
|
40
41
|
* TODO RDF-star
|
|
41
|
-
-
|
|
42
|
+
- the basic element is the term
|
|
42
43
|
- terms can be normalized and hashed
|
|
43
44
|
- each term is assigned a numeric identifier that is local to the database and not otherwise exposed
|
|
44
45
|
- assume this is a native-endian ~size_t~ integer; we are not gonna screw around with portability across cpu architectures
|
|
@@ -54,7 +55,7 @@
|
|
|
54
55
|
- so subjects and objects can now be /statements/ in addition to URIs and bnodes (and literals for objects)
|
|
55
56
|
- so it shouldn't be the end of the world to make that a thing
|
|
56
57
|
- albeit backward-compatibility to existing stores might be a problem
|
|
57
|
-
- well if anybody wants to hire me
|
|
58
|
+
- well if anybody wants to hire me to do that for them, they can
|
|
58
59
|
* TODO change history
|
|
59
60
|
- anyway, that aside, what we're actually after is being able to access the state of the database at the instant of a particular transaction
|
|
60
61
|
- random access is ideal
|
|
@@ -97,7 +98,8 @@
|
|
|
97
98
|
- why not just stick a bit on the end of that as to whether it's added or removed
|
|
98
99
|
- so we have ~added~ and ~removed~ tables of the form ~change id => statement id~
|
|
99
100
|
- we also have i dunno, ~state~ or something of the form ~statement id => change id, bit for added/removed~
|
|
100
|
-
** TODO global
|
|
101
|
+
** TODO global modification time
|
|
102
|
+
- [X] temporary global mtime in stats databsae
|
|
101
103
|
- which resources have been affected since this time/transaction id
|
|
102
104
|
* TODO principals (multi-user)
|
|
103
105
|
- each individual user gets their own quad store from their point of view
|
|
@@ -108,7 +110,7 @@
|
|
|
108
110
|
- you can't add or delete statements in other people's slices and they can't change yours
|
|
109
111
|
- though they should be able to transfer ownership of a set of statements to you somehow
|
|
110
112
|
- (but the person receiving should be able to decline the transfer)
|
|
111
|
-
** TODO
|
|
113
|
+
** TODO lenses/perspectives
|
|
112
114
|
- my concern here is a way to have a single repository that can support multiple users without "leaking" content from other users
|
|
113
115
|
- like we /could/ just partition these on the disk but there are reasons not to do this:
|
|
114
116
|
1. it's gonna be a pain in the ass for downstream applications in the best case
|
data/lib/rdf/lmdb/version.rb
CHANGED
data/lib/rdf/lmdb.rb
CHANGED
|
@@ -88,15 +88,17 @@ module RDF
|
|
|
88
88
|
'Cannot execute a rolled back transaction. Open a new one instead.' if
|
|
89
89
|
@rolledback
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
if @mutable && !@changes.empty?
|
|
92
|
+
ret = if @txn
|
|
93
|
+
@changes.apply(@repository)
|
|
94
|
+
else
|
|
95
|
+
wrap_txn { @changes.apply(@repository) }
|
|
96
|
+
end
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
@changes = RDF::Changeset.new
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
ret
|
|
101
|
+
end
|
|
100
102
|
end
|
|
101
103
|
|
|
102
104
|
def rollback
|
|
@@ -116,6 +118,9 @@ module RDF
|
|
|
116
118
|
class Repository < ::RDF::Repository
|
|
117
119
|
private
|
|
118
120
|
|
|
121
|
+
LMDB_OPTS =
|
|
122
|
+
%i[fixedmap nosubdir nosync rdonly nometasync writemap mapasync notls]
|
|
123
|
+
|
|
119
124
|
# for the mapsize parameter
|
|
120
125
|
UNITS = { nil => 1 }
|
|
121
126
|
'kmgtpe'.split('').each_with_index do |x, i|
|
|
@@ -144,17 +149,19 @@ module RDF
|
|
|
144
149
|
factor.to_i * UNITS[unit]
|
|
145
150
|
end
|
|
146
151
|
|
|
147
|
-
def init_lmdb dir, **options
|
|
148
|
-
dir
|
|
149
|
-
dir
|
|
152
|
+
def init_lmdb dir = nil, **options
|
|
153
|
+
dir ||= options[:dir]
|
|
154
|
+
raise ArgumentError, 'must pass in either dir or dir: keyword' unless dir
|
|
155
|
+
|
|
156
|
+
@dir = Pathname(dir).expand_path
|
|
157
|
+
@dir.mkdir unless @dir.exist?
|
|
150
158
|
|
|
151
159
|
options[:mapsize] = int_bytes options[:mapsize] if options[:mapsize]
|
|
152
160
|
|
|
153
|
-
|
|
154
|
-
@lmdb = ::LMDB.new dir, **options
|
|
161
|
+
@lmdb_opts = options.slice(*LMDB_OPTS)
|
|
155
162
|
|
|
156
163
|
# XXX trip over the old database layout for now
|
|
157
|
-
dbs =
|
|
164
|
+
dbs = env.database.keys.map(&:to_sym)
|
|
158
165
|
unless dbs.empty? or dbs.include? :int2term
|
|
159
166
|
err = <<-ERR.tr_s("\n ", ' ')
|
|
160
167
|
This version uses an updated (and incompatible) database layout.
|
|
@@ -163,9 +170,8 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
163
170
|
raise ArgumentError, err
|
|
164
171
|
end
|
|
165
172
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
@dbs = {
|
|
173
|
+
env.transaction? do
|
|
174
|
+
dbs = {
|
|
169
175
|
# this is the control database, it gets no flags
|
|
170
176
|
control: [],
|
|
171
177
|
# actual instance data
|
|
@@ -187,7 +193,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
187
193
|
# gp2stmt: [:dupsort, :dupfixed],
|
|
188
194
|
# go2stmt: [:dupsort, :dupfixed],
|
|
189
195
|
}.map do |name, flags|
|
|
190
|
-
[name,
|
|
196
|
+
[name, env.database(name.to_s,
|
|
191
197
|
**(flags + [:create]).map { |f| [f, true] }.to_h)]
|
|
192
198
|
end.to_h
|
|
193
199
|
|
|
@@ -196,7 +202,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
196
202
|
|
|
197
203
|
# t.commit
|
|
198
204
|
end
|
|
199
|
-
|
|
205
|
+
env.sync
|
|
200
206
|
end
|
|
201
207
|
|
|
202
208
|
SPO = %i[subject predicate object].freeze
|
|
@@ -216,35 +222,42 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
216
222
|
}.freeze
|
|
217
223
|
|
|
218
224
|
def last_key db
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
225
|
+
env.transaction? do
|
|
226
|
+
db = env[db] if db.is_a? Symbol
|
|
227
|
+
if db.size != 0
|
|
228
|
+
# the last entry in the database should be the highest number
|
|
229
|
+
db.cursor { |c| c.last }.first.unpack1 ?J
|
|
230
|
+
else
|
|
231
|
+
nil
|
|
232
|
+
end
|
|
233
|
+
end
|
|
223
234
|
end
|
|
224
235
|
|
|
225
236
|
def int_for term
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
raw.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
raw.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
raw.
|
|
237
|
+
env.transaction? true do
|
|
238
|
+
case term
|
|
239
|
+
when nil, RDF::Query::Variable then 0
|
|
240
|
+
when RDF::Statement
|
|
241
|
+
terms = term.to_a.map { |t| int_for t }
|
|
242
|
+
unless terms.include? nil # the statement implicitly not here
|
|
243
|
+
if raw = env[:ints2stmt].get(terms.pack 'J3')
|
|
244
|
+
raw.unpack1 ?J
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
when Hash # of integers
|
|
248
|
+
if raw = env[:ints2stmt].get(term.values_at(*SPO).pack 'J3')
|
|
249
|
+
raw.unpack1 ?J
|
|
250
|
+
end
|
|
251
|
+
when RDF::Term
|
|
252
|
+
thash = hash_term term
|
|
253
|
+
if raw = env[:hash2term].get(thash)
|
|
254
|
+
raw.unpack1 ?J
|
|
255
|
+
end
|
|
256
|
+
when String
|
|
257
|
+
# assume this is the hash string
|
|
258
|
+
if raw = env[:hash2term].get(term)
|
|
259
|
+
raw.unpack1 ?J
|
|
260
|
+
end
|
|
248
261
|
end
|
|
249
262
|
end
|
|
250
263
|
end
|
|
@@ -252,38 +265,44 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
252
265
|
def store_term term
|
|
253
266
|
return 0 if term.nil?
|
|
254
267
|
raise ArgumentError, 'must be a term' unless term.is_a? RDF::Term
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return ix
|
|
259
|
-
end
|
|
268
|
+
env.transaction? do
|
|
269
|
+
# get the hash first
|
|
270
|
+
thash = hash_term term
|
|
260
271
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
272
|
+
if ix = int_for(thash)
|
|
273
|
+
ix
|
|
274
|
+
else
|
|
275
|
+
# this should start with 1, not zero
|
|
276
|
+
ix = (last_key(env[:int2term]) || 0) + 1
|
|
277
|
+
ib = [ix].pack ?J
|
|
278
|
+
env[:int2term].put ib, term.to_ntriples.to_nfc
|
|
265
279
|
|
|
266
|
-
|
|
267
|
-
|
|
280
|
+
# we need the hash too to resolve the term the other way
|
|
281
|
+
env[:hash2term].put thash, ib
|
|
268
282
|
|
|
269
|
-
|
|
283
|
+
ix # return the current index
|
|
284
|
+
end
|
|
285
|
+
end
|
|
270
286
|
end
|
|
271
287
|
|
|
272
288
|
def store_stmt statement, ints = nil
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
return ib.unpack1 ?J
|
|
277
|
-
end
|
|
289
|
+
env.transaction? do
|
|
290
|
+
ints ||= statement.to_h.transform_values { |v| store_term v }
|
|
291
|
+
ik = ints.values_at(*SPO).pack 'J3'
|
|
278
292
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
293
|
+
if ib = env[:ints2stmt].get(ik)
|
|
294
|
+
ib.unpack1 ?J
|
|
295
|
+
else
|
|
296
|
+
# this should start with 1, not zero
|
|
297
|
+
ix = (last_key(:statement) || 0) + 1
|
|
298
|
+
ib = [ix].pack ?J
|
|
282
299
|
|
|
283
|
-
|
|
284
|
-
|
|
300
|
+
env[:statement].put ib, ik # number to triple-number
|
|
301
|
+
env[:ints2stmt].put ik, ib # triple-number to number
|
|
285
302
|
|
|
286
|
-
|
|
303
|
+
ix # the index integer
|
|
304
|
+
end
|
|
305
|
+
end
|
|
287
306
|
end
|
|
288
307
|
|
|
289
308
|
# everything gets normalized to NFC on the way in (i
|
|
@@ -300,95 +319,104 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
300
319
|
def add_one statement
|
|
301
320
|
# get the integer keys for the terms and statement
|
|
302
321
|
terms = statement.to_h
|
|
303
|
-
ints = terms.transform_values { |v| store_term v }
|
|
304
|
-
ipack = ints.transform_values { |v| [v].pack ?J }
|
|
305
|
-
sint = store_stmt statement, ints
|
|
306
|
-
spack = [sint].pack ?J
|
|
307
322
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
323
|
+
env.transaction? do
|
|
324
|
+
ints = terms.transform_values { |v| store_term v }
|
|
325
|
+
ipack = ints.transform_values { |v| [v].pack ?J }
|
|
326
|
+
sint = store_stmt statement, ints
|
|
327
|
+
spack = [sint].pack ?J
|
|
328
|
+
|
|
329
|
+
# now we map the SPO indices
|
|
330
|
+
SPO_MAP.each do |k, d|
|
|
331
|
+
db = env[d]
|
|
332
|
+
ik = ipack[k]
|
|
333
|
+
# note we test before inserting or lmdb will dutifully
|
|
334
|
+
# create unlimited duplicate values and results will be wrong
|
|
335
|
+
db.put ik, spack unless db.has? ik, spack
|
|
336
|
+
end
|
|
316
337
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
338
|
+
# now we do the pair indices
|
|
339
|
+
PAIR_MAP.each do |pair, d|
|
|
340
|
+
db = env[d]
|
|
341
|
+
ik = ipack.values_at(*pair).join
|
|
342
|
+
db.put ik, spack unless db.has? ik, spack
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# associate the statement with its graph; note zero is the null graph
|
|
346
|
+
gint = ints[:graph_name] || 0
|
|
347
|
+
gpack = [gint].pack ?J
|
|
323
348
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
@dbs[:g2stmt].put gpack, spack unless @dbs[:g2stmt].has? gpack, spack
|
|
328
|
-
@dbs[:stmt2g].put spack, gpack unless @dbs[:stmt2g].has? spack, gpack
|
|
349
|
+
env[:g2stmt].put gpack, spack unless env[:g2stmt].has? gpack, spack
|
|
350
|
+
env[:stmt2g].put spack, gpack unless env[:stmt2g].has? spack, gpack
|
|
351
|
+
end
|
|
329
352
|
end
|
|
330
353
|
|
|
331
354
|
def rm_one statement, scan: true
|
|
332
355
|
terms = statement.to_h
|
|
333
|
-
ints = terms.transform_values { |v| int_for v }
|
|
334
|
-
# if none of the terms resolve, we don't have it
|
|
335
|
-
return [] if ints.values_at(*SPO).include? nil
|
|
336
|
-
# same goes for the statement
|
|
337
|
-
sint = int_for(ints) or return []
|
|
338
|
-
spack = [sint].pack ?J
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
gint = ints[:graph_name] or return []
|
|
342
|
-
gpack = [gint].pack ?J
|
|
343
|
-
graphs = @dbs[:stmt2g].each_value(spack).to_a.uniq
|
|
344
|
-
|
|
345
|
-
out = []
|
|
346
|
-
unless graphs.empty?
|
|
347
|
-
# this will dissociate the statement from the graph
|
|
348
|
-
@dbs[:g2stmt].delete? gpack, spack
|
|
349
|
-
@dbs[:stmt2g].delete? spack, gpack
|
|
350
|
-
|
|
351
|
-
if graphs.size == 1 and graphs.first == gpack
|
|
352
|
-
# nuke the statement if this is the only instance of it
|
|
353
|
-
@dbs[:statement].delete? spack
|
|
354
|
-
@dbs[:ints2stmt].delete? ints.values_at(*SPO).pack('J3')
|
|
355
|
-
|
|
356
|
-
# now we nuke the indexes
|
|
357
|
-
|
|
358
|
-
# first the original spo
|
|
359
|
-
SPO_MAP.map do |k, d|
|
|
360
|
-
ib = [ints[k]].pack ?J
|
|
361
|
-
@dbs[d].delete? ib, spack
|
|
362
|
-
out << ints[k]
|
|
363
|
-
end
|
|
364
356
|
|
|
365
|
-
|
|
366
|
-
|
|
357
|
+
op = -> _ = nil do
|
|
358
|
+
ints = terms.transform_values { |v| int_for v }
|
|
359
|
+
# if none of the terms resolve, we don't have it
|
|
360
|
+
return [] if ints.values_at(*SPO).include? nil
|
|
361
|
+
# same goes for the statement
|
|
362
|
+
sint = int_for(ints) or return []
|
|
363
|
+
spack = [sint].pack ?J
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
gint = ints[:graph_name] or return []
|
|
367
|
+
gpack = [gint].pack ?J
|
|
368
|
+
graphs = env[:stmt2g].each_value(spack).to_a.uniq
|
|
369
|
+
|
|
370
|
+
out = []
|
|
371
|
+
unless graphs.empty?
|
|
372
|
+
# this will dissociate the statement from the graph
|
|
373
|
+
env[:g2stmt].delete? gpack, spack
|
|
374
|
+
env[:stmt2g].delete? spack, gpack
|
|
375
|
+
|
|
376
|
+
if graphs.size == 1 and graphs.first == gpack
|
|
377
|
+
# nuke the statement if this is the only instance of it
|
|
378
|
+
env[:statement].delete? spack
|
|
379
|
+
env[:ints2stmt].delete? ints.values_at(*SPO).pack('J3')
|
|
380
|
+
|
|
381
|
+
# now we nuke the indexes
|
|
382
|
+
|
|
383
|
+
# first the original spo
|
|
384
|
+
SPO_MAP.map do |k, d|
|
|
385
|
+
ib = [ints[k]].pack ?J
|
|
386
|
+
env[d].delete? ib, spack
|
|
387
|
+
out << ints[k]
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# add the graph if it is not null
|
|
391
|
+
out << terms[:graph_name] if terms[:graph_name] and gint != 0
|
|
367
392
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
393
|
+
# and now the pair map
|
|
394
|
+
ipack = ints.slice(*SPO).transform_values { |v| [v].pack ?J }
|
|
395
|
+
PAIR_MAP.map do |pair, d|
|
|
396
|
+
ib = ipack.values_at(*pair).join
|
|
397
|
+
env[d].delete? ib, spack
|
|
398
|
+
end
|
|
373
399
|
end
|
|
374
400
|
end
|
|
375
|
-
end
|
|
376
401
|
|
|
377
|
-
|
|
378
|
-
|
|
402
|
+
# nuke any unused terms
|
|
403
|
+
clean_terms out if scan
|
|
379
404
|
|
|
380
|
-
|
|
405
|
+
out
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
env.transaction? &op
|
|
381
409
|
end
|
|
382
410
|
|
|
383
411
|
def clean_terms terms
|
|
384
412
|
terms.map! { |t| t.is_a?(RDF::Term) ? hash_term(t) : t.to_s }.uniq
|
|
385
|
-
|
|
413
|
+
env.transaction? do
|
|
386
414
|
terms.each do |hash|
|
|
387
415
|
next if hash == NULL_SHA256
|
|
388
|
-
next unless ib =
|
|
389
|
-
unless SPOG_MAP.values.any? {|d|
|
|
390
|
-
|
|
391
|
-
|
|
416
|
+
next unless ib = env[:hash2term].get(hash)
|
|
417
|
+
unless SPOG_MAP.values.any? {|d| env[d].get ib }
|
|
418
|
+
env[:int2term].delete? ib
|
|
419
|
+
env[:hash2term].delete? hash
|
|
392
420
|
end
|
|
393
421
|
end
|
|
394
422
|
end
|
|
@@ -399,32 +427,36 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
399
427
|
statement.incomplete?
|
|
400
428
|
end
|
|
401
429
|
|
|
402
|
-
def resolve_term candidate, cache:
|
|
430
|
+
def resolve_term candidate, cache: nil, write: true
|
|
431
|
+
cache ||= @icache
|
|
403
432
|
int = nil
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
433
|
+
|
|
434
|
+
term = env.transaction? do
|
|
435
|
+
case candidate
|
|
436
|
+
when nil then return
|
|
437
|
+
when Integer
|
|
438
|
+
int = candidate
|
|
439
|
+
return if int == 0
|
|
440
|
+
return cache[int] if cache[int]
|
|
441
|
+
str = [int].pack ?J
|
|
442
|
+
env[:int2term][str] or return
|
|
443
|
+
when String
|
|
444
|
+
int = candidate.unpack1 ?J
|
|
445
|
+
str = [int].pack ?J
|
|
446
|
+
if candidate == str
|
|
447
|
+
return if int == 0
|
|
448
|
+
return cache[int] if cache[int]
|
|
449
|
+
env[:int2term][str] or return
|
|
450
|
+
else
|
|
451
|
+
return if candidate == NULL_SHA256
|
|
452
|
+
str = env[:hash2term][candidate] or return
|
|
453
|
+
[:int2term][str] or return
|
|
454
|
+
int = str.unpack1 ?J
|
|
455
|
+
end
|
|
456
|
+
else
|
|
457
|
+
raise ArgumentError, 'not an integer or a string'
|
|
458
|
+
end
|
|
459
|
+
end
|
|
428
460
|
|
|
429
461
|
term.force_encoding 'utf-8'
|
|
430
462
|
|
|
@@ -433,22 +465,17 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
433
465
|
term
|
|
434
466
|
end
|
|
435
467
|
|
|
436
|
-
def
|
|
437
|
-
|
|
468
|
+
def resolve_terms string, cache: nil, write: true, hash: false
|
|
469
|
+
cache ||= @icache
|
|
470
|
+
# we create a sequence because they may be duplicate
|
|
438
471
|
seq = []
|
|
439
|
-
until string.empty?
|
|
440
|
-
seq << string.slice!(0, length)
|
|
441
|
-
end
|
|
442
|
-
seq
|
|
443
|
-
end
|
|
444
472
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
end.to_h
|
|
473
|
+
out = env.transaction? do
|
|
474
|
+
string.unpack('J*').each_with_object({}) do |i, h|
|
|
475
|
+
seq << i
|
|
476
|
+
h[i] ||= resolve_term(i, cache: cache, write: write)
|
|
477
|
+
end
|
|
478
|
+
end
|
|
452
479
|
|
|
453
480
|
# if we aren't returning a hash, make sure the result is
|
|
454
481
|
# returned in order
|
|
@@ -456,12 +483,12 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
456
483
|
end
|
|
457
484
|
|
|
458
485
|
def each_maybe_with_graph has_graph = false, &block
|
|
459
|
-
|
|
460
|
-
cache =
|
|
461
|
-
|
|
486
|
+
op = -> _ = nil do
|
|
487
|
+
cache = @icache
|
|
488
|
+
env[:statement].each do |spack, spo|
|
|
462
489
|
spo = resolve_terms spo, cache: cache, write: true
|
|
463
490
|
|
|
464
|
-
|
|
491
|
+
env[:stmt2g].each_value spack do |gpack|
|
|
465
492
|
gint = gpack.unpack1 ?J
|
|
466
493
|
# setting the default graph to zero seems like something
|
|
467
494
|
# i would do
|
|
@@ -472,11 +499,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
472
499
|
end
|
|
473
500
|
end
|
|
474
501
|
|
|
475
|
-
|
|
476
|
-
body.call
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
#@lmdb.active_txn ? body.call : @lmdb.transaction(true, &body)
|
|
502
|
+
env.transaction? true, &op
|
|
480
503
|
end
|
|
481
504
|
|
|
482
505
|
def check_triple_quad arg, name: :triple, quad: false
|
|
@@ -531,7 +554,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
531
554
|
ihash = thash.transform_values { |v| int_for v }
|
|
532
555
|
cache = thash.keys.map { |k| [ihash[k], thash[k]] }.to_h
|
|
533
556
|
|
|
534
|
-
|
|
557
|
+
op = -> _ = nil do
|
|
535
558
|
# if the graph is nonexistent there is nothing to show
|
|
536
559
|
return if thash[:graph_name] and !ihash[:graph_name]
|
|
537
560
|
|
|
@@ -542,17 +565,17 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
542
565
|
stmt = RDF::Statement.new(**thash)
|
|
543
566
|
sint = int_for(stmt) or return
|
|
544
567
|
spack = [sint].pack ?J
|
|
545
|
-
first =
|
|
568
|
+
first = env[:statement].get(spack) or return
|
|
546
569
|
|
|
547
570
|
# warn thash.inspect, ihash.inspect
|
|
548
571
|
|
|
549
572
|
# note
|
|
550
573
|
if gint = ihash[:graph_name]
|
|
551
574
|
gpack = [gint].pack ?J
|
|
552
|
-
return unless
|
|
575
|
+
return unless env[:stmt2g].has? spack, gpack
|
|
553
576
|
yield stmt
|
|
554
577
|
else
|
|
555
|
-
|
|
578
|
+
env[:stmt2g].each_value spack do |gpack|
|
|
556
579
|
# return if gpack.unpack1(?J) == 0
|
|
557
580
|
graph = resolve_term gpack, cache: cache, write: true
|
|
558
581
|
yield RDF::Statement.from(stmt, graph_name: graph)
|
|
@@ -562,18 +585,18 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
562
585
|
# if only a single component (e.g. :subject) is present then
|
|
563
586
|
# we only need to check (e.g.) :s2stmt.
|
|
564
587
|
pos = thash.keys.first
|
|
565
|
-
db =
|
|
588
|
+
db = env[SPOG_MAP[pos]]
|
|
566
589
|
ix = ihash[pos] or return # note ihash[pos] may be nil
|
|
567
590
|
anchor = [ix].pack ?J
|
|
568
591
|
return unless db.has? anchor
|
|
569
592
|
|
|
570
593
|
db.each_value anchor do |spack|
|
|
571
|
-
spo = resolve_terms
|
|
594
|
+
spo = resolve_terms env[:statement][spack],
|
|
572
595
|
cache: cache, write: true
|
|
573
596
|
if pos == :graph_name
|
|
574
597
|
yield RDF::Statement(*spo, graph_name: thash[:graph_name])
|
|
575
598
|
else
|
|
576
|
-
|
|
599
|
+
env[:stmt2g].each_value spack do |gpack|
|
|
577
600
|
gint = gpack.unpack1 ?J
|
|
578
601
|
graph = resolve_term gint, cache: cache, write: true
|
|
579
602
|
yield RDF::Statement(*spo, graph_name: graph)
|
|
@@ -582,7 +605,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
582
605
|
end
|
|
583
606
|
elsif thash.keys.count == 2 and thash[:graph_name]
|
|
584
607
|
pos = (thash.keys - [:graph_name]).first
|
|
585
|
-
db =
|
|
608
|
+
db = env[SPO_MAP[pos]]
|
|
586
609
|
ix = ihash[pos] or return
|
|
587
610
|
anchor = [ix].pack ?J
|
|
588
611
|
return unless db.has? anchor
|
|
@@ -590,10 +613,10 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
590
613
|
# warn "ix: #{ix} #{ihash.inspect} orr bug here?"
|
|
591
614
|
|
|
592
615
|
db.each_value anchor do |spack|
|
|
593
|
-
spo =
|
|
616
|
+
spo = env[:statement][spack]
|
|
594
617
|
# warn "node: #{spack.unpack1 ?J} spo: #{spo.unpack 'J*'}"
|
|
595
618
|
gpack = [ihash[:graph_name]].pack ?J
|
|
596
|
-
next unless
|
|
619
|
+
next unless env[:stmt2g].has? spack, gpack
|
|
597
620
|
spo = resolve_terms spo
|
|
598
621
|
yield RDF::Statement(*spo, graph_name: thash[:graph_name])
|
|
599
622
|
end
|
|
@@ -608,7 +631,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
608
631
|
(pr - thash.keys).empty? and ihash.values_at(*pr).none?(&:nil?)
|
|
609
632
|
end.map do |pr, _|
|
|
610
633
|
v = ihash.values_at(*pr).pack 'J2'
|
|
611
|
-
c =
|
|
634
|
+
c = env[PAIR_MAP[pr]].cardinality(v)
|
|
612
635
|
[c, pr]
|
|
613
636
|
end.sort do |a, b|
|
|
614
637
|
a.first <=> b.first
|
|
@@ -619,17 +642,17 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
619
642
|
cache: cache, write: true) if ihash[:graph_name]
|
|
620
643
|
|
|
621
644
|
ib = ihash.values_at(*pair).pack 'J2'
|
|
622
|
-
|
|
623
|
-
spo = resolve_terms
|
|
645
|
+
env[PAIR_MAP[pair]].each_value ib do |spack|
|
|
646
|
+
spo = resolve_terms env[:statement][spack],
|
|
624
647
|
cache: cache, write: true
|
|
625
648
|
|
|
626
649
|
if ihash[:graph_name]
|
|
627
650
|
# warn g, ihash.inspect
|
|
628
651
|
gpack = [ihash[:graph_name]].pack ?J
|
|
629
|
-
next unless
|
|
652
|
+
next unless env[:stmt2g].has? spack, gpack
|
|
630
653
|
yield RDF::Statement(*spo, graph_name: g)
|
|
631
654
|
else
|
|
632
|
-
|
|
655
|
+
env[:stmt2g].each_value spack do |gpack|
|
|
633
656
|
gint = gpack.unpack1 ?J
|
|
634
657
|
g = resolve_term gint, cache: cache, write: true
|
|
635
658
|
yield RDF::Statement(*spo, graph_name: g)
|
|
@@ -639,21 +662,14 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
639
662
|
end
|
|
640
663
|
end
|
|
641
664
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
# ret = nil
|
|
645
|
-
# @lmdb.transaction do
|
|
646
|
-
# ret = body.call
|
|
647
|
-
# end
|
|
648
|
-
|
|
649
|
-
# ret
|
|
665
|
+
env.transaction? true, &op
|
|
650
666
|
end
|
|
651
667
|
|
|
652
668
|
def log_mtime time = nil
|
|
653
669
|
time ||= Time.now in: ?Z
|
|
654
670
|
nsecs = time.utc.to_r
|
|
655
671
|
nsecs = (nsecs * 10**9).numerator
|
|
656
|
-
|
|
672
|
+
env.transaction? { env[:control]['mtime'] = [nsecs].pack ?q }
|
|
657
673
|
time
|
|
658
674
|
end
|
|
659
675
|
|
|
@@ -667,6 +683,8 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
667
683
|
raise ArgumentError, "Invalid transaction class #{@tx_class}" unless
|
|
668
684
|
@tx_class.is_a? Class and @tx_class <= DEFAULT_TX_CLASS
|
|
669
685
|
|
|
686
|
+
@icache = {}
|
|
687
|
+
|
|
670
688
|
init_lmdb dir, **options
|
|
671
689
|
super uri: uri, title: title, **options, &block
|
|
672
690
|
end
|
|
@@ -681,14 +699,13 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
681
699
|
:serializable
|
|
682
700
|
end
|
|
683
701
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
702
|
+
attr_reader :dir
|
|
703
|
+
|
|
704
|
+
alias_method :path, :dir
|
|
687
705
|
|
|
688
706
|
def clear
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
end
|
|
707
|
+
env.transaction? { env.databases.each { |db| env[db].clear } }
|
|
708
|
+
|
|
692
709
|
# we do not clear the main database; that nukes the sub-databases
|
|
693
710
|
# @lmdb.database.clear
|
|
694
711
|
end
|
|
@@ -698,7 +715,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
698
715
|
end
|
|
699
716
|
|
|
700
717
|
def close
|
|
701
|
-
|
|
718
|
+
env.close
|
|
702
719
|
end
|
|
703
720
|
|
|
704
721
|
# Return a {::Time} object representing when the store was last written.
|
|
@@ -706,7 +723,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
706
723
|
# @return [Time] said modification time
|
|
707
724
|
#
|
|
708
725
|
def mtime
|
|
709
|
-
if packed =
|
|
726
|
+
if packed = env[:control]['mtime']
|
|
710
727
|
nsecs = Rational(packed.unpack1(?q), 10 ** 9)
|
|
711
728
|
Time.at nsecs, in: ?Z
|
|
712
729
|
else
|
|
@@ -718,10 +735,9 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
718
735
|
|
|
719
736
|
def insert_statement statement
|
|
720
737
|
complete! statement
|
|
721
|
-
|
|
738
|
+
env.transaction? do |t|
|
|
722
739
|
add_one statement
|
|
723
740
|
log_mtime
|
|
724
|
-
t.commit # cargo cult?
|
|
725
741
|
end
|
|
726
742
|
nil
|
|
727
743
|
end
|
|
@@ -731,7 +747,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
731
747
|
# because we want the transaction on the outside.
|
|
732
748
|
complete! statement
|
|
733
749
|
# warn "WTF LOL #{statement.inspect}"
|
|
734
|
-
|
|
750
|
+
env.transaction? do |t|
|
|
735
751
|
if statement.variable?
|
|
736
752
|
query(statement).each { |stmt| rm_one stmt }
|
|
737
753
|
else
|
|
@@ -739,14 +755,12 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
739
755
|
end
|
|
740
756
|
|
|
741
757
|
log_mtime
|
|
742
|
-
|
|
743
|
-
t.commit
|
|
744
758
|
end
|
|
745
759
|
nil
|
|
746
760
|
end
|
|
747
761
|
|
|
748
762
|
def insert_statements statements
|
|
749
|
-
|
|
763
|
+
env.transaction? do
|
|
750
764
|
statements.each do |statement|
|
|
751
765
|
complete! statement
|
|
752
766
|
add_one statement
|
|
@@ -758,7 +772,7 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
758
772
|
end
|
|
759
773
|
|
|
760
774
|
def delete_statements statements
|
|
761
|
-
|
|
775
|
+
env.transaction? do
|
|
762
776
|
hashes = []
|
|
763
777
|
|
|
764
778
|
# we don't know what's in here but it may contain statements
|
|
@@ -781,8 +795,6 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
781
795
|
clean_terms hashes.uniq
|
|
782
796
|
|
|
783
797
|
log_mtime
|
|
784
|
-
|
|
785
|
-
t.commit
|
|
786
798
|
end
|
|
787
799
|
|
|
788
800
|
nil
|
|
@@ -791,82 +803,92 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
791
803
|
# data retrieval
|
|
792
804
|
|
|
793
805
|
def each &block
|
|
794
|
-
return enum_for :each unless
|
|
806
|
+
return enum_for :each unless block
|
|
795
807
|
|
|
796
808
|
each_maybe_with_graph(&block)
|
|
797
809
|
end
|
|
798
810
|
|
|
799
811
|
def each_subject &block
|
|
800
|
-
return enum_for :each_subject unless
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
812
|
+
return enum_for :each_subject unless block
|
|
813
|
+
env.transaction? true do
|
|
814
|
+
env[:s2stmt].cursor do |c|
|
|
815
|
+
while (k, _ = c.next true)
|
|
816
|
+
block.call(resolve_term k)
|
|
817
|
+
end
|
|
804
818
|
end
|
|
805
819
|
end
|
|
806
820
|
end
|
|
807
821
|
|
|
808
822
|
def each_predicate &block
|
|
809
|
-
return enum_for :each_predicate unless
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
823
|
+
return enum_for :each_predicate unless block
|
|
824
|
+
env.transaction? true do
|
|
825
|
+
env[:p2stmt].cursor do |c|
|
|
826
|
+
while (k, _ = c.next true)
|
|
827
|
+
block.call(resolve_term k)
|
|
828
|
+
end
|
|
813
829
|
end
|
|
814
830
|
end
|
|
815
831
|
end
|
|
816
832
|
|
|
817
833
|
def each_object &block
|
|
818
|
-
return enum_for :each_object unless
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
834
|
+
return enum_for :each_object unless block
|
|
835
|
+
|
|
836
|
+
env.transaction? true do
|
|
837
|
+
env[:o2stmt].cursor do |c|
|
|
838
|
+
while (k, _ = c.next true)
|
|
839
|
+
block.call(resolve_term k)
|
|
840
|
+
end
|
|
822
841
|
end
|
|
823
842
|
end
|
|
824
843
|
end
|
|
825
844
|
|
|
826
845
|
def each_graph &block
|
|
827
|
-
return enum_for :each_graph unless
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
846
|
+
return enum_for :each_graph unless block
|
|
847
|
+
|
|
848
|
+
env.transaction? true do
|
|
849
|
+
env[:g2stmt].cursor do |c|
|
|
850
|
+
while (k, _ = c.next true)
|
|
851
|
+
block.call RDF::Graph.new(graph_name: resolve_term(k), data: self)
|
|
852
|
+
end
|
|
831
853
|
end
|
|
832
854
|
end
|
|
833
855
|
end
|
|
834
856
|
|
|
835
857
|
def each_term &block
|
|
836
|
-
return enum_for :each_term unless
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
v.
|
|
841
|
-
|
|
858
|
+
return enum_for :each_term unless block
|
|
859
|
+
|
|
860
|
+
env.transaction? true do
|
|
861
|
+
env[:int2term].cursor do |c|
|
|
862
|
+
while (_, v = c.next)
|
|
863
|
+
# yield RDF::NTriples::Reader.unserialize v
|
|
864
|
+
v.force_encoding 'utf-8'
|
|
865
|
+
block.call RDF::NTriples::Reader.parse_object(v, intern: true)
|
|
866
|
+
end
|
|
842
867
|
end
|
|
843
868
|
end
|
|
844
869
|
end
|
|
845
870
|
|
|
846
871
|
def project_graph graph_name, &block
|
|
847
|
-
return enum_for :project_graph, graph_name unless
|
|
848
|
-
|
|
872
|
+
return enum_for :project_graph, graph_name unless block
|
|
873
|
+
|
|
874
|
+
op = -> _ = nil do
|
|
849
875
|
gint = graph_name ? int_for(graph_name) : 0
|
|
850
876
|
return unless gint
|
|
851
877
|
gpack = [gint].pack ?J
|
|
852
878
|
cache = {}
|
|
853
|
-
|
|
854
|
-
next unless
|
|
879
|
+
env[:statement].each do |spack, spo|
|
|
880
|
+
next unless env[:stmt2g].has? spack, gpack
|
|
855
881
|
spo = resolve_terms spo, cache: cache, write: true
|
|
856
882
|
|
|
857
883
|
block.call RDF::Statement(*spo, graph_name: graph_name)
|
|
858
884
|
end
|
|
859
885
|
end
|
|
860
886
|
|
|
861
|
-
|
|
862
|
-
body.call
|
|
863
|
-
end
|
|
864
|
-
|
|
865
|
-
#@lmdb.active_txn ? body.call : @lmdb.transaction(true, &body)
|
|
887
|
+
env.transaction? true, &op
|
|
866
888
|
end
|
|
867
889
|
|
|
868
890
|
def count
|
|
869
|
-
|
|
891
|
+
env[:stmt2g].size
|
|
870
892
|
end
|
|
871
893
|
|
|
872
894
|
def empty?
|
|
@@ -881,17 +903,17 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
881
903
|
|
|
882
904
|
def delete_insert deletes, inserts
|
|
883
905
|
ret = nil
|
|
884
|
-
|
|
906
|
+
ret = env.transaction? { super(deletes, inserts) }
|
|
885
907
|
commit_transaction # this is to satiate the test suite
|
|
886
908
|
ret
|
|
887
909
|
end
|
|
888
910
|
|
|
889
911
|
def env
|
|
890
|
-
@lmdb
|
|
912
|
+
(@lmdb ||= {})[Process.pid] ||= ::LMDB.new dir, @lmdb_opts
|
|
891
913
|
end
|
|
892
914
|
|
|
893
915
|
def transaction mutable: false, &block
|
|
894
|
-
return begin_transaction mutable: mutable unless
|
|
916
|
+
return begin_transaction mutable: mutable unless block
|
|
895
917
|
|
|
896
918
|
begin
|
|
897
919
|
begin_transaction mutable: mutable, &block
|
|
@@ -912,39 +934,61 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
912
934
|
def has_graph? graph_name
|
|
913
935
|
raise ArgumentError, 'graph_name must be an RDF::Term' unless
|
|
914
936
|
graph_name.is_a? RDF::Term
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
937
|
+
|
|
938
|
+
env.transaction? true do
|
|
939
|
+
if int = int_for(graph_name)
|
|
940
|
+
pack = [int].pack ?J
|
|
941
|
+
env[:g2stmt].has? pack
|
|
942
|
+
end
|
|
943
|
+
end
|
|
918
944
|
end
|
|
919
945
|
|
|
920
946
|
def has_subject? subject
|
|
921
947
|
raise ArgumentError, 'subject must be an RDF::Term' unless
|
|
922
948
|
subject.is_a? RDF::Term
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
949
|
+
|
|
950
|
+
env.transaction? true do
|
|
951
|
+
if int = int_for(subject)
|
|
952
|
+
pack = [int].pack ?J
|
|
953
|
+
# XXX fix this upstream
|
|
954
|
+
!!env[:s2stmt].has?(pack)
|
|
955
|
+
else
|
|
956
|
+
false
|
|
957
|
+
end
|
|
958
|
+
end
|
|
926
959
|
end
|
|
927
960
|
|
|
928
961
|
def has_predicate? predicate
|
|
929
962
|
raise ArgumentError, 'predicate must be an RDF::Term' unless
|
|
930
963
|
predicate.is_a? RDF::Term
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
964
|
+
|
|
965
|
+
env.transaction? true do
|
|
966
|
+
if int = int_for(predicate)
|
|
967
|
+
pack = [int].pack ?J
|
|
968
|
+
env[:p2stmt].has? pack
|
|
969
|
+
end
|
|
970
|
+
end
|
|
934
971
|
end
|
|
935
972
|
|
|
936
973
|
def has_object? object
|
|
937
974
|
raise ArgumentError, 'object must be an RDF::Term' unless
|
|
938
975
|
object.is_a? RDF::Term
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
976
|
+
|
|
977
|
+
env.transaction? true do
|
|
978
|
+
if int = int_for(object)
|
|
979
|
+
pack = [int].pack ?J
|
|
980
|
+
env[:o2stmt].has? pack
|
|
981
|
+
end
|
|
982
|
+
end
|
|
942
983
|
end
|
|
943
984
|
|
|
944
985
|
def has_term? term
|
|
945
986
|
raise ArgumentError, 'term must be an RDF::Term' unless
|
|
946
987
|
term.is_a? RDF::Term
|
|
947
|
-
|
|
988
|
+
|
|
989
|
+
env.transaction? true do
|
|
990
|
+
env[:hash2term].has? hash_term(term)
|
|
991
|
+
end
|
|
948
992
|
end
|
|
949
993
|
|
|
950
994
|
def has_triple? triple
|
|
@@ -955,7 +999,6 @@ Currently you have to dump from the old layout and reload the new one. Sorry!
|
|
|
955
999
|
has_statement? check_triple_quad quad, quad: true
|
|
956
1000
|
end
|
|
957
1001
|
|
|
958
|
-
|
|
959
1002
|
# lol, ruby
|
|
960
1003
|
end
|
|
961
1004
|
end
|
data/rdf-lmdb.gemspec
CHANGED
|
@@ -25,7 +25,7 @@ robust key-value store.
|
|
|
25
25
|
spec.require_paths = ["lib"]
|
|
26
26
|
|
|
27
27
|
# ruby
|
|
28
|
-
spec.required_ruby_version = '>= 2
|
|
28
|
+
spec.required_ruby_version = '>= 3.2'
|
|
29
29
|
|
|
30
30
|
# dev/test dependencies
|
|
31
31
|
spec.add_development_dependency 'bundler', '~> 2'
|
|
@@ -36,5 +36,5 @@ robust key-value store.
|
|
|
36
36
|
# stuff we use
|
|
37
37
|
spec.add_runtime_dependency 'unf', '~> 0.1'
|
|
38
38
|
spec.add_runtime_dependency 'rdf', '~> 3'
|
|
39
|
-
spec.add_runtime_dependency 'lmdb', '~> 0
|
|
39
|
+
spec.add_runtime_dependency 'lmdb', '~> 0', '>= 0.8.1'
|
|
40
40
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rdf-lmdb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dorian Taylor
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: bundler
|
|
@@ -99,20 +99,20 @@ dependencies:
|
|
|
99
99
|
requirements:
|
|
100
100
|
- - "~>"
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '0
|
|
102
|
+
version: '0'
|
|
103
103
|
- - ">="
|
|
104
104
|
- !ruby/object:Gem::Version
|
|
105
|
-
version: 0.
|
|
105
|
+
version: 0.8.1
|
|
106
106
|
type: :runtime
|
|
107
107
|
prerelease: false
|
|
108
108
|
version_requirements: !ruby/object:Gem::Requirement
|
|
109
109
|
requirements:
|
|
110
110
|
- - "~>"
|
|
111
111
|
- !ruby/object:Gem::Version
|
|
112
|
-
version: '0
|
|
112
|
+
version: '0'
|
|
113
113
|
- - ">="
|
|
114
114
|
- !ruby/object:Gem::Version
|
|
115
|
-
version: 0.
|
|
115
|
+
version: 0.8.1
|
|
116
116
|
description: |
|
|
117
117
|
This module implements RDF::Repository on top of LMDB, a fast and
|
|
118
118
|
robust key-value store.
|
|
@@ -147,14 +147,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
147
147
|
requirements:
|
|
148
148
|
- - ">="
|
|
149
149
|
- !ruby/object:Gem::Version
|
|
150
|
-
version: '2
|
|
150
|
+
version: '3.2'
|
|
151
151
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
152
|
requirements:
|
|
153
153
|
- - ">="
|
|
154
154
|
- !ruby/object:Gem::Version
|
|
155
155
|
version: '0'
|
|
156
156
|
requirements: []
|
|
157
|
-
rubygems_version: 3.6.
|
|
157
|
+
rubygems_version: 3.6.7
|
|
158
158
|
specification_version: 4
|
|
159
159
|
summary: Symas LMDB back-end for RDF::Repository
|
|
160
160
|
test_files: []
|