sparql 3.2.0 → 3.2.4

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +59 -38
  3. data/VERSION +1 -1
  4. data/bin/sparql +2 -31
  5. data/lib/rack/sparql/conneg.rb +22 -1
  6. data/lib/sinatra/sparql/extensions.rb +1 -1
  7. data/lib/sinatra/sparql.rb +57 -12
  8. data/lib/sparql/algebra/expression.rb +63 -10
  9. data/lib/sparql/algebra/extensions.rb +39 -35
  10. data/lib/sparql/algebra/operator/abs.rb +1 -1
  11. data/lib/sparql/algebra/operator/adjust.rb +69 -0
  12. data/lib/sparql/algebra/operator/alt.rb +1 -1
  13. data/lib/sparql/algebra/operator/avg.rb +3 -1
  14. data/lib/sparql/algebra/operator/bgp.rb +9 -1
  15. data/lib/sparql/algebra/operator/clear.rb +13 -3
  16. data/lib/sparql/algebra/operator/construct.rb +1 -1
  17. data/lib/sparql/algebra/operator/count.rb +36 -6
  18. data/lib/sparql/algebra/operator/create.rb +5 -4
  19. data/lib/sparql/algebra/operator/dataset.rb +29 -11
  20. data/lib/sparql/algebra/operator/day.rb +2 -2
  21. data/lib/sparql/algebra/operator/delete.rb +3 -1
  22. data/lib/sparql/algebra/operator/delete_data.rb +1 -1
  23. data/lib/sparql/algebra/operator/delete_where.rb +1 -1
  24. data/lib/sparql/algebra/operator/distinct.rb +2 -2
  25. data/lib/sparql/algebra/operator/divide.rb +1 -1
  26. data/lib/sparql/algebra/operator/drop.rb +15 -6
  27. data/lib/sparql/algebra/operator/encode_for_uri.rb +2 -4
  28. data/lib/sparql/algebra/operator/exprlist.rb +3 -1
  29. data/lib/sparql/algebra/operator/extend.rb +73 -5
  30. data/lib/sparql/algebra/operator/filter.rb +6 -1
  31. data/lib/sparql/algebra/operator/function_call.rb +64 -0
  32. data/lib/sparql/algebra/operator/graph.rb +57 -7
  33. data/lib/sparql/algebra/operator/group.rb +105 -6
  34. data/lib/sparql/algebra/operator/group_concat.rb +25 -1
  35. data/lib/sparql/algebra/operator/hours.rb +2 -2
  36. data/lib/sparql/algebra/operator/if.rb +10 -10
  37. data/lib/sparql/algebra/operator/insert.rb +3 -1
  38. data/lib/sparql/algebra/operator/insert_data.rb +1 -1
  39. data/lib/sparql/algebra/operator/is_blank.rb +1 -2
  40. data/lib/sparql/algebra/operator/is_iri.rb +1 -2
  41. data/lib/sparql/algebra/operator/is_literal.rb +1 -2
  42. data/lib/sparql/algebra/operator/is_numeric.rb +1 -2
  43. data/lib/sparql/algebra/operator/join.rb +39 -5
  44. data/lib/sparql/algebra/operator/lcase.rb +2 -3
  45. data/lib/sparql/algebra/operator/left_join.rb +27 -9
  46. data/lib/sparql/algebra/operator/max.rb +3 -1
  47. data/lib/sparql/algebra/operator/min.rb +4 -2
  48. data/lib/sparql/algebra/operator/minus.rb +46 -6
  49. data/lib/sparql/algebra/operator/minutes.rb +2 -2
  50. data/lib/sparql/algebra/operator/modify.rb +21 -0
  51. data/lib/sparql/algebra/operator/month.rb +2 -2
  52. data/lib/sparql/algebra/operator/multiply.rb +1 -1
  53. data/lib/sparql/algebra/operator/notoneof.rb +12 -3
  54. data/lib/sparql/algebra/operator/order.rb +44 -0
  55. data/lib/sparql/algebra/operator/path_opt.rb +9 -65
  56. data/lib/sparql/algebra/operator/path_plus.rb +18 -10
  57. data/lib/sparql/algebra/operator/path_range.rb +178 -0
  58. data/lib/sparql/algebra/operator/path_star.rb +7 -4
  59. data/lib/sparql/algebra/operator/path_zero.rb +110 -0
  60. data/lib/sparql/algebra/operator/plus.rb +8 -6
  61. data/lib/sparql/algebra/operator/project.rb +64 -5
  62. data/lib/sparql/algebra/operator/reduced.rb +3 -3
  63. data/lib/sparql/algebra/operator/regex.rb +1 -1
  64. data/lib/sparql/algebra/operator/reverse.rb +12 -1
  65. data/lib/sparql/algebra/operator/sample.rb +3 -1
  66. data/lib/sparql/algebra/operator/seconds.rb +2 -2
  67. data/lib/sparql/algebra/operator/seq.rb +4 -4
  68. data/lib/sparql/algebra/operator/sequence.rb +14 -1
  69. data/lib/sparql/algebra/operator/service.rb +86 -0
  70. data/lib/sparql/algebra/operator/strlang.rb +1 -2
  71. data/lib/sparql/algebra/operator/subtract.rb +10 -6
  72. data/lib/sparql/algebra/operator/sum.rb +9 -7
  73. data/lib/sparql/algebra/operator/table.rb +50 -7
  74. data/lib/sparql/algebra/operator/timezone.rb +2 -2
  75. data/lib/sparql/algebra/operator/triple.rb +51 -0
  76. data/lib/sparql/algebra/operator/tz.rb +2 -2
  77. data/lib/sparql/algebra/operator/ucase.rb +1 -1
  78. data/lib/sparql/algebra/operator/update.rb +22 -1
  79. data/lib/sparql/algebra/operator/using.rb +18 -1
  80. data/lib/sparql/algebra/operator/with.rb +1 -1
  81. data/lib/sparql/algebra/operator/year.rb +2 -2
  82. data/lib/sparql/algebra/operator.rb +69 -22
  83. data/lib/sparql/algebra/query.rb +5 -3
  84. data/lib/sparql/algebra.rb +42 -6
  85. data/lib/sparql/grammar/meta.rb +1367 -267
  86. data/lib/sparql/grammar/parser11.rb +842 -331
  87. data/lib/sparql/grammar/terminals11.rb +2 -2
  88. data/lib/sparql/grammar.rb +6 -4
  89. data/lib/sparql/results.rb +3 -2
  90. data/lib/sparql/server.rb +93 -0
  91. data/lib/sparql.rb +8 -5
  92. metadata +49 -13
@@ -0,0 +1,86 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL Service operator.
5
+ #
6
+ # [59] ServiceGraphPattern ::= 'SERVICE' 'SILENT'? VarOrIri GroupGraphPattern
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ #
11
+ # SELECT ?s ?o1 ?o2 {
12
+ # ?s ?p1 ?o1 .
13
+ # SERVICE <http://example.org/sparql> {
14
+ # ?s ?p2 ?o2
15
+ # }
16
+ # }
17
+ #
18
+ # @example SSE
19
+ # (prefix ((: <http://example.org/>))
20
+ # (project (?s ?o1 ?o2)
21
+ # (join
22
+ # (bgp (triple ?s ?p1 ?o1))
23
+ # (service :sparql
24
+ # (bgp (triple ?s ?p2 ?o2))))))
25
+ #
26
+ # @see https://www.w3.org/TR/sparql11-query/#QSynIRI
27
+ class Service < Operator
28
+ include Query
29
+
30
+ NAME = [:service]
31
+
32
+ ##
33
+ # Executes this query on the given `queryable` graph or repository.
34
+ # Really a pass-through, as this is a syntactic object used for providing
35
+ # graph_name for URIs.
36
+ #
37
+ # @param [RDF::Queryable] queryable
38
+ # the graph or repository to query
39
+ # @param [Hash{Symbol => Object}] options
40
+ # any additional keyword options
41
+ # @yield [solution]
42
+ # each matching solution, statement or boolean
43
+ # @yieldparam [RDF::Statement, RDF::Query::Solution, Boolean] solution
44
+ # @yieldreturn [void] ignored
45
+ # @return [RDF::Query::Solutions]
46
+ # the resulting solution sequence
47
+ # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
48
+ def execute(queryable, **options, &block)
49
+ debug(options) {"Service"}
50
+ silent = operands.first == :silent
51
+ location, query = operands
52
+ query_sparql = query.to_sparql
53
+ debug(options) {"query: #{query_sparql}"}
54
+ raise NotImplementedError, "SERVICE operator not implemented"
55
+ end
56
+
57
+ ##
58
+ # Returns an optimized version of this query.
59
+ #
60
+ # Replace with the query with URIs having their lexical shortcut removed
61
+ #
62
+ # @return [Prefix] a copy of `self`
63
+ # @see SPARQL::Algebra::Expression#optimize
64
+ def optimize(**options)
65
+ operands.last.optimize(**options)
66
+ end
67
+
68
+ ##
69
+ #
70
+ # Returns a partial SPARQL grammar for this term.
71
+ #
72
+ # @return [String]
73
+ def to_sparql(**options)
74
+ silent = operands.first == :silent
75
+ ops = silent ? operands[1..-1] : operands
76
+ location, query = ops
77
+
78
+
79
+ str = "SERVICE "
80
+ str << "SILENT " if silent
81
+ str << location.to_sparql(**options) + " {" + query.to_sparql(**options) + "}"
82
+ str
83
+ end
84
+ end # Service
85
+ end # Operator
86
+ end; end # SPARQL::Algebra
@@ -13,8 +13,7 @@ module SPARQL; module Algebra
13
13
  # }
14
14
  #
15
15
  # @example SSE
16
- # (prefix
17
- # ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
16
+ # (prefix ((: <http://example.org/>))
18
17
  # (project (?s ?s2)
19
18
  # (extend ((?s2 (strlang ?str "en-US")))
20
19
  # (filter (langMatches (lang ?str) "en")
@@ -31,17 +31,21 @@ module SPARQL; module Algebra
31
31
  ##
32
32
  # Returns the arithmetic difference of the operands.
33
33
  #
34
- # @param [RDF::Literal::Numeric] left
34
+ # @param [RDF::Literal::Numeric, RDF::Literal::Temporal] left
35
35
  # a numeric literal
36
- # @param [RDF::Literal::Numeric] right
36
+ # @param [RDF::Literal::Numeric, RDF::Literal::Temporal, RDF::Literal::Duration] right
37
37
  # a numeric literal
38
- # @return [RDF::Literal::Numeric]
39
- # @raise [TypeError] if either operand is not a numeric literal
38
+ # @return [RDF::Literal::Numeric, RDF::Literal::Temporal, RDF::Literal::Duration]
39
+ # @raise [TypeError] if either operand is neither a numeric nor a temporal literal
40
40
  def apply(left, right, **options)
41
41
  case
42
42
  when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
43
43
  left - right
44
- else raise TypeError, "expected two RDF::Literal::Numeric operands, but got #{left.inspect} and #{right.inspect}"
44
+ when left.is_a?(RDF::Literal::Temporal) && right.is_a?(RDF::Literal::Temporal)
45
+ left - right
46
+ when left.is_a?(RDF::Literal::Temporal) && right.is_a?(RDF::Literal::Duration)
47
+ left - right
48
+ else raise TypeError, "expected two RDF::Literal::Numeric, Temporal operands, or a Temporal and a Duration, but got #{left.inspect} and #{right.inspect}"
45
49
  end
46
50
  end
47
51
 
@@ -51,7 +55,7 @@ module SPARQL; module Algebra
51
55
  #
52
56
  # @return [String]
53
57
  def to_sparql(**options)
54
- "#{operands.first.to_sparql(**options)} - #{operands.last.to_sparql(**options)}"
58
+ "(#{operands.first.to_sparql(**options)} - #{operands.last.to_sparql(**options)})"
55
59
  end
56
60
  end # Subtract
57
61
  end # Operator
@@ -7,15 +7,15 @@ module SPARQL; module Algebra
7
7
  #
8
8
  # @example SPARQL Grammar
9
9
  # PREFIX : <http://www.example.org/>
10
- # SELECT (SUM(?O) AS ?sum)
10
+ # SELECT (SUM(?o) AS ?sum)
11
11
  # WHERE { ?s :dec ?o }
12
12
  #
13
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))))))
14
+ # (prefix ((: <http://www.example.org/>))
15
+ # (project (?sum)
16
+ # (extend ((?sum ??.0))
17
+ # (group () ((??.0 (sum ?o)))
18
+ # (bgp (triple ?s :dec ?o))))))
19
19
  #
20
20
  # @see https://www.w3.org/TR/sparql11-query/#defn_aggSum
21
21
  class Sum < Operator
@@ -47,7 +47,9 @@ module SPARQL; module Algebra
47
47
  #
48
48
  # @return [String]
49
49
  def to_sparql(**options)
50
- "SUM(" + operands.to_sparql(**options) + ")"
50
+ distinct = operands.first == :distinct
51
+ args = distinct ? operands[1..-1] : operands
52
+ "SUM(#{'DISTINCT ' if distinct}#{args.to_sparql(**options)})"
51
53
  end
52
54
  end # Sum
53
55
  end # Operator
@@ -8,7 +8,7 @@ module SPARQL; module Algebra
8
8
  #
9
9
  # [28] ValuesClause ::= ( 'VALUES' DataBlock )?
10
10
  #
11
- # @example SPARQL Grammar
11
+ # @example SPARQL Grammar (ValuesClause)
12
12
  # PREFIX dc: <http://purl.org/dc/elements/1.1/>
13
13
  # PREFIX : <http://example.org/book/>
14
14
  # PREFIX ns: <http://example.org/ns#>
@@ -18,7 +18,7 @@ module SPARQL; module Algebra
18
18
  # }
19
19
  # VALUES ?book { :book1 }
20
20
  #
21
- # @example SSE
21
+ # @example SSE (ValuesClause)
22
22
  # (prefix ((dc: <http://purl.org/dc/elements/1.1/>)
23
23
  # (: <http://example.org/book/>)
24
24
  # (ns: <http://example.org/ns#>))
@@ -27,8 +27,38 @@ module SPARQL; module Algebra
27
27
  # (bgp (triple ?book dc:title ?title) (triple ?book ns:price ?price))
28
28
  # (table (vars ?book) (row (?book :book1)))) ))
29
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))) ))
58
+ #
30
59
  # @example empty table
31
60
  # (table unit)
61
+ #
32
62
  # @see https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#inline-data
33
63
  class Table < Operator
34
64
  include Query
@@ -59,30 +89,43 @@ module SPARQL; module Algebra
59
89
  end
60
90
  @solutions << RDF::Query::Solution.new(bindings)
61
91
  end
92
+ @solutions.variable_names = self.variables.keys
62
93
  @solutions.each(&block) if block_given?
63
94
  @solutions
64
95
  end
96
+
97
+ ##
98
+ # In-scope variables for a table are the variables operand
99
+ #
100
+ # @return [Hash{Symbol => RDF::Query::Variable}]
101
+ def variables
102
+ in_scope = operands.first.is_a?(Array) ? operands.first[1..-1] : []
103
+ in_scope.inject({}) {|memo, v| memo.merge(v.variables)}
104
+ end
65
105
 
66
106
  ##
67
107
  #
68
108
  # Returns a partial SPARQL grammar for this operator.
69
109
  #
110
+ # @param [Boolean] top_level (true)
111
+ # Treat this as a top-level, generating SELECT ... WHERE {}
70
112
  # @return [String]
71
- def to_sparql(**options)
72
- str = "VALUES (#{operands.first[1..-1].map { |e| e.to_sparql(**options) }.join(' ')}) {\n"
113
+ def to_sparql(top_level: true, **options)
114
+ str = "VALUES (#{Array(operands.first)[1..-1].map { |e| e.to_sparql(**options) }.join(' ')}) {\n"
73
115
  operands[1..-1].each do |row|
74
116
  line = '('
75
117
  row[1..-1].each do |col|
76
- line << "#{col[1].to_sparql(**options)} "
118
+ v = col[1].to_sparql(**options)
119
+ line << v + ' '
77
120
  end
78
- line = line.chop
121
+ line = line.chomp(' ')
79
122
  line << ")\n"
80
123
 
81
124
  str << line
82
125
  end
83
126
 
84
127
  str << "}\n"
85
- str
128
+ top_level ? Operator.to_sparql(str, **options) : str
86
129
  end
87
130
  end # Table
88
131
  end # Operator
@@ -33,10 +33,10 @@ module SPARQL; module Algebra
33
33
  #
34
34
  # @param [RDF::Literal] operand
35
35
  # the operand
36
- # @return [RDF::Literal]
36
+ # @return [RDF::Literal::Temporal]
37
37
  # @raise [TypeError] if the operand is not a simple literal
38
38
  def apply(operand, **options)
39
- raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
39
+ raise TypeError, "expected an RDF::Literal::Temporal, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::Temporal)
40
40
  raise TypeError, "literal has no timezone" unless res = operand.timezone
41
41
  res
42
42
  end
@@ -0,0 +1,51 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL `triple` operator.
5
+ #
6
+ # If the 3-tuple (term1, term2, term3) is an RDF-star triple, the function returns this triple. If the 3-tuple is not an RDF-star triple, then the function raises an error.
7
+ #
8
+ # [121] BuiltInCall ::= ... | 'TRIPLE' '(' Expression ',' Expression ',' Expression ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.com/ns#>
12
+ # SELECT * {
13
+ # ?s ?p ?o .
14
+ # BIND(TRIPLE(?s, ?p, ?o) AS ?t1)
15
+ # }
16
+ #
17
+ # @example SSE
18
+ # (prefix ((: <http://example.com/ns#>))
19
+ # (extend ((?t1 (triple ?s ?p ?o)))
20
+ # (bgp (triple ?s ?p ?o))))
21
+ #
22
+ # @note This operator overlaps with RDF::Query::Pattern as used as an operand to a BGP.
23
+ # @see https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#triple
24
+ class Triple < Operator::Ternary
25
+ include Evaluatable
26
+
27
+ NAME = :triple
28
+
29
+ ##
30
+ # @param [RDF::Term] subject
31
+ # @param [RDF::Term] predicate
32
+ # @param [RDF::Term] object
33
+ # @return [RDF::URI]
34
+ # @raise [TypeError] if the operand is not a simple literal
35
+ def apply(subject, predicate, object, **options)
36
+ triple = RDF::Statement(subject, predicate, object)
37
+ raise TypeError, "valid components, but got #{triple.inspect}" unless triple.valid?
38
+ triple
39
+ end
40
+
41
+ ##
42
+ #
43
+ # Returns a partial SPARQL grammar for this operator.
44
+ #
45
+ # @return [String]
46
+ def to_sparql(**options)
47
+ "TRIPLE(#{operands.to_sparql(delimiter: ', ', **options)})"
48
+ end
49
+ end # Triple
50
+ end # Operator
51
+ end; end # SPARQL::Algebra
@@ -29,12 +29,12 @@ module SPARQL; module Algebra
29
29
  ##
30
30
  # Returns the timezone part of arg as a simple literal. Returns the empty string if there is no timezone.
31
31
  #
32
- # @param [RDF::Literal] operand
32
+ # @param [RDF::Literal::Temporal] operand
33
33
  # the operand
34
34
  # @return [RDF::Literal]
35
35
  # @raise [TypeError] if the operand is not a simple literal
36
36
  def apply(operand, **options)
37
- raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
37
+ raise TypeError, "expected an RDF::Literal::Temporal, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::Temporal)
38
38
  operand.tz
39
39
  end
40
40
  ##
@@ -14,7 +14,7 @@ module SPARQL; module Algebra
14
14
  # @example SSE
15
15
  # (prefix
16
16
  # ((: <http://example.org/>))
17
- # (project (?str ?ustr)
17
+ # (project (?s ?ustr)
18
18
  # (extend ((?ustr (ucase ?str)))
19
19
  # (bgp (triple ?s :str ?str)))))
20
20
  #
@@ -21,6 +21,27 @@ module SPARQL; module Algebra
21
21
  # (delete ((triple ?a foaf:knows ?b)))
22
22
  # (insert ((triple ?b foaf:knows ?a)))) ))
23
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))))
41
+ # (modify
42
+ # (bgp (triple ?a foaf:knows ?b))
43
+ # (insert ((triple ?b foaf:knows ?a))))))
44
+ #
24
45
  # @see https://www.w3.org/TR/sparql11-update/#graphUpdate
25
46
  class Update < Operator
26
47
  include SPARQL::Algebra::Update
@@ -58,7 +79,7 @@ module SPARQL; module Algebra
58
79
  #
59
80
  # @return [String]
60
81
  def to_sparql(**options)
61
- str = operands.map { |e| e.to_sparql(**options) }.join("\n")
82
+ str = operands.map { |e| e.to_sparql(**options) }.join(";\n")
62
83
  end
63
84
  end # Update
64
85
  end # Operator
@@ -28,6 +28,21 @@ module SPARQL; module Algebra
28
28
  # (bgp (triple :a foaf:knows ?s) (triple ?s ?p ?o)))
29
29
  # (delete ((triple ?s ?p ?o)))) ))
30
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
43
+ # (using (:g1 :g2) (bgp (triple ?s ?p ?o)))
44
+ # (insert ((triple ?s ?p "q"))))))
45
+ #
31
46
  # @see https://www.w3.org/TR/sparql11-update/#add
32
47
  class Using < Operator
33
48
  include SPARQL::Algebra::Query
@@ -61,7 +76,9 @@ module SPARQL; module Algebra
61
76
  #
62
77
  # @return [String]
63
78
  def to_sparql(**options)
64
- str = "USING #{operands.first.to_sparql(**options)}\n"
79
+ str = "\n" + operands.first.map do |op|
80
+ "USING #{op.to_sparql(**options)}\n"
81
+ end.join("")
65
82
  content = operands.last.to_sparql(top_level: false, **options)
66
83
  str << Operator.to_sparql(content, project: nil, **options)
67
84
  end
@@ -85,7 +85,7 @@ module SPARQL; module Algebra
85
85
  #
86
86
  # @return [String]
87
87
  def to_sparql(**options)
88
- with, where, ops = operands
88
+ with, where, *ops = operands
89
89
  str = "WITH #{with.to_sparql(**options)}\n"
90
90
 
91
91
  # The content of the WHERE clause, may be USING
@@ -31,10 +31,10 @@ module SPARQL; module Algebra
31
31
  #
32
32
  # @param [RDF::Literal] operand
33
33
  # the operand
34
- # @return [RDF::Literal]
34
+ # @return [RDF::Literal::Temporal]
35
35
  # @raise [TypeError] if the operand is not a simple literal
36
36
  def apply(operand, **options)
37
- raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
37
+ raise TypeError, "expected an RDF::Literal::Temporal, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::Temporal)
38
38
  RDF::Literal(operand.object.year)
39
39
  end
40
40