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,11 +3,44 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `prefix` operator.
5
5
  #
6
- # @example
7
- # (update
6
+ # [29] Update ::= Prologue ( Update1 ( ';' Update )? )?
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # PREFIX foaf: <http://xmlns.com/foaf/0.1/>
11
+ # DELETE { ?a foaf:knows ?b }
12
+ # INSERT { ?b foaf:knows ?a }
13
+ # WHERE { ?a foaf:knows ?b }
14
+ #
15
+ # @example SSE
16
+ # (prefix ((: <http://example.org/>)
17
+ # (foaf: <http://xmlns.com/foaf/0.1/>))
18
+ # (update
19
+ # (modify
20
+ # (bgp (triple ?a foaf:knows ?b))
21
+ # (delete ((triple ?a foaf:knows ?b)))
22
+ # (insert ((triple ?b foaf:knows ?a)))) ))
23
+ #
24
+ # @example SPARQL Grammar (update multiple)
25
+ # PREFIX : <http://example.org/>
26
+ # PREFIX foaf: <http://xmlns.com/foaf/0.1/>
27
+ #
28
+ # DELETE { ?a foaf:knows ?b . }
29
+ # WHERE { ?a foaf:knows ?b . }
30
+ # ;
31
+ # INSERT { ?b foaf:knows ?a . }
32
+ # WHERE { ?a foaf:knows ?b .}
33
+ #
34
+ # @example SSE (update multiple)
35
+ # (prefix ((: <http://example.org/>)
36
+ # (foaf: <http://xmlns.com/foaf/0.1/>))
37
+ # (update
38
+ # (modify
39
+ # (bgp (triple ?a foaf:knows ?b))
40
+ # (delete ((triple ?a foaf:knows ?b))))
8
41
  # (modify
9
- # (bgp (triple ?s ?p ?o))
10
- # (insert ((triple ?s ?p "q")))))
42
+ # (bgp (triple ?a foaf:knows ?b))
43
+ # (insert ((triple ?b foaf:knows ?a))))))
11
44
  #
12
45
  # @see https://www.w3.org/TR/sparql11-update/#graphUpdate
13
46
  class Update < Operator
@@ -39,6 +72,15 @@ module SPARQL; module Algebra
39
72
  end
40
73
  queryable
41
74
  end
75
+
76
+ ##
77
+ #
78
+ # Returns a partial SPARQL grammar for this operator.
79
+ #
80
+ # @return [String]
81
+ def to_sparql(**options)
82
+ str = operands.map { |e| e.to_sparql(**options) }.join(";\n")
83
+ end
42
84
  end # Update
43
85
  end # Operator
44
86
  end; end # SPARQL::Algebra
@@ -6,8 +6,42 @@ module SPARQL; module Algebra
6
6
  #
7
7
  # The USING and USING NAMED clauses affect the RDF Dataset used while evaluating the WHERE clause. This describes a dataset in the same way as FROM and FROM NAMED clauses describe RDF Datasets in the SPARQL 1.1 Query Language
8
8
  #
9
- # @example
10
- # (using (:g1) (bgp (triple ?s ?p ?o)))
9
+ # [44] UsingClause ::= 'USING' ( iri | 'NAMED' iri )
10
+ #
11
+ # @example SPARQL Grammar
12
+ # PREFIX : <http://example.org/>
13
+ # PREFIX foaf: <http://xmlns.com/foaf/0.1/>
14
+ #
15
+ # DELETE { ?s ?p ?o }
16
+ # USING <http://example.org/g2>
17
+ # WHERE {
18
+ # :a foaf:knows ?s .
19
+ # ?s ?p ?o
20
+ # }
21
+ #
22
+ # @example SSE
23
+ # (prefix
24
+ # ((: <http://example.org/>) (foaf: <http://xmlns.com/foaf/0.1/>))
25
+ # (update
26
+ # (modify
27
+ # (using (:g2)
28
+ # (bgp (triple :a foaf:knows ?s) (triple ?s ?p ?o)))
29
+ # (delete ((triple ?s ?p ?o)))) ))
30
+ #
31
+ # @example SPARQL Grammar (multiple clauses)
32
+ # PREFIX : <http://example.org/>
33
+ #
34
+ # INSERT { ?s ?p "q" }
35
+ # USING :g1
36
+ # USING :g2
37
+ # WHERE { ?s ?p ?o }
38
+ #
39
+ # @example SSE (multiple clauses)
40
+ # (prefix ((: <http://example.org/>))
41
+ # (update
42
+ # (modify (using (:g1 :g2)
43
+ # (bgp (triple ?s ?p ?o)))
44
+ # (insert ((triple ?s ?p "q"))))))
11
45
  #
12
46
  # @see https://www.w3.org/TR/sparql11-update/#add
13
47
  class Using < Operator
@@ -35,6 +69,19 @@ module SPARQL; module Algebra
35
69
  debug(options) {"Using"}
36
70
  Dataset.new(*operands).execute(queryable, depth: options[:depth].to_i + 1, **options, &block)
37
71
  end
72
+
73
+ ##
74
+ #
75
+ # Returns a partial SPARQL grammar for this operator.
76
+ #
77
+ # @return [String]
78
+ def to_sparql(**options)
79
+ str = "\n" + operands.first.map do |op|
80
+ "USING #{op.to_sparql(**options)}\n"
81
+ end.join("")
82
+ content = operands.last.to_sparql(top_level: false, **options)
83
+ str << Operator.to_sparql(content, project: nil, **options)
84
+ end
38
85
  end # Using
39
86
  end # Operator
40
87
  end; end # SPARQL::Algebra
@@ -5,14 +5,24 @@ module SPARQL; module Algebra
5
5
  ##
6
6
  # The SPARQL `uuid` function.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>)
10
- # (xsd: <http://www.w3.org/2001/XMLSchema#>))
11
- # (project (?length)
12
- # (extend ((?length (strlen (str ?uuid))))
13
- # (filter (&& (isIRI ?uuid) (regex (str ?uuid) "^urn: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 (uuid)))
15
- # (bgp))))))
8
+ # [121] BuiltInCall ::= ... | 'UUID' NIL
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
13
+ # ASK {
14
+ # BIND(UUID() AS ?u1)
15
+ # BIND(UUID() AS ?u2)
16
+ # FILTER(?u1 != ?u2)
17
+ # }
18
+ #
19
+ # @example SSE
20
+ # (prefix
21
+ # ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
22
+ # (ask
23
+ # (filter (!= ?u1 ?u2)
24
+ # (extend ((?u1 (uuid)) (?u2 (uuid)))
25
+ # (bgp)))))
16
26
  #
17
27
  # @see https://www.w3.org/TR/sparql11-query/#func-uuid
18
28
  class UUID < Operator::Nullary
@@ -24,9 +34,18 @@ module SPARQL; module Algebra
24
34
  # Return a fresh IRI from the UUID URN scheme. Each call of UUID() returns a different UUID. It must not be the "nil" UUID (all zeroes). The variant and version of the UUID is implementation dependent.
25
35
  #
26
36
  # @return [RDF::URI]
27
- def apply
37
+ def apply(**options)
28
38
  RDF::URI("urn:uuid:#{SecureRandom.uuid}")
29
39
  end
40
+
41
+ ##
42
+ #
43
+ # Returns a partial SPARQL grammar for this operator.
44
+ #
45
+ # @return [String]
46
+ def to_sparql(**options)
47
+ "UUID(" + operands.to_sparql(delimiter: ', ', **options) + ")"
48
+ end
30
49
  end # UUID
31
50
  end # Operator
32
51
  end; end # SPARQL::Algebra
@@ -6,10 +6,21 @@ module SPARQL; module Algebra
6
6
  #
7
7
  # The WITH clause provides a convenience for when an operation primarily refers to a single graph.
8
8
  #
9
- # @example
10
- # (with :g1
11
- # (bgp (triple ?s ?p ?o))
12
- # (insert ((triple ?s ?p "z"))))
9
+ # [41] Modify ::= ( 'WITH' iri )? ( DeleteClause InsertClause? | InsertClause ) UsingClause* 'WHERE' GroupGraphPattern
10
+ #
11
+ # @example SPARQL Grammar
12
+ # PREFIX : <http://example/>
13
+ # WITH :g
14
+ # DELETE { <base:s> ?p ?o . }
15
+ # WHERE { ?s ?p ?o }
16
+ #
17
+ # @example SSE
18
+ # (prefix ((: <http://example/>))
19
+ # (update
20
+ # (modify
21
+ # (with :g
22
+ # (bgp (triple ?s ?p ?o))
23
+ # (delete ((triple <base:s> ?p ?o)))))))
13
24
  #
14
25
  # @see https://www.w3.org/TR/sparql11-update/#deleteInsert
15
26
  class With < Operator
@@ -67,6 +78,29 @@ module SPARQL; module Algebra
67
78
  end
68
79
  end
69
80
  end
81
+
82
+ ##
83
+ #
84
+ # Returns a partial SPARQL grammar for this operator.
85
+ #
86
+ # @return [String]
87
+ def to_sparql(**options)
88
+ with, where, *ops = operands
89
+ str = "WITH #{with.to_sparql(**options)}\n"
90
+
91
+ # The content of the WHERE clause, may be USING
92
+ content = where.to_sparql(top_level: false, **options)
93
+
94
+ # DELETE | INSERT | DELETE INSERT
95
+ str << ops.to_sparql(top_level: false, delimiter: "\n", **options) + "\n"
96
+
97
+ # Append the WHERE or USING clause
98
+ str << if where.is_a?(Using)
99
+ content
100
+ else
101
+ Operator.to_sparql(content, project: nil, **options)
102
+ end
103
+ end
70
104
  end # With
71
105
  end # Operator
72
106
  end; end # SPARQL::Algebra
@@ -5,11 +5,20 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Returns the year part of `arg` as an integer.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>))
10
- # (project (?s ?x)
11
- # (extend ((?x (year ?date)))
12
- # (bgp (triple ?s :date ?date)))))
8
+ # [121] BuiltInCall ::= ... | 'YEAR' '(' Expression ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # SELECT ?s (YEAR(?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 (year ?date)))
21
+ # (bgp (triple ?s :date ?date)))))
13
22
  #
14
23
  # @see https://www.w3.org/TR/sparql11-query/#func-year
15
24
  class Year < Operator::Unary
@@ -24,10 +33,19 @@ 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
  RDF::Literal(operand.object.year)
30
39
  end
40
+
41
+ ##
42
+ #
43
+ # Returns a partial SPARQL grammar for this operator.
44
+ #
45
+ # @return [String]
46
+ def to_sparql(**options)
47
+ "YEAR(#{operands.last.to_sparql(**options)})"
48
+ end
31
49
  end # Year
32
50
  end # Operator
33
51
  end; end # SPARQL::Algebra
@@ -49,6 +49,7 @@ module SPARQL; module Algebra
49
49
  autoload :Sum, 'sparql/algebra/operator/sum'
50
50
  autoload :SHA1, 'sparql/algebra/operator/sha1'
51
51
  autoload :SHA256, 'sparql/algebra/operator/sha256'
52
+ autoload :SHA384, 'sparql/algebra/operator/sha384'
52
53
  autoload :SHA512, 'sparql/algebra/operator/sha512'
53
54
  autoload :Str, 'sparql/algebra/operator/str'
54
55
  autoload :Timezone, 'sparql/algebra/operator/timezone'
@@ -105,6 +106,7 @@ module SPARQL; module Algebra
105
106
  autoload :Coalesce, 'sparql/algebra/operator/coalesce'
106
107
  autoload :Desc, 'sparql/algebra/operator/desc'
107
108
  autoload :Exprlist, 'sparql/algebra/operator/exprlist'
109
+ autoload :FunctionCall, 'sparql/algebra/operator/function_call'
108
110
  autoload :GroupConcat, 'sparql/algebra/operator/group_concat'
109
111
  autoload :In, 'sparql/algebra/operator/in'
110
112
  autoload :NotIn, 'sparql/algebra/operator/notin'
@@ -171,7 +173,6 @@ module SPARQL; module Algebra
171
173
  when :> then GreaterThan
172
174
  when :>= then GreaterThanOrEqual
173
175
  when :abs then Abs
174
- when :add then Add
175
176
  when :alt then Alt
176
177
  when :and, :'&&' then And
177
178
  when :avg then Avg
@@ -204,7 +205,6 @@ module SPARQL; module Algebra
204
205
  when :md5 then MD5
205
206
  when :max then Max
206
207
  when :min then Min
207
- when :minus then Minus
208
208
  when :minutes then Minutes
209
209
  when :month then Month
210
210
  when :multiply then Multiply
@@ -231,6 +231,7 @@ module SPARQL; module Algebra
231
231
  when :sequence then Sequence
232
232
  when :sha1 then SHA1
233
233
  when :sha256 then SHA256
234
+ when :sha384 then SHA384
234
235
  when :sha512 then SHA512
235
236
  when :str then Str
236
237
  when :strafter then StrAfter
@@ -254,6 +255,7 @@ module SPARQL; module Algebra
254
255
  when :asc then Asc
255
256
  when :desc then Desc
256
257
  when :exprlist then Exprlist
258
+ when :function_call then FunctionCall
257
259
 
258
260
  # Datasets
259
261
  when :dataset then Dataset
@@ -278,7 +280,6 @@ module SPARQL; module Algebra
278
280
  when :reduced then Reduced
279
281
  when :slice then Slice
280
282
  when :table then Table
281
- when :triple then RDF::Query::Pattern
282
283
  when :union then Union
283
284
 
284
285
  # Update forms
@@ -301,7 +302,7 @@ module SPARQL; module Algebra
301
302
 
302
303
  # RDF-star
303
304
  when :istriple then IsTriple
304
- when :triple then Triple
305
+ when :triple then RDF::Query::Pattern
305
306
  when :subject then Subject
306
307
  when :predicate then Predicate
307
308
  when :object then Object
@@ -314,8 +315,8 @@ module SPARQL; module Algebra
314
315
  # @param [Array<RDF::Term>] operands
315
316
  # @return [RDF::Term]
316
317
  # @see Operator#evaluate
317
- def self.evaluate(*operands)
318
- self.new(*operands).evaluate(RDF::Query::Solution.new)
318
+ def self.evaluate(*operands, **options)
319
+ self.new(*operands, **options).evaluate(RDF::Query::Solution.new, **options)
319
320
  end
320
321
 
321
322
  ##
@@ -333,6 +334,120 @@ module SPARQL; module Algebra
333
334
  self.const_get(:ARITY)
334
335
  end
335
336
 
337
+ ##
338
+ # Generate a top-level Grammar, using collected options
339
+ #
340
+ # @param [String] content
341
+ # @param [Operator] datasets ([])
342
+ # @param [Operator] distinct (false)
343
+ # @param [Hash{Symbol => Operator}] extensions
344
+ # Variable bindings
345
+ # @param [Array<Operator>] filter_ops ([])
346
+ # Filter Operations
347
+ # @param [Integer] limit (nil)
348
+ # @param [Array<Operator>] group_ops ([])
349
+ # @param [Array<Operator>] having_ops ([])
350
+ # @param [Integer] offset (nil)
351
+ # @param [Array<Operator>] order_ops ([])
352
+ # Order Operations
353
+ # @param [Array<Symbol,Operator>] project (%i(*))
354
+ # Terms to project
355
+ # @param [Operator] reduced (false)
356
+ # @param [Operator] values_clause (nil)
357
+ # Top-level Values clause
358
+ # @param [Operator] where_clause (true)
359
+ # Emit 'WHERE' before GroupGraphPattern
360
+ # @param [Hash{Symbol => Object}] options
361
+ # @return [String]
362
+ def self.to_sparql(content,
363
+ datasets: [],
364
+ distinct: false,
365
+ extensions: {},
366
+ filter_ops: [],
367
+ group_ops: [],
368
+ having_ops: [],
369
+ limit: nil,
370
+ offset: nil,
371
+ order_ops: [],
372
+ project: %i(*),
373
+ reduced: false,
374
+ values_clause: nil,
375
+ where_clause: true,
376
+ **options)
377
+ str = ""
378
+
379
+ # Projections
380
+ if project
381
+ str << "SELECT "
382
+ str << "DISTINCT " if distinct
383
+ str << "REDUCED " if reduced
384
+
385
+ str << project.map do |p|
386
+ if expr = extensions.delete(p)
387
+ v = expr.to_sparql(as_statement: true, **options)
388
+ v = "<< #{v} >>" if expr.is_a?(RDF::Statement)
389
+ pp = p.to_sparql(**options)
390
+ # Replace projected variables with their extension, if any
391
+ '(' + v + ' AS ' + pp + ')'
392
+ else
393
+ p.to_sparql(**options)
394
+ end
395
+ end.join(" ") + "\n"
396
+ end
397
+
398
+ # DatasetClause
399
+ datasets.each do |ds|
400
+ str << "FROM #{ds.to_sparql(**options)}\n"
401
+ end
402
+
403
+ # Bind
404
+ extensions.each do |as, expression|
405
+ v = expression.to_sparql(as_statement: true, **options)
406
+ v = "<< #{v} >>" if expression.is_a?(RDF::Statement)
407
+ content << "\nBIND (" << v << " AS " << as.to_sparql(**options) << ") ."
408
+ end
409
+
410
+ # Filter
411
+ filter_ops.each do |f|
412
+ content << "\nFILTER (#{f.to_sparql(**options)}) ."
413
+ end
414
+
415
+ # WhereClause / GroupGraphPattern
416
+ str << (where_clause ? "WHERE {\n#{content}\n}\n" : "{\n#{content}\n}\n")
417
+
418
+ ##
419
+ # SolutionModifier
420
+ #
421
+ # GroupClause
422
+ unless group_ops.empty?
423
+ ops = group_ops.map do |o|
424
+ # Replace projected variables with their extension, if any
425
+ o.is_a?(Array) ?
426
+ "(" + [o.last, :AS, o.first].to_sparql(**options) + ")" :
427
+ o.to_sparql(**options)
428
+ end
429
+ str << "GROUP BY #{ops.join(' ')}\n"
430
+ end
431
+
432
+ # HavingClause
433
+ unless having_ops.empty?
434
+ str << "HAVING #{having_ops.to_sparql(**options)}"
435
+ end
436
+
437
+ # OrderClause
438
+ unless order_ops.empty?
439
+ str << "ORDER BY #{order_ops.to_sparql(**options)}\n"
440
+ end
441
+
442
+ # LimitOffsetClauses
443
+ str << "OFFSET #{offset}\n" unless offset.nil?
444
+ str << "LIMIT #{limit}\n" unless limit.nil?
445
+
446
+ # Values Clause
447
+ str << values_clause.to_sparql(top_level: false, **options) if values_clause
448
+ str
449
+ end
450
+
336
451
  ARITY = -1 # variable arity
337
452
 
338
453
  ##
@@ -558,12 +673,8 @@ module SPARQL; module Algebra
558
673
  # @return [SPARQL::Algebra::Expression] `self`
559
674
  def rewrite(&block)
560
675
  @operands = @operands.map do |op|
561
- # Rewrite the operand
562
- unless new_op = block.call(op)
563
- # Not re-written, rewrite
564
- new_op = op.respond_to?(:rewrite) ? op.rewrite(&block) : op
565
- end
566
- new_op
676
+ new_op = block.call(op)
677
+ new_op.respond_to?(:rewrite) ? new_op.rewrite(&block) : new_op
567
678
  end
568
679
  self
569
680
  end
@@ -581,9 +692,19 @@ module SPARQL; module Algebra
581
692
  ##
582
693
  # Returns an S-Expression (SXP) representation of this operator
583
694
  #
695
+ # @param [Hash{Symbol => RDF::URI}] prefixes (nil)
696
+ # @param [RDF::URI] base_uri (nil)
697
+ # @return [String]
698
+ def to_sxp(prefixes: nil, base_uri: nil)
699
+ to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
700
+ end
701
+
702
+ ##
703
+ # Returns a partial SPARQL grammar for the operator.
704
+ #
584
705
  # @return [String]
585
- def to_sxp
586
- to_sxp_bin.to_sxp
706
+ def to_sparql(**options)
707
+ raise NotImplementedError, "#{self.class}#to_sparql(#{operands.map(&:class).join(', ')})"
587
708
  end
588
709
 
589
710
  ##
@@ -5,7 +5,7 @@ class NilClass
5
5
  # Returns the SXP representation of this object.
6
6
  #
7
7
  # @return [String]
8
- def to_sxp
8
+ def to_sxp(**options)
9
9
  RDF.nil.to_s
10
10
  end
11
11
  end
@@ -17,7 +17,7 @@ class FalseClass
17
17
  # Returns the SXP representation of this object.
18
18
  #
19
19
  # @return [String]
20
- def to_sxp
20
+ def to_sxp(**options)
21
21
  'false'
22
22
  end
23
23
  end
@@ -29,7 +29,7 @@ class TrueClass
29
29
  # Returns the SXP representation of this object.
30
30
  #
31
31
  # @return [String]
32
- def to_sxp
32
+ def to_sxp(**options)
33
33
  'true'
34
34
  end
35
35
  end
@@ -19,6 +19,24 @@ module SPARQL
19
19
  #
20
20
  # {RDF::Query} and {RDF::Query::Pattern} are used as primitives for `bgp` and `triple` expressions.
21
21
  #
22
+ # # Background
23
+ #
24
+ # The SPARQL Algebra, and the S-Expressions used to represent it, are based on those of [Jena](https://jena.apache.org/documentation/notes/sse.html). Generally, an S-Expression generated by this Gem can be used as an SSE input to Jena, or an SSE output from Jena can also be used as input to this Gem.
25
+ #
26
+ # S-Expressions generally follow a standardized nesting resulting from parsing the original SPARQL Grammar. The individual operators map to SPARQL Grammar productions, and in most cases, the SPARQL Grammar can be reproduced by turning the S-Expression back into SPARQL (see {SPARQL::Algebra::Operator#to_sparql}). The order of operations will typically be as follows:
27
+ #
28
+ # * {SPARQL::Algebra::Operator::Base}
29
+ # * {SPARQL::Algebra::Operator::Prefix}
30
+ # * {SPARQL::Algebra::Operator::Slice}
31
+ # * {SPARQL::Algebra::Operator::Distinct}
32
+ # * {SPARQL::Algebra::Operator::Reduced}
33
+ # * {SPARQL::Algebra::Operator::Project}
34
+ # * {SPARQL::Algebra::Operator::Order}
35
+ # * {SPARQL::Algebra::Operator::Filter}
36
+ # * {SPARQL::Algebra::Operator::Extend}
37
+ # * {SPARQL::Algebra::Operator::Group}
38
+ # * {SPARQL::Algebra::Query} (many classes implement Query)
39
+ #
22
40
  # # Queries
23
41
  #
24
42
  # require 'sparql/algebra'
@@ -262,6 +280,7 @@ module SPARQL
262
280
  # * {SPARQL::Algebra::Operator::Extend}
263
281
  # * {SPARQL::Algebra::Operator::Filter}
264
282
  # * {SPARQL::Algebra::Operator::Floor}
283
+ # * {SPARQL::Algebra::Operator::FunctionCall}
265
284
  # * {SPARQL::Algebra::Operator::Graph}
266
285
  # * {SPARQL::Algebra::Operator::GreaterThan}
267
286
  # * {SPARQL::Algebra::Operator::GreaterThanOrEqual}
@@ -339,11 +358,9 @@ module SPARQL
339
358
  # * {SPARQL::Algebra::Operator::With}
340
359
  # * {SPARQL::Algebra::Operator::Year}
341
360
  #
342
- # TODO
343
- # ====
344
- # * Operator#optimize needs to be completed and tested.
345
361
  #
346
362
  # @see http://www.w3.org/TR/sparql11-query/#sparqlAlgebra
363
+ # @see https://jena.apache.org/documentation/notes/sse.html
347
364
  module Algebra
348
365
  include RDF
349
366