sparql 3.1.6 → 3.2.1

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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +31 -22
  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 +28 -3
  8. data/lib/sparql/algebra/extensions.rb +109 -45
  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 +20 -2
  16. data/lib/sparql/algebra/operator/base.rb +18 -1
  17. data/lib/sparql/algebra/operator/bgp.rb +13 -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 +26 -2
  22. data/lib/sparql/algebra/operator/coalesce.rb +33 -11
  23. data/lib/sparql/algebra/operator/compare.rb +48 -40
  24. data/lib/sparql/algebra/operator/concat.rb +26 -2
  25. data/lib/sparql/algebra/operator/construct.rb +29 -6
  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 +53 -7
  29. data/lib/sparql/algebra/operator/create.rb +20 -2
  30. data/lib/sparql/algebra/operator/dataset.rb +27 -2
  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 +29 -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 +20 -3
  39. data/lib/sparql/algebra/operator/divide.rb +27 -3
  40. data/lib/sparql/algebra/operator/drop.rb +27 -3
  41. data/lib/sparql/algebra/operator/encode_for_uri.rb +23 -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 +15 -2
  45. data/lib/sparql/algebra/operator/extend.rb +64 -6
  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/function_call.rb +64 -0
  49. data/lib/sparql/algebra/operator/graph.rb +69 -6
  50. data/lib/sparql/algebra/operator/greater_than.rb +14 -4
  51. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +14 -4
  52. data/lib/sparql/algebra/operator/group.rb +105 -8
  53. data/lib/sparql/algebra/operator/group_concat.rb +44 -8
  54. data/lib/sparql/algebra/operator/hours.rb +24 -6
  55. data/lib/sparql/algebra/operator/if.rb +20 -3
  56. data/lib/sparql/algebra/operator/in.rb +18 -1
  57. data/lib/sparql/algebra/operator/insert.rb +24 -2
  58. data/lib/sparql/algebra/operator/insert_data.rb +23 -2
  59. data/lib/sparql/algebra/operator/iri.rb +22 -5
  60. data/lib/sparql/algebra/operator/is_blank.rb +21 -4
  61. data/lib/sparql/algebra/operator/is_iri.rb +21 -4
  62. data/lib/sparql/algebra/operator/is_literal.rb +21 -4
  63. data/lib/sparql/algebra/operator/is_numeric.rb +23 -6
  64. data/lib/sparql/algebra/operator/is_triple.rb +33 -1
  65. data/lib/sparql/algebra/operator/join.rb +56 -1
  66. data/lib/sparql/algebra/operator/lang.rb +26 -1
  67. data/lib/sparql/algebra/operator/lang_matches.rb +23 -2
  68. data/lib/sparql/algebra/operator/lcase.rb +23 -3
  69. data/lib/sparql/algebra/operator/left_join.rb +42 -1
  70. data/lib/sparql/algebra/operator/less_than.rb +14 -4
  71. data/lib/sparql/algebra/operator/less_than_or_equal.rb +14 -4
  72. data/lib/sparql/algebra/operator/load.rb +25 -2
  73. data/lib/sparql/algebra/operator/max.rb +20 -2
  74. data/lib/sparql/algebra/operator/md5.rb +23 -6
  75. data/lib/sparql/algebra/operator/min.rb +22 -4
  76. data/lib/sparql/algebra/operator/minus.rb +65 -7
  77. data/lib/sparql/algebra/operator/minutes.rb +24 -6
  78. data/lib/sparql/algebra/operator/modify.rb +41 -5
  79. data/lib/sparql/algebra/operator/month.rb +24 -6
  80. data/lib/sparql/algebra/operator/move.rb +20 -2
  81. data/lib/sparql/algebra/operator/multiply.rb +27 -4
  82. data/lib/sparql/algebra/operator/negate.rb +24 -4
  83. data/lib/sparql/algebra/operator/not.rb +25 -4
  84. data/lib/sparql/algebra/operator/not_equal.rb +16 -1
  85. data/lib/sparql/algebra/operator/notexists.rb +30 -6
  86. data/lib/sparql/algebra/operator/notin.rb +20 -3
  87. data/lib/sparql/algebra/operator/notoneof.rb +21 -2
  88. data/lib/sparql/algebra/operator/now.rb +25 -6
  89. data/lib/sparql/algebra/operator/object.rb +33 -1
  90. data/lib/sparql/algebra/operator/or.rb +26 -3
  91. data/lib/sparql/algebra/operator/order.rb +71 -2
  92. data/lib/sparql/algebra/operator/path.rb +29 -2
  93. data/lib/sparql/algebra/operator/path_opt.rb +21 -2
  94. data/lib/sparql/algebra/operator/path_plus.rb +21 -2
  95. data/lib/sparql/algebra/operator/path_star.rb +20 -2
  96. data/lib/sparql/algebra/operator/plus.rb +43 -4
  97. data/lib/sparql/algebra/operator/predicate.rb +33 -1
  98. data/lib/sparql/algebra/operator/prefix.rb +24 -3
  99. data/lib/sparql/algebra/operator/project.rb +69 -5
  100. data/lib/sparql/algebra/operator/rand.rb +31 -3
  101. data/lib/sparql/algebra/operator/reduced.rb +20 -3
  102. data/lib/sparql/algebra/operator/regex.rb +27 -19
  103. data/lib/sparql/algebra/operator/replace.rb +27 -7
  104. data/lib/sparql/algebra/operator/reverse.rb +31 -2
  105. data/lib/sparql/algebra/operator/round.rb +26 -3
  106. data/lib/sparql/algebra/operator/same_term.rb +25 -7
  107. data/lib/sparql/algebra/operator/sample.rb +33 -9
  108. data/lib/sparql/algebra/operator/seconds.rb +24 -6
  109. data/lib/sparql/algebra/operator/seq.rb +20 -2
  110. data/lib/sparql/algebra/operator/sequence.rb +4 -11
  111. data/lib/sparql/algebra/operator/sha1.rb +19 -2
  112. data/lib/sparql/algebra/operator/sha256.rb +19 -2
  113. data/lib/sparql/algebra/operator/sha384.rb +19 -2
  114. data/lib/sparql/algebra/operator/sha512.rb +19 -2
  115. data/lib/sparql/algebra/operator/slice.rb +27 -5
  116. data/lib/sparql/algebra/operator/str.rb +22 -2
  117. data/lib/sparql/algebra/operator/strafter.rb +26 -3
  118. data/lib/sparql/algebra/operator/strbefore.rb +26 -3
  119. data/lib/sparql/algebra/operator/strdt.rb +23 -2
  120. data/lib/sparql/algebra/operator/strends.rb +26 -4
  121. data/lib/sparql/algebra/operator/strlang.rb +25 -7
  122. data/lib/sparql/algebra/operator/strlen.rb +24 -3
  123. data/lib/sparql/algebra/operator/strstarts.rb +26 -3
  124. data/lib/sparql/algebra/operator/struuid.rb +30 -10
  125. data/lib/sparql/algebra/operator/subject.rb +33 -1
  126. data/lib/sparql/algebra/operator/substr.rb +24 -3
  127. data/lib/sparql/algebra/operator/subtract.rb +29 -3
  128. data/lib/sparql/algebra/operator/sum.rb +25 -7
  129. data/lib/sparql/algebra/operator/table.rb +76 -4
  130. data/lib/sparql/algebra/operator/timezone.rb +24 -6
  131. data/lib/sparql/algebra/operator/tz.rb +23 -6
  132. data/lib/sparql/algebra/operator/ucase.rb +24 -3
  133. data/lib/sparql/algebra/operator/union.rb +29 -6
  134. data/lib/sparql/algebra/operator/update.rb +46 -4
  135. data/lib/sparql/algebra/operator/using.rb +49 -2
  136. data/lib/sparql/algebra/operator/uuid.rb +28 -9
  137. data/lib/sparql/algebra/operator/with.rb +38 -4
  138. data/lib/sparql/algebra/operator/year.rb +24 -6
  139. data/lib/sparql/algebra/operator.rb +135 -14
  140. data/lib/sparql/algebra/sxp_extensions.rb +3 -3
  141. data/lib/sparql/algebra.rb +20 -3
  142. data/lib/sparql/grammar/meta.rb +1103 -907
  143. data/lib/sparql/grammar/parser11.rb +63 -56
  144. metadata +43 -29
  145. data/lib/sparql/algebra/operator/triple.rb +0 -27
@@ -3,8 +3,20 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `strlen` operator.
5
5
  #
6
- # @example
7
- # (strlen ?x)
6
+ # [121] BuiltInCall ::= ... 'STRLEN' '(' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # SELECT ?str (STRLEN(?str) AS ?len) WHERE {
11
+ # ?s :str ?str
12
+ # }
13
+ #
14
+ # @example SSE
15
+ # (prefix
16
+ # ((: <http://example.org/>))
17
+ # (project (?str ?len)
18
+ # (extend ((?len (strlen ?str)))
19
+ # (bgp (triple ?s :str ?str)))))
8
20
  #
9
21
  # @see https://www.w3.org/TR/sparql11-query/#func-strlen
10
22
  # @see https://www.w3.org/TR/xpath-functions/#func-string-length
@@ -25,10 +37,19 @@ module SPARQL; module Algebra
25
37
  # the operand
26
38
  # @return [RDF::Literal::Integer] length of string
27
39
  # @raise [TypeError] if the operand is not a numeric value
28
- def apply(operand)
40
+ def apply(operand, **options)
29
41
  raise TypeError, "expected a plain RDF::Literal, but got #{operand.inspect}" unless operand.literal? && operand.plain?
30
42
  RDF::Literal(operand.to_s.length)
31
43
  end
44
+
45
+ ##
46
+ #
47
+ # Returns a partial SPARQL grammar for this operator.
48
+ #
49
+ # @return [String]
50
+ def to_sparql(**options)
51
+ "STRLEN(" + operands.to_sparql(delimiter: ', ', **options) + ")"
52
+ end
32
53
  end # StrLen
33
54
  end # Operator
34
55
  end; end # SPARQL::Algebra
@@ -3,8 +3,22 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # A SPARQL `strstarts` operator.
5
5
  #
6
- # @example
7
- # (strstarts ?x ?y)
6
+ # [121] BuiltInCall ::= ... | 'STRSTARTS' '(' Expression ',' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+
11
+ # SELECT ?s ?str WHERE {
12
+ # ?s :str ?str
13
+ # FILTER STRSTARTS(?str, "a")
14
+ # }
15
+ #
16
+ # @example SSE
17
+ # (prefix
18
+ # ((: <http://example.org/>))
19
+ # (project (?s ?str)
20
+ # (filter (strstarts ?str "a")
21
+ # (bgp (triple ?s :str ?str)))))
8
22
  #
9
23
  # @see https://www.w3.org/TR/sparql11-query/#func-strstarts
10
24
  # @see https://www.w3.org/TR/xpath-functions/#func-starts-with
@@ -33,7 +47,7 @@ module SPARQL; module Algebra
33
47
  # a literal
34
48
  # @return [RDF::Literal::Boolean]
35
49
  # @raise [TypeError] if operands are not compatible
36
- def apply(left, right)
50
+ def apply(left, right, **options)
37
51
  case
38
52
  when !left.compatible?(right)
39
53
  raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
@@ -41,6 +55,15 @@ module SPARQL; module Algebra
41
55
  else RDF::Literal::FALSE
42
56
  end
43
57
  end
58
+
59
+ ##
60
+ #
61
+ # Returns a partial SPARQL grammar for this operator.
62
+ #
63
+ # @return [String]
64
+ def to_sparql(**options)
65
+ "STRSTARTS(" + operands.to_sparql(delimiter: ', ', **options) + ")"
66
+ end
44
67
  end # StrStarts
45
68
  end # Operator
46
69
  end; end # SPARQL::Algebra
@@ -3,16 +3,27 @@ require 'securerandom'
3
3
  module SPARQL; module Algebra
4
4
  class Operator
5
5
  ##
6
- # The SPARQL `uuid` function.
6
+ # [121] BuiltInCall ::= ... | 'STRUUID' NIL
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>)
10
- # (xsd: <http://www.w3.org/2001/XMLSchema#>))
11
- # (project (?length)
12
- # (extend ((?length (strlen ?uuid)))
13
- # (filter (&& (isLiteral ?uuid) (regex ?uuid "^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$" "i"))
14
- # (extend ((?uuid (struuid)))
15
- # (bgp))))))
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ # SELECT (STRLEN(?uuid) AS ?length)
12
+ # WHERE {
13
+ # BIND(STRUUID() AS ?uuid)
14
+ # FILTER(ISLITERAL(?uuid) && REGEX(?uuid, "^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$", "i"))
15
+ # }
16
+ #
17
+ # @example SSE
18
+ # (prefix ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
19
+ # (project (?length)
20
+ # (extend ((?length (strlen ?uuid)))
21
+ # (filter
22
+ # (&&
23
+ # (isLiteral ?uuid)
24
+ # (regex ?uuid "^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$" "i"))
25
+ # (extend ((?uuid (struuid)))
26
+ # (bgp))))))
16
27
  #
17
28
  # @see https://www.w3.org/TR/sparql11-query/#func-struuid
18
29
  class StrUUID < Operator::Nullary
@@ -24,9 +35,18 @@ module SPARQL; module Algebra
24
35
  # Return a string that is the scheme specific part of UUID. That is, as a simple literal, the result of generating a UUID, converting to a simple literal and removing the initial urn:uuid:.
25
36
  #
26
37
  # @return [RDF::URI]
27
- def apply
38
+ def apply(**options)
28
39
  RDF::Literal(SecureRandom.uuid)
29
40
  end
41
+
42
+ ##
43
+ #
44
+ # Returns a partial SPARQL grammar for this operator.
45
+ #
46
+ # @return [String]
47
+ def to_sparql(**options)
48
+ "STRUUID(" + operands.to_sparql(delimiter: ', ', **options) + ")"
49
+ end
30
50
  end # StrUUID
31
51
  end # Operator
32
52
  end; end # SPARQL::Algebra
@@ -7,6 +7,29 @@ module SPARQL; module Algebra
7
7
  #
8
8
  # If triple is an RDF-star triple, the function returns the subject of this triple. Passing anything other than an RDF-star triple is an error.
9
9
  #
10
+ # [121] BuiltInCall ::= ... | 'SUBJECT' '(' Expression ')'
11
+ #
12
+ # @example SPARQL Grammar
13
+ # PREFIX : <http://example.com/ns#>
14
+ # SELECT * {
15
+ # ?t :source :g
16
+ # FILTER(isTriple(?t))
17
+ # FILTER(SUBJECT(?t) = :s)
18
+ # FILTER(PREDICATE(?t) = :p)
19
+ # FILTER(OBJECT(?t) = :o)
20
+ # }
21
+ #
22
+ # @example SSE
23
+ # (prefix
24
+ # ((: <http://example.com/ns#>))
25
+ # (filter
26
+ # (exprlist
27
+ # (isTRIPLE ?t)
28
+ # (= (subject ?t) :s)
29
+ # (= (predicate ?t) :p)
30
+ # (= (object ?t) :o))
31
+ # (bgp (triple ?t :source :g))) )
32
+ #
10
33
  # @see https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#subject
11
34
  class Subject < Operator::Unary
12
35
  include Evaluatable
@@ -20,10 +43,19 @@ module SPARQL; module Algebra
20
43
  # the operand
21
44
  # @return [RDF::Literal]
22
45
  # @raise [TypeError] if the operand is not a statement
23
- def apply(operand)
46
+ def apply(operand, **options)
24
47
  raise TypeError, "expected an RDF::Statement, but got #{operand.inspect}" unless operand.is_a?(RDF::Statement)
25
48
  operand.subject
26
49
  end
50
+
51
+ ##
52
+ #
53
+ # Returns a partial SPARQL grammar for this operator.
54
+ #
55
+ # @return [String]
56
+ def to_sparql(**options)
57
+ "SUBJECT(" + operands.last.to_sparql(**options) + ")"
58
+ end
27
59
  end # Subject
28
60
  end # Operator
29
61
  end; end # SPARQL::Algebra
@@ -3,8 +3,20 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # A SPARQL `substr` operator.
5
5
  #
6
- # @example
7
- # (substr ?x ?y)
6
+ # [123] SubstringExpression ::= 'SUBSTR' '(' Expression ',' Expression ( ',' Expression )? ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # SELECT ?s ?str (SUBSTR(?str,1,1) AS ?substr)
11
+ # WHERE {
12
+ # ?s :str ?str
13
+ # }
14
+ #
15
+ # @example SSE
16
+ # (prefix ((: <http://example.org/>))
17
+ # (project (?s ?str ?substr)
18
+ # (extend ((?substr (substr ?str 1 1)))
19
+ # (bgp (triple ?s :str ?str)))))
8
20
  #
9
21
  # @see https://www.w3.org/TR/sparql11-query/#func-substr
10
22
  # @see https://www.w3.org/TR/xpath-functions/#func-substring
@@ -49,7 +61,7 @@ module SPARQL; module Algebra
49
61
  # an optional length of the substring.
50
62
  # @return [RDF::Literal]
51
63
  # @raise [TypeError] if operands are not compatible
52
- def apply(source, startingLoc, length)
64
+ def apply(source, startingLoc, length, **options)
53
65
  raise TypeError, "expected a plain RDF::Literal, but got #{source.inspect}" unless source.literal? && source.plain?
54
66
  text = text.to_s
55
67
 
@@ -75,6 +87,15 @@ module SPARQL; module Algebra
75
87
  def to_sxp_bin
76
88
  [NAME] + operands.reject {|o| o.to_s == ""}
77
89
  end
90
+
91
+ ##
92
+ #
93
+ # Returns a partial SPARQL grammar for this operator.
94
+ #
95
+ # @return [String]
96
+ def to_sparql(**options)
97
+ "SUBSTR(" + operands.to_sparql(delimiter: ', ', **options) + ")"
98
+ end
78
99
  end # SubStr
79
100
  end # Operator
80
101
  end; end # SPARQL::Algebra
@@ -2,8 +2,25 @@ module SPARQL; module Algebra
2
2
  class Operator
3
3
  ##
4
4
  # The SPARQL numeric `subtract` operator.
5
- # (- ?x ?y)
6
- # (subtract ?x ?y)
5
+ #
6
+ # [116] AdditiveExpression ::= MultiplicativeExpression ( '-' MultiplicativeExpression )?
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # SELECT ?s WHERE {
11
+ # ?s :p ?o .
12
+ # ?s2 :p ?o2 .
13
+ # FILTER(?o - ?o2 = 3) .
14
+ # }
15
+ #
16
+ # @example SSE
17
+ # (prefix
18
+ # ((: <http://example.org/>))
19
+ # (project (?s)
20
+ # (filter (= (- ?o ?o2) 3)
21
+ # (bgp
22
+ # (triple ?s :p ?o)
23
+ # (triple ?s2 :p ?o2)))))
7
24
  #
8
25
  # @see https://www.w3.org/TR/xpath-functions/#func-numeric-subtract
9
26
  class Subtract < Operator::Binary
@@ -20,13 +37,22 @@ module SPARQL; module Algebra
20
37
  # a numeric literal
21
38
  # @return [RDF::Literal::Numeric]
22
39
  # @raise [TypeError] if either operand is not a numeric literal
23
- def apply(left, right)
40
+ def apply(left, right, **options)
24
41
  case
25
42
  when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
26
43
  left - right
27
44
  else raise TypeError, "expected two RDF::Literal::Numeric operands, but got #{left.inspect} and #{right.inspect}"
28
45
  end
29
46
  end
47
+
48
+ ##
49
+ #
50
+ # Returns a partial SPARQL grammar for this operator.
51
+ #
52
+ # @return [String]
53
+ def to_sparql(**options)
54
+ "(#{operands.first.to_sparql(**options)} - #{operands.last.to_sparql(**options)})"
55
+ end
30
56
  end # Subtract
31
57
  end # Operator
32
58
  end; end # SPARQL::Algebra
@@ -3,12 +3,19 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `sum` set function.
5
5
  #
6
- # @example
7
- # (prefix ((: <http://www.example.org/>))
8
- # (project (?sum)
9
- # (extend ((?sum ??.0))
10
- # (group () ((??.0 (sum ?o)))
11
- # (bgp (triple ?s :dec ?o))))))
6
+ # [127] Aggregate::= ... | 'SUM' '(' 'DISTINCT'? Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://www.example.org/>
10
+ # SELECT (SUM(?o) AS ?sum)
11
+ # WHERE { ?s :dec ?o }
12
+ #
13
+ # @example SSE
14
+ # (prefix ((: <http://www.example.org/>))
15
+ # (project (?sum)
16
+ # (extend ((?sum ??.0))
17
+ # (group () ((??.0 (sum ?o)))
18
+ # (bgp (triple ?s :dec ?o))))))
12
19
  #
13
20
  # @see https://www.w3.org/TR/sparql11-query/#defn_aggSum
14
21
  class Sum < Operator
@@ -22,7 +29,7 @@ module SPARQL; module Algebra
22
29
  # @param [Enumerable<Array<RDF::Term>>] enum
23
30
  # enum of evaluated operand
24
31
  # @return [RDF::Literal::Numeric] The sum 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?
@@ -33,6 +40,17 @@ module SPARQL; module Algebra
33
40
  raise TypeError, "Averaging non-numeric types: #{enum.flatten}"
34
41
  end
35
42
  end
43
+
44
+ ##
45
+ #
46
+ # Returns a partial SPARQL grammar for this operator.
47
+ #
48
+ # @return [String]
49
+ def to_sparql(**options)
50
+ distinct = operands.first == :distinct
51
+ args = distinct ? operands[1..-1] : operands
52
+ "SUM(#{'DISTINCT ' if distinct}#{args.to_sparql(**options)})"
53
+ end
36
54
  end # Sum
37
55
  end # Operator
38
56
  end; end # SPARQL::Algebra
@@ -6,13 +6,59 @@ module SPARQL; module Algebra
6
6
  # This is used to provide inline values. Each row becomes
7
7
  # a solution.
8
8
  #
9
- # @example
10
- # (table (vars ?book ?title)
11
- # (row (?title "SPARQL Tutorial"))
12
- # (row (?book :book2)))
9
+ # [28] ValuesClause ::= ( 'VALUES' DataBlock )?
10
+ #
11
+ # @example SPARQL Grammar (ValuesClause)
12
+ # PREFIX dc: <http://purl.org/dc/elements/1.1/>
13
+ # PREFIX : <http://example.org/book/>
14
+ # PREFIX ns: <http://example.org/ns#>
15
+ # SELECT ?book ?title ?price {
16
+ # ?book dc:title ?title ;
17
+ # ns:price ?price .
18
+ # }
19
+ # VALUES ?book { :book1 }
20
+ #
21
+ # @example SSE (ValuesClause)
22
+ # (prefix ((dc: <http://purl.org/dc/elements/1.1/>)
23
+ # (: <http://example.org/book/>)
24
+ # (ns: <http://example.org/ns#>))
25
+ # (project (?book ?title ?price)
26
+ # (join
27
+ # (bgp (triple ?book dc:title ?title) (triple ?book ns:price ?price))
28
+ # (table (vars ?book) (row (?book :book1)))) ))
29
+ #
30
+ # @example SPARQL Grammar (empty query no values)
31
+ # SELECT * { } VALUES () { }
32
+ #
33
+ # @example SSE (empty query no values)
34
+ # (join (bgp) (table empty))
35
+ #
36
+ # [61] InlineData ::= 'VALUES' DataBlock
37
+ #
38
+ # @example SPARQL Grammar (InlineData)
39
+ # PREFIX dc: <http://purl.org/dc/elements/1.1/>
40
+ # PREFIX : <http://example.org/book/>
41
+ # PREFIX ns: <http://example.org/ns#>
42
+ #
43
+ # SELECT ?book ?title ?price
44
+ # {
45
+ # VALUES ?book { :book1 }
46
+ # ?book dc:title ?title ;
47
+ # ns:price ?price .
48
+ # }
49
+ #
50
+ # @example SSE (InlineData)
51
+ # (prefix ((dc: <http://purl.org/dc/elements/1.1/>)
52
+ # (: <http://example.org/book/>)
53
+ # (ns: <http://example.org/ns#>))
54
+ # (project (?book ?title ?price)
55
+ # (join
56
+ # (table (vars ?book) (row (?book :book1)))
57
+ # (bgp (triple ?book dc:title ?title) (triple ?book ns:price ?price))) ))
13
58
  #
14
59
  # @example empty table
15
60
  # (table unit)
61
+ #
16
62
  # @see https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#inline-data
17
63
  class Table < Operator
18
64
  include Query
@@ -46,6 +92,32 @@ module SPARQL; module Algebra
46
92
  @solutions.each(&block) if block_given?
47
93
  @solutions
48
94
  end
95
+
96
+ ##
97
+ #
98
+ # Returns a partial SPARQL grammar for this operator.
99
+ #
100
+ # @param [Boolean] top_level (true)
101
+ # Treat this as a top-level, generating SELECT ... WHERE {}
102
+ # @return [String]
103
+ def to_sparql(top_level: true, **options)
104
+ str = "VALUES (#{Array(operands.first)[1..-1].map { |e| e.to_sparql(**options) }.join(' ')}) {\n"
105
+ operands[1..-1].each do |row|
106
+ line = '('
107
+ row[1..-1].each do |col|
108
+ v = col[1].to_sparql(as_statement: true, **options)
109
+ v = "<< #{v} >>" if col[1].is_a?(RDF::Statement)
110
+ line << v + ' '
111
+ end
112
+ line = line.chomp(' ')
113
+ line << ")\n"
114
+
115
+ str << line
116
+ end
117
+
118
+ str << "}\n"
119
+ top_level ? Operator.to_sparql(str, **options) : str
120
+ end
49
121
  end # Table
50
122
  end # Operator
51
123
  end; end # SPARQL::Algebra
@@ -5,11 +5,20 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Returns the timezone part of `arg` as an xsd:dayTimeDuration. Raises an error if there is no timezone.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>))
10
- # (project (?s ?x)
11
- # (extend ((?x (timezone ?date)))
12
- # (bgp (triple ?s :date ?date)))))
8
+ # [121] BuiltInCall ::= ... | 'TIMEZONE' '(' Expression ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # SELECT ?s (TIMEZONE(?date) AS ?x) WHERE {
13
+ # ?s :date ?date
14
+ # }
15
+ #
16
+ # @example SSE
17
+ # (prefix
18
+ # ((: <http://example.org/>))
19
+ # (project (?s ?x)
20
+ # (extend ((?x (timezone ?date)))
21
+ # (bgp (triple ?s :date ?date)))))
13
22
  #
14
23
  # @see https://www.w3.org/TR/sparql11-query/#func-timezone
15
24
  class Timezone < Operator::Unary
@@ -26,11 +35,20 @@ module SPARQL; module Algebra
26
35
  # the operand
27
36
  # @return [RDF::Literal]
28
37
  # @raise [TypeError] if the operand is not a simple literal
29
- def apply(operand)
38
+ def apply(operand, **options)
30
39
  raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
31
40
  raise TypeError, "literal has no timezone" unless res = operand.timezone
32
41
  res
33
42
  end
43
+
44
+ ##
45
+ #
46
+ # Returns a partial SPARQL grammar for this operator.
47
+ #
48
+ # @return [String]
49
+ def to_sparql(**options)
50
+ "TIMEZONE(" + operands.to_sparql(**options) + ")"
51
+ end
34
52
  end # Timezone
35
53
  end # Operator
36
54
  end; end # SPARQL::Algebra
@@ -5,11 +5,20 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Returns the timezone part of `arg` as a simple literal. Returns the empty string if there is no timezone.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>))
10
- # (project (?s ?x)
11
- # (extend ((?x (tz ?date)))
12
- # (bgp (triple ?s :date ?date)))))
8
+ # [121] BuiltInCall ::= ... | 'TZ' '(' Expression ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # SELECT ?s (TZ(?date) AS ?x) WHERE {
13
+ # ?s :date ?date
14
+ # }
15
+ #
16
+ # @example SSE
17
+ # (prefix
18
+ # ((: <http://example.org/>))
19
+ # (project (?s ?x)
20
+ # (extend ((?x (tz ?date)))
21
+ # (bgp (triple ?s :date ?date)))))
13
22
  #
14
23
  # @see https://www.w3.org/TR/sparql11-query/#func-tz
15
24
  class TZ < Operator::Unary
@@ -24,10 +33,18 @@ module SPARQL; module Algebra
24
33
  # the operand
25
34
  # @return [RDF::Literal]
26
35
  # @raise [TypeError] if the operand is not a simple literal
27
- def apply(operand)
36
+ def apply(operand, **options)
28
37
  raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
29
38
  operand.tz
30
39
  end
40
+ ##
41
+ #
42
+ # Returns a partial SPARQL grammar for this operator.
43
+ #
44
+ # @return [String]
45
+ def to_sparql(**options)
46
+ "TZ(" + operands.to_sparql(**options) + ")"
47
+ end
31
48
  end # TZ
32
49
  end # Operator
33
50
  end; end # SPARQL::Algebra
@@ -3,8 +3,20 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL logical `ucase` operator.
5
5
  #
6
- # @example
7
- # (ucase ?x)
6
+ # [121] BuiltInCall ::= ... | 'UCASE' '(' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # SELECT ?s (UCASE(?str) AS ?ustr) WHERE {
11
+ # ?s :str ?str
12
+ # }
13
+ #
14
+ # @example SSE
15
+ # (prefix
16
+ # ((: <http://example.org/>))
17
+ # (project (?s ?ustr)
18
+ # (extend ((?ustr (ucase ?str)))
19
+ # (bgp (triple ?s :str ?str)))))
8
20
  #
9
21
  # @see https://www.w3.org/TR/sparql11-query/#func-ucase
10
22
  # @see https://www.w3.org/TR/xpath-functions/#func-ucase
@@ -20,12 +32,21 @@ module SPARQL; module Algebra
20
32
  # the operand
21
33
  # @return [RDF::Literal] literal of same type
22
34
  # @raise [TypeError] if the operand is not a literal value
23
- def apply(operand)
35
+ def apply(operand, **options)
24
36
  case operand
25
37
  when RDF::Literal then RDF::Literal(operand.to_s.upcase, datatype: operand.datatype, language: operand.language)
26
38
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
27
39
  end
28
40
  end
41
+
42
+ ##
43
+ #
44
+ # Returns a partial SPARQL grammar for this operator.
45
+ #
46
+ # @return [String]
47
+ def to_sparql(**options)
48
+ "UCASE(" + operands.last.to_sparql(**options) + ")"
49
+ end
29
50
  end # UCase
30
51
  end # Operator
31
52
  end; end # SPARQL::Algebra
@@ -3,12 +3,19 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `union` operator.
5
5
  #
6
- # @example
7
- # (prefix ((: <http://example/>))
8
- # (union
9
- # (bgp (triple ?s ?p ?o))
10
- # (graph ?g
11
- # (bgp (triple ?s ?p ?o)))))
6
+ # [67] GroupOrUnionGraphPattern::= GroupGraphPattern ( 'UNION' GroupGraphPattern )*
7
+ #
8
+ # @example SPARQL Grammar
9
+ # SELECT * {
10
+ # { ?s ?p ?o }
11
+ # UNION
12
+ # { GRAPH ?g { ?s ?p ?o } }}
13
+ #
14
+ # @example SSE
15
+ # (union
16
+ # (bgp (triple ?s ?p ?o))
17
+ # (graph ?g
18
+ # (bgp (triple ?s ?p ?o))))
12
19
  #
13
20
  # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
14
21
  class Union < Operator::Binary
@@ -66,6 +73,22 @@ module SPARQL; module Algebra
66
73
  @operands = ops
67
74
  self
68
75
  end
76
+
77
+ ##
78
+ #
79
+ # Returns a partial SPARQL grammar for this operator.
80
+ #
81
+ # @param [Boolean] top_level (true)
82
+ # Treat this as a top-level, generating SELECT ... WHERE {}
83
+ # @return [String]
84
+ def to_sparql(top_level: true, **options)
85
+ str = "{\n"
86
+ str << operands[0].to_sparql(top_level: false, **options)
87
+ str << "\n} UNION {\n"
88
+ str << operands[1].to_sparql(top_level: false, **options)
89
+ str << "\n}"
90
+ top_level ? Operator.to_sparql(str, **options) : str
91
+ end
69
92
  end # Union
70
93
  end # Operator
71
94
  end; end # SPARQL::Algebra