sparql 3.1.6 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +31 -22
- data/VERSION +1 -1
- data/bin/sparql +14 -4
- data/lib/sparql/algebra/aggregate.rb +1 -1
- data/lib/sparql/algebra/evaluatable.rb +4 -4
- data/lib/sparql/algebra/expression.rb +28 -3
- data/lib/sparql/algebra/extensions.rb +109 -45
- data/lib/sparql/algebra/operator/abs.rb +23 -3
- data/lib/sparql/algebra/operator/add.rb +21 -2
- data/lib/sparql/algebra/operator/alt.rb +26 -2
- data/lib/sparql/algebra/operator/and.rb +25 -3
- data/lib/sparql/algebra/operator/asc.rb +20 -1
- data/lib/sparql/algebra/operator/ask.rb +17 -1
- data/lib/sparql/algebra/operator/avg.rb +20 -2
- data/lib/sparql/algebra/operator/base.rb +18 -1
- data/lib/sparql/algebra/operator/bgp.rb +13 -1
- data/lib/sparql/algebra/operator/bnode.rb +34 -11
- data/lib/sparql/algebra/operator/bound.rb +22 -1
- data/lib/sparql/algebra/operator/ceil.rb +26 -3
- data/lib/sparql/algebra/operator/clear.rb +26 -2
- data/lib/sparql/algebra/operator/coalesce.rb +33 -11
- data/lib/sparql/algebra/operator/compare.rb +48 -40
- data/lib/sparql/algebra/operator/concat.rb +26 -2
- data/lib/sparql/algebra/operator/construct.rb +29 -6
- data/lib/sparql/algebra/operator/contains.rb +25 -3
- data/lib/sparql/algebra/operator/copy.rb +19 -2
- data/lib/sparql/algebra/operator/count.rb +53 -7
- data/lib/sparql/algebra/operator/create.rb +20 -2
- data/lib/sparql/algebra/operator/dataset.rb +27 -2
- data/lib/sparql/algebra/operator/datatype.rb +26 -7
- data/lib/sparql/algebra/operator/day.rb +24 -6
- data/lib/sparql/algebra/operator/delete.rb +29 -2
- data/lib/sparql/algebra/operator/delete_data.rb +23 -2
- data/lib/sparql/algebra/operator/delete_where.rb +24 -2
- data/lib/sparql/algebra/operator/desc.rb +20 -1
- data/lib/sparql/algebra/operator/describe.rb +27 -4
- data/lib/sparql/algebra/operator/distinct.rb +20 -3
- data/lib/sparql/algebra/operator/divide.rb +27 -3
- data/lib/sparql/algebra/operator/drop.rb +27 -3
- data/lib/sparql/algebra/operator/encode_for_uri.rb +23 -3
- data/lib/sparql/algebra/operator/equal.rb +13 -3
- data/lib/sparql/algebra/operator/exists.rb +28 -4
- data/lib/sparql/algebra/operator/exprlist.rb +15 -2
- data/lib/sparql/algebra/operator/extend.rb +64 -6
- data/lib/sparql/algebra/operator/filter.rb +27 -5
- data/lib/sparql/algebra/operator/floor.rb +26 -3
- data/lib/sparql/algebra/operator/function_call.rb +64 -0
- data/lib/sparql/algebra/operator/graph.rb +69 -6
- data/lib/sparql/algebra/operator/greater_than.rb +14 -4
- data/lib/sparql/algebra/operator/greater_than_or_equal.rb +14 -4
- data/lib/sparql/algebra/operator/group.rb +105 -8
- data/lib/sparql/algebra/operator/group_concat.rb +44 -8
- data/lib/sparql/algebra/operator/hours.rb +24 -6
- data/lib/sparql/algebra/operator/if.rb +20 -3
- data/lib/sparql/algebra/operator/in.rb +18 -1
- data/lib/sparql/algebra/operator/insert.rb +24 -2
- data/lib/sparql/algebra/operator/insert_data.rb +23 -2
- data/lib/sparql/algebra/operator/iri.rb +22 -5
- data/lib/sparql/algebra/operator/is_blank.rb +21 -4
- data/lib/sparql/algebra/operator/is_iri.rb +21 -4
- data/lib/sparql/algebra/operator/is_literal.rb +21 -4
- data/lib/sparql/algebra/operator/is_numeric.rb +23 -6
- data/lib/sparql/algebra/operator/is_triple.rb +33 -1
- data/lib/sparql/algebra/operator/join.rb +56 -1
- data/lib/sparql/algebra/operator/lang.rb +26 -1
- data/lib/sparql/algebra/operator/lang_matches.rb +23 -2
- data/lib/sparql/algebra/operator/lcase.rb +23 -3
- data/lib/sparql/algebra/operator/left_join.rb +42 -1
- data/lib/sparql/algebra/operator/less_than.rb +14 -4
- data/lib/sparql/algebra/operator/less_than_or_equal.rb +14 -4
- data/lib/sparql/algebra/operator/load.rb +25 -2
- data/lib/sparql/algebra/operator/max.rb +20 -2
- data/lib/sparql/algebra/operator/md5.rb +23 -6
- data/lib/sparql/algebra/operator/min.rb +22 -4
- data/lib/sparql/algebra/operator/minus.rb +65 -7
- data/lib/sparql/algebra/operator/minutes.rb +24 -6
- data/lib/sparql/algebra/operator/modify.rb +41 -5
- data/lib/sparql/algebra/operator/month.rb +24 -6
- data/lib/sparql/algebra/operator/move.rb +20 -2
- data/lib/sparql/algebra/operator/multiply.rb +27 -4
- data/lib/sparql/algebra/operator/negate.rb +24 -4
- data/lib/sparql/algebra/operator/not.rb +25 -4
- data/lib/sparql/algebra/operator/not_equal.rb +16 -1
- data/lib/sparql/algebra/operator/notexists.rb +30 -6
- data/lib/sparql/algebra/operator/notin.rb +20 -3
- data/lib/sparql/algebra/operator/notoneof.rb +21 -2
- data/lib/sparql/algebra/operator/now.rb +25 -6
- data/lib/sparql/algebra/operator/object.rb +33 -1
- data/lib/sparql/algebra/operator/or.rb +26 -3
- data/lib/sparql/algebra/operator/order.rb +71 -2
- data/lib/sparql/algebra/operator/path.rb +29 -2
- data/lib/sparql/algebra/operator/path_opt.rb +21 -2
- data/lib/sparql/algebra/operator/path_plus.rb +21 -2
- data/lib/sparql/algebra/operator/path_star.rb +20 -2
- data/lib/sparql/algebra/operator/plus.rb +43 -4
- data/lib/sparql/algebra/operator/predicate.rb +33 -1
- data/lib/sparql/algebra/operator/prefix.rb +24 -3
- data/lib/sparql/algebra/operator/project.rb +69 -5
- data/lib/sparql/algebra/operator/rand.rb +31 -3
- data/lib/sparql/algebra/operator/reduced.rb +20 -3
- data/lib/sparql/algebra/operator/regex.rb +27 -19
- data/lib/sparql/algebra/operator/replace.rb +27 -7
- data/lib/sparql/algebra/operator/reverse.rb +31 -2
- data/lib/sparql/algebra/operator/round.rb +26 -3
- data/lib/sparql/algebra/operator/same_term.rb +25 -7
- data/lib/sparql/algebra/operator/sample.rb +33 -9
- data/lib/sparql/algebra/operator/seconds.rb +24 -6
- data/lib/sparql/algebra/operator/seq.rb +20 -2
- data/lib/sparql/algebra/operator/sequence.rb +4 -11
- data/lib/sparql/algebra/operator/sha1.rb +19 -2
- data/lib/sparql/algebra/operator/sha256.rb +19 -2
- data/lib/sparql/algebra/operator/sha384.rb +19 -2
- data/lib/sparql/algebra/operator/sha512.rb +19 -2
- data/lib/sparql/algebra/operator/slice.rb +27 -5
- data/lib/sparql/algebra/operator/str.rb +22 -2
- data/lib/sparql/algebra/operator/strafter.rb +26 -3
- data/lib/sparql/algebra/operator/strbefore.rb +26 -3
- data/lib/sparql/algebra/operator/strdt.rb +23 -2
- data/lib/sparql/algebra/operator/strends.rb +26 -4
- data/lib/sparql/algebra/operator/strlang.rb +25 -7
- data/lib/sparql/algebra/operator/strlen.rb +24 -3
- data/lib/sparql/algebra/operator/strstarts.rb +26 -3
- data/lib/sparql/algebra/operator/struuid.rb +30 -10
- data/lib/sparql/algebra/operator/subject.rb +33 -1
- data/lib/sparql/algebra/operator/substr.rb +24 -3
- data/lib/sparql/algebra/operator/subtract.rb +29 -3
- data/lib/sparql/algebra/operator/sum.rb +25 -7
- data/lib/sparql/algebra/operator/table.rb +76 -4
- data/lib/sparql/algebra/operator/timezone.rb +24 -6
- data/lib/sparql/algebra/operator/tz.rb +23 -6
- data/lib/sparql/algebra/operator/ucase.rb +24 -3
- data/lib/sparql/algebra/operator/union.rb +29 -6
- data/lib/sparql/algebra/operator/update.rb +46 -4
- data/lib/sparql/algebra/operator/using.rb +49 -2
- data/lib/sparql/algebra/operator/uuid.rb +28 -9
- data/lib/sparql/algebra/operator/with.rb +38 -4
- data/lib/sparql/algebra/operator/year.rb +24 -6
- data/lib/sparql/algebra/operator.rb +135 -14
- data/lib/sparql/algebra/sxp_extensions.rb +3 -3
- data/lib/sparql/algebra.rb +20 -3
- data/lib/sparql/grammar/meta.rb +1103 -907
- data/lib/sparql/grammar/parser11.rb +63 -56
- metadata +43 -29
- data/lib/sparql/algebra/operator/triple.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9bcab10eb6706316b68b44a0fd917d7b735b18a8353b51e49ef124fc966176d
|
4
|
+
data.tar.gz: 6da59b4e90fd1b7a7d80c42d941f7c27f6bf95892d17302caf16a13809b03afa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2f99aee7d5b9482bbd653333eeefd215da872291993a2ba138ed9bcfc3f92812672cd1508dfbd11a729d527c9724f0a80ec816c5c84fd2df9933b4b91b5a296
|
7
|
+
data.tar.gz: 41a11caf8e85ca4bd01213bb0c0c236314560338dbd2825bd2437afbf4fd9855b994150737dbcad00838dc5ac50e368d72e5bfe2e516566a6319f824bdcacc56
|
data/README.md
CHANGED
@@ -23,8 +23,7 @@ This is a [Ruby][] implementation of [SPARQL][] for [RDF.rb][].
|
|
23
23
|
* Compatible with any [Rack][] or [Sinatra][] application and any Rack-based framework.
|
24
24
|
* Helper method for describing [SPARQL Service Description][SSD]
|
25
25
|
* Implementation Report: {file:etc/earl.html EARL}
|
26
|
-
* Compatible with Ruby >= 2.
|
27
|
-
* Compatible with older Ruby versions with the help of the [Backports][] gem.
|
26
|
+
* Compatible with Ruby >= 2.6.
|
28
27
|
* Supports Unicode query strings both on all versions of Ruby.
|
29
28
|
* Provisional support for [SPARQL-star][].
|
30
29
|
|
@@ -248,27 +247,27 @@ a full set of RDF formats.
|
|
248
247
|
### Querying a repository with a SPARQL query
|
249
248
|
|
250
249
|
queryable = RDF::Repository.load("etc/doap.ttl")
|
251
|
-
|
252
|
-
queryable.query(
|
250
|
+
query = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
|
251
|
+
queryable.query(query) do |result|
|
253
252
|
result.inspect
|
254
253
|
end
|
255
254
|
|
256
255
|
### Executing a SPARQL query against a repository
|
257
256
|
|
258
257
|
queryable = RDF::Repository.load("etc/doap.ttl")
|
259
|
-
|
260
|
-
|
258
|
+
query = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
|
259
|
+
query.execute(queryable) do |result|
|
261
260
|
result.inspect
|
262
261
|
end
|
263
262
|
|
264
263
|
### Updating a repository
|
265
264
|
|
266
265
|
queryable = RDF::Repository.load("etc/doap.ttl")
|
267
|
-
|
266
|
+
update = SPARQL.parse(%(
|
268
267
|
PREFIX doap: <http://usefulinc.com/ns/doap#>
|
269
268
|
INSERT DATA { <https://rubygems> doap:implements <http://www.w3.org/TR/sparql11-update/>}
|
270
269
|
), update: true)
|
271
|
-
|
270
|
+
update.execute(queryable)
|
272
271
|
|
273
272
|
### Rendering solutions as JSON, XML, CSV, TSV or HTML
|
274
273
|
queryable = RDF::Repository.load("etc/doap.ttl")
|
@@ -277,8 +276,15 @@ a full set of RDF formats.
|
|
277
276
|
|
278
277
|
### Parsing a SPARQL query string to SSE
|
279
278
|
|
280
|
-
|
281
|
-
|
279
|
+
query = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
|
280
|
+
query.to_sxp #=> (bgp (triple ?s ?p ?o))
|
281
|
+
|
282
|
+
### Parsing a SSE to SPARQL query or update string to SPARQL
|
283
|
+
|
284
|
+
# Note: if the SSE uses extension functions, they either must be XSD casting functions, or custom functions which are registered extensions. (See [SPARQL Extension Functions](#sparql-extension-functions))
|
285
|
+
|
286
|
+
query = SPARQL::Algebra.parse(%{(bgp (triple ?s ?p ?o))})
|
287
|
+
sparql = query.to_sparql #=> "SELECT * WHERE { ?s ?p ?o }"
|
282
288
|
|
283
289
|
### Command line processing
|
284
290
|
|
@@ -289,6 +295,10 @@ a full set of RDF formats.
|
|
289
295
|
sparql parse etc/input.rq
|
290
296
|
sparql parse -e "SELECT * WHERE { ?s ?p ?o }"
|
291
297
|
|
298
|
+
# Generate SPARQL Query from SSE
|
299
|
+
sparql parse --sse etc/input.sse --format sparql
|
300
|
+
sparql parse --sse --format sparql -e "(dataset (<http://usefulinc.com/ns/doap>) (bgp (triple ?s ?p ?o))))"
|
301
|
+
|
292
302
|
# Run query using SSE input
|
293
303
|
sparql execute --dataset etc/doap.ttl --sse etc/input.sse
|
294
304
|
sparql execute --sse -e "(dataset (<etc/doap.ttl>) (bgp (triple ?s ?p ?o))))"
|
@@ -368,19 +378,19 @@ Full documentation available on [Rubydoc.info][SPARQL doc]
|
|
368
378
|
|
369
379
|
## Dependencies
|
370
380
|
|
371
|
-
* [Ruby](https://ruby-lang.org/) (>= 2.
|
372
|
-
* [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.
|
373
|
-
* [SPARQL::Client](https://rubygems.org/gems/sparql-client) (~> 3.
|
374
|
-
* [SXP](https://rubygems.org/gems/sxp) (~> 1.
|
375
|
-
* [Builder](https://rubygems.org/gems/builder) (
|
376
|
-
* [JSON](https://rubygems.org/gems/json) (
|
377
|
-
* Soft dependency on [Linked Data][] (>= 3.
|
378
|
-
* Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (
|
381
|
+
* [Ruby](https://ruby-lang.org/) (>= 2.6)
|
382
|
+
* [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.2)
|
383
|
+
* [SPARQL::Client](https://rubygems.org/gems/sparql-client) (~> 3.1)
|
384
|
+
* [SXP](https://rubygems.org/gems/sxp) (~> 1.2)
|
385
|
+
* [Builder](https://rubygems.org/gems/builder) (~> 3.2)
|
386
|
+
* [JSON](https://rubygems.org/gems/json) (~> 2.6)
|
387
|
+
* Soft dependency on [Linked Data][] (>= 3.1)
|
388
|
+
* Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (~> 1.12)
|
379
389
|
Falls back to REXML for XML parsing Builder for XML serializing. Nokogiri is much more efficient
|
380
|
-
* Soft dependency on [Equivalent XML](https://rubygems.org/gems/equivalent-xml) (>= 0.
|
390
|
+
* Soft dependency on [Equivalent XML](https://rubygems.org/gems/equivalent-xml) (>= 0.6)
|
381
391
|
Equivalent XML performs more efficient comparisons of XML Literals when Nokogiri is included
|
382
|
-
* Soft dependency on [Rack][] (
|
383
|
-
* Soft dependency on [Sinatra][] (
|
392
|
+
* Soft dependency on [Rack][] (~> 2.2)
|
393
|
+
* Soft dependency on [Sinatra][] (~> 2.1)
|
384
394
|
|
385
395
|
## Installation
|
386
396
|
|
@@ -450,7 +460,6 @@ A copy of the [SPARQL 1.0 tests][] and [SPARQL 1.1 tests][] are also included in
|
|
450
460
|
[RDF.rb]: https://rubydoc.info/github/ruby-rdf/rdf
|
451
461
|
[RDF-star]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html
|
452
462
|
[SPARQL-star]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#sparql-query-language
|
453
|
-
[Backports]: https://rubygems.org/gems/backports
|
454
463
|
[Linked Data]: https://rubygems.org/gems/linkeddata
|
455
464
|
[SPARQL doc]: https://rubydoc.info/github/ruby-rdf/sparql/frames
|
456
465
|
[SPARQL XML]: https://www.w3.org/TR/rdf-sparql-XMLres/
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1
|
1
|
+
3.2.1
|
data/bin/sparql
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'rubygems'
|
3
3
|
$:.unshift("../../lib", __FILE__)
|
4
|
+
require 'logger'
|
4
5
|
require 'sparql'
|
5
6
|
begin
|
6
7
|
require 'linkeddata'
|
@@ -44,9 +45,18 @@ def run(input, **options)
|
|
44
45
|
SPARQL::Grammar.parse(input, **options)
|
45
46
|
end
|
46
47
|
|
47
|
-
puts ("\nSSE:\n" + query.to_sse) if options[:debug]
|
48
|
+
puts ("\nSSE:\n" + query.to_sse) if options[:debug]
|
48
49
|
|
49
|
-
|
50
|
+
if options[:parse_only]
|
51
|
+
case options[:format]
|
52
|
+
when :sparql
|
53
|
+
puts ("\nSPARQL:\n" + query.to_sparql)
|
54
|
+
when nil, :sse
|
55
|
+
puts ("\nSSE:\n" + query.to_sse)
|
56
|
+
else
|
57
|
+
$stderr.puts "Unknown output format for parsing: #{options[:format]}. Use 'sse' or 'sparql'"
|
58
|
+
end
|
59
|
+
else
|
50
60
|
res = query.execute(options[:dataset], logger: options[:logger])
|
51
61
|
display_results(res, **options)
|
52
62
|
end
|
@@ -97,7 +107,7 @@ def usage
|
|
97
107
|
puts " --dataset: File containing RDF graph or dataset"
|
98
108
|
puts " --debug: Display detailed debug output"
|
99
109
|
puts " --execute,-e: Use option argument as the SPARQL input if no query-file given"
|
100
|
-
puts " --format: Output format for results"
|
110
|
+
puts " --format: Output format for results (json, xml, csv, tsv, html, sparql, sse, or another RDF format)"
|
101
111
|
puts " --port,-p Port on which to run server; defaults to 9292"
|
102
112
|
puts " --sse: Query input is in SSE format"
|
103
113
|
puts " --update: Process query as a SPARQL Update"
|
@@ -150,7 +160,7 @@ end
|
|
150
160
|
|
151
161
|
case cmd
|
152
162
|
when 'execute', 'parse'
|
153
|
-
options[:
|
163
|
+
options[:parse_only] = true if cmd == 'parse'
|
154
164
|
input ||= ARGV.empty? ? $stdin.read : RDF::Util::File.open_file(ARGV.first).read
|
155
165
|
run(input, **options)
|
156
166
|
when 'query'
|
@@ -44,7 +44,7 @@ module SPARQL; module Algebra
|
|
44
44
|
# Enumerable yielding evaluated operands
|
45
45
|
# @return [RDF::Term]
|
46
46
|
# @abstract
|
47
|
-
def apply(enum)
|
47
|
+
def apply(enum, **options)
|
48
48
|
raise NotImplementedError, "#{self.class}#apply(#{operands.map(&:class).join(', ')})"
|
49
49
|
end
|
50
50
|
|
@@ -15,16 +15,16 @@ module SPARQL; module Algebra
|
|
15
15
|
# @abstract
|
16
16
|
def evaluate(bindings, **options)
|
17
17
|
args = operands.map { |operand| operand.evaluate(bindings, depth: options[:depth].to_i + 1, **options) }
|
18
|
-
options[:memoize] ? memoize(*args) : apply(*args)
|
18
|
+
options[:memoize] ? memoize(*args, **options) : apply(*args, **options)
|
19
19
|
end
|
20
20
|
|
21
21
|
##
|
22
22
|
# @param [Array<RDF::Term>] operands
|
23
23
|
# evaluated operands
|
24
24
|
# @return [RDF::Term] the memoized result
|
25
|
-
def memoize(*operands)
|
25
|
+
def memoize(*operands, **options)
|
26
26
|
@cache ||= RDF::Util::Cache.new(options[:memoize].is_a?(Integer) ? options[:memoize] : -1)
|
27
|
-
@cache[operands] ||= apply(*operands)
|
27
|
+
@cache[operands] ||= apply(*operands, **options)
|
28
28
|
end
|
29
29
|
|
30
30
|
##
|
@@ -32,7 +32,7 @@ module SPARQL; module Algebra
|
|
32
32
|
# evaluated operands
|
33
33
|
# @return [RDF::Term]
|
34
34
|
# @abstract
|
35
|
-
def apply(*operands)
|
35
|
+
def apply(*operands, **options)
|
36
36
|
raise NotImplementedError, "#{self.class}#apply(#{operands.map(&:class).join(', ')})"
|
37
37
|
end
|
38
38
|
|
@@ -66,9 +66,11 @@ module SPARQL; module Algebra
|
|
66
66
|
#
|
67
67
|
# @param [Array] sse
|
68
68
|
# a SPARQL S-Expression (SSE) form
|
69
|
+
# @param [Hash{Symbol => Object}] options
|
70
|
+
# any additional options (see {Operator#initialize})
|
69
71
|
# @return [Expression]
|
70
|
-
def self.for(*sse)
|
71
|
-
self.new(sse)
|
72
|
+
def self.for(*sse, **options)
|
73
|
+
self.new(sse, **options)
|
72
74
|
end
|
73
75
|
class << self; alias_method :[], :for; end
|
74
76
|
|
@@ -86,6 +88,13 @@ module SPARQL; module Algebra
|
|
86
88
|
raise ArgumentError, "invalid SPARQL::Algebra::Expression form: #{sse.inspect}" unless sse.is_a?(Array)
|
87
89
|
|
88
90
|
operator = Operator.for(sse.first, sse.length - 1)
|
91
|
+
|
92
|
+
# If we don't find an operator, and sse.first is an extension IRI, use a function call
|
93
|
+
if !operator && sse.first.is_a?(RDF::URI) && self.extension?(sse.first)
|
94
|
+
operator = Operator.for(:function_call, sse.length)
|
95
|
+
sse.unshift(:function_call)
|
96
|
+
end
|
97
|
+
|
89
98
|
unless operator
|
90
99
|
return case sse.first
|
91
100
|
when Array
|
@@ -115,11 +124,16 @@ module SPARQL; module Algebra
|
|
115
124
|
end
|
116
125
|
|
117
126
|
debug(options) {"#{operator.inspect}(#{operands.map(&:inspect).join(',')})"}
|
127
|
+
logger = options[:logger]
|
118
128
|
options.delete_if {|k, v| [:debug, :logger, :depth, :prefixes, :base_uri, :update, :validate].include?(k) }
|
119
129
|
begin
|
120
130
|
operator.new(*operands, **options)
|
121
131
|
rescue ArgumentError => e
|
122
|
-
|
132
|
+
if logger
|
133
|
+
logger.error("Operator=#{operator.inspect}: #{e}")
|
134
|
+
else
|
135
|
+
raise "Operator=#{operator.inspect}: #{e}"
|
136
|
+
end
|
123
137
|
end
|
124
138
|
end
|
125
139
|
|
@@ -163,6 +177,17 @@ module SPARQL; module Algebra
|
|
163
177
|
@extensions ||= {}
|
164
178
|
end
|
165
179
|
|
180
|
+
##
|
181
|
+
# Is an extension function available?
|
182
|
+
#
|
183
|
+
# It's either a registered extension, or an XSD casting function
|
184
|
+
#
|
185
|
+
# @param [RDF::URI] function
|
186
|
+
# @return [Boolean]
|
187
|
+
def self.extension?(function)
|
188
|
+
function.to_s.start_with?(RDF::XSD.to_s) || self.extensions[function]
|
189
|
+
end
|
190
|
+
|
166
191
|
##
|
167
192
|
# Invoke an extension function.
|
168
193
|
#
|
@@ -43,6 +43,15 @@ class Object
|
|
43
43
|
def deep_dup
|
44
44
|
dup
|
45
45
|
end
|
46
|
+
|
47
|
+
##
|
48
|
+
#
|
49
|
+
# Returns a partial SPARQL grammar for this term.
|
50
|
+
#
|
51
|
+
# @return [String]
|
52
|
+
def to_sparql(**options)
|
53
|
+
to_sxp(**options)
|
54
|
+
end
|
46
55
|
end
|
47
56
|
|
48
57
|
##
|
@@ -57,20 +66,14 @@ class Array
|
|
57
66
|
end
|
58
67
|
|
59
68
|
##
|
60
|
-
# Evaluates the array using the given variable `bindings`.
|
61
69
|
#
|
62
|
-
#
|
63
|
-
# an XSD datatype, and the second is the expression to be evaluated.
|
64
|
-
# The result is cast as a literal of the appropriate type
|
70
|
+
# Returns a partial SPARQL grammar for this array.
|
65
71
|
#
|
66
|
-
# @param
|
67
|
-
#
|
68
|
-
# @
|
69
|
-
|
70
|
-
|
71
|
-
# @see SPARQL::Algebra::Expression.evaluate
|
72
|
-
def evaluate(bindings, **options)
|
73
|
-
SPARQL::Algebra::Expression.extension(*self.map {|o| o.evaluate(bindings, **options)})
|
72
|
+
# @param [String] delimiter (" ")
|
73
|
+
# If the first element is an IRI, treat it as an extension function
|
74
|
+
# @return [String]
|
75
|
+
def to_sparql(delimiter: " ", **options)
|
76
|
+
map {|e| e.to_sparql(**options)}.join(delimiter)
|
74
77
|
end
|
75
78
|
|
76
79
|
##
|
@@ -216,15 +219,6 @@ end
|
|
216
219
|
##
|
217
220
|
# Extensions for Ruby's `Hash` class.
|
218
221
|
class Hash
|
219
|
-
##
|
220
|
-
# Returns the SXP representation of this object, defaults to `self`.
|
221
|
-
#
|
222
|
-
# @return [String]
|
223
|
-
def to_sxp_bin
|
224
|
-
to_a.to_sxp_bin
|
225
|
-
end
|
226
|
-
def to_sxp; to_sxp_bin; end
|
227
|
-
|
228
222
|
##
|
229
223
|
# A duplicate of this hash.
|
230
224
|
#
|
@@ -278,24 +272,19 @@ module RDF::Term
|
|
278
272
|
# @see SPARQL::Algebra::Expression#optimize
|
279
273
|
def optimize(**options)
|
280
274
|
optimized = self.deep_dup
|
281
|
-
optimized.lexical = nil if optimized.respond_to?(:lexical=)
|
282
|
-
optimized
|
275
|
+
#optimized.lexical = nil if optimized.respond_to?(:lexical=)
|
276
|
+
#optimized
|
283
277
|
end
|
284
|
-
end # RDF::Term
|
285
278
|
|
286
|
-
class RDF::Literal::Double
|
287
279
|
##
|
288
|
-
#
|
280
|
+
#
|
281
|
+
# Returns a partial SPARQL grammar for this term.
|
289
282
|
#
|
290
283
|
# @return [String]
|
291
|
-
def
|
292
|
-
|
293
|
-
when nan? then 'nan.0'
|
294
|
-
when infinite? then (infinite? > 0 ? '+inf.0' : '-inf.0')
|
295
|
-
else canonicalize.to_s.downcase
|
296
|
-
end
|
284
|
+
def to_sparql(**options)
|
285
|
+
to_sxp(**options)
|
297
286
|
end
|
298
|
-
end
|
287
|
+
end # RDF::Term
|
299
288
|
|
300
289
|
# Override RDF::Queryable to execute against SPARQL::Algebra::Query elements as well as RDF::Query and RDF::Pattern
|
301
290
|
module RDF::Queryable
|
@@ -343,6 +332,15 @@ module RDF::Queryable
|
|
343
332
|
query_without_sparql(pattern, **options, &block)
|
344
333
|
end
|
345
334
|
end
|
335
|
+
|
336
|
+
##
|
337
|
+
#
|
338
|
+
# Returns a partial SPARQL grammar for this term.
|
339
|
+
#
|
340
|
+
# @return [String]
|
341
|
+
def to_sparql(**options)
|
342
|
+
raise NotImplementedError, "SPARQL::Algebra '#{first}' operator not implemented"
|
343
|
+
end
|
346
344
|
end
|
347
345
|
|
348
346
|
class RDF::Statement
|
@@ -361,9 +359,31 @@ class RDF::Statement
|
|
361
359
|
##
|
362
360
|
# Returns an S-Expression (SXP) representation
|
363
361
|
#
|
362
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes (nil)
|
363
|
+
# @param [RDF::URI] base_uri (nil)
|
364
364
|
# @return [String]
|
365
|
-
def to_sxp
|
366
|
-
to_sxp_bin.to_sxp
|
365
|
+
def to_sxp(prefixes: nil, base_uri: nil)
|
366
|
+
to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
|
367
|
+
end
|
368
|
+
|
369
|
+
##
|
370
|
+
#
|
371
|
+
# Returns a partial SPARQL grammar for this term.
|
372
|
+
#
|
373
|
+
# @param [Boolean] as_statement (false) serialize as < ... >, otherwise TRIPLE(...)
|
374
|
+
# @return [String]
|
375
|
+
def to_sparql(as_statement: false, **options)
|
376
|
+
if as_statement
|
377
|
+
to_triple.map do |term|
|
378
|
+
if term.is_a?(::RDF::Statement)
|
379
|
+
"<<" + term.to_sparql(as_statement: true, **options) + ">>"
|
380
|
+
else
|
381
|
+
term.to_sparql(**options)
|
382
|
+
end
|
383
|
+
end.join(" ")
|
384
|
+
else
|
385
|
+
"TRIPLE(#{to_triple.to_sparql(as_statement: true, **options)})"
|
386
|
+
end
|
367
387
|
end
|
368
388
|
|
369
389
|
##
|
@@ -411,6 +431,38 @@ class RDF::Query
|
|
411
431
|
end
|
412
432
|
end
|
413
433
|
|
434
|
+
##
|
435
|
+
#
|
436
|
+
# Returns a partial SPARQL grammar for this query.
|
437
|
+
#
|
438
|
+
# @param [Boolean] top_level (true)
|
439
|
+
# Treat this as a top-level, generating SELECT ... WHERE {}
|
440
|
+
# @param [Array<Operator>] filter_ops ([])
|
441
|
+
# Filter Operations
|
442
|
+
# @return [String]
|
443
|
+
def to_sparql(top_level: true, filter_ops: [], **options)
|
444
|
+
str = @patterns.map { |e| e.to_sparql(as_statement: true, top_level: false, **options) }.join(". \n")
|
445
|
+
str = "GRAPH #{graph_name.to_sparql(**options)} {\n#{str}\n}\n" if graph_name
|
446
|
+
if top_level
|
447
|
+
SPARQL::Algebra::Operator.to_sparql(str, filter_ops: filter_ops, **options)
|
448
|
+
else
|
449
|
+
# Filters
|
450
|
+
filter_ops.each do |op|
|
451
|
+
str << "\nFILTER (#{op.to_sparql(**options)}) ."
|
452
|
+
end
|
453
|
+
|
454
|
+
# Extensons
|
455
|
+
extensions = options.fetch(:extensions, [])
|
456
|
+
extensions.each do |as, expression|
|
457
|
+
v = expression.to_sparql(as_statement: true, **options)
|
458
|
+
v = "<< #{v} >>" if expression.is_a?(RDF::Statement)
|
459
|
+
str << "\nBIND (" << v << " AS " << as.to_sparql(**options) << ") ."
|
460
|
+
end
|
461
|
+
str = "{#{str}}" unless filter_ops.empty? && extensions.empty?
|
462
|
+
str
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
414
466
|
##
|
415
467
|
# Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables
|
416
468
|
#
|
@@ -462,11 +514,11 @@ class RDF::Query
|
|
462
514
|
def optimize!(**options)
|
463
515
|
@patterns = @patterns.map do |pattern|
|
464
516
|
components = pattern.to_quad.map do |term|
|
465
|
-
if term.respond_to?(:lexical=)
|
466
|
-
|
467
|
-
else
|
517
|
+
#if term.respond_to?(:lexical=)
|
518
|
+
# term.dup.instance_eval {@lexical = nil; self}
|
519
|
+
#else
|
468
520
|
term
|
469
|
-
end
|
521
|
+
#end
|
470
522
|
end
|
471
523
|
RDF::Query::Pattern.from(components, **pattern.options)
|
472
524
|
end
|
@@ -530,11 +582,15 @@ class RDF::Query::Variable
|
|
530
582
|
self
|
531
583
|
end
|
532
584
|
|
533
|
-
|
534
|
-
#
|
535
|
-
|
536
|
-
|
537
|
-
|
585
|
+
##
|
586
|
+
#
|
587
|
+
# Returns a partial SPARQL grammar for this term.
|
588
|
+
#
|
589
|
+
# The Non-distinguished form (`??xxx`) is not part of the grammar, so replace with a blank-node
|
590
|
+
#
|
591
|
+
# @return [String]
|
592
|
+
def to_sparql(**options)
|
593
|
+
self.distinguished? ? super : "_:_nd#{self.name}"
|
538
594
|
end
|
539
595
|
end # RDF::Query::Variable
|
540
596
|
|
@@ -576,5 +632,13 @@ class RDF::Query::Solution
|
|
576
632
|
def to_sxp_bin
|
577
633
|
to_a.to_sxp_bin
|
578
634
|
end
|
579
|
-
|
635
|
+
|
636
|
+
# Transform Solution into an SXP
|
637
|
+
#
|
638
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes (nil)
|
639
|
+
# @param [RDF::URI] base_uri (nil)
|
640
|
+
# @return [String]
|
641
|
+
def to_sxp(prefixes: nil, base_uri: nil)
|
642
|
+
to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
|
643
|
+
end
|
580
644
|
end # RDF::Query::Solution
|
@@ -3,8 +3,19 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL logical `abs` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [121] BuiltInCall ::= ... | 'ABS' '(' Expression ')'
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example.org/>
|
10
|
+
# SELECT * WHERE {
|
11
|
+
# ?s :num ?num
|
12
|
+
# FILTER(ABS(?num) >= 2)
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://example.org/>))
|
17
|
+
# (filter (>= (abs ?num) 2)
|
18
|
+
# (bgp (triple ?s :num ?num))))
|
8
19
|
#
|
9
20
|
# @see https://www.w3.org/TR/sparql11-query/#func-abs
|
10
21
|
# @see https://www.w3.org/TR/xpath-functions/#func-abs
|
@@ -20,12 +31,21 @@ module SPARQL; module Algebra
|
|
20
31
|
# the operand
|
21
32
|
# @return [RDF::Literal] literal of same type
|
22
33
|
# @raise [TypeError] if the operand is not a numeric value
|
23
|
-
def apply(operand)
|
34
|
+
def apply(operand, **options)
|
24
35
|
case operand
|
25
36
|
when RDF::Literal::Numeric then operand.abs
|
26
37
|
else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
|
27
38
|
end
|
28
39
|
end
|
40
|
+
|
41
|
+
##
|
42
|
+
#
|
43
|
+
# Returns a partial SPARQL grammar for this operator.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def to_sparql(**options)
|
47
|
+
"ABS(#{operands.first.to_sparql(**options)})"
|
48
|
+
end
|
29
49
|
end # Abs
|
30
50
|
end # Operator
|
31
51
|
end; end # SPARQL::Algebra
|
@@ -6,8 +6,15 @@ module SPARQL; module Algebra
|
|
6
6
|
#
|
7
7
|
# The ADD operation is a shortcut for inserting all data from an input graph into a destination graph. Data from the input graph is not affected, and initial data from the destination graph, if any, is kept intact.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# [35] Add ::= "ADD" "SILENT"? GraphOrDefault "TO" GraphOrDefault
|
10
|
+
#
|
11
|
+
# @example SPARQL Update
|
12
|
+
# PREFIX : <http://example.org/>
|
13
|
+
# ADD DEFAULT TO :g1
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://example.org/>))
|
17
|
+
# (update (add default :g1)))
|
11
18
|
#
|
12
19
|
# @see https://www.w3.org/TR/sparql11-update/#add
|
13
20
|
class Add < Operator
|
@@ -51,6 +58,18 @@ module SPARQL; module Algebra
|
|
51
58
|
end
|
52
59
|
queryable
|
53
60
|
end
|
61
|
+
|
62
|
+
##
|
63
|
+
#
|
64
|
+
# Returns a partial SPARQL grammar for this operator.
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
def to_sparql(**options)
|
68
|
+
*args, last = operands.dup
|
69
|
+
args += [:TO, last]
|
70
|
+
|
71
|
+
"ADD " + args.to_sparql(**options)
|
72
|
+
end
|
54
73
|
end # Add
|
55
74
|
end # Operator
|
56
75
|
end; end # SPARQL::Algebra
|
@@ -7,8 +7,23 @@ module SPARQL; module Algebra
|
|
7
7
|
#
|
8
8
|
# eval(Path(X, alt(P,Q), Y)) = Union(eval(Path(X, P, Y)), eval(Path(X, Q, Y)))
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# [89] PathAlternative ::= PathSequence ( '|' PathSequence )*
|
11
|
+
#
|
12
|
+
# @example SPARQL Query
|
13
|
+
# PREFIX : <http://www.example.org/>
|
14
|
+
# SELECT ?t
|
15
|
+
# WHERE {
|
16
|
+
# :a :p1|:p2/:p3|:p4 ?t
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# @example SSE
|
20
|
+
# (prefix ((: <http://www.example.org/>))
|
21
|
+
# (project (?t)
|
22
|
+
# (path :a
|
23
|
+
# (alt
|
24
|
+
# (alt :p1 (seq :p2 :p3))
|
25
|
+
# :p4)
|
26
|
+
# ?t)))
|
12
27
|
#
|
13
28
|
# @see https://www.w3.org/TR/sparql11-query/#defn_evalPP_alternative
|
14
29
|
class Alt < Operator::Binary
|
@@ -57,6 +72,15 @@ module SPARQL; module Algebra
|
|
57
72
|
query = Union.new(qa, qb)
|
58
73
|
queryable.query(query, depth: options[:depth].to_i + 1, **options, &block)
|
59
74
|
end
|
75
|
+
|
76
|
+
##
|
77
|
+
#
|
78
|
+
# Returns a partial SPARQL grammar for this operator.
|
79
|
+
#
|
80
|
+
# @return [String]
|
81
|
+
def to_sparql(**options)
|
82
|
+
"(#{operands.first.to_sparql(**options)}|#{operands.last.to_sparql(**options)})"
|
83
|
+
end
|
60
84
|
end # Alt
|
61
85
|
end # Operator
|
62
86
|
end; end # SPARQL::Algebra
|
@@ -3,9 +3,22 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL logical `and` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# [112] ConditionalAndExpression::= ValueLogical ( '&&' ValueLogical )*
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
10
|
+
# PREFIX : <http://example.org/ns#>
|
11
|
+
# SELECT ?a
|
12
|
+
# WHERE { ?a :p ?v .
|
13
|
+
# FILTER ("true"^^xsd:boolean && ?v) .
|
14
|
+
# }
|
15
|
+
#
|
16
|
+
# @example SSE
|
17
|
+
# (prefix
|
18
|
+
# ((xsd: <http://www.w3.org/2001/XMLSchema#>) (: <http://example.org/ns#>))
|
19
|
+
# (project (?a)
|
20
|
+
# (filter (&& true ?v)
|
21
|
+
# (bgp (triple ?a :p ?v)))))
|
9
22
|
#
|
10
23
|
# @see https://www.w3.org/TR/sparql11-query/#func-logical-and
|
11
24
|
# @see https://www.w3.org/TR/sparql11-query/#evaluation
|
@@ -60,6 +73,15 @@ module SPARQL; module Algebra
|
|
60
73
|
else RDF::Literal(left && right)
|
61
74
|
end
|
62
75
|
end
|
76
|
+
|
77
|
+
##
|
78
|
+
#
|
79
|
+
# Returns a partial SPARQL grammar for this operator.
|
80
|
+
#
|
81
|
+
# @return [String]
|
82
|
+
def to_sparql(**options)
|
83
|
+
"(#{operands.first.to_sparql(**options)} && #{operands.last.to_sparql(**options)})"
|
84
|
+
end
|
63
85
|
end # And
|
64
86
|
end # Operator
|
65
87
|
end; end # SPARQL::Algebra
|