sparql 3.1.2 → 3.1.7

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -12
  3. data/VERSION +1 -1
  4. data/bin/sparql +20 -11
  5. data/lib/sinatra/sparql.rb +1 -1
  6. data/lib/sparql.rb +5 -6
  7. data/lib/sparql/algebra.rb +4 -4
  8. data/lib/sparql/algebra/aggregate.rb +1 -1
  9. data/lib/sparql/algebra/evaluatable.rb +4 -4
  10. data/lib/sparql/algebra/expression.rb +46 -31
  11. data/lib/sparql/algebra/extensions.rb +52 -25
  12. data/lib/sparql/algebra/operator.rb +22 -17
  13. data/lib/sparql/algebra/operator/abs.rb +1 -1
  14. data/lib/sparql/algebra/operator/avg.rb +8 -1
  15. data/lib/sparql/algebra/operator/bgp.rb +1 -1
  16. data/lib/sparql/algebra/operator/bnode.rb +1 -1
  17. data/lib/sparql/algebra/operator/ceil.rb +1 -1
  18. data/lib/sparql/algebra/operator/compare.rb +39 -33
  19. data/lib/sparql/algebra/operator/construct.rb +2 -1
  20. data/lib/sparql/algebra/operator/contains.rb +1 -1
  21. data/lib/sparql/algebra/operator/count.rb +1 -1
  22. data/lib/sparql/algebra/operator/dataset.rb +1 -1
  23. data/lib/sparql/algebra/operator/datatype.rb +1 -1
  24. data/lib/sparql/algebra/operator/day.rb +1 -1
  25. data/lib/sparql/algebra/operator/delete.rb +2 -2
  26. data/lib/sparql/algebra/operator/delete_where.rb +1 -1
  27. data/lib/sparql/algebra/operator/divide.rb +1 -1
  28. data/lib/sparql/algebra/operator/encode_for_uri.rb +1 -1
  29. data/lib/sparql/algebra/operator/equal.rb +1 -1
  30. data/lib/sparql/algebra/operator/extend.rb +2 -12
  31. data/lib/sparql/algebra/operator/floor.rb +1 -1
  32. data/lib/sparql/algebra/operator/graph.rb +1 -1
  33. data/lib/sparql/algebra/operator/greater_than.rb +3 -2
  34. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +2 -2
  35. data/lib/sparql/algebra/operator/group_concat.rb +1 -1
  36. data/lib/sparql/algebra/operator/hours.rb +1 -1
  37. data/lib/sparql/algebra/operator/insert.rb +1 -1
  38. data/lib/sparql/algebra/operator/iri.rb +1 -1
  39. data/lib/sparql/algebra/operator/is_blank.rb +1 -1
  40. data/lib/sparql/algebra/operator/is_iri.rb +1 -1
  41. data/lib/sparql/algebra/operator/is_literal.rb +1 -1
  42. data/lib/sparql/algebra/operator/is_numeric.rb +1 -1
  43. data/lib/sparql/algebra/operator/is_triple.rb +30 -0
  44. data/lib/sparql/algebra/operator/lang.rb +1 -1
  45. data/lib/sparql/algebra/operator/lang_matches.rb +1 -1
  46. data/lib/sparql/algebra/operator/lcase.rb +1 -1
  47. data/lib/sparql/algebra/operator/left_join.rb +4 -0
  48. data/lib/sparql/algebra/operator/less_than.rb +3 -2
  49. data/lib/sparql/algebra/operator/less_than_or_equal.rb +2 -2
  50. data/lib/sparql/algebra/operator/max.rb +8 -1
  51. data/lib/sparql/algebra/operator/md5.rb +1 -1
  52. data/lib/sparql/algebra/operator/min.rb +8 -1
  53. data/lib/sparql/algebra/operator/minutes.rb +1 -1
  54. data/lib/sparql/algebra/operator/month.rb +1 -1
  55. data/lib/sparql/algebra/operator/multiply.rb +1 -1
  56. data/lib/sparql/algebra/operator/negate.rb +1 -1
  57. data/lib/sparql/algebra/operator/not.rb +1 -1
  58. data/lib/sparql/algebra/operator/not_equal.rb +3 -1
  59. data/lib/sparql/algebra/operator/now.rb +1 -1
  60. data/lib/sparql/algebra/operator/object.rb +27 -0
  61. data/lib/sparql/algebra/operator/order.rb +7 -1
  62. data/lib/sparql/algebra/operator/plus.rb +1 -1
  63. data/lib/sparql/algebra/operator/predicate.rb +27 -0
  64. data/lib/sparql/algebra/operator/rand.rb +1 -1
  65. data/lib/sparql/algebra/operator/regex.rb +1 -1
  66. data/lib/sparql/algebra/operator/replace.rb +1 -1
  67. data/lib/sparql/algebra/operator/round.rb +1 -1
  68. data/lib/sparql/algebra/operator/same_term.rb +1 -1
  69. data/lib/sparql/algebra/operator/sample.rb +9 -2
  70. data/lib/sparql/algebra/operator/seconds.rb +1 -1
  71. data/lib/sparql/algebra/operator/sha1.rb +1 -1
  72. data/lib/sparql/algebra/operator/sha256.rb +1 -1
  73. data/lib/sparql/algebra/operator/sha384.rb +1 -1
  74. data/lib/sparql/algebra/operator/sha512.rb +1 -1
  75. data/lib/sparql/algebra/operator/str.rb +1 -1
  76. data/lib/sparql/algebra/operator/strafter.rb +1 -1
  77. data/lib/sparql/algebra/operator/strbefore.rb +1 -1
  78. data/lib/sparql/algebra/operator/strdt.rb +1 -1
  79. data/lib/sparql/algebra/operator/strends.rb +1 -1
  80. data/lib/sparql/algebra/operator/strlang.rb +1 -1
  81. data/lib/sparql/algebra/operator/strlen.rb +1 -1
  82. data/lib/sparql/algebra/operator/strstarts.rb +1 -1
  83. data/lib/sparql/algebra/operator/struuid.rb +1 -1
  84. data/lib/sparql/algebra/operator/subject.rb +29 -0
  85. data/lib/sparql/algebra/operator/substr.rb +1 -1
  86. data/lib/sparql/algebra/operator/subtract.rb +1 -1
  87. data/lib/sparql/algebra/operator/sum.rb +1 -1
  88. data/lib/sparql/algebra/operator/timezone.rb +1 -1
  89. data/lib/sparql/algebra/operator/triple.rb +27 -0
  90. data/lib/sparql/algebra/operator/tz.rb +1 -1
  91. data/lib/sparql/algebra/operator/ucase.rb +1 -1
  92. data/lib/sparql/algebra/operator/uuid.rb +1 -1
  93. data/lib/sparql/algebra/operator/with.rb +1 -1
  94. data/lib/sparql/algebra/operator/year.rb +1 -1
  95. data/lib/sparql/extensions.rb +6 -12
  96. data/lib/sparql/grammar.rb +2 -28
  97. data/lib/sparql/grammar/meta.rb +5739 -2365
  98. data/lib/sparql/grammar/parser11.rb +119 -59
  99. data/lib/sparql/grammar/terminals11.rb +3 -0
  100. data/lib/sparql/results.rb +17 -9
  101. metadata +31 -42
@@ -54,6 +54,10 @@ module SPARQL; module Algebra
54
54
  autoload :Timezone, 'sparql/algebra/operator/timezone'
55
55
  autoload :TZ, 'sparql/algebra/operator/tz'
56
56
  autoload :Year, 'sparql/algebra/operator/year'
57
+ autoload :IsTriple, 'sparql/algebra/operator/is_triple'
58
+ autoload :Subject, 'sparql/algebra/operator/subject'
59
+ autoload :Predicate, 'sparql/algebra/operator/predicate'
60
+ autoload :Object, 'sparql/algebra/operator/object'
57
61
 
58
62
  # Binary operators
59
63
  autoload :And, 'sparql/algebra/operator/and'
@@ -294,6 +298,14 @@ module SPARQL; module Algebra
294
298
  when :update then Update
295
299
  when :using then Using
296
300
  when :with then With
301
+
302
+ # RDF-star
303
+ when :istriple then IsTriple
304
+ when :triple then Triple
305
+ when :subject then Subject
306
+ when :predicate then Predicate
307
+ when :object then Object
308
+
297
309
  else nil # not found
298
310
  end
299
311
  end
@@ -302,8 +314,8 @@ module SPARQL; module Algebra
302
314
  # @param [Array<RDF::Term>] operands
303
315
  # @return [RDF::Term]
304
316
  # @see Operator#evaluate
305
- def self.evaluate(*operands)
306
- self.new(*operands).evaluate(RDF::Query::Solution.new)
317
+ def self.evaluate(*operands, **options)
318
+ self.new(*operands, **options).evaluate(RDF::Query::Solution.new, **options)
307
319
  end
308
320
 
309
321
  ##
@@ -336,8 +348,8 @@ module SPARQL; module Algebra
336
348
  # @option options [Boolean] :memoize (false)
337
349
  # whether to memoize results for particular operands
338
350
  # @raise [TypeError] if any operand is invalid
339
- def initialize(*operands)
340
- @options = operands.last.is_a?(Hash) ? operands.pop.dup : {}
351
+ def initialize(*operands, **options)
352
+ @options = options.dup
341
353
  @operands = operands.map! do |operand|
342
354
  case operand
343
355
  when Array
@@ -358,7 +370,7 @@ module SPARQL; module Algebra
358
370
  ##
359
371
  # Deep duplicate operands
360
372
  def deep_dup
361
- self.class.new(*operands.map(&:deep_dup))
373
+ self.class.new(*operands.map(&:deep_dup), **@options)
362
374
  end
363
375
 
364
376
  ##
@@ -571,13 +583,6 @@ module SPARQL; module Algebra
571
583
  #
572
584
  # @return [String]
573
585
  def to_sxp
574
- begin
575
- require 'sxp' # @see https://rubygems.org/gems/sxp
576
- rescue LoadError
577
- abort "SPARQL::Algebra::Operator#to_sxp requires the SXP gem (hint: `gem install sxp')."
578
- end
579
- require 'sparql/algebra/sxp_extensions'
580
-
581
586
  to_sxp_bin.to_sxp
582
587
  end
583
588
 
@@ -752,7 +757,7 @@ module SPARQL; module Algebra
752
757
  ##
753
758
  # @param [Hash{Symbol => Object}] options
754
759
  # any additional options (see {Operator#initialize})
755
- def initialize(options = {})
760
+ def initialize(**options)
756
761
  super
757
762
  end
758
763
  end # Nullary
@@ -771,7 +776,7 @@ module SPARQL; module Algebra
771
776
  # the operand
772
777
  # @param [Hash{Symbol => Object}] options
773
778
  # any additional options (see {Operator#initialize})
774
- def initialize(arg, options = {})
779
+ def initialize(arg, **options)
775
780
  super
776
781
  end
777
782
  end # Unary
@@ -792,7 +797,7 @@ module SPARQL; module Algebra
792
797
  # the second operand
793
798
  # @param [Hash{Symbol => Object}] options
794
799
  # any additional options (see {Operator#initialize})
795
- def initialize(arg1, arg2, options = {})
800
+ def initialize(arg1, arg2, **options)
796
801
  super
797
802
  end
798
803
  end # Binary
@@ -815,7 +820,7 @@ module SPARQL; module Algebra
815
820
  # the third operand
816
821
  # @param [Hash{Symbol => Object}] options
817
822
  # any additional options (see {Operator#initialize})
818
- def initialize(arg1, arg2, arg3, options = {})
823
+ def initialize(arg1, arg2, arg3, **options)
819
824
  super
820
825
  end
821
826
  end # Ternary
@@ -840,7 +845,7 @@ module SPARQL; module Algebra
840
845
  # the forth operand
841
846
  # @param [Hash{Symbol => Object}] options
842
847
  # any additional options (see {Operator#initialize})
843
- def initialize(arg1, arg2, arg3, arg4, options = {})
848
+ def initialize(arg1, arg2, arg3, arg4, **options)
844
849
  super
845
850
  end
846
851
  end # Ternary
@@ -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
@@ -141,7 +141,7 @@ module SPARQL; module Algebra
141
141
  debug(options) {"=> default data source #{uri}"}
142
142
  default_datasets << uri
143
143
  end
144
- load_opts = {debug: options.fetch(:debug, nil), graph_name: uri, base_uri: uri}
144
+ load_opts = {logger: options.fetch(:logger, false), graph_name: uri, base_uri: uri}
145
145
  unless queryable.has_graph?(uri)
146
146
  debug(options) {"=> load #{uri}"}
147
147
  queryable.load(uri.to_s, **load_opts)
@@ -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
@@ -32,7 +32,7 @@ module SPARQL; module Algebra
32
32
  # If `from` does not exist, unless the `silent` operator is present
33
33
  # @see https://www.w3.org/TR/sparql11-update/
34
34
  def execute(queryable, solutions: nil, **options)
35
- debug(options) {"Delete: #{solution} against #{operands.to_sse}"}
35
+ debug(options) {"Delete: #{solutions} against #{operands.to_sse}"}
36
36
  # Only binds the first solution
37
37
  solution = solutions.is_a?(RDF::Query::Solutions) ? solutions.first : solutions
38
38
  # Operands are an array of patterns and Queries (when named).
@@ -47,7 +47,7 @@ module SPARQL; module Algebra
47
47
  end
48
48
  patterns.each do |pattern|
49
49
  pattern = pattern.dup.bind(solution)
50
- debug(options) {"Delete statement #{statement.to_sse}"}
50
+ debug(options) {"Delete pattern #{pattern.to_sse}"}
51
51
  queryable.delete(RDF::Statement.from(pattern)) if pattern.bound? || pattern.constant?
52
52
  end
53
53
  queryable
@@ -46,7 +46,7 @@ module SPARQL; module Algebra
46
46
  debug(options) {"DeleteWhere solution #{solution.to_sse}"}
47
47
  query.each_statement do |pattern|
48
48
  pattern = pattern.dup.bind(solution)
49
- debug(options) {"DeleteWhere statement #{statement.to_sse}"}
49
+ debug(options) {"DeleteWhere pattern #{pattern.to_sse}"}
50
50
  queryable.delete(RDF::Statement.from(pattern)) if pattern.bound? || pattern.constant?
51
51
  end
52
52
  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)
@@ -28,12 +28,6 @@ module SPARQL; module Algebra
28
28
  #
29
29
  # Extend(Ω, var, expr) = { Extend(μ, var, expr) | μ in Ω }
30
30
  #
31
- # For SPARQL*, expr may be an embedded tiple pattern
32
- #
33
- # (extend
34
- # ((?t (triple ?bob foaf:age ?age)))
35
- # (bgp (triple ?t dct:source ?src)))
36
- #
37
31
  # @param [RDF::Queryable] queryable
38
32
  # the graph or repository to query
39
33
  # @param [Hash{Symbol => Object}] options
@@ -56,12 +50,8 @@ module SPARQL; module Algebra
56
50
  depth: options[:depth].to_i + 1,
57
51
  **options)
58
52
  debug(options) {"===> + #{var} => #{val.inspect}"}
59
- solution.bindings[var.to_sym] = if val.is_a?(RDF::Query::Pattern)
60
- # Variable is bound to the solution
61
- val.bind(solution)
62
- else
63
- val
64
- end
53
+ val = val.dup.bind(solution) if val.is_a?(RDF::Query::Pattern)
54
+ solution.bindings[var.to_sym] = val
65
55
  rescue TypeError => e
66
56
  # Evaluates to error, ignore
67
57
  debug(options) {"===> #{var} error: #{e.message}"}
@@ -24,7 +24,7 @@ module SPARQL; module Algebra
24
24
  # the operand
25
25
  # @return [RDF::Literal] literal of same type
26
26
  # @raise [TypeError] if the operand is not a numeric value
27
- def apply(operand)
27
+ def apply(operand, **options)
28
28
  case operand
29
29
  when RDF::Literal::Numeric then operand.floor
30
30
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
@@ -36,7 +36,7 @@ module SPARQL; module Algebra
36
36
  # @param [Array<RDF::Query::Pattern>] patterns
37
37
  # Quads
38
38
  # @return [RDF::Query]
39
- def self.new(name, patterns, &block)
39
+ def self.new(name, patterns, **options, &block)
40
40
  case patterns
41
41
  when RDF::Query
42
42
  # Record that the argument as a (bgp) for re-serialization back to SSE