sparql 3.0.1 → 3.1.4
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/README.md +188 -73
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/bin/sparql +44 -24
- data/lib/rack/sparql.rb +1 -1
- data/lib/rack/sparql/conneg.rb +3 -3
- data/lib/sinatra/sparql.rb +5 -5
- data/lib/sparql.rb +17 -16
- data/lib/sparql/algebra.rb +15 -23
- data/lib/sparql/algebra/aggregate.rb +4 -4
- data/lib/sparql/algebra/evaluatable.rb +2 -2
- data/lib/sparql/algebra/expression.rb +63 -40
- data/lib/sparql/algebra/extensions.rb +180 -33
- data/lib/sparql/algebra/operator.rb +37 -16
- data/lib/sparql/algebra/operator/abs.rb +2 -2
- data/lib/sparql/algebra/operator/add.rb +3 -3
- data/lib/sparql/algebra/operator/alt.rb +4 -4
- data/lib/sparql/algebra/operator/and.rb +7 -7
- data/lib/sparql/algebra/operator/asc.rb +3 -3
- data/lib/sparql/algebra/operator/ask.rb +4 -14
- data/lib/sparql/algebra/operator/avg.rb +6 -4
- data/lib/sparql/algebra/operator/base.rb +10 -10
- data/lib/sparql/algebra/operator/bgp.rb +1 -1
- data/lib/sparql/algebra/operator/bnode.rb +5 -5
- data/lib/sparql/algebra/operator/bound.rb +3 -3
- data/lib/sparql/algebra/operator/ceil.rb +2 -2
- data/lib/sparql/algebra/operator/clear.rb +3 -3
- data/lib/sparql/algebra/operator/coalesce.rb +3 -13
- data/lib/sparql/algebra/operator/compare.rb +8 -8
- data/lib/sparql/algebra/operator/concat.rb +4 -4
- data/lib/sparql/algebra/operator/construct.rb +4 -14
- data/lib/sparql/algebra/operator/contains.rb +2 -2
- data/lib/sparql/algebra/operator/copy.rb +3 -3
- data/lib/sparql/algebra/operator/count.rb +3 -3
- data/lib/sparql/algebra/operator/create.rb +3 -3
- data/lib/sparql/algebra/operator/dataset.rb +6 -17
- data/lib/sparql/algebra/operator/datatype.rb +1 -1
- data/lib/sparql/algebra/operator/day.rb +1 -1
- data/lib/sparql/algebra/operator/delete.rb +9 -7
- data/lib/sparql/algebra/operator/delete_data.rb +3 -3
- data/lib/sparql/algebra/operator/delete_where.rb +6 -6
- data/lib/sparql/algebra/operator/desc.rb +1 -1
- data/lib/sparql/algebra/operator/describe.rb +3 -13
- data/lib/sparql/algebra/operator/distinct.rb +4 -14
- data/lib/sparql/algebra/operator/divide.rb +1 -1
- data/lib/sparql/algebra/operator/drop.rb +3 -3
- data/lib/sparql/algebra/operator/encode_for_uri.rb +3 -3
- data/lib/sparql/algebra/operator/equal.rb +2 -2
- data/lib/sparql/algebra/operator/exists.rb +5 -5
- data/lib/sparql/algebra/operator/exprlist.rb +3 -13
- data/lib/sparql/algebra/operator/extend.rb +19 -18
- data/lib/sparql/algebra/operator/filter.rb +6 -16
- data/lib/sparql/algebra/operator/floor.rb +2 -2
- data/lib/sparql/algebra/operator/graph.rb +6 -17
- data/lib/sparql/algebra/operator/greater_than.rb +5 -5
- data/lib/sparql/algebra/operator/greater_than_or_equal.rb +5 -5
- data/lib/sparql/algebra/operator/group.rb +25 -25
- data/lib/sparql/algebra/operator/group_concat.rb +6 -6
- data/lib/sparql/algebra/operator/hours.rb +1 -1
- data/lib/sparql/algebra/operator/if.rb +5 -15
- data/lib/sparql/algebra/operator/in.rb +4 -14
- data/lib/sparql/algebra/operator/insert.rb +7 -5
- data/lib/sparql/algebra/operator/insert_data.rb +3 -3
- data/lib/sparql/algebra/operator/iri.rb +1 -1
- data/lib/sparql/algebra/operator/is_blank.rb +1 -1
- data/lib/sparql/algebra/operator/is_iri.rb +1 -1
- data/lib/sparql/algebra/operator/is_literal.rb +1 -1
- data/lib/sparql/algebra/operator/is_numeric.rb +1 -1
- data/lib/sparql/algebra/operator/join.rb +12 -10
- data/lib/sparql/algebra/operator/lang.rb +1 -1
- data/lib/sparql/algebra/operator/lang_matches.rb +3 -3
- data/lib/sparql/algebra/operator/lcase.rb +2 -2
- data/lib/sparql/algebra/operator/left_join.rb +15 -12
- data/lib/sparql/algebra/operator/less_than.rb +5 -5
- data/lib/sparql/algebra/operator/less_than_or_equal.rb +5 -5
- data/lib/sparql/algebra/operator/load.rb +3 -3
- data/lib/sparql/algebra/operator/max.rb +6 -4
- data/lib/sparql/algebra/operator/md5.rb +1 -1
- data/lib/sparql/algebra/operator/min.rb +6 -4
- data/lib/sparql/algebra/operator/minus.rb +12 -11
- data/lib/sparql/algebra/operator/minutes.rb +1 -1
- data/lib/sparql/algebra/operator/modify.rb +4 -4
- data/lib/sparql/algebra/operator/month.rb +1 -1
- data/lib/sparql/algebra/operator/move.rb +3 -3
- data/lib/sparql/algebra/operator/multiply.rb +1 -1
- data/lib/sparql/algebra/operator/negate.rb +1 -1
- data/lib/sparql/algebra/operator/not.rb +1 -1
- data/lib/sparql/algebra/operator/not_equal.rb +2 -2
- data/lib/sparql/algebra/operator/notexists.rb +4 -4
- data/lib/sparql/algebra/operator/notin.rb +4 -14
- data/lib/sparql/algebra/operator/notoneof.rb +5 -6
- data/lib/sparql/algebra/operator/now.rb +1 -1
- data/lib/sparql/algebra/operator/or.rb +7 -7
- data/lib/sparql/algebra/operator/order.rb +6 -16
- data/lib/sparql/algebra/operator/path.rb +6 -5
- data/lib/sparql/algebra/operator/path_opt.rb +16 -16
- data/lib/sparql/algebra/operator/path_plus.rb +8 -8
- data/lib/sparql/algebra/operator/path_star.rb +4 -4
- data/lib/sparql/algebra/operator/plus.rb +3 -3
- data/lib/sparql/algebra/operator/prefix.rb +10 -10
- data/lib/sparql/algebra/operator/project.rb +4 -14
- data/lib/sparql/algebra/operator/rand.rb +1 -1
- data/lib/sparql/algebra/operator/reduced.rb +4 -14
- data/lib/sparql/algebra/operator/regex.rb +6 -6
- data/lib/sparql/algebra/operator/replace.rb +4 -4
- data/lib/sparql/algebra/operator/reverse.rb +4 -4
- data/lib/sparql/algebra/operator/round.rb +2 -2
- data/lib/sparql/algebra/operator/same_term.rb +8 -5
- data/lib/sparql/algebra/operator/sample.rb +3 -3
- data/lib/sparql/algebra/operator/seconds.rb +1 -1
- data/lib/sparql/algebra/operator/seq.rb +5 -6
- data/lib/sparql/algebra/operator/sequence.rb +4 -4
- data/lib/sparql/algebra/operator/sha1.rb +1 -1
- data/lib/sparql/algebra/operator/sha256.rb +1 -1
- data/lib/sparql/algebra/operator/sha384.rb +1 -1
- data/lib/sparql/algebra/operator/sha512.rb +1 -1
- data/lib/sparql/algebra/operator/slice.rb +4 -14
- data/lib/sparql/algebra/operator/str.rb +1 -1
- data/lib/sparql/algebra/operator/strafter.rb +2 -2
- data/lib/sparql/algebra/operator/strbefore.rb +2 -2
- data/lib/sparql/algebra/operator/strdt.rb +2 -2
- data/lib/sparql/algebra/operator/strends.rb +2 -2
- data/lib/sparql/algebra/operator/strlang.rb +2 -2
- data/lib/sparql/algebra/operator/strlen.rb +2 -2
- data/lib/sparql/algebra/operator/strstarts.rb +2 -2
- data/lib/sparql/algebra/operator/struuid.rb +1 -1
- data/lib/sparql/algebra/operator/substr.rb +4 -4
- data/lib/sparql/algebra/operator/subtract.rb +1 -1
- data/lib/sparql/algebra/operator/sum.rb +6 -4
- data/lib/sparql/algebra/operator/table.rb +3 -3
- data/lib/sparql/algebra/operator/timezone.rb +1 -1
- data/lib/sparql/algebra/operator/tz.rb +1 -1
- data/lib/sparql/algebra/operator/ucase.rb +2 -2
- data/lib/sparql/algebra/operator/union.rb +9 -8
- data/lib/sparql/algebra/operator/update.rb +4 -4
- data/lib/sparql/algebra/operator/using.rb +4 -4
- data/lib/sparql/algebra/operator/uuid.rb +1 -1
- data/lib/sparql/algebra/operator/with.rb +7 -7
- data/lib/sparql/algebra/operator/year.rb +1 -1
- data/lib/sparql/algebra/query.rb +2 -2
- data/lib/sparql/algebra/update.rb +2 -2
- data/lib/sparql/algebra/version.rb +1 -1
- data/lib/sparql/extensions.rb +5 -5
- data/lib/sparql/grammar.rb +111 -11
- data/lib/sparql/grammar/meta.rb +2340 -907
- data/lib/sparql/grammar/parser11.rb +69 -69
- data/lib/sparql/grammar/terminals11.rb +2 -0
- data/lib/sparql/results.rb +73 -46
- data/lib/sparql/version.rb +1 -1
- metadata +38 -65
@@ -4,7 +4,7 @@ require 'json'
|
|
4
4
|
# Extensions for Ruby's `NilClass` class.
|
5
5
|
class NilClass
|
6
6
|
|
7
|
-
def evaluate(bindings, options
|
7
|
+
def evaluate(bindings, **options)
|
8
8
|
self
|
9
9
|
end
|
10
10
|
|
@@ -27,6 +27,22 @@ class Object
|
|
27
27
|
def to_sse
|
28
28
|
SXP::Generator.string(self.to_sxp_bin)
|
29
29
|
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# A duplicate of this object.
|
33
|
+
#
|
34
|
+
# @return [Object] a copy of `self`
|
35
|
+
# @see SPARQL::Algebra::Expression#optimize
|
36
|
+
def optimize(**options)
|
37
|
+
self.deep_dup
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Default for deep_dup is shallow dup
|
42
|
+
# @return [Object]
|
43
|
+
def deep_dup
|
44
|
+
dup
|
45
|
+
end
|
30
46
|
end
|
31
47
|
|
32
48
|
##
|
@@ -53,8 +69,8 @@ class Array
|
|
53
69
|
# options passed from query
|
54
70
|
# @return [RDF::Term]
|
55
71
|
# @see SPARQL::Algebra::Expression.evaluate
|
56
|
-
def evaluate(bindings, options
|
57
|
-
SPARQL::Algebra::Expression.extension(*self.map {|o| o.evaluate(bindings, options)})
|
72
|
+
def evaluate(bindings, **options)
|
73
|
+
SPARQL::Algebra::Expression.extension(*self.map {|o| o.evaluate(bindings, **options)})
|
58
74
|
end
|
59
75
|
|
60
76
|
##
|
@@ -66,11 +82,34 @@ class Array
|
|
66
82
|
# @param [Hash{Symbol => Object}] options
|
67
83
|
# @raise [NotImplementedError]
|
68
84
|
# If an attempt is made to perform an unsupported operation
|
69
|
-
# @see
|
70
|
-
def execute(queryable, options
|
85
|
+
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
86
|
+
def execute(queryable, **options)
|
71
87
|
raise NotImplementedError, "SPARQL::Algebra '#{first}' operator not implemented"
|
72
88
|
end
|
73
89
|
|
90
|
+
##
|
91
|
+
# Return an optimized version of this array.
|
92
|
+
#
|
93
|
+
# @return [Array] a copy of `self`
|
94
|
+
# @see SPARQL::Algebra::Expression#optimize
|
95
|
+
def optimize(**options)
|
96
|
+
self.map do |op|
|
97
|
+
op.optimize(**options) if op.respond_to?(:optimize)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables
|
103
|
+
#
|
104
|
+
# @param [RDF::Query::Solution] solution
|
105
|
+
# @return [self]
|
106
|
+
def bind(solution)
|
107
|
+
map! do |op|
|
108
|
+
op.respond_to?(:bind) ? op.bind(solution) : op
|
109
|
+
end
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
74
113
|
##
|
75
114
|
# Returns `true` if any of the operands are variables, `false`
|
76
115
|
# otherwise.
|
@@ -78,7 +117,7 @@ class Array
|
|
78
117
|
# @return [Boolean] `true` or `false`
|
79
118
|
# @see #constant?
|
80
119
|
def variable?
|
81
|
-
any?(
|
120
|
+
any? {|op| op.respond_to?(:variable?) && op.variable?}
|
82
121
|
end
|
83
122
|
def constant?; !(variable?); end
|
84
123
|
|
@@ -166,6 +205,12 @@ class Array
|
|
166
205
|
each {|e| e.validate! if e.respond_to?(:validate!)}
|
167
206
|
self
|
168
207
|
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Deep duplicate
|
211
|
+
def deep_dup
|
212
|
+
map(&:deep_dup)
|
213
|
+
end
|
169
214
|
end
|
170
215
|
|
171
216
|
##
|
@@ -179,6 +224,21 @@ class Hash
|
|
179
224
|
to_a.to_sxp_bin
|
180
225
|
end
|
181
226
|
def to_sxp; to_sxp_bin; end
|
227
|
+
|
228
|
+
##
|
229
|
+
# A duplicate of this hash.
|
230
|
+
#
|
231
|
+
# @return [Hash] a copy of `self`
|
232
|
+
# @see SPARQL::Algebra::Expression#optimize
|
233
|
+
def optimize(**options)
|
234
|
+
self.deep_dup
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# Deep duplicate
|
239
|
+
def deep_dup
|
240
|
+
inject({}) {|memo, (k, v)| memo.merge(k => v.deep_dup)}
|
241
|
+
end
|
182
242
|
end
|
183
243
|
|
184
244
|
##
|
@@ -191,7 +251,7 @@ module RDF::Term
|
|
191
251
|
# @param [Hash{Symbol => Object}] options ({})
|
192
252
|
# options passed from query
|
193
253
|
# @return [RDF::Term]
|
194
|
-
def evaluate(bindings, options
|
254
|
+
def evaluate(bindings, **options)
|
195
255
|
self
|
196
256
|
end
|
197
257
|
|
@@ -210,8 +270,33 @@ module RDF::Term
|
|
210
270
|
def vars
|
211
271
|
variable? ? [self] : []
|
212
272
|
end
|
273
|
+
|
274
|
+
##
|
275
|
+
# A duplicate of this term.
|
276
|
+
#
|
277
|
+
# @return [RDF::Term] a copy of `self`
|
278
|
+
# @see SPARQL::Algebra::Expression#optimize
|
279
|
+
def optimize(**options)
|
280
|
+
optimized = self.deep_dup
|
281
|
+
optimized.lexical = nil if optimized.respond_to?(:lexical=)
|
282
|
+
optimized
|
283
|
+
end
|
213
284
|
end # RDF::Term
|
214
285
|
|
286
|
+
class RDF::Literal::Double
|
287
|
+
##
|
288
|
+
# Returns the SXP representation of this object.
|
289
|
+
#
|
290
|
+
# @return [String]
|
291
|
+
def to_sxp
|
292
|
+
case
|
293
|
+
when nan? then 'nan.0'
|
294
|
+
when infinite? then (infinite? > 0 ? '+inf.0' : '-inf.0')
|
295
|
+
else canonicalize.to_s.downcase
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
215
300
|
# Override RDF::Queryable to execute against SPARQL::Algebra::Query elements as well as RDF::Query and RDF::Pattern
|
216
301
|
module RDF::Queryable
|
217
302
|
alias_method :query_without_sparql, :query
|
@@ -243,7 +328,7 @@ module RDF::Queryable
|
|
243
328
|
solutions = if method(:query_execute).arity == 1
|
244
329
|
query_execute(pattern, &block)
|
245
330
|
else
|
246
|
-
query_execute(pattern, options, &block)
|
331
|
+
query_execute(pattern, **options, &block)
|
247
332
|
end
|
248
333
|
after_query(pattern) if respond_to?(:after_query)
|
249
334
|
|
@@ -252,25 +337,45 @@ module RDF::Queryable
|
|
252
337
|
solutions
|
253
338
|
else
|
254
339
|
# Return an enumerator
|
255
|
-
enum_for(:query, pattern, options)
|
340
|
+
enum_for(:query, pattern, **options)
|
256
341
|
end
|
257
342
|
else
|
258
|
-
query_without_sparql(pattern, options, &block)
|
343
|
+
query_without_sparql(pattern, **options, &block)
|
259
344
|
end
|
260
345
|
end
|
261
|
-
|
262
346
|
end
|
263
347
|
|
264
348
|
class RDF::Statement
|
265
349
|
# Transform Statement Pattern into an SXP
|
266
350
|
# @return [Array]
|
267
351
|
def to_sxp_bin
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
352
|
+
[ (has_graph? ? :quad : :triple),
|
353
|
+
(:inferred if inferred?),
|
354
|
+
subject,
|
355
|
+
predicate,
|
356
|
+
object,
|
357
|
+
graph_name
|
358
|
+
].compact.map(&:to_sxp_bin)
|
273
359
|
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# Returns an S-Expression (SXP) representation
|
363
|
+
#
|
364
|
+
# @return [String]
|
365
|
+
def to_sxp
|
366
|
+
to_sxp_bin.to_sxp
|
367
|
+
end
|
368
|
+
|
369
|
+
##
|
370
|
+
# A duplicate of this Statement.
|
371
|
+
#
|
372
|
+
# @return [RDF::Statement] a copy of `self`
|
373
|
+
# @see SPARQL::Algebra::Expression#optimize
|
374
|
+
def optimize(**options)
|
375
|
+
self.dup
|
376
|
+
end
|
377
|
+
|
378
|
+
def executable?; false; end
|
274
379
|
end
|
275
380
|
|
276
381
|
class RDF::Query
|
@@ -306,6 +411,16 @@ class RDF::Query
|
|
306
411
|
end
|
307
412
|
end
|
308
413
|
|
414
|
+
##
|
415
|
+
# Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables
|
416
|
+
#
|
417
|
+
# @param [RDF::Query::Solution] solution
|
418
|
+
# @return [self]
|
419
|
+
def bind(solution)
|
420
|
+
patterns.each {|p| p.bind(solution)}
|
421
|
+
self
|
422
|
+
end
|
423
|
+
|
309
424
|
# Query results in a boolean result (e.g., ASK)
|
310
425
|
# @return [Boolean]
|
311
426
|
def query_yields_boolean?
|
@@ -338,25 +453,34 @@ class RDF::Query
|
|
338
453
|
variables.values
|
339
454
|
end
|
340
455
|
|
456
|
+
alias_method :optimize_without_expression!, :optimize!
|
341
457
|
##
|
342
|
-
#
|
343
|
-
# otherwise.
|
458
|
+
# Optimize the query, removing lexical shortcuts in URIs
|
344
459
|
#
|
345
|
-
# @return [
|
460
|
+
# @return [self]
|
461
|
+
# @see SPARQL::Algebra::Expression#optimize!
|
462
|
+
def optimize!(**options)
|
463
|
+
@patterns = @patterns.map do |pattern|
|
464
|
+
components = pattern.to_quad.map do |term|
|
465
|
+
if term.respond_to?(:lexical=)
|
466
|
+
term.dup.instance_eval {@lexical = nil; self}
|
467
|
+
else
|
468
|
+
term
|
469
|
+
end
|
470
|
+
end
|
471
|
+
RDF::Query::Pattern.from(components, **pattern.options)
|
472
|
+
end
|
473
|
+
self.optimize_without_expression!(**options)
|
474
|
+
end
|
475
|
+
|
476
|
+
##
|
477
|
+
# Returns `true` as this is executable.
|
478
|
+
#
|
479
|
+
# @return [Boolean] `true`
|
346
480
|
def executable?; true; end
|
347
481
|
end
|
348
482
|
|
349
483
|
class RDF::Query::Pattern
|
350
|
-
# Transform Query Pattern into an SXP
|
351
|
-
# @return [Array]
|
352
|
-
def to_sxp_bin
|
353
|
-
if has_graph?
|
354
|
-
[:quad, subject, predicate, object, graph_name]
|
355
|
-
else
|
356
|
-
[:triple, subject, predicate, object]
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
484
|
##
|
361
485
|
# Return the non-destinguished variables contained within this pattern
|
362
486
|
# @return [Array<RDF::Query::Variable>]
|
@@ -370,6 +494,12 @@ class RDF::Query::Pattern
|
|
370
494
|
def vars
|
371
495
|
variables.values
|
372
496
|
end
|
497
|
+
|
498
|
+
##
|
499
|
+
# Returns `true` as this is executable.
|
500
|
+
#
|
501
|
+
# @return [Boolean] `true`
|
502
|
+
def executable?; true; end
|
373
503
|
end
|
374
504
|
|
375
505
|
##
|
@@ -386,14 +516,18 @@ class RDF::Query::Variable
|
|
386
516
|
# options passed from query
|
387
517
|
# @return [RDF::Term] the value of this variable
|
388
518
|
# @raise [TypeError] if the variable is not bound
|
389
|
-
def evaluate(bindings, options
|
519
|
+
def evaluate(bindings, **options)
|
390
520
|
raise TypeError if bindings.respond_to?(:bound?) && !bindings.bound?(self)
|
391
521
|
bindings[name.to_sym]
|
392
522
|
end
|
393
523
|
|
394
|
-
|
395
|
-
|
396
|
-
|
524
|
+
##
|
525
|
+
# Return self
|
526
|
+
#
|
527
|
+
# @return [RDF::Query::Variable] a copy of `self`
|
528
|
+
# @see SPARQL::Algebra::Expression#optimize
|
529
|
+
def optimize(**options)
|
530
|
+
self
|
397
531
|
end
|
398
532
|
end # RDF::Query::Variable
|
399
533
|
|
@@ -424,3 +558,16 @@ class RDF::Query::Solutions
|
|
424
558
|
end
|
425
559
|
alias_method :filter!, :filter
|
426
560
|
end # RDF::Query::Solutions
|
561
|
+
|
562
|
+
##
|
563
|
+
# Extensions for `RDF::Query::Solution`.
|
564
|
+
class RDF::Query::Solution
|
565
|
+
##
|
566
|
+
# Returns the SXP representation of this object, defaults to `self`.
|
567
|
+
#
|
568
|
+
# @return [String]
|
569
|
+
def to_sxp_bin
|
570
|
+
to_a.to_sxp_bin
|
571
|
+
end
|
572
|
+
def to_sxp; to_sxp_bin; end
|
573
|
+
end # RDF::Query::Solution
|
@@ -146,8 +146,6 @@ module SPARQL; module Algebra
|
|
146
146
|
autoload :Using, 'sparql/algebra/operator/using'
|
147
147
|
autoload :With, 'sparql/algebra/operator/with'
|
148
148
|
|
149
|
-
|
150
|
-
|
151
149
|
##
|
152
150
|
# Returns an operator class for the given operator `name`.
|
153
151
|
#
|
@@ -331,7 +329,7 @@ module SPARQL; module Algebra
|
|
331
329
|
# @overload initialize(*operands)
|
332
330
|
# @param [Array<RDF::Term>] operands
|
333
331
|
#
|
334
|
-
# @overload initialize(*operands, options)
|
332
|
+
# @overload initialize(*operands, **options)
|
335
333
|
# @param [Array<RDF::Term>] operands
|
336
334
|
# @param [Hash{Symbol => Object}] options
|
337
335
|
# any additional options
|
@@ -357,6 +355,22 @@ module SPARQL; module Algebra
|
|
357
355
|
end
|
358
356
|
end
|
359
357
|
|
358
|
+
##
|
359
|
+
# Deep duplicate operands
|
360
|
+
def deep_dup
|
361
|
+
self.class.new(*operands.map(&:deep_dup), @options)
|
362
|
+
end
|
363
|
+
|
364
|
+
##
|
365
|
+
# Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables
|
366
|
+
#
|
367
|
+
# @param [RDF::Query::Solution] solution
|
368
|
+
# @return [self]
|
369
|
+
def bind(solution)
|
370
|
+
@operands.each {|op| op.bind(solution)}
|
371
|
+
self
|
372
|
+
end
|
373
|
+
|
360
374
|
##
|
361
375
|
# Base URI used for reading data sources with relative URIs
|
362
376
|
#
|
@@ -434,7 +448,7 @@ module SPARQL; module Algebra
|
|
434
448
|
# @return [Boolean] `true` or `false`
|
435
449
|
# @see #constant?
|
436
450
|
def variable?
|
437
|
-
operands.any?(
|
451
|
+
operands.any? {|op| op.respond_to?(:variable?) && op.variable?}
|
438
452
|
end
|
439
453
|
|
440
454
|
##
|
@@ -491,23 +505,37 @@ module SPARQL; module Algebra
|
|
491
505
|
#
|
492
506
|
# For constant expressions containing no variables, returns the result
|
493
507
|
# of evaluating the expression with empty bindings; otherwise returns
|
494
|
-
# `self`.
|
508
|
+
# a copy of `self`.
|
495
509
|
#
|
496
510
|
# Optimization is not possible if the expression raises an exception,
|
497
511
|
# such as a `TypeError` or `ZeroDivisionError`, which must be conserved
|
498
512
|
# at runtime.
|
499
513
|
#
|
500
514
|
# @return [SPARQL::Algebra::Expression]
|
501
|
-
|
515
|
+
# @see RDF::Query#optimize
|
516
|
+
def optimize(**options)
|
502
517
|
if constant?
|
503
518
|
# Note that if evaluation results in a `TypeError` or other error,
|
504
519
|
# we must return `self` so that the error is conserved at runtime:
|
505
520
|
evaluate(RDF::Query::Solution.new) rescue self
|
506
521
|
else
|
507
|
-
super # returns `self`
|
522
|
+
super # returns a copy of `self`
|
508
523
|
end
|
509
524
|
end
|
510
525
|
|
526
|
+
##
|
527
|
+
# Optimizes this query by optimizing its constituent operands
|
528
|
+
# according to their cost estimates.
|
529
|
+
#
|
530
|
+
# @return [self]
|
531
|
+
# @see RDF::Query#optimize!
|
532
|
+
def optimize!(**options)
|
533
|
+
@operands.map! do |op|
|
534
|
+
op.optimize(**options) if op.respond_to?(:optimize)
|
535
|
+
end
|
536
|
+
self
|
537
|
+
end
|
538
|
+
|
511
539
|
##
|
512
540
|
# Rewrite operands by yielding each operand. Recursively descends
|
513
541
|
# through operands implementing this method.
|
@@ -532,7 +560,7 @@ module SPARQL; module Algebra
|
|
532
560
|
# Returns the SPARQL S-Expression (SSE) representation of this operator.
|
533
561
|
#
|
534
562
|
# @return [Array]
|
535
|
-
# @see
|
563
|
+
# @see https://openjena.org/wiki/SSE
|
536
564
|
def to_sxp_bin
|
537
565
|
operator = [self.class.const_get(:NAME)].flatten.first
|
538
566
|
[operator, *(operands || []).map(&:to_sxp_bin)]
|
@@ -543,13 +571,6 @@ module SPARQL; module Algebra
|
|
543
571
|
#
|
544
572
|
# @return [String]
|
545
573
|
def to_sxp
|
546
|
-
begin
|
547
|
-
require 'sxp' # @see http://rubygems.org/gems/sxp
|
548
|
-
rescue LoadError
|
549
|
-
abort "SPARQL::Algebra::Operator#to_sxp requires the SXP gem (hint: `gem install sxp')."
|
550
|
-
end
|
551
|
-
require 'sparql/algebra/sxp_extensions'
|
552
|
-
|
553
574
|
to_sxp_bin.to_sxp
|
554
575
|
end
|
555
576
|
|
@@ -647,7 +668,7 @@ module SPARQL; module Algebra
|
|
647
668
|
# @param [RDF::Literal] literal
|
648
669
|
# @return [RDF::Literal::Boolean] `true` or `false`
|
649
670
|
# @raise [TypeError] if the literal could not be coerced to an `RDF::Literal::Boolean`
|
650
|
-
# @see
|
671
|
+
# @see https://www.w3.org/TR/sparql11-query/#ebv
|
651
672
|
def boolean(literal)
|
652
673
|
case literal
|
653
674
|
when FalseClass then RDF::Literal::FALSE
|