sparql 3.1.5 → 3.2.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.
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