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
@@ -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, options = {}, &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
@@ -24,8 +24,9 @@ module SPARQL; module Algebra
24
24
  # a literal
25
25
  # @return [RDF::Literal::Boolean] `true` or `false`
26
26
  # @raise [TypeError] if either operand is not a literal
27
- def apply(left, right)
28
- super
27
+ def apply(left, right, **options)
28
+ #require 'byebug'; byebug if super == RDF::Literal(1)
29
+ RDF::Literal(super == RDF::Literal(1))
29
30
  end
30
31
  end # GreaterThan
31
32
  end # Operator
@@ -25,8 +25,8 @@ module SPARQL; module Algebra
25
25
  # a literal
26
26
  # @return [RDF::Literal::Boolean] `true` or `false`
27
27
  # @raise [TypeError] if either operand is not a literal
28
- def apply(left, right)
29
- super
28
+ def apply(left, right, **options)
29
+ RDF::Literal(super >= RDF::Literal(0))
30
30
  end
31
31
  end # GreaterThanOrEqual
32
32
  end # Operator
@@ -50,7 +50,7 @@ module SPARQL; module Algebra
50
50
  # enum of evaluated operand
51
51
  # @return [RDF::Term] An arbitrary term
52
52
  # @raise [TypeError] If enum is empty
53
- def apply(enum, separator)
53
+ def apply(enum, separator, **options)
54
54
  RDF::Literal(enum.flatten.map(&:to_s).join(separator.to_s))
55
55
  end
56
56
  end # GroupConcat
@@ -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.hour)
28
28
  end
@@ -29,7 +29,7 @@ module SPARQL; module Algebra
29
29
  # a simple literal
30
30
  # @return [RDF::URI]
31
31
  # @raise [TypeError] if the operand is not a simple literal
32
- def apply(literal)
32
+ def apply(literal, **options)
33
33
  raise TypeError, "expected an simple literal, but got #{literal.inspect}" unless literal.literal? && literal.simple?
34
34
  base = Operator.base_uri || RDF::URI("")
35
35
  base.join(literal.to_s)
@@ -23,7 +23,7 @@ module SPARQL; module Algebra
23
23
  # an RDF term
24
24
  # @return [RDF::Literal::Boolean] `true` or `false`
25
25
  # @raise [TypeError] if the operand is not an RDF term
26
- def apply(term)
26
+ def apply(term, **options)
27
27
  case term
28
28
  when RDF::Node then RDF::Literal::TRUE
29
29
  when RDF::Term then RDF::Literal::FALSE
@@ -23,7 +23,7 @@ module SPARQL; module Algebra
23
23
  # an RDF term
24
24
  # @return [RDF::Literal::Boolean] `true` or `false`
25
25
  # @raise [TypeError] if the operand is not an RDF term
26
- def apply(term)
26
+ def apply(term, **options)
27
27
  case term
28
28
  when RDF::URI then RDF::Literal::TRUE
29
29
  when RDF::Term then RDF::Literal::FALSE
@@ -24,7 +24,7 @@ module SPARQL; module Algebra
24
24
  # an RDF term
25
25
  # @return [RDF::Literal::Boolean] `true` or `false`
26
26
  # @raise [TypeError] if the operand is not an RDF term
27
- def apply(term)
27
+ def apply(term, **options)
28
28
  case term
29
29
  when RDF::Literal then RDF::Literal::TRUE
30
30
  when RDF::Term then RDF::Literal::FALSE
@@ -26,7 +26,7 @@ module SPARQL; module Algebra
26
26
  # an RDF term
27
27
  # @return [RDF::Literal::Boolean] `true` or `false`
28
28
  # @raise [TypeError] if the operand is not an RDF term
29
- def apply(term)
29
+ def apply(term, **options)
30
30
  case term
31
31
  when RDF::Literal::NonPositiveInteger then RDF::Literal::FALSE
32
32
  when RDF::Literal::NonNegativeInteger then RDF::Literal::FALSE
@@ -0,0 +1,30 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL `isTRIPLE` operator.
5
+ #
6
+ # Returns true if term is an RDF-star triple. Returns false otherwise.
7
+ #
8
+ # @see https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#istriple
9
+ class IsTriple < Operator::Unary
10
+ include Evaluatable
11
+
12
+ NAME = :isTRIPLE
13
+
14
+ ##
15
+ # Returns `true` if the operand is an `RDF::Statement`, `false` otherwise.
16
+ #
17
+ # @param [RDF::Term] term
18
+ # an RDF term
19
+ # @return [RDF::Literal::Boolean] `true` or `false`
20
+ # @raise [TypeError] if the operand is not an RDF term
21
+ def apply(term, **options)
22
+ case term
23
+ when RDF::Statement then RDF::Literal::TRUE
24
+ when RDF::Term then RDF::Literal::FALSE
25
+ else raise TypeError, "expected an RDF::Term, but got #{term.inspect}"
26
+ end
27
+ end
28
+ end # IsTriple
29
+ end # Operator
30
+ end; end # SPARQL::Algebra
@@ -18,7 +18,7 @@ module SPARQL; module Algebra
18
18
  # a literal
19
19
  # @return [RDF::Literal] a simple literal
20
20
  # @raise [TypeError] if the operand is not a literal
21
- def apply(literal)
21
+ def apply(literal, **options)
22
22
  case literal
23
23
  when RDF::Literal then RDF::Literal(literal.language.to_s)
24
24
  else raise TypeError, "expected an RDF::Literal, but got #{literal.inspect}"
@@ -27,7 +27,7 @@ module SPARQL; module Algebra
27
27
  # @return [RDF::Literal::Boolean] `true` or `false`
28
28
  # @raise [TypeError] if either operand is unbound
29
29
  # @raise [TypeError] if either operand is not a simple literal
30
- def apply(language_tag, language_range)
30
+ def apply(language_tag, language_range, **options)
31
31
  raise TypeError, "expected a plain RDF::Literal for language_tag, but got #{language_tag.inspect}" unless language_tag.is_a?(RDF::Literal) && language_tag.simple?
32
32
  language_tag = language_tag.to_s.downcase
33
33
 
@@ -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 literal value
23
- def apply(operand)
23
+ def apply(operand, **options)
24
24
  case operand
25
25
  when RDF::Literal then RDF::Literal(operand.to_s.downcase, datatype: operand.datatype, language: operand.language)
26
26
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
@@ -37,6 +37,10 @@ module SPARQL; module Algebra
37
37
  def execute(queryable, **options, &block)
38
38
  filter = operand(2)
39
39
 
40
+ raise ArgumentError,
41
+ "leftjoin operator accepts at most two arguments with an optional filter" if
42
+ operands.length < 2 || operands.length > 3
43
+
40
44
  debug(options) {"LeftJoin"}
41
45
  left = queryable.query(operand(0), depth: options[:depth].to_i + 1, **options)
42
46
  debug(options) {"=>(leftjoin left) #{left.inspect}"}
@@ -24,8 +24,9 @@ module SPARQL; module Algebra
24
24
  # a literal
25
25
  # @return [RDF::Literal::Boolean] `true` or `false`
26
26
  # @raise [TypeError] if either operand is not a literal
27
- def apply(left, right)
28
- super
27
+ def apply(left, right, **options)
28
+ #require 'byebug'; byebug if super == RDF::Literal(-1)
29
+ RDF::Literal(super == RDF::Literal(-1))
29
30
  end
30
31
  end # LessThan
31
32
  end # Operator
@@ -24,8 +24,8 @@ module SPARQL; module Algebra
24
24
  # a literal
25
25
  # @return [RDF::Literal::Boolean] `true` or `false`
26
26
  # @raise [TypeError] if either operand is not a literal
27
- def apply(left, right)
28
- super
27
+ def apply(left, right, **options)
28
+ RDF::Literal(super <= RDF::Literal(0))
29
29
  end
30
30
  end # LessThanOrEqual
31
31
  end # Operator
@@ -16,6 +16,13 @@ module SPARQL; module Algebra
16
16
 
17
17
  NAME = :max
18
18
 
19
+ def initialize(*operands, **options)
20
+ raise ArgumentError,
21
+ "max 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
  # Max is a SPARQL set function that return the maximum value from a group respectively.
21
28
  #
@@ -24,7 +31,7 @@ module SPARQL; module Algebra
24
31
  # @param [Enumerable<Array<RDF::Term>>] enum
25
32
  # enum of evaluated operand
26
33
  # @return [RDF::Literal] The maximum value of the terms
27
- def apply(enum)
34
+ def apply(enum, **options)
28
35
  # FIXME: we don't actually do anything with distinct
29
36
  operands.shift if distinct = (operands.first == :distinct)
30
37
  if enum.empty?
@@ -26,7 +26,7 @@ module SPARQL; module Algebra
26
26
  # the operand
27
27
  # @return [RDF::Literal]
28
28
  # @raise [TypeError] if the operand is not a simple literal
29
- def apply(operand)
29
+ def apply(operand, **options)
30
30
  raise TypeError, "expected an RDF::Literal, but got #{operand.inspect}" unless operand.literal?
31
31
  raise TypeError, "expected simple literal or xsd:string, but got #{operand.inspect}" unless (operand.datatype || RDF::XSD.string) == RDF::XSD.string
32
32
  RDF::Literal(Digest::MD5.new.hexdigest(operand.to_s))
@@ -16,6 +16,13 @@ module SPARQL; module Algebra
16
16
 
17
17
  NAME = :min
18
18
 
19
+ def initialize(*operands, **options)
20
+ raise ArgumentError,
21
+ "min 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
  # Min is a SPARQL set function that return the minimum value from a group respectively.
21
28
  #
@@ -24,7 +31,7 @@ module SPARQL; module Algebra
24
31
  # @param [Enumerable<Array<RDF::Term>>] enum
25
32
  # enum of evaluated operand
26
33
  # @return [RDF::Literal] The maximum value of the terms
27
- def apply(enum)
34
+ def apply(enum, **options)
28
35
  # FIXME: we don't actually do anything with distinct
29
36
  operands.shift if distinct = (operands.first == :distinct)
30
37
  if enum.empty?
@@ -24,7 +24,7 @@ module SPARQL; module Algebra
24
24
  # the operand
25
25
  # @return [RDF::Literal]
26
26
  # @raise [TypeError] if the operand is not a simple literal
27
- def apply(operand)
27
+ def apply(operand, **options)
28
28
  raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
29
29
  RDF::Literal(operand.object.minute)
30
30
  end
@@ -24,7 +24,7 @@ module SPARQL; module Algebra
24
24
  # the operand
25
25
  # @return [RDF::Literal]
26
26
  # @raise [TypeError] if the operand is not a simple literal
27
- def apply(operand)
27
+ def apply(operand, **options)
28
28
  raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
29
29
  RDF::Literal(operand.object.month)
30
30
  end
@@ -22,7 +22,7 @@ module SPARQL; module Algebra
22
22
  # a numeric literal
23
23
  # @return [RDF::Literal::Numeric]
24
24
  # @raise [TypeError] if either operand is not a numeric literal
25
- def apply(left, right)
25
+ def apply(left, right, **options)
26
26
  case
27
27
  when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
28
28
  left * right
@@ -20,7 +20,7 @@ module SPARQL; module Algebra
20
20
  # a numeric literal
21
21
  # @return [RDF::Literal::Numeric]
22
22
  # @raise [TypeError] if the operand is not a numeric literal
23
- def apply(term)
23
+ def apply(term, **options)
24
24
  case term
25
25
  when RDF::Literal::Numeric then -term
26
26
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{term.inspect}"
@@ -23,7 +23,7 @@ module SPARQL; module Algebra
23
23
  # the operand
24
24
  # @return [RDF::Literal::Boolean] `true` or `false`
25
25
  # @raise [TypeError] if the operand could not be coerced to a boolean literal
26
- def apply(operand)
26
+ def apply(operand, **options)
27
27
  case bool = boolean(operand)
28
28
  when RDF::Literal::Boolean
29
29
  RDF::Literal(bool.false?)
@@ -12,13 +12,15 @@ module SPARQL; module Algebra
12
12
  # Returns `true` if the operands are not equal; returns `false`
13
13
  # otherwise.
14
14
  #
15
+ # Comparing unknown datatypes might have different lexical forms but be the same value.
16
+ #
15
17
  # @param [RDF::Term] term1
16
18
  # an RDF term
17
19
  # @param [RDF::Term] term2
18
20
  # an RDF term
19
21
  # @return [RDF::Literal::Boolean] `true` or `false`
20
22
  # @raise [TypeError] if either operand is not an RDF term
21
- def apply(term1, term2)
23
+ def apply(term1, term2, **options)
22
24
  RDF::Literal(super.false?)
23
25
  end
24
26
  end # NotEqual
@@ -23,7 +23,7 @@ module SPARQL; module Algebra
23
23
  # Returns an XSD dateTime value for the current query execution. All calls to this function in any one query execution must return the same value. The exact moment returned is not specified.
24
24
  #
25
25
  # @return [RDF::Literal::Double] random value
26
- def apply
26
+ def apply(**options)
27
27
  RDF::Literal(DateTime.now)
28
28
  end
29
29
  end # Now
@@ -0,0 +1,27 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL `OBJECT` operator.
5
+ #
6
+ # If triple is an RDF-star triple, the function returns the object of this triple. Passing anything other than an RDF-star triple is an error.
7
+ #
8
+ # @see https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#object
9
+ class Object < Operator::Unary
10
+ include Evaluatable
11
+
12
+ NAME = :object
13
+
14
+ ##
15
+ # Returns the object part of arg.
16
+ #
17
+ # @param [RDF::Statement] operand
18
+ # the operand
19
+ # @return [RDF::Literal]
20
+ # @raise [TypeError] if the operand is not a statement
21
+ def apply(operand, **options)
22
+ raise TypeError, "expected an RDF::Statement, but got #{operand.inspect}" unless operand.is_a?(RDF::Statement)
23
+ operand.object
24
+ end
25
+ end # Object
26
+ end # Operator
27
+ end; end # SPARQL::Algebra
@@ -40,7 +40,13 @@ module SPARQL; module Algebra
40
40
  memo = begin
41
41
  a_eval = op.evaluate(a, queryable: queryable, depth: options[:depth].to_i + 1, **options) rescue nil
42
42
  b_eval = op.evaluate(b, queryable: queryable, depth: options[:depth].to_i + 1, **options) rescue nil
43
- comp = Operator::Compare.evaluate(a_eval, b_eval).to_i
43
+ comp = begin
44
+ Operator::Compare.evaluate(a_eval, b_eval, order_by: true).to_s.to_i
45
+ rescue TypeError
46
+ # Type sError is effectively zero
47
+ debug(options) {"(order) rescue(#{$!}): #{a_eval.inspect}, #{b_eval.inspect}"}
48
+ RDF::Literal(0)
49
+ end
44
50
  comp = -comp if op.is_a?(Operator::Desc)
45
51
  comp
46
52
  end if memo == 0
@@ -23,7 +23,7 @@ module SPARQL; module Algebra
23
23
  # a numeric literal
24
24
  # @return [RDF::Literal::Numeric]
25
25
  # @raise [TypeError] if either operand is not a numeric literal
26
- def apply(left, right = nil)
26
+ def apply(left, right = nil, **options)
27
27
  case
28
28
  when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
29
29
  left + right
@@ -0,0 +1,27 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL `PREDICATE` operator.
5
+ #
6
+ # If triple is an RDF-star triple, the function returns the predicate of this triple. Passing anything other than an RDF-star triple is an error.
7
+ #
8
+ # @see https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#predicate
9
+ class Predicate < Operator::Unary
10
+ include Evaluatable
11
+
12
+ NAME = :predicate
13
+
14
+ ##
15
+ # Returns the predicate part of arg.
16
+ #
17
+ # @param [RDF::Statement] operand
18
+ # the operand
19
+ # @return [RDF::Literal]
20
+ # @raise [TypeError] if the operand is not a statement
21
+ def apply(operand, **options)
22
+ raise TypeError, "expected an RDF::Statement, but got #{operand.inspect}" unless operand.is_a?(RDF::Statement)
23
+ operand.predicate
24
+ end
25
+ end # Predicate
26
+ end # Operator
27
+ end; end # SPARQL::Algebra