sparql 3.1.5 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -28
  3. data/VERSION +1 -1
  4. data/bin/sparql +14 -4
  5. data/lib/sparql/algebra/aggregate.rb +1 -1
  6. data/lib/sparql/algebra/evaluatable.rb +4 -4
  7. data/lib/sparql/algebra/expression.rb +4 -1
  8. data/lib/sparql/algebra/extensions.rb +96 -29
  9. data/lib/sparql/algebra/operator/abs.rb +23 -3
  10. data/lib/sparql/algebra/operator/add.rb +21 -2
  11. data/lib/sparql/algebra/operator/alt.rb +26 -2
  12. data/lib/sparql/algebra/operator/and.rb +25 -3
  13. data/lib/sparql/algebra/operator/asc.rb +20 -1
  14. data/lib/sparql/algebra/operator/ask.rb +17 -1
  15. data/lib/sparql/algebra/operator/avg.rb +18 -2
  16. data/lib/sparql/algebra/operator/base.rb +18 -1
  17. data/lib/sparql/algebra/operator/bgp.rb +5 -1
  18. data/lib/sparql/algebra/operator/bnode.rb +34 -11
  19. data/lib/sparql/algebra/operator/bound.rb +22 -1
  20. data/lib/sparql/algebra/operator/ceil.rb +26 -3
  21. data/lib/sparql/algebra/operator/clear.rb +16 -2
  22. data/lib/sparql/algebra/operator/coalesce.rb +33 -11
  23. data/lib/sparql/algebra/operator/compare.rb +48 -33
  24. data/lib/sparql/algebra/operator/concat.rb +26 -2
  25. data/lib/sparql/algebra/operator/construct.rb +31 -7
  26. data/lib/sparql/algebra/operator/contains.rb +25 -3
  27. data/lib/sparql/algebra/operator/copy.rb +19 -2
  28. data/lib/sparql/algebra/operator/count.rb +18 -2
  29. data/lib/sparql/algebra/operator/create.rb +19 -2
  30. data/lib/sparql/algebra/operator/dataset.rb +17 -0
  31. data/lib/sparql/algebra/operator/datatype.rb +26 -7
  32. data/lib/sparql/algebra/operator/day.rb +24 -6
  33. data/lib/sparql/algebra/operator/delete.rb +27 -2
  34. data/lib/sparql/algebra/operator/delete_data.rb +23 -2
  35. data/lib/sparql/algebra/operator/delete_where.rb +24 -2
  36. data/lib/sparql/algebra/operator/desc.rb +20 -1
  37. data/lib/sparql/algebra/operator/describe.rb +27 -4
  38. data/lib/sparql/algebra/operator/distinct.rb +18 -1
  39. data/lib/sparql/algebra/operator/divide.rb +27 -3
  40. data/lib/sparql/algebra/operator/drop.rb +17 -2
  41. data/lib/sparql/algebra/operator/encode_for_uri.rb +25 -3
  42. data/lib/sparql/algebra/operator/equal.rb +13 -3
  43. data/lib/sparql/algebra/operator/exists.rb +28 -4
  44. data/lib/sparql/algebra/operator/exprlist.rb +12 -1
  45. data/lib/sparql/algebra/operator/extend.rb +33 -18
  46. data/lib/sparql/algebra/operator/filter.rb +27 -5
  47. data/lib/sparql/algebra/operator/floor.rb +26 -3
  48. data/lib/sparql/algebra/operator/graph.rb +13 -0
  49. data/lib/sparql/algebra/operator/greater_than.rb +14 -4
  50. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +14 -4
  51. data/lib/sparql/algebra/operator/group.rb +34 -8
  52. data/lib/sparql/algebra/operator/group_concat.rb +20 -8
  53. data/lib/sparql/algebra/operator/hours.rb +24 -6
  54. data/lib/sparql/algebra/operator/if.rb +21 -4
  55. data/lib/sparql/algebra/operator/in.rb +18 -1
  56. data/lib/sparql/algebra/operator/insert.rb +22 -2
  57. data/lib/sparql/algebra/operator/insert_data.rb +23 -2
  58. data/lib/sparql/algebra/operator/iri.rb +22 -5
  59. data/lib/sparql/algebra/operator/is_blank.rb +20 -2
  60. data/lib/sparql/algebra/operator/is_iri.rb +20 -2
  61. data/lib/sparql/algebra/operator/is_literal.rb +20 -2
  62. data/lib/sparql/algebra/operator/is_numeric.rb +22 -4
  63. data/lib/sparql/algebra/operator/is_triple.rb +62 -0
  64. data/lib/sparql/algebra/operator/join.rb +22 -1
  65. data/lib/sparql/algebra/operator/lang.rb +26 -1
  66. data/lib/sparql/algebra/operator/lang_matches.rb +23 -2
  67. data/lib/sparql/algebra/operator/lcase.rb +24 -3
  68. data/lib/sparql/algebra/operator/left_join.rb +29 -1
  69. data/lib/sparql/algebra/operator/less_than.rb +14 -4
  70. data/lib/sparql/algebra/operator/less_than_or_equal.rb +14 -4
  71. data/lib/sparql/algebra/operator/load.rb +25 -2
  72. data/lib/sparql/algebra/operator/max.rb +18 -2
  73. data/lib/sparql/algebra/operator/md5.rb +23 -6
  74. data/lib/sparql/algebra/operator/min.rb +19 -3
  75. data/lib/sparql/algebra/operator/minus.rb +25 -7
  76. data/lib/sparql/algebra/operator/minutes.rb +24 -6
  77. data/lib/sparql/algebra/operator/modify.rb +41 -5
  78. data/lib/sparql/algebra/operator/month.rb +24 -6
  79. data/lib/sparql/algebra/operator/move.rb +20 -2
  80. data/lib/sparql/algebra/operator/multiply.rb +27 -4
  81. data/lib/sparql/algebra/operator/negate.rb +24 -4
  82. data/lib/sparql/algebra/operator/not.rb +25 -4
  83. data/lib/sparql/algebra/operator/not_equal.rb +16 -1
  84. data/lib/sparql/algebra/operator/notexists.rb +30 -6
  85. data/lib/sparql/algebra/operator/notin.rb +20 -3
  86. data/lib/sparql/algebra/operator/notoneof.rb +12 -2
  87. data/lib/sparql/algebra/operator/now.rb +25 -6
  88. data/lib/sparql/algebra/operator/object.rb +59 -0
  89. data/lib/sparql/algebra/operator/or.rb +26 -3
  90. data/lib/sparql/algebra/operator/order.rb +27 -2
  91. data/lib/sparql/algebra/operator/path.rb +29 -2
  92. data/lib/sparql/algebra/operator/path_opt.rb +21 -2
  93. data/lib/sparql/algebra/operator/path_plus.rb +21 -2
  94. data/lib/sparql/algebra/operator/path_star.rb +20 -2
  95. data/lib/sparql/algebra/operator/plus.rb +43 -4
  96. data/lib/sparql/algebra/operator/predicate.rb +59 -0
  97. data/lib/sparql/algebra/operator/prefix.rb +24 -3
  98. data/lib/sparql/algebra/operator/project.rb +51 -5
  99. data/lib/sparql/algebra/operator/rand.rb +31 -3
  100. data/lib/sparql/algebra/operator/reduced.rb +18 -1
  101. data/lib/sparql/algebra/operator/regex.rb +27 -19
  102. data/lib/sparql/algebra/operator/replace.rb +27 -7
  103. data/lib/sparql/algebra/operator/reverse.rb +20 -2
  104. data/lib/sparql/algebra/operator/round.rb +26 -3
  105. data/lib/sparql/algebra/operator/same_term.rb +25 -7
  106. data/lib/sparql/algebra/operator/sample.rb +31 -9
  107. data/lib/sparql/algebra/operator/seconds.rb +24 -6
  108. data/lib/sparql/algebra/operator/seq.rb +20 -2
  109. data/lib/sparql/algebra/operator/sequence.rb +0 -10
  110. data/lib/sparql/algebra/operator/sha1.rb +19 -2
  111. data/lib/sparql/algebra/operator/sha256.rb +19 -2
  112. data/lib/sparql/algebra/operator/sha384.rb +19 -2
  113. data/lib/sparql/algebra/operator/sha512.rb +19 -2
  114. data/lib/sparql/algebra/operator/slice.rb +27 -5
  115. data/lib/sparql/algebra/operator/str.rb +22 -2
  116. data/lib/sparql/algebra/operator/strafter.rb +26 -3
  117. data/lib/sparql/algebra/operator/strbefore.rb +26 -3
  118. data/lib/sparql/algebra/operator/strdt.rb +23 -2
  119. data/lib/sparql/algebra/operator/strends.rb +26 -4
  120. data/lib/sparql/algebra/operator/strlang.rb +26 -7
  121. data/lib/sparql/algebra/operator/strlen.rb +24 -3
  122. data/lib/sparql/algebra/operator/strstarts.rb +26 -3
  123. data/lib/sparql/algebra/operator/struuid.rb +30 -10
  124. data/lib/sparql/algebra/operator/subject.rb +61 -0
  125. data/lib/sparql/algebra/operator/substr.rb +24 -3
  126. data/lib/sparql/algebra/operator/subtract.rb +29 -3
  127. data/lib/sparql/algebra/operator/sum.rb +18 -2
  128. data/lib/sparql/algebra/operator/table.rb +42 -4
  129. data/lib/sparql/algebra/operator/timezone.rb +24 -6
  130. data/lib/sparql/algebra/operator/tz.rb +23 -6
  131. data/lib/sparql/algebra/operator/ucase.rb +24 -3
  132. data/lib/sparql/algebra/operator/union.rb +29 -6
  133. data/lib/sparql/algebra/operator/update.rb +25 -4
  134. data/lib/sparql/algebra/operator/using.rb +32 -2
  135. data/lib/sparql/algebra/operator/uuid.rb +28 -9
  136. data/lib/sparql/algebra/operator/with.rb +38 -4
  137. data/lib/sparql/algebra/operator/year.rb +24 -6
  138. data/lib/sparql/algebra/operator.rb +112 -7
  139. data/lib/sparql/algebra/sxp_extensions.rb +3 -3
  140. data/lib/sparql/grammar/meta.rb +5390 -2410
  141. data/lib/sparql/grammar/parser11.rb +119 -53
  142. data/lib/sparql/grammar/terminals11.rb +2 -0
  143. data/lib/sparql/grammar.rb +0 -25
  144. metadata +40 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27f805f342a0db67d53df5b59f045adbf206e846cf4100b3918e9fb7933413d0
4
- data.tar.gz: 3afbfd95de7fb479e8d06c20a758d636ff23e699db48ed25e5906497bc2e254b
3
+ metadata.gz: ecbe9289bf43f7fa28940a82545ec08b19c54d8bdf64693934405e83ddb4cc53
4
+ data.tar.gz: 24ab0942be18a9d9d281452ba9a7195dcad2a31755bda6d84afe4f49fe7c34c1
5
5
  SHA512:
6
- metadata.gz: 12ce7f125ff98950f7fdd9e63e42645fc9bd23e79146971526e78413f254d979a1e202ac90cca1f83b8721ca43f7c6e8e88bf6029a5138bc8337ad2c2a85de72
7
- data.tar.gz: 1b8bb78258345466d763a3fdfbc19b40cc759a6c2a7b8189cccd6e7cecbbbcbb2cdb1fc04869063bcdbc33ecd532292b3d4e25bc426256c63f1e804044aa8cbb
6
+ metadata.gz: 89a77c749eb99b0fe83f27d5f413556ac2f6cf22af7e06b8e0588155bbf5a50eb053b1f87ffe11a13b5fd873d5fcaaee1166cdf336aacd3029380898a82da382
7
+ data.tar.gz: 13be95c405b9fdf7e678bc9bbaf6dcc45075a692a08e1762deacc0779948996fdc992376f3a564644f50270282c76a759023d7393e28db07ec7828a73324a948
data/README.md CHANGED
@@ -23,10 +23,9 @@ 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.2.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
- * Provisional support for [SPARQL*][].
28
+ * Provisional support for [SPARQL-star][].
30
29
 
31
30
  ## Description
32
31
 
@@ -96,9 +95,9 @@ Then, use the function in a query:
96
95
 
97
96
  See {SPARQL::Algebra::Expression.register_extension} for details.
98
97
 
99
- ### SPARQLStar (SPARQL*)
98
+ ### SPARQLStar (SPARQL-star)
100
99
 
101
- The gem supports [SPARQL*][] where patterns may include sub-patterns recursively, for a kind of Reification.
100
+ The gem supports [SPARQL-star][] where patterns may include sub-patterns recursively, for a kind of Reification.
102
101
 
103
102
  For example, the following Turtle* file uses a statement as the subject of another statement:
104
103
 
@@ -159,7 +158,7 @@ As well as a `CONSTRUCT`:
159
158
  <<?bob foaf:age ?age>> ?b ?c .
160
159
  }
161
160
 
162
- Note that results can be serialized only when the format supports [RDF*][].
161
+ Note that results can be serialized only when the format supports [RDF-star][].
163
162
 
164
163
  #### SPARQL results
165
164
 
@@ -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
- sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
252
- queryable.query(sse) do |result|
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
- sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
260
- sse.execute(queryable) do |result|
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
- sse = SPARQL.parse(%(
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
- sse.execute(queryable)
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,13 @@ a full set of RDF formats.
277
276
 
278
277
  ### Parsing a SPARQL query string to SSE
279
278
 
280
- sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
281
- sse.to_sxp #=> (bgp (triple ?s ?p ?o))
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
+ query = SPARQL::Algebra.parse(%{(bgp (triple ?s ?p ?o))})
285
+ sparql = query.to_sparql #=> "SELECT * WHERE { ?s ?p ?o }"
282
286
 
283
287
  ### Command line processing
284
288
 
@@ -289,6 +293,10 @@ a full set of RDF formats.
289
293
  sparql parse etc/input.rq
290
294
  sparql parse -e "SELECT * WHERE { ?s ?p ?o }"
291
295
 
296
+ # Generate SPARQL Query from SSE
297
+ sparql parse --sse etc/input.sse --format sparql
298
+ sparql parse --sse --format sparql -e "(dataset (<http://usefulinc.com/ns/doap>) (bgp (triple ?s ?p ?o))))"
299
+
292
300
  # Run query using SSE input
293
301
  sparql execute --dataset etc/doap.ttl --sse etc/input.sse
294
302
  sparql execute --sse -e "(dataset (<etc/doap.ttl>) (bgp (triple ?s ?p ?o))))"
@@ -368,19 +376,19 @@ Full documentation available on [Rubydoc.info][SPARQL doc]
368
376
 
369
377
  ## Dependencies
370
378
 
371
- * [Ruby](https://ruby-lang.org/) (>= 2.2.2)
372
- * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.0)
373
- * [SPARQL::Client](https://rubygems.org/gems/sparql-client) (~> 3.0)
374
- * [SXP](https://rubygems.org/gems/sxp) (~> 1.0)
375
- * [Builder](https://rubygems.org/gems/builder) (>= 3.0.0)
376
- * [JSON](https://rubygems.org/gems/json) (>= 1.8.2)
377
- * Soft dependency on [Linked Data][] (>= 3.0)
378
- * Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (>= 1.7)
379
+ * [Ruby](https://ruby-lang.org/) (>= 2.6)
380
+ * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.2)
381
+ * [SPARQL::Client](https://rubygems.org/gems/sparql-client) (~> 3.1)
382
+ * [SXP](https://rubygems.org/gems/sxp) (~> 1.2)
383
+ * [Builder](https://rubygems.org/gems/builder) (~> 3.2)
384
+ * [JSON](https://rubygems.org/gems/json) (~> 2.6)
385
+ * Soft dependency on [Linked Data][] (>= 3.1)
386
+ * Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (~> 1.12)
379
387
  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.3.0)
388
+ * Soft dependency on [Equivalent XML](https://rubygems.org/gems/equivalent-xml) (>= 0.6)
381
389
  Equivalent XML performs more efficient comparisons of XML Literals when Nokogiri is included
382
- * Soft dependency on [Rack][] (>= 2.0)
383
- * Soft dependency on [Sinatra][] (>= 2.0)
390
+ * Soft dependency on [Rack][] (~> 2.2)
391
+ * Soft dependency on [Sinatra][] (~> 2.1)
384
392
 
385
393
  ## Installation
386
394
 
@@ -448,9 +456,8 @@ A copy of the [SPARQL 1.0 tests][] and [SPARQL 1.1 tests][] are also included in
448
456
  [grammar]: https://www.w3.org/TR/sparql11-query/#grammar
449
457
  [RDF 1.1]: https://www.w3.org/TR/rdf11-concepts
450
458
  [RDF.rb]: https://rubydoc.info/github/ruby-rdf/rdf
451
- [RDF*]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html
452
- [SPARQL*]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#sparql-query-language
453
- [Backports]: https://rubygems.org/gems/backports
459
+ [RDF-star]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html
460
+ [SPARQL-star]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#sparql-query-language
454
461
  [Linked Data]: https://rubygems.org/gems/linkeddata
455
462
  [SPARQL doc]: https://rubydoc.info/github/ruby-rdf/sparql/frames
456
463
  [SPARQL XML]: https://www.w3.org/TR/rdf-sparql-XMLres/
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.5
1
+ 3.2.0
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] || options[:to_sse]
48
+ puts ("\nSSE:\n" + query.to_sse) if options[:debug]
48
49
 
49
- unless options[:to_sse]
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[:to_sse] = true if cmd == 'parse'
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
 
@@ -4,6 +4,8 @@ module SPARQL; module Algebra
4
4
  #
5
5
  # @abstract
6
6
  module Expression
7
+ include RDF::Util::Logger
8
+
7
9
  ##
8
10
  # @example
9
11
  # Expression.parse('(isLiteral 3.1415)')
@@ -410,7 +412,8 @@ module SPARQL; module Algebra
410
412
  end
411
413
 
412
414
  def debug(*args, &block)
413
- Expression.debug(*args, &block)
415
+ options = args.last.is_a?(Hash) ? args.pop : {}
416
+ log_debug(*args, **options, &block)
414
417
  end
415
418
  end # Expression
416
419
  end; end # SPARQL::Algebra
@@ -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
  ##
@@ -56,6 +65,16 @@ class Array
56
65
  map {|x| x.to_sxp_bin}
57
66
  end
58
67
 
68
+ ##
69
+ #
70
+ # Returns a partial SPARQL grammar for this array.
71
+ #
72
+ # @param [String] delimiter (" ")
73
+ # @return [String]
74
+ def to_sparql(delimiter: " ", **options)
75
+ map {|e| e.to_sparql(**options)}.join(delimiter)
76
+ end
77
+
59
78
  ##
60
79
  # Evaluates the array using the given variable `bindings`.
61
80
  #
@@ -216,15 +235,6 @@ end
216
235
  ##
217
236
  # Extensions for Ruby's `Hash` class.
218
237
  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
238
  ##
229
239
  # A duplicate of this hash.
230
240
  #
@@ -278,24 +288,20 @@ module RDF::Term
278
288
  # @see SPARQL::Algebra::Expression#optimize
279
289
  def optimize(**options)
280
290
  optimized = self.deep_dup
281
- optimized.lexical = nil if optimized.respond_to?(:lexical=)
282
- optimized
291
+ #optimized.lexical = nil if optimized.respond_to?(:lexical=)
292
+ #optimized
283
293
  end
284
- end # RDF::Term
285
294
 
286
- class RDF::Literal::Double
287
295
  ##
288
- # Returns the SXP representation of this object.
296
+ #
297
+ # Returns a partial SPARQL grammar for this term.
289
298
  #
290
299
  # @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
300
+ def to_sparql(**options)
301
+ to_sxp(**options)
297
302
  end
298
- end
303
+ end # RDF::Term
304
+
299
305
 
300
306
  # Override RDF::Queryable to execute against SPARQL::Algebra::Query elements as well as RDF::Query and RDF::Pattern
301
307
  module RDF::Queryable
@@ -308,7 +314,7 @@ module RDF::Queryable
308
314
  #
309
315
  # @example
310
316
  # queryable.query([nil, RDF::DOAP.developer, nil])
311
- # queryable.query(predicate: RDF::DOAP.developer)
317
+ # queryable.query({predicate: RDF::DOAP.developer})
312
318
  #
313
319
  # op = SPARQL::Algebra::Expression.parse(%q((bgp (triple ?a doap:developer ?b))))
314
320
  # queryable.query(op)
@@ -343,6 +349,15 @@ module RDF::Queryable
343
349
  query_without_sparql(pattern, **options, &block)
344
350
  end
345
351
  end
352
+
353
+ ##
354
+ #
355
+ # Returns a partial SPARQL grammar for this term.
356
+ #
357
+ # @return [String]
358
+ def to_sparql(**options)
359
+ raise NotImplementedError, "SPARQL::Algebra '#{first}' operator not implemented"
360
+ end
346
361
  end
347
362
 
348
363
  class RDF::Statement
@@ -361,9 +376,29 @@ class RDF::Statement
361
376
  ##
362
377
  # Returns an S-Expression (SXP) representation
363
378
  #
379
+ # @param [Hash{Symbol => RDF::URI}] prefixes (nil)
380
+ # @param [RDF::URI] base_uri (nil)
364
381
  # @return [String]
365
- def to_sxp
366
- to_sxp_bin.to_sxp
382
+ def to_sxp(prefixes: nil, base_uri: nil)
383
+ to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
384
+ end
385
+
386
+ ##
387
+ #
388
+ # Returns a partial SPARQL grammar for this term.
389
+ #
390
+ # @param [Boolean] as_statement (false) serialize as < ... >, otherwise TRIPLE(...)
391
+ # @return [String]
392
+ def to_sparql(as_statement: false, **options)
393
+ return "TRIPLE(#{to_triple.to_sparql(as_statement: true, **options)})" unless as_statement
394
+
395
+ to_triple.map do |term|
396
+ if term.is_a?(::RDF::Statement)
397
+ "<<" + term.to_sparql(**options) + ">>"
398
+ else
399
+ term.to_sparql(**options)
400
+ end
401
+ end.join(" ") + " ."
367
402
  end
368
403
 
369
404
  ##
@@ -411,6 +446,19 @@ class RDF::Query
411
446
  end
412
447
  end
413
448
 
449
+ ##
450
+ #
451
+ # Returns a partial SPARQL grammar for this term.
452
+ #
453
+ # @param [Boolean] top_level (true)
454
+ # Treat this as a top-level, generating SELECT ... WHERE {}
455
+ # @return [String]
456
+ def to_sparql(top_level: true, **options)
457
+ str = @patterns.map { |e| e.to_sparql(as_statement: true, top_level: false, **options) }.join("\n")
458
+ str = "GRAPH #{graph_name.to_sparql(**options)} {\n#{str}\n}\n" if graph_name
459
+ top_level ? SPARQL::Algebra::Operator.to_sparql(str, **options) : str
460
+ end
461
+
414
462
  ##
415
463
  # Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables
416
464
  #
@@ -462,11 +510,11 @@ class RDF::Query
462
510
  def optimize!(**options)
463
511
  @patterns = @patterns.map do |pattern|
464
512
  components = pattern.to_quad.map do |term|
465
- if term.respond_to?(:lexical=)
466
- term.dup.instance_eval {@lexical = nil; self}
467
- else
513
+ #if term.respond_to?(:lexical=)
514
+ # term.dup.instance_eval {@lexical = nil; self}
515
+ #else
468
516
  term
469
- end
517
+ #end
470
518
  end
471
519
  RDF::Query::Pattern.from(components, **pattern.options)
472
520
  end
@@ -529,6 +577,17 @@ class RDF::Query::Variable
529
577
  def optimize(**options)
530
578
  self
531
579
  end
580
+
581
+ ##
582
+ #
583
+ # Returns a partial SPARQL grammar for this term.
584
+ #
585
+ # The Non-distinguished form (`??xxx`) is not part of the grammar, so replace with a blank-node
586
+ #
587
+ # @return [String]
588
+ def to_sparql(**options)
589
+ self.distinguished? ? super : "_:_nd#{self.name}"
590
+ end
532
591
  end # RDF::Query::Variable
533
592
 
534
593
  ##
@@ -569,5 +628,13 @@ class RDF::Query::Solution
569
628
  def to_sxp_bin
570
629
  to_a.to_sxp_bin
571
630
  end
572
- def to_sxp; to_sxp_bin; end
631
+
632
+ # Transform Solution into an SXP
633
+ #
634
+ # @param [Hash{Symbol => RDF::URI}] prefixes (nil)
635
+ # @param [RDF::URI] base_uri (nil)
636
+ # @return [String]
637
+ def to_sxp(prefixes: nil, base_uri: nil)
638
+ to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
639
+ end
573
640
  end # RDF::Query::Solution
@@ -3,8 +3,19 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL logical `abs` operator.
5
5
  #
6
- # @example
7
- # (abs ?x)
6
+ # [121] BuiltInCall ::= ... | 'ABS' '(' Expression ')'
7
+ #
8
+ # @example SPARQL Query
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
- # @example
10
- # (add default <a>)
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
- # @example
11
- # (alt a b)
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
- # @example
7
- # (&& ?x ?y)
8
- # (and ?x ?y)
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
@@ -3,7 +3,15 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL ascending sort operator.
5
5
  #
6
- # @example
6
+ # [24] OrderCondition ::= ( ( 'ASC' | 'DESC' ) BrackettedExpression ) | ( Constraint | Var )
7
+ #
8
+ # @example SPARQL Query
9
+ # PREFIX foaf: <http://xmlns.com/foaf/0.1/>
10
+ # SELECT ?name
11
+ # WHERE { ?x foaf:name ?name }
12
+ # ORDER BY ASC(?name)
13
+ #
14
+ # @example SSE
7
15
  # (prefix ((foaf: <http://xmlns.com/foaf/0.1/>))
8
16
  # (project (?name)
9
17
  # (order ((asc ?name))
@@ -27,6 +35,17 @@ module SPARQL; module Algebra
27
35
  def evaluate(bindings, **options)
28
36
  operand(0).evaluate(bindings, depth: options[:depth].to_i + 1, **options)
29
37
  end
38
+
39
+ ##
40
+ #
41
+ # Returns a partial SPARQL grammar for this operator.
42
+ #
43
+ # Provides order to descendant query.
44
+ #
45
+ # @return [String]
46
+ def to_sparql(**options)
47
+ "ASC(#{operands.last.to_sparql(**options)})"
48
+ end
30
49
  end # Asc
31
50
  end # Operator
32
51
  end; end # SPARQL::Algebra