sparql 3.1.4 → 3.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -7
  3. data/VERSION +1 -1
  4. data/bin/sparql +1 -0
  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 +11 -5
  8. data/lib/sparql/algebra/extensions.rb +9 -2
  9. data/lib/sparql/algebra/operator/abs.rb +1 -1
  10. data/lib/sparql/algebra/operator/avg.rb +8 -1
  11. data/lib/sparql/algebra/operator/bgp.rb +1 -1
  12. data/lib/sparql/algebra/operator/bnode.rb +1 -1
  13. data/lib/sparql/algebra/operator/ceil.rb +1 -1
  14. data/lib/sparql/algebra/operator/compare.rb +39 -33
  15. data/lib/sparql/algebra/operator/construct.rb +2 -1
  16. data/lib/sparql/algebra/operator/contains.rb +1 -1
  17. data/lib/sparql/algebra/operator/count.rb +1 -1
  18. data/lib/sparql/algebra/operator/datatype.rb +1 -1
  19. data/lib/sparql/algebra/operator/day.rb +1 -1
  20. data/lib/sparql/algebra/operator/divide.rb +1 -1
  21. data/lib/sparql/algebra/operator/encode_for_uri.rb +1 -1
  22. data/lib/sparql/algebra/operator/equal.rb +1 -1
  23. data/lib/sparql/algebra/operator/extend.rb +2 -12
  24. data/lib/sparql/algebra/operator/floor.rb +1 -1
  25. data/lib/sparql/algebra/operator/graph.rb +1 -1
  26. data/lib/sparql/algebra/operator/greater_than.rb +3 -2
  27. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +2 -2
  28. data/lib/sparql/algebra/operator/group_concat.rb +1 -1
  29. data/lib/sparql/algebra/operator/hours.rb +1 -1
  30. data/lib/sparql/algebra/operator/iri.rb +1 -1
  31. data/lib/sparql/algebra/operator/is_blank.rb +1 -1
  32. data/lib/sparql/algebra/operator/is_iri.rb +1 -1
  33. data/lib/sparql/algebra/operator/is_literal.rb +1 -1
  34. data/lib/sparql/algebra/operator/is_numeric.rb +1 -1
  35. data/lib/sparql/algebra/operator/is_triple.rb +30 -0
  36. data/lib/sparql/algebra/operator/lang.rb +1 -1
  37. data/lib/sparql/algebra/operator/lang_matches.rb +1 -1
  38. data/lib/sparql/algebra/operator/lcase.rb +1 -1
  39. data/lib/sparql/algebra/operator/left_join.rb +4 -0
  40. data/lib/sparql/algebra/operator/less_than.rb +3 -2
  41. data/lib/sparql/algebra/operator/less_than_or_equal.rb +2 -2
  42. data/lib/sparql/algebra/operator/max.rb +8 -1
  43. data/lib/sparql/algebra/operator/md5.rb +1 -1
  44. data/lib/sparql/algebra/operator/min.rb +8 -1
  45. data/lib/sparql/algebra/operator/minutes.rb +1 -1
  46. data/lib/sparql/algebra/operator/month.rb +1 -1
  47. data/lib/sparql/algebra/operator/multiply.rb +1 -1
  48. data/lib/sparql/algebra/operator/negate.rb +1 -1
  49. data/lib/sparql/algebra/operator/not.rb +1 -1
  50. data/lib/sparql/algebra/operator/not_equal.rb +3 -1
  51. data/lib/sparql/algebra/operator/now.rb +1 -1
  52. data/lib/sparql/algebra/operator/object.rb +27 -0
  53. data/lib/sparql/algebra/operator/order.rb +7 -1
  54. data/lib/sparql/algebra/operator/plus.rb +1 -1
  55. data/lib/sparql/algebra/operator/predicate.rb +27 -0
  56. data/lib/sparql/algebra/operator/rand.rb +1 -1
  57. data/lib/sparql/algebra/operator/regex.rb +1 -1
  58. data/lib/sparql/algebra/operator/replace.rb +1 -1
  59. data/lib/sparql/algebra/operator/round.rb +1 -1
  60. data/lib/sparql/algebra/operator/same_term.rb +1 -1
  61. data/lib/sparql/algebra/operator/sample.rb +9 -2
  62. data/lib/sparql/algebra/operator/seconds.rb +1 -1
  63. data/lib/sparql/algebra/operator/sha1.rb +1 -1
  64. data/lib/sparql/algebra/operator/sha256.rb +1 -1
  65. data/lib/sparql/algebra/operator/sha384.rb +1 -1
  66. data/lib/sparql/algebra/operator/sha512.rb +1 -1
  67. data/lib/sparql/algebra/operator/str.rb +1 -1
  68. data/lib/sparql/algebra/operator/strafter.rb +1 -1
  69. data/lib/sparql/algebra/operator/strbefore.rb +1 -1
  70. data/lib/sparql/algebra/operator/strdt.rb +1 -1
  71. data/lib/sparql/algebra/operator/strends.rb +1 -1
  72. data/lib/sparql/algebra/operator/strlang.rb +1 -1
  73. data/lib/sparql/algebra/operator/strlen.rb +1 -1
  74. data/lib/sparql/algebra/operator/strstarts.rb +1 -1
  75. data/lib/sparql/algebra/operator/struuid.rb +1 -1
  76. data/lib/sparql/algebra/operator/subject.rb +29 -0
  77. data/lib/sparql/algebra/operator/substr.rb +1 -1
  78. data/lib/sparql/algebra/operator/subtract.rb +1 -1
  79. data/lib/sparql/algebra/operator/sum.rb +1 -1
  80. data/lib/sparql/algebra/operator/timezone.rb +1 -1
  81. data/lib/sparql/algebra/operator/triple.rb +27 -0
  82. data/lib/sparql/algebra/operator/tz.rb +1 -1
  83. data/lib/sparql/algebra/operator/ucase.rb +1 -1
  84. data/lib/sparql/algebra/operator/uuid.rb +1 -1
  85. data/lib/sparql/algebra/operator/year.rb +1 -1
  86. data/lib/sparql/algebra/operator.rb +22 -10
  87. data/lib/sparql/extensions.rb +6 -12
  88. data/lib/sparql/grammar/meta.rb +5390 -2410
  89. data/lib/sparql/grammar/parser11.rb +116 -50
  90. data/lib/sparql/grammar/terminals11.rb +2 -0
  91. data/lib/sparql/grammar.rb +2 -27
  92. metadata +32 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ddc77cee587255c81cfcb3cd9d05759a3c98398821e23a25c3111f71e9b44c9
4
- data.tar.gz: 48290eb8ba7ab1539c73c2fc3477b4004b8a15c5f09624ef24de5e3fe692ab03
3
+ metadata.gz: 0fc6d6745c325bd23d83fe640eb238a22406b567cf06223703afd90ea5733be1
4
+ data.tar.gz: 056cde1c14633aa791f492be673eb023bab95d7af4e5b19fb94c99540fc22908
5
5
  SHA512:
6
- metadata.gz: 71b0e62c9d8d418e508befea92ca5723a24a0ccce9fcebf43f40ce7ee4a8299c81fdad5ae4302465defd04708abd04ef10c863ef1538f25c71c5a24ea45e826a
7
- data.tar.gz: 6c1b568ed72dcdda4f68f613bcbf3de38512b8cde4b1c6b2a20d51370fb5bd4efce7dee766e3cfde64222853c52937890d5fcbeb48d4448a2694f0dce0729d0c
6
+ metadata.gz: 32187664d7d06bd49cffa8354987ce3f11ba44b35960a92ac80353a538a15489b342f1d3e66a0ad792971489e83cc57ab05b936e93f8e04fe2f5df4a527d3d39
7
+ data.tar.gz: 9d8a75fd40c9ccbac6a9753d9b7a04b9e26a4504a55636d61d3d34c1d4dde77c6838d5ac45828a40d06b7c4658971c1f435da0c6812e7b2eda4aa5dfcfaa9cda
data/README.md CHANGED
@@ -4,7 +4,7 @@ This is a [Ruby][] implementation of [SPARQL][] for [RDF.rb][].
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/sparql.png)](https://badge.fury.io/rb/sparql)
6
6
  [![Build Status](https://github.com/ruby-rdf/sparql/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/sparql/actions?query=workflow%3ACI)
7
- [![Coverage Status](https://coveralls.io/repos/ruby-rdf/sparql/badge.svg)](https://coveralls.io/r/ruby-rdf/sparql)
7
+ [![Coverage Status](https://coveralls.io/repos/ruby-rdf/sparql/badge.svg?branch=develop)](https://coveralls.io/r/ruby-rdf/sparql?branch=develop)
8
8
  [![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf)
9
9
 
10
10
  ## Features
@@ -26,7 +26,7 @@ This is a [Ruby][] implementation of [SPARQL][] for [RDF.rb][].
26
26
  * Compatible with Ruby >= 2.2.2.
27
27
  * Compatible with older Ruby versions with the help of the [Backports][] gem.
28
28
  * Supports Unicode query strings both on all versions of Ruby.
29
- * Provisional support for [SPARQL*][].
29
+ * Provisional support for [SPARQL-star][].
30
30
 
31
31
  ## Description
32
32
 
@@ -96,9 +96,9 @@ Then, use the function in a query:
96
96
 
97
97
  See {SPARQL::Algebra::Expression.register_extension} for details.
98
98
 
99
- ### SPARQLStar (SPARQL*)
99
+ ### SPARQLStar (SPARQL-star)
100
100
 
101
- The gem supports [SPARQL*][] where patterns may include sub-patterns recursively, for a kind of Reification.
101
+ The gem supports [SPARQL-star][] where patterns may include sub-patterns recursively, for a kind of Reification.
102
102
 
103
103
  For example, the following Turtle* file uses a statement as the subject of another statement:
104
104
 
@@ -159,7 +159,7 @@ As well as a `CONSTRUCT`:
159
159
  <<?bob foaf:age ?age>> ?b ?c .
160
160
  }
161
161
 
162
- Note that results can be serialized only when the format supports [RDF*][].
162
+ Note that results can be serialized only when the format supports [RDF-star][].
163
163
 
164
164
  #### SPARQL results
165
165
 
@@ -448,8 +448,8 @@ A copy of the [SPARQL 1.0 tests][] and [SPARQL 1.1 tests][] are also included in
448
448
  [grammar]: https://www.w3.org/TR/sparql11-query/#grammar
449
449
  [RDF 1.1]: https://www.w3.org/TR/rdf11-concepts
450
450
  [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
451
+ [RDF-star]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html
452
+ [SPARQL-star]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#sparql-query-language
453
453
  [Backports]: https://rubygems.org/gems/backports
454
454
  [Linked Data]: https://rubygems.org/gems/linkeddata
455
455
  [SPARQL doc]: https://rubydoc.info/github/ruby-rdf/sparql/frames
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.4
1
+ 3.1.8
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,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)')
@@ -53,7 +55,7 @@ module SPARQL; module Algebra
53
55
  def self.open(filename, **options, &block)
54
56
  RDF::Util::File.open_file(filename, **options) do |file|
55
57
  options[:base_uri] ||= filename
56
- Expression.parse(file, options, &block)
58
+ Expression.parse(file, **options, &block)
57
59
  end
58
60
  end
59
61
 
@@ -114,8 +116,11 @@ module SPARQL; module Algebra
114
116
 
115
117
  debug(options) {"#{operator.inspect}(#{operands.map(&:inspect).join(',')})"}
116
118
  options.delete_if {|k, v| [:debug, :logger, :depth, :prefixes, :base_uri, :update, :validate].include?(k) }
117
- operands << options unless options.empty?
118
- operator.new(*operands)
119
+ begin
120
+ operator.new(*operands, **options)
121
+ rescue ArgumentError => e
122
+ error(options) {"Operator=#{operator.inspect}: #{e}"}
123
+ end
119
124
  end
120
125
 
121
126
  ##
@@ -332,7 +337,7 @@ module SPARQL; module Algebra
332
337
  # @param [Hash{Symbol => Object}] options ({})
333
338
  # options passed from query
334
339
  # @return [Expression] `self`
335
- def evaluate(bindings, options = {})
340
+ def evaluate(bindings, **options)
336
341
  self
337
342
  end
338
343
 
@@ -407,7 +412,8 @@ module SPARQL; module Algebra
407
412
  end
408
413
 
409
414
  def debug(*args, &block)
410
- Expression.debug(*args, &block)
415
+ options = args.last.is_a?(Hash) ? args.pop : {}
416
+ log_debug(*args, **options, &block)
411
417
  end
412
418
  end # Expression
413
419
  end; end # SPARQL::Algebra
@@ -308,7 +308,7 @@ module RDF::Queryable
308
308
  #
309
309
  # @example
310
310
  # queryable.query([nil, RDF::DOAP.developer, nil])
311
- # queryable.query(predicate: RDF::DOAP.developer)
311
+ # queryable.query({predicate: RDF::DOAP.developer})
312
312
  #
313
313
  # op = SPARQL::Algebra::Expression.parse(%q((bgp (triple ?a doap:developer ?b))))
314
314
  # queryable.query(op)
@@ -320,7 +320,7 @@ module RDF::Queryable
320
320
  # @yieldreturn [void] ignored
321
321
  # @return [Enumerator]
322
322
  # @see RDF::Queryable#query_pattern
323
- def query(pattern, options = {}, &block)
323
+ def query(pattern, **options, &block)
324
324
  raise TypeError, "#{self} is not queryable" if respond_to?(:queryable?) && !queryable?
325
325
 
326
326
  if pattern.is_a?(SPARQL::Algebra::Operator) && pattern.respond_to?(:execute)
@@ -529,6 +529,13 @@ class RDF::Query::Variable
529
529
  def optimize(**options)
530
530
  self
531
531
  end
532
+
533
+ # Display variable as SXP
534
+ # @return [Array]
535
+ def to_sxp
536
+ prefix = distinguished? ? (existential? ? '$' : '?') : (existential? ? '$$' : '??')
537
+ unbound? ? "#{prefix}#{name}".to_sym.to_sxp : ["#{prefix}#{name}".to_sym, value].to_sxp
538
+ end
532
539
  end # RDF::Query::Variable
533
540
 
534
541
  ##
@@ -20,7 +20,7 @@ module SPARQL; module Algebra
20
20
  # the operand
21
21
  # @return [RDF::Literal] literal of same type
22
22
  # @raise [TypeError] if the operand is not a numeric value
23
- def apply(operand)
23
+ def apply(operand, **options)
24
24
  case operand
25
25
  when RDF::Literal::Numeric then operand.abs
26
26
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
@@ -16,13 +16,20 @@ module SPARQL; module Algebra
16
16
 
17
17
  NAME = :avg
18
18
 
19
+ def initialize(*operands, **options)
20
+ raise ArgumentError,
21
+ "avg operator accepts at most one argument with an optional :distinct" if
22
+ (operands - %i{distinct}).length != 1
23
+ super
24
+ end
25
+
19
26
  ##
20
27
  # The Avg set function calculates the average value for an expression over a group. It is defined in terms of Sum and Count.
21
28
  #
22
29
  # @param [Enumerable<Array<RDF::Term>>] enum
23
30
  # enum of evaluated operand
24
31
  # @return [RDF::Literal::Numeric] The numeric average of the terms
25
- def apply(enum)
32
+ def apply(enum, **options)
26
33
  # FIXME: we don't actually do anything with distinct
27
34
  operands.shift if distinct = (operands.first == :distinct)
28
35
  if enum.empty?
@@ -22,7 +22,7 @@ module SPARQL; module Algebra
22
22
  # @yieldparam [RDF::Query::Solution] solution
23
23
  # @yieldreturn [void] ignored
24
24
  # @return [RDF::Query]
25
- def self.new(*patterns, &block)
25
+ def self.new(*patterns, **options, &block)
26
26
  RDF::Query.new(*patterns, graph_name: false, &block)
27
27
  end
28
28
  end # BGP
@@ -57,7 +57,7 @@ module SPARQL; module Algebra
57
57
  # a query solution containing zero or more variable bindings
58
58
  # @return [RDF::Node]
59
59
  # @raise [TypeError] if the operand is not a simple literal or nil
60
- def apply(literal, bindings)
60
+ def apply(literal, bindings, **options)
61
61
  @@bnode_base ||= "b0"
62
62
  @@bindings ||= bindings
63
63
  @@bnodes ||= {}
@@ -20,7 +20,7 @@ module SPARQL; module Algebra
20
20
  # the operand
21
21
  # @return [RDF::Literal] literal of same type
22
22
  # @raise [TypeError] if the operand is not a numeric value
23
- def apply(operand)
23
+ def apply(operand, **options)
24
24
  case operand
25
25
  when RDF::Literal::Numeric then operand.ceil
26
26
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
@@ -30,62 +30,68 @@ module SPARQL; module Algebra
30
30
  # @param [RDF::Literal] right
31
31
  # a literal
32
32
  # @return [RDF::Literal::Integer] `-1`, `0`, or `1`
33
- # @raise [TypeError] if either operand is not a literal
34
- def apply(left, right)
33
+ # @raise [TypeError] if either operand is not a term
34
+ def apply(left, right, **options)
35
+ RDF::Literal(spaceship(left, right, **options))
36
+ end
37
+
38
+ private
39
+ # Define <=> as private for recursive statements
40
+ def spaceship(left, right, **options)
35
41
  case
36
42
  # @see https://www.w3.org/TR/sparql11-query/#OperatorMapping
37
43
  # @see https://www.w3.org/TR/sparql11-query/#modOrderBy
38
44
  when left.is_a?(RDF::Literal) && right.is_a?(RDF::Literal)
39
- case
40
45
  # @see https://www.w3.org/TR/xpath-functions/#string-compare
41
46
  # @see https://www.w3.org/TR/xpath-functions/#comp.numeric
42
47
  # @see https://www.w3.org/TR/xpath-functions/#op.boolean
43
48
  # @see https://www.w3.org/TR/xpath-functions/#comp.duration.datetime
44
- when (left.simple? && right.simple?) ||
45
- (left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)) ||
46
- (left.datatype == right.datatype && left.language == right.language)
47
- RDF::Literal(left.send(self.class.const_get(:NAME), right))
48
-
49
- # A plain literal is lower than an RDF literal with type xsd:string of the same lexical form.
50
- when left.simple? && right.datatype == RDF::XSD.string && left.value == right.value
51
- RDF::Literal(-1)
52
- when right.simple? && left.datatype == RDF::XSD.string && right.value == left.value
53
- RDF::Literal(-1)
54
-
55
- else
56
- left <=> right
57
- end
58
-
49
+ left <=> right
59
50
  when left.is_a?(RDF::URI) && right.is_a?(RDF::URI)
51
+ raise TypeError, "Comparing IRIs not supported" unless options[:order_by] || left == right
60
52
  # Pairs of IRIs are ordered by comparing them as simple literals.
61
- RDF::Literal(RDF::Literal(left.to_s).send(self.class.const_get(:NAME), RDF::Literal(right.to_s)))
53
+ left.to_s <=> right.to_s
62
54
  when left.is_a?(RDF::Node) && right.is_a?(RDF::Node)
55
+ raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by] || left == right
63
56
  # BNode comparison is undefined.
64
- RDF::Literal(0)
57
+ left == right ? 0 : 1
65
58
  when left.nil? && right.nil?
66
- RDF::Literal(0)
67
-
59
+ 0
60
+
61
+ when left.is_a?(RDF::Statement) && right.is_a?(RDF::Statement)
62
+ v = spaceship(left.subject, right.subject, **options)
63
+ v = spaceship(left.predicate, right.predicate, **options) if v == 0
64
+ v = spaceship(left.object, right.object, **options) if v == 0
65
+ v
66
+ when left.is_a?(RDF::Statement) && right.is_a?(RDF::Term)
67
+ raise TypeError, "Comparing statement with #{right.inspect}" unless options[:order_by]
68
+ 1
69
+ when right.is_a?(RDF::Statement) && left.is_a?(RDF::Term)
70
+ raise TypeError, "Comparing statement with #{left.inspect}" unless options[:order_by]
71
+ -1
72
+
68
73
  # SPARQL also fixes an order between some kinds of RDF terms that would not otherwise be ordered:
69
74
 
70
75
  when left.nil? && !right.nil?
71
- RDF::Literal(-1)
76
+ -1
72
77
  when right.nil?
73
- RDF::Literal(1)
78
+ 1
74
79
 
75
80
  when left.is_a?(RDF::Node) && right.is_a?(RDF::Term)
76
- RDF::Literal(-1)
81
+ raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by]
82
+ # Nodes lower than other terms
83
+ -1
77
84
  when right.is_a?(RDF::Node) && left.is_a?(RDF::Term)
78
- RDF::Literal(1)
79
-
80
- when left.is_a?(RDF::Node) && right.is_a?(RDF::URI)
81
- RDF::Literal(-1)
82
- when right.is_a?(RDF::Node) && left.is_a?(RDF::URI)
83
- RDF::Literal(1)
85
+ raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by]
86
+ 1
84
87
 
85
88
  when left.is_a?(RDF::URI) && right.is_a?(RDF::Term)
86
- RDF::Literal(-1)
89
+ raise TypeError, "Comparing IRIs not supported" unless options[:order_by]
90
+ # IRIs lower than terms other than nodes
91
+ -1
87
92
  when right.is_a?(RDF::URI) && left.is_a?(RDF::Term)
88
- RDF::Literal(1)
93
+ raise TypeError, "Comparing IRIs not supported" unless options[:order_by]
94
+ 1
89
95
  else raise TypeError, "expected two RDF::Term operands, but got #{left.inspect} and #{right.inspect}"
90
96
  end
91
97
  end
@@ -52,10 +52,11 @@ module SPARQL; module Algebra
52
52
  terms[r] = case o = pattern.send(r)
53
53
  when RDF::Node then nodes[o] ||= RDF::Node.new
54
54
  when RDF::Query::Variable then solution[o]
55
+ when RDF::Query::Pattern then RDF::Statement.from(o.dup.bind(solution))
55
56
  else o
56
57
  end
57
58
  end
58
-
59
+
59
60
  statement = RDF::Statement.from(terms)
60
61
 
61
62
  # Sanity checking on statement
@@ -31,7 +31,7 @@ module SPARQL; module Algebra
31
31
  # a literal
32
32
  # @return [RDF::Literal::Boolean]
33
33
  # @raise [TypeError] if operands are not compatible
34
- def apply(left, right)
34
+ def apply(left, right, **options)
35
35
  case
36
36
  when !left.compatible?(right)
37
37
  raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
@@ -22,7 +22,7 @@ module SPARQL; module Algebra
22
22
  # @param [Enumerable<Array<RDF::Term>>] enum
23
23
  # enum of evaluated operand
24
24
  # @return [RDF::Literal::Integer] The number of non-error terms in the multiset
25
- def apply(enum)
25
+ def apply(enum, **options)
26
26
  RDF::Literal(enum.length)
27
27
  end
28
28
  end # Count
@@ -27,7 +27,7 @@ module SPARQL; module Algebra
27
27
  # a typed or simple literal
28
28
  # @return [RDF::URI] the datatype IRI, or `xsd:string` for simple literals
29
29
  # @raise [TypeError] if the operand is not a typed or simple literal
30
- def apply(literal)
30
+ def apply(literal, **options)
31
31
  case literal
32
32
  when RDF::Literal then literal.datatype
33
33
  else raise TypeError, "expected an RDF::Literal, but got #{literal.inspect}"
@@ -22,7 +22,7 @@ module SPARQL; module Algebra
22
22
  # the operand
23
23
  # @return [RDF::Literal]
24
24
  # @raise [TypeError] if the operand is not a simple literal
25
- def apply(operand)
25
+ def apply(operand, **options)
26
26
  raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
27
27
  RDF::Literal(operand.object.day)
28
28
  end
@@ -21,7 +21,7 @@ module SPARQL; module Algebra
21
21
  # a numeric literal
22
22
  # @return [RDF::Literal::Numeric]
23
23
  # @raise [TypeError] if either operand is not a numeric literal
24
- def apply(left, right)
24
+ def apply(left, right, **options)
25
25
  case
26
26
  when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
27
27
  # For xsd:decimal and xsd:integer operands, if the divisor is
@@ -27,7 +27,7 @@ module SPARQL; module Algebra
27
27
  # the operand
28
28
  # @return [RDF::Literal] literal of same type
29
29
  # @raise [TypeError] if the operand is not a literal value
30
- def apply(operand)
30
+ def apply(operand, **options)
31
31
  case operand
32
32
  when RDF::Literal then RDF::Literal(CGI.escape(operand.to_s))
33
33
  else raise TypeError, "expected an RDF::Literal, but got #{operand.inspect}"
@@ -26,7 +26,7 @@ module SPARQL; module Algebra
26
26
  # @raise [TypeError] if either operand is not an RDF term or operands are not comperable
27
27
  #
28
28
  # @see RDF::Term#==
29
- def apply(term1, term2)
29
+ def apply(term1, term2, **options)
30
30
  term1 = term1.dup.extend(RDF::TypeCheck)
31
31
  term2 = term2.dup.extend(RDF::TypeCheck)
32
32
  RDF::Literal(term1 == term2)