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,7 +3,15 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL ascending sort operator.
5
5
  #
6
- # @example
6
+ # [24] OrderCondition ::= ( ( 'ASC' | 'DESC' ) BrackettedExpression ) | ( Constraint | Var )
7
+ #
8
+ # @example SPARQL Query
9
+ # PREFIX foaf: <http://xmlns.com/foaf/0.1/>
10
+ # SELECT ?name
11
+ # WHERE { ?x foaf:name ?name }
12
+ # ORDER BY ASC(?name)
13
+ #
14
+ # @example SSE
7
15
  # (prefix ((foaf: <http://xmlns.com/foaf/0.1/>))
8
16
  # (project (?name)
9
17
  # (order ((asc ?name))
@@ -27,6 +35,17 @@ module SPARQL; module Algebra
27
35
  def evaluate(bindings, **options)
28
36
  operand(0).evaluate(bindings, depth: options[:depth].to_i + 1, **options)
29
37
  end
38
+
39
+ ##
40
+ #
41
+ # Returns a partial SPARQL grammar for this operator.
42
+ #
43
+ # Provides order to descendant query.
44
+ #
45
+ # @return [String]
46
+ def to_sparql(**options)
47
+ "ASC(#{operands.last.to_sparql(**options)})"
48
+ end
30
49
  end # Asc
31
50
  end # Operator
32
51
  end; end # SPARQL::Algebra
@@ -5,7 +5,13 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Applications can use the ASK form to test whether or not a query pattern has a solution. No information is returned about the possible query solutions, just whether or not a solution exists.
7
7
  #
8
- # @example
8
+ # [12] AskQuery ::= 'ASK' DatasetClause* WhereClause ValuesClause
9
+ #
10
+ # @example SPARQL Query
11
+ # PREFIX : <http://example/>
12
+ # ASK { :x :p ?x }
13
+ #
14
+ # @example SSE
9
15
  # (prefix ((: <http://example/>))
10
16
  # (ask
11
17
  # (bgp (triple :x :p ?x))))
@@ -41,6 +47,16 @@ module SPARQL; module Algebra
41
47
  def query_yields_boolean?
42
48
  true
43
49
  end
50
+
51
+ ##
52
+ #
53
+ # Returns a partial SPARQL grammar for this term.
54
+ #
55
+ # @return [String]
56
+ def to_sparql(**options)
57
+ "ASK\n" +
58
+ operands.first.to_sparql(top_level: true, project: nil, **options)
59
+ end
44
60
  end # Ask
45
61
  end # Operator
46
62
  end; end # SPARQL::Algebra
@@ -3,7 +3,14 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `avg` set function.
5
5
  #
6
- # @example
6
+ # [127] Aggregate::= ... | 'AVG' '(' 'DISTINCT'? Expression ')'
7
+ #
8
+ # @example SPARQL Query
9
+ # PREFIX : <http://www.example.org/>
10
+ # SELECT (AVG(?o) AS ?avg)
11
+ # WHERE { ?s :dec ?o }
12
+ #
13
+ # @example SSE
7
14
  # (prefix ((: <http://www.example.org/>))
8
15
  # (project (?avg)
9
16
  # (extend ((?avg ??.0))
@@ -29,7 +36,7 @@ module SPARQL; module Algebra
29
36
  # @param [Enumerable<Array<RDF::Term>>] enum
30
37
  # enum of evaluated operand
31
38
  # @return [RDF::Literal::Numeric] The numeric average of the terms
32
- def apply(enum)
39
+ def apply(enum, **options)
33
40
  # FIXME: we don't actually do anything with distinct
34
41
  operands.shift if distinct = (operands.first == :distinct)
35
42
  if enum.empty?
@@ -40,6 +47,17 @@ module SPARQL; module Algebra
40
47
  raise TypeError, "Averaging non-numeric types: #{enum.flatten}"
41
48
  end
42
49
  end
50
+
51
+ ##
52
+ #
53
+ # Returns a partial SPARQL grammar for this operator.
54
+ #
55
+ # @return [String]
56
+ def to_sparql(**options)
57
+ distinct = operands.first == :distinct
58
+ args = distinct ? operands[1..-1] : operands
59
+ "AVG(#{'DISTINCT ' if distinct}#{args.to_sparql(**options)})"
60
+ end
43
61
  end # Avg
44
62
  end # Operator
45
63
  end; end # SPARQL::Algebra
@@ -3,7 +3,13 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `base` operator.
5
5
  #
6
- # @example
6
+ # [5] BaseDecl ::= 'BASE' IRIREF
7
+ #
8
+ # @example SPARQL Grammar
9
+ # BASE <http://example.org/>
10
+ # SELECT * { <a> <b> 123.0 }
11
+ #
12
+ # @example SSE
7
13
  # (base <http://example.org/>
8
14
  # (bgp (triple <a> <b> 123.0)))
9
15
  #
@@ -56,6 +62,17 @@ module SPARQL; module Algebra
56
62
  def query_yields_statements?
57
63
  operands.last.query_yields_statements?
58
64
  end
65
+
66
+ ##
67
+ #
68
+ # Returns a partial SPARQL grammar for this term.
69
+ #
70
+ # @return [String]
71
+ def to_sparql(**options)
72
+ str = "BASE #{operands.first.to_sparql}\n"
73
+
74
+ str << operands.last.to_sparql(base_uri: operands.first, **options)
75
+ end
59
76
  end # Base
60
77
  end # Operator
61
78
  end; end # SPARQL::Algebra
@@ -5,10 +5,22 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Query with `graph_name` set to false.
7
7
  #
8
- # @example
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example/>
10
+ # SELECT * { ?s ?p ?o }
11
+ #
12
+ # @example SSE
9
13
  # (prefix ((: <http://example/>))
10
14
  # (bgp (triple ?s ?p ?o)))
11
15
  #
16
+ # @example SPARQL Grammar (sparql-star)
17
+ # PREFIX : <http://example.com/ns#>
18
+ # SELECT * {<< :a :b :c >> :p1 :o1.}
19
+ #
20
+ # @example SSE (sparql-star)
21
+ # (prefix ((: <http://example.com/ns#>))
22
+ # (bgp (triple (triple :a :b :c) :p1 :o1)))
23
+ #
12
24
  # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
13
25
  class BGP < Operator
14
26
  NAME = [:bgp]
@@ -5,16 +5,30 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # The BNODE function constructs a blank node that is distinct from all blank nodes in the dataset being queried and distinct from all blank nodes created by calls to this constructor for other query solutions. If the no argument form is used, every call results in a distinct blank node. If the form with a simple literal is used, every call results in distinct blank nodes for different simple literals, and the same blank node for calls with the same simple literal within expressions for one solution mapping.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>)
10
- # (xsd: <http://www.w3.org/2001/XMLSchema#>))
11
- # (project (?s1 ?s2 ?b1 ?b2)
12
- # (extend ((?b1 (bnode ?s1)) (?b2 (bnode ?s2)))
13
- # (filter (exprlist (|| (= ?a :s1) (= ?a :s3)) (|| (= ?b :s1) (= ?b :s3)))
14
- # (bgp
15
- # (triple ?a :str ?s1)
16
- # (triple ?b :str ?s2)
17
- # )))))
8
+ # [121] BuiltInCall ::= ... | 'BNODE' ( '(' Expression ')' | NIL )
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
13
+ # SELECT ?s1 ?s2 (BNODE(?s1) AS ?b1) (BNODE(?s2) AS ?b2)
14
+ # WHERE {
15
+ # ?a :str ?s1 .
16
+ # ?b :str ?s2 .
17
+ # FILTER (?a = :s1 || ?a = :s3)
18
+ # FILTER (?b = :s1 || ?b = :s3)
19
+ # }
20
+ #
21
+ # @example SSE
22
+ # (prefix
23
+ # ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
24
+ # (project (?s1 ?s2 ?b1 ?b2)
25
+ # (extend
26
+ # ((?b1 (bnode ?s1)) (?b2 (bnode ?s2)))
27
+ # (filter
28
+ # (exprlist
29
+ # (|| (= ?a :s1) (= ?a :s3))
30
+ # (|| (= ?b :s1) (= ?b :s3)))
31
+ # (bgp (triple ?a :str ?s1) (triple ?b :str ?s2))) )) )
18
32
  #
19
33
  # @see https://www.w3.org/TR/sparql11-query/#func-bnode
20
34
  class BNode < Operator::Unary
@@ -57,7 +71,7 @@ module SPARQL; module Algebra
57
71
  # a query solution containing zero or more variable bindings
58
72
  # @return [RDF::Node]
59
73
  # @raise [TypeError] if the operand is not a simple literal or nil
60
- def apply(literal, bindings)
74
+ def apply(literal, bindings, **options)
61
75
  @@bnode_base ||= "b0"
62
76
  @@bindings ||= bindings
63
77
  @@bnodes ||= {}
@@ -86,6 +100,15 @@ module SPARQL; module Algebra
86
100
  def to_sxp_bin
87
101
  [NAME] + operands.reject {|o| o == false}
88
102
  end
103
+
104
+ ##
105
+ #
106
+ # Returns a partial SPARQL grammar for this operator.
107
+ #
108
+ # @return [String]
109
+ def to_sparql(**options)
110
+ "BNODE(#{operands.last.to_sparql(**options)})"
111
+ end
89
112
  end # BNode
90
113
  end # Operator
91
114
  end; end # SPARQL::Algebra
@@ -3,7 +3,19 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `bound` operator.
5
5
  #
6
- # @example
6
+ # [121] BuiltInCall ::= ... | 'BOUND' '(' Var ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/ns#>
10
+ # SELECT ?a ?c
11
+ # WHERE
12
+ # { ?a :b ?c .
13
+ # OPTIONAL
14
+ # { ?c :d ?e } .
15
+ # FILTER (! bound(?e))
16
+ # }
17
+ #
18
+ # @example SSE
7
19
  # (prefix ((: <http://example.org/ns#>))
8
20
  # (project (?a ?c)
9
21
  # (filter (! (bound ?e))
@@ -46,6 +58,15 @@ module SPARQL; module Algebra
46
58
  else raise TypeError, "expected an RDF::Query::Variable, but got #{var.inspect}"
47
59
  end
48
60
  end
61
+
62
+ ##
63
+ #
64
+ # Returns a partial SPARQL grammar for this operator.
65
+ #
66
+ # @return [String]
67
+ def to_sparql(**options)
68
+ "bound(" + operands.first.to_sparql(**options) + ")"
69
+ end
49
70
  end # Bound
50
71
  end # Operator
51
72
  end; end # SPARQL::Algebra
@@ -3,8 +3,22 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL logical `ceil` operator.
5
5
  #
6
- # @example
7
- # (ceil ?x)
6
+ # [121] BuiltInCall ::= ... 'CEIL' '(' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ # SELECT ?s ?num (CEIL(?num) AS ?ceil) WHERE {
12
+ # ?s :num ?num
13
+ # }
14
+ #
15
+ # @example SSE
16
+ # (prefix
17
+ # ((: <http://example.org/>)
18
+ # (xsd: <http://www.w3.org/2001/XMLSchema#>))
19
+ # (project (?s ?num ?ceil)
20
+ # (extend ((?ceil (ceil ?num)))
21
+ # (bgp (triple ?s :num ?num)))))
8
22
  #
9
23
  # @see https://www.w3.org/TR/sparql11-query/#func-ceil
10
24
  # @see https://www.w3.org/TR/xpath-functions/#func-ceil
@@ -20,12 +34,21 @@ module SPARQL; module Algebra
20
34
  # the operand
21
35
  # @return [RDF::Literal] literal of same type
22
36
  # @raise [TypeError] if the operand is not a numeric value
23
- def apply(operand)
37
+ def apply(operand, **options)
24
38
  case operand
25
39
  when RDF::Literal::Numeric then operand.ceil
26
40
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
27
41
  end
28
42
  end
43
+
44
+ ##
45
+ #
46
+ # Returns a partial SPARQL grammar for this operator.
47
+ #
48
+ # @return [String]
49
+ def to_sparql(**options)
50
+ "CEIL(#{operands.to_sparql(**options)})"
51
+ end
29
52
  end # Ceil
30
53
  end # Operator
31
54
  end; end # SPARQL::Algebra
@@ -6,8 +6,19 @@ module SPARQL; module Algebra
6
6
  #
7
7
  # The CLEAR operation removes all the triples in the specified graph(s) in the Graph Store.
8
8
  #
9
- # @example
10
- # (clear silent default)
9
+ # [32] Clear ::= 'CLEAR' 'SILENT'? GraphRefAll
10
+ #
11
+ # @example SPARQL Grammar (SILENT DEFAULT)
12
+ # CLEAR SILENT DEFAULT
13
+ #
14
+ # @example SSE (SILENT DEFAULT)
15
+ # (update (clear silent default))
16
+ #
17
+ # @example SPARQL Grammar (IRI)
18
+ # CLEAR GRAPH <http://example.com/>
19
+ #
20
+ # @example SSE (IRI)
21
+ # (update (clear <http://example.com/>))
11
22
  #
12
23
  # @see https://www.w3.org/TR/sparql11-update/#clear
13
24
  class Clear < Operator
@@ -58,6 +69,19 @@ module SPARQL; module Algebra
58
69
 
59
70
  queryable
60
71
  end
72
+
73
+ ##
74
+ #
75
+ # Returns a partial SPARQL grammar for this operator.
76
+ #
77
+ # @return [String]
78
+ def to_sparql(**options)
79
+ silent = operands.first == :silent
80
+ str = "CLEAR "
81
+ str << "SILENT " if operands.first == :silent
82
+ str << "GRAPH " if operands.last.is_a?(RDF::URI)
83
+ str << operands.last.to_sparql(**options)
84
+ end
61
85
  end # Clear
62
86
  end # Operator
63
87
  end; end # SPARQL::Algebra
@@ -3,17 +3,30 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `coalesce` function.
5
5
  #
6
- # @example
7
- # (prefix ((: <http://example.org/>)
8
- # (xsd: <http://www.w3.org/2001/XMLSchema#>))
9
- # (project (?cx ?div ?def ?err)
10
- # (extend ((?cx (coalesce ?x -1))
11
- # (?div (coalesce (/ ?o ?x) -2))
12
- # (?def (coalesce ?z -3))
13
- # (?err (coalesce ?z)))
14
- # (leftjoin
15
- # (bgp (triple ?s :p ?o))
16
- # (bgp (triple ?s :q ?x))))))
6
+ # [121] BuiltInCall ::= ... | 'COALESCE' ExpressionList
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example/>
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ #
12
+ # SELECT ?X (SAMPLE(?v) AS ?S)
13
+ # {
14
+ # ?s :p ?v .
15
+ # OPTIONAL { ?s :q ?w }
16
+ # }
17
+ # GROUP BY (COALESCE(?w, "1605-11-05"^^xsd:date) AS ?X)
18
+ #
19
+ # @example SSE
20
+ # (prefix
21
+ # ((: <http://example/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
22
+ # (project (?X ?S)
23
+ # (extend ((?S ??.0))
24
+ # (group
25
+ # ((?X (coalesce ?w "1605-11-05"^^xsd:date)))
26
+ # ((??.0 (sample ?v)))
27
+ # (leftjoin
28
+ # (bgp (triple ?s :p ?v))
29
+ # (bgp (triple ?s :q ?w)))))))
17
30
  #
18
31
  # @see https://www.w3.org/TR/sparql11-query/#func-coalesce
19
32
  class Coalesce < Operator
@@ -50,6 +63,15 @@ module SPARQL; module Algebra
50
63
  end
51
64
  raise TypeError, "None of the operands evaluated"
52
65
  end
66
+
67
+ ##
68
+ #
69
+ # Returns a partial SPARQL grammar for this operator.
70
+ #
71
+ # @return [String]
72
+ def to_sparql(**options)
73
+ "COALESCE(#{operands.to_sparql(delimiter: ', ', **options)})"
74
+ end
53
75
  end # Coalesce
54
76
  end # Operator
55
77
  end; end # SPARQL::Algebra
@@ -30,69 +30,77 @@ 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
+ ##
39
+ #
40
+ # Returns a partial SPARQL grammar for this operator.
41
+ #
42
+ # @return [String]
43
+ def to_sparql(**options)
44
+ "(#{operands.first.to_sparql(**options)} #{self.class.const_get(:NAME)} #{operands.last.to_sparql(**options)})"
45
+ end
46
+
47
+ private
48
+ # Define <=> as private for recursive statements
49
+ def spaceship(left, right, **options)
35
50
  case
36
51
  # @see https://www.w3.org/TR/sparql11-query/#OperatorMapping
37
52
  # @see https://www.w3.org/TR/sparql11-query/#modOrderBy
38
53
  when left.is_a?(RDF::Literal) && right.is_a?(RDF::Literal)
39
- case
40
54
  # @see https://www.w3.org/TR/xpath-functions/#string-compare
41
55
  # @see https://www.w3.org/TR/xpath-functions/#comp.numeric
42
56
  # @see https://www.w3.org/TR/xpath-functions/#op.boolean
43
57
  # @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
-
58
+ left <=> right
59
59
  when left.is_a?(RDF::URI) && right.is_a?(RDF::URI)
60
+ raise TypeError, "Comparing IRIs not supported" unless options[:order_by] || left == right
60
61
  # 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)))
62
+ left.to_s <=> right.to_s
62
63
  when left.is_a?(RDF::Node) && right.is_a?(RDF::Node)
64
+ raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by] || left == right
63
65
  # BNode comparison is undefined.
64
- RDF::Literal(0)
65
- when left.is_a?(RDF::Statement) && right.is_a?(RDF::Statement)
66
- RDF::Literal(RDF::Literal(left.to_s).send(self.class.const_get(:NAME), RDF::Literal(right.to_s)))
66
+ left == right ? 0 : 1
67
67
  when left.nil? && right.nil?
68
- RDF::Literal(0)
69
-
68
+ 0
69
+
70
+ when left.is_a?(RDF::Statement) && right.is_a?(RDF::Statement)
71
+ v = spaceship(left.subject, right.subject, **options)
72
+ v = spaceship(left.predicate, right.predicate, **options) if v == 0
73
+ v = spaceship(left.object, right.object, **options) if v == 0
74
+ v
75
+ when left.is_a?(RDF::Statement) && right.is_a?(RDF::Term)
76
+ raise TypeError, "Comparing statement with #{right.inspect}" unless options[:order_by]
77
+ 1
78
+ when right.is_a?(RDF::Statement) && left.is_a?(RDF::Term)
79
+ raise TypeError, "Comparing statement with #{left.inspect}" unless options[:order_by]
80
+ -1
81
+
70
82
  # SPARQL also fixes an order between some kinds of RDF terms that would not otherwise be ordered:
71
83
 
72
84
  when left.nil? && !right.nil?
73
- RDF::Literal(-1)
85
+ -1
74
86
  when right.nil?
75
- RDF::Literal(1)
87
+ 1
76
88
 
77
89
  when left.is_a?(RDF::Node) && right.is_a?(RDF::Term)
78
- RDF::Literal(-1)
90
+ raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by]
91
+ # Nodes lower than other terms
92
+ -1
79
93
  when right.is_a?(RDF::Node) && left.is_a?(RDF::Term)
80
- RDF::Literal(1)
81
-
82
- when left.is_a?(RDF::Statement) && right.is_a?(RDF::Term)
83
- RDF::Literal(-1)
84
- when right.is_a?(RDF::Statement) && left.is_a?(RDF::Term)
85
- RDF::Literal(1)
86
-
87
- when left.is_a?(RDF::Node) && right.is_a?(RDF::URI)
88
- RDF::Literal(-1)
89
- when right.is_a?(RDF::Node) && left.is_a?(RDF::URI)
90
- RDF::Literal(1)
94
+ raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by]
95
+ 1
91
96
 
92
97
  when left.is_a?(RDF::URI) && right.is_a?(RDF::Term)
93
- RDF::Literal(-1)
98
+ raise TypeError, "Comparing IRIs not supported" unless options[:order_by]
99
+ # IRIs lower than terms other than nodes
100
+ -1
94
101
  when right.is_a?(RDF::URI) && left.is_a?(RDF::Term)
95
- RDF::Literal(1)
102
+ raise TypeError, "Comparing IRIs not supported" unless options[:order_by]
103
+ 1
96
104
  else raise TypeError, "expected two RDF::Term operands, but got #{left.inspect} and #{right.inspect}"
97
105
  end
98
106
  end
@@ -5,8 +5,23 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # The CONCAT function corresponds to the XPath fn:concat function. The function accepts string literals as arguments.
7
7
  #
8
- # @example
9
- # (concat ?a ?b ...)
8
+ # [121] BuiltInCall ::= ... 'CONCAT' ExpressionList
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # SELECT (CONCAT(?str1,?str2) AS ?str) WHERE {
13
+ # :s6 :str ?str1 .
14
+ # :s7 :str ?str2 .
15
+ # }
16
+ #
17
+ # @example SSE
18
+ # (prefix
19
+ # ((: <http://example.org/>))
20
+ # (project (?str)
21
+ # (extend ((?str (concat ?str1 ?str2)))
22
+ # (bgp
23
+ # (triple :s6 :str ?str1)
24
+ # (triple :s7 :str ?str2)))))
10
25
  #
11
26
  # @see https://www.w3.org/TR/sparql11-query/#func-concat
12
27
  # @see https://www.w3.org/TR/xpath-functions/#func-concat
@@ -48,6 +63,15 @@ module SPARQL; module Algebra
48
63
  end
49
64
  end
50
65
  end
66
+
67
+ ##
68
+ #
69
+ # Returns a partial SPARQL grammar for this operator.
70
+ #
71
+ # @return [String]
72
+ def to_sparql(**options)
73
+ "CONCAT(#{operands.to_sparql(delimiter: ', ', **options)})"
74
+ end
51
75
  end # Concat
52
76
  end # Operator
53
77
  end; end # SPARQL::Algebra
@@ -5,12 +5,22 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # The CONSTRUCT query form returns a single RDF graph specified by a graph template. The result is an RDF graph formed by taking each query solution in the solution sequence, substituting for the variables in the graph template, and combining the triples into a single RDF graph by set union.
7
7
  #
8
- # @example
9
- # (prefix ((rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
10
- # (foaf: <http://xmlns.com/foaf/0.1/>))
11
- # (construct ((triple ?s ?p ?o))
12
- # (project (?s ?p ?o)
13
- # (bgp (triple ?s ?p ?o)))))
8
+ # [10] ConstructQuery ::= 'CONSTRUCT' ( ConstructTemplate DatasetClause* WhereClause SolutionModifier | DatasetClause* 'WHERE' '{' TriplesTemplate? '}' SolutionModifier ) ValuesClause
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example/>
12
+ # CONSTRUCT { ?x :p2 ?v }
13
+ # WHERE {
14
+ # ?x :p ?o .
15
+ # OPTIONAL {?o :q ?v }
16
+ # }
17
+ #
18
+ # @example SSE
19
+ # (prefix ((: <http://example/>))
20
+ # (construct ((triple ?x :p2 ?v))
21
+ # (leftjoin
22
+ # (bgp (triple ?x :p ?o))
23
+ # (bgp (triple ?o :q ?v)))))
14
24
  #
15
25
  # @see https://www.w3.org/TR/sparql11-query/#construct
16
26
  class Construct < Operator::Binary
@@ -81,6 +91,19 @@ module SPARQL; module Algebra
81
91
  def query_yields_statements?
82
92
  true
83
93
  end
94
+
95
+ ##
96
+ #
97
+ # Returns a partial SPARQL grammar for this term.
98
+ #
99
+ # @return [String]
100
+ def to_sparql(**options)
101
+ str = "CONSTRUCT {\n" +
102
+ operands[0].map { |e| e.to_sparql(as_statement: true, top_level: false, **options) }.join(". \n") +
103
+ "\n}\n"
104
+
105
+ str << operands[1].to_sparql(top_level: true, project: nil, **options)
106
+ end
84
107
  end # Construct
85
108
  end # Operator
86
109
  end; end # SPARQL::Algebra
@@ -3,8 +3,21 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # A SPARQL `contains` operator.
5
5
  #
6
- # @example
7
- # (contains ?x ?y)
6
+ # [121] BuiltInCall ::= ... | 'CONTAINS' '(' Expression ',' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # SELECT ?s ?str WHERE {
11
+ # ?s :str ?str
12
+ # FILTER CONTAINS(?str, "a")
13
+ # }
14
+ #
15
+ # @example SSE
16
+ # (prefix
17
+ # ((: <http://example.org/>))
18
+ # (project (?s ?str)
19
+ # (filter (contains ?str "a")
20
+ # (bgp (triple ?s :str ?str)))))
8
21
  #
9
22
  # @see https://www.w3.org/TR/sparql11-query/#func-contains
10
23
  # @see https://www.w3.org/TR/xpath-functions/#func-contains
@@ -31,7 +44,7 @@ module SPARQL; module Algebra
31
44
  # a literal
32
45
  # @return [RDF::Literal::Boolean]
33
46
  # @raise [TypeError] if operands are not compatible
34
- def apply(left, right)
47
+ def apply(left, right, **options)
35
48
  case
36
49
  when !left.compatible?(right)
37
50
  raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
@@ -39,6 +52,15 @@ module SPARQL; module Algebra
39
52
  else RDF::Literal::FALSE
40
53
  end
41
54
  end
55
+
56
+ ##
57
+ #
58
+ # Returns a partial SPARQL grammar for this operator.
59
+ #
60
+ # @return [String]
61
+ def to_sparql(**options)
62
+ "contains(" + operands.to_sparql(delimiter: ', ', **options) + ")"
63
+ end
42
64
  end # Contains
43
65
  end # Operator
44
66
  end; end # SPARQL::Algebra