sparql 1.1.5 → 1.1.6

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -32
  3. data/VERSION +1 -1
  4. data/bin/sparql +8 -6
  5. data/lib/sparql.rb +4 -2
  6. data/lib/sparql/algebra.rb +74 -4
  7. data/lib/sparql/algebra/aggregate.rb +1 -1
  8. data/lib/sparql/algebra/evaluatable.rb +1 -1
  9. data/lib/sparql/algebra/expression.rb +24 -16
  10. data/lib/sparql/algebra/extensions.rb +37 -9
  11. data/lib/sparql/algebra/operator.rb +75 -12
  12. data/lib/sparql/algebra/operator/add.rb +41 -19
  13. data/lib/sparql/algebra/operator/and.rb +2 -2
  14. data/lib/sparql/algebra/operator/asc.rb +1 -1
  15. data/lib/sparql/algebra/operator/ask.rb +1 -1
  16. data/lib/sparql/algebra/operator/base.rb +1 -1
  17. data/lib/sparql/algebra/operator/bgp.rb +1 -1
  18. data/lib/sparql/algebra/operator/bnode.rb +1 -1
  19. data/lib/sparql/algebra/operator/clear.rb +63 -0
  20. data/lib/sparql/algebra/operator/coalesce.rb +1 -1
  21. data/lib/sparql/algebra/operator/concat.rb +3 -3
  22. data/lib/sparql/algebra/operator/construct.rb +2 -2
  23. data/lib/sparql/algebra/operator/copy.rb +64 -0
  24. data/lib/sparql/algebra/operator/create.rb +49 -0
  25. data/lib/sparql/algebra/operator/dataset.rb +6 -31
  26. data/lib/sparql/algebra/operator/delete.rb +55 -0
  27. data/lib/sparql/algebra/operator/delete_data.rb +41 -0
  28. data/lib/sparql/algebra/operator/delete_where.rb +57 -0
  29. data/lib/sparql/algebra/operator/distinct.rb +1 -1
  30. data/lib/sparql/algebra/operator/drop.rb +66 -0
  31. data/lib/sparql/algebra/operator/exists.rb +2 -2
  32. data/lib/sparql/algebra/operator/exprlist.rb +1 -1
  33. data/lib/sparql/algebra/operator/extend.rb +3 -3
  34. data/lib/sparql/algebra/operator/filter.rb +2 -2
  35. data/lib/sparql/algebra/operator/graph.rb +39 -5
  36. data/lib/sparql/algebra/operator/group.rb +5 -5
  37. data/lib/sparql/algebra/operator/group_concat.rb +1 -1
  38. data/lib/sparql/algebra/operator/if.rb +3 -3
  39. data/lib/sparql/algebra/operator/in.rb +1 -1
  40. data/lib/sparql/algebra/operator/insert.rb +54 -0
  41. data/lib/sparql/algebra/operator/insert_data.rb +41 -0
  42. data/lib/sparql/algebra/operator/join.rb +2 -2
  43. data/lib/sparql/algebra/operator/lcase.rb +1 -1
  44. data/lib/sparql/algebra/operator/left_join.rb +2 -2
  45. data/lib/sparql/algebra/operator/load.rb +48 -0
  46. data/lib/sparql/algebra/operator/minus.rb +2 -2
  47. data/lib/sparql/algebra/operator/modify.rb +53 -0
  48. data/lib/sparql/algebra/operator/move.rb +67 -0
  49. data/lib/sparql/algebra/operator/notexists.rb +1 -1
  50. data/lib/sparql/algebra/operator/notin.rb +2 -2
  51. data/lib/sparql/algebra/operator/or.rb +2 -2
  52. data/lib/sparql/algebra/operator/order.rb +3 -3
  53. data/lib/sparql/algebra/operator/plus.rb +14 -8
  54. data/lib/sparql/algebra/operator/prefix.rb +1 -1
  55. data/lib/sparql/algebra/operator/project.rb +1 -1
  56. data/lib/sparql/algebra/operator/reduced.rb +1 -1
  57. data/lib/sparql/algebra/operator/replace.rb +1 -1
  58. data/lib/sparql/algebra/operator/slice.rb +1 -1
  59. data/lib/sparql/algebra/operator/strafter.rb +1 -1
  60. data/lib/sparql/algebra/operator/strbefore.rb +2 -2
  61. data/lib/sparql/algebra/operator/strdt.rb +1 -1
  62. data/lib/sparql/algebra/operator/strlang.rb +1 -1
  63. data/lib/sparql/algebra/operator/substr.rb +2 -2
  64. data/lib/sparql/algebra/operator/ucase.rb +1 -1
  65. data/lib/sparql/algebra/operator/union.rb +1 -1
  66. data/lib/sparql/algebra/operator/update.rb +44 -0
  67. data/lib/sparql/algebra/operator/using.rb +40 -0
  68. data/lib/sparql/algebra/operator/with.rb +72 -0
  69. data/lib/sparql/algebra/update.rb +56 -0
  70. data/lib/sparql/extensions.rb +8 -8
  71. data/lib/sparql/grammar.rb +31 -8
  72. data/lib/sparql/grammar/meta.rb +3758 -3273
  73. data/lib/sparql/grammar/parser11.rb +240 -46
  74. data/lib/sparql/grammar/terminals11.rb +5 -5
  75. data/lib/sparql/results.rb +26 -26
  76. metadata +38 -30
@@ -78,12 +78,17 @@ class Array
78
78
  # @return [Boolean] `true` or `false`
79
79
  # @see #constant?
80
80
  def variable?
81
- any? do |operand|
82
- operand.is_a?(Variable) ||
83
- (operand.respond_to?(:variable?) && operand.variable?)
84
- end
81
+ any?(&:variable?)
85
82
  end
86
83
  def constant?; !(variable?); end
84
+
85
+ ##
86
+ # Does this contain any nodes?
87
+ #
88
+ # @return [Boolean]
89
+ def has_blank_nodes?
90
+ any?(&:has_blank_nodes?)
91
+ end
87
92
  def evaluatable?; true; end
88
93
  def executable?; false; end
89
94
  def aggregate?; false; end
@@ -207,7 +212,7 @@ module RDF::Queryable
207
212
  #
208
213
  # @example
209
214
  # queryable.query([nil, RDF::DOAP.developer, nil])
210
- # queryable.query(:predicate => RDF::DOAP.developer)
215
+ # queryable.query(predicate: RDF::DOAP.developer)
211
216
  #
212
217
  # op = SPARQL::Algebra::Expression.parse(%q((bgp (triple ?a doap:developer ?b))))
213
218
  # queryable.query(op)
@@ -245,6 +250,18 @@ module RDF::Queryable
245
250
 
246
251
  end
247
252
 
253
+ class RDF::Statement
254
+ # Transform Statement Pattern into an SXP
255
+ # @return [Array]
256
+ def to_sxp_bin
257
+ if has_context?
258
+ [:quad, subject, predicate, object, context]
259
+ else
260
+ [:triple, subject, predicate, object]
261
+ end
262
+ end
263
+ end
264
+
248
265
  class RDF::Query
249
266
  # Equivalence for Queries:
250
267
  # Same Patterns
@@ -263,13 +280,20 @@ class RDF::Query
263
280
 
264
281
  # Transform Query into an Array form of an SSE
265
282
  #
266
- # If Query is named, it's treated as a GroupGraphPattern, otherwise, a BGP
283
+ # If Query has the `as_container` option set, serialize as Quads
284
+ # Otherwise, If Query is named, serialize as a GroupGraphPattern.
285
+ # Otherise, serialize as a BGP
267
286
  #
268
287
  # @return [Array]
269
288
  def to_sxp_bin
270
- res = [:bgp] + patterns.map(&:to_sxp_bin)
271
- (context ? [:graph, context, res] : res)
289
+ if options[:as_container]
290
+ [:graph, context] + [patterns.map(&:to_sxp_bin)]
291
+ else
292
+ res = [:bgp] + patterns.map(&:to_sxp_bin)
293
+ (context ? [:graph, context, res] : res)
294
+ end
272
295
  end
296
+
273
297
  # Query results in a boolean result (e.g., ASK)
274
298
  # @return [Boolean]
275
299
  def query_yields_boolean?
@@ -293,7 +317,11 @@ class RDF::Query::Pattern
293
317
  # Transform Query Pattern into an SXP
294
318
  # @return [Array]
295
319
  def to_sxp_bin
296
- [:triple, subject, predicate, object]
320
+ if has_context?
321
+ [:quad, subject, predicate, object, context]
322
+ else
323
+ [:triple, subject, predicate, object]
324
+ end
297
325
  end
298
326
  end
299
327
 
@@ -56,7 +56,6 @@ module SPARQL; module Algebra
56
56
  autoload :Year, 'sparql/algebra/operator/year'
57
57
 
58
58
  # Binary operators
59
- autoload :Add, 'sparql/algebra/operator/add'
60
59
  autoload :And, 'sparql/algebra/operator/and'
61
60
  autoload :Compare, 'sparql/algebra/operator/compare'
62
61
  autoload :Concat, 'sparql/algebra/operator/concat'
@@ -118,6 +117,26 @@ module SPARQL; module Algebra
118
117
  autoload :Table, 'sparql/algebra/operator/table'
119
118
  autoload :Union, 'sparql/algebra/operator/union'
120
119
 
120
+ # Update operators
121
+ autoload :Add, 'sparql/algebra/operator/add'
122
+ autoload :Clear, 'sparql/algebra/operator/clear'
123
+ autoload :Copy, 'sparql/algebra/operator/copy'
124
+ autoload :Create, 'sparql/algebra/operator/create'
125
+ autoload :Delete, 'sparql/algebra/operator/delete'
126
+ autoload :DeleteData, 'sparql/algebra/operator/delete_data'
127
+ autoload :DeleteWhere, 'sparql/algebra/operator/delete_where'
128
+ autoload :Drop, 'sparql/algebra/operator/drop'
129
+ autoload :Insert, 'sparql/algebra/operator/insert'
130
+ autoload :InsertData, 'sparql/algebra/operator/insert_data'
131
+ autoload :Load, 'sparql/algebra/operator/load'
132
+ autoload :Modify, 'sparql/algebra/operator/modify'
133
+ autoload :Move, 'sparql/algebra/operator/move'
134
+ autoload :Update, 'sparql/algebra/operator/update'
135
+ autoload :Using, 'sparql/algebra/operator/using'
136
+ autoload :With, 'sparql/algebra/operator/with'
137
+
138
+
139
+
121
140
  ##
122
141
  # Returns an operator class for the given operator `name`.
123
142
  #
@@ -131,7 +150,7 @@ module SPARQL; module Algebra
131
150
  when :'/' then Divide
132
151
  when :'=' then Equal
133
152
  when :* then Multiply
134
- when :+ then arity.eql?(1) ? Plus : Add
153
+ when :+ then Plus
135
154
  when :- then arity.eql?(1) ? Negate : Subtract
136
155
  when :< then LessThan
137
156
  when :<= then LessThanOrEqual
@@ -216,7 +235,7 @@ module SPARQL; module Algebra
216
235
 
217
236
  # Datasets
218
237
  when :dataset then Dataset
219
-
238
+
220
239
  # Query forms
221
240
  when :ask then Ask
222
241
  when :base then Base
@@ -239,6 +258,24 @@ module SPARQL; module Algebra
239
258
  when :table then Table
240
259
  when :triple then RDF::Query::Pattern
241
260
  when :union then Union
261
+
262
+ # Update forms
263
+ when :add then Add
264
+ when :clear then Clear
265
+ when :copy then Copy
266
+ when :create then Create
267
+ when :delete then Delete
268
+ when :deletedata then DeleteData
269
+ when :deletewhere then DeleteWhere
270
+ when :drop then Drop
271
+ when :insert then Insert
272
+ when :insertdata then InsertData
273
+ when :load then Load
274
+ when :modify then Modify
275
+ when :move then Move
276
+ when :update then Update
277
+ when :using then Using
278
+ when :with then With
242
279
  else nil # not found
243
280
  end
244
281
  end
@@ -303,7 +340,7 @@ module SPARQL; module Algebra
303
340
  def base_uri
304
341
  Operator.base_uri
305
342
  end
306
-
343
+
307
344
  ##
308
345
  # Base URI used for reading data sources with relative URIs
309
346
  #
@@ -311,7 +348,7 @@ module SPARQL; module Algebra
311
348
  def self.base_uri
312
349
  @base_uri
313
350
  end
314
-
351
+
315
352
  ##
316
353
  # Set Base URI associated with SPARQL document, typically done
317
354
  # when reading SPARQL from a URI
@@ -321,7 +358,7 @@ module SPARQL; module Algebra
321
358
  def self.base_uri=(uri)
322
359
  @base_uri = RDF::URI(uri)
323
360
  end
324
-
361
+
325
362
  ##
326
363
  # Prefixes useful for future serialization
327
364
  #
@@ -330,7 +367,7 @@ module SPARQL; module Algebra
330
367
  def prefixes
331
368
  Operator.prefixes
332
369
  end
333
-
370
+
334
371
  ##
335
372
  # Prefixes useful for future serialization
336
373
  #
@@ -339,7 +376,7 @@ module SPARQL; module Algebra
339
376
  def self.prefixes
340
377
  @prefixes
341
378
  end
342
-
379
+
343
380
  ##
344
381
  # Prefixes useful for future serialization
345
382
  #
@@ -349,7 +386,7 @@ module SPARQL; module Algebra
349
386
  def self.prefixes=(hash)
350
387
  @prefixes = hash
351
388
  end
352
-
389
+
353
390
  ##
354
391
  # Any additional options for this operator.
355
392
  #
@@ -379,9 +416,17 @@ module SPARQL; module Algebra
379
416
  # @return [Boolean] `true` or `false`
380
417
  # @see #constant?
381
418
  def variable?
419
+ operands.any?(&:variable?)
420
+ end
421
+
422
+ ##
423
+ # Returns `true` if any of the operands are nodes, `false`
424
+ # otherwise.
425
+ #
426
+ # @return [Boolean]
427
+ def has_blank_nodes?
382
428
  operands.any? do |operand|
383
- operand.is_a?(Variable) ||
384
- (operand.respond_to?(:variable?) && operand.variable?)
429
+ operand.respond_to?(:has_blank_nodes?) ? operand.has_blank_nodes? : operand.node?
385
430
  end
386
431
  end
387
432
 
@@ -486,7 +531,7 @@ module SPARQL; module Algebra
486
531
  abort "SPARQL::Algebra::Operator#to_sxp requires the SXP gem (hint: `gem install sxp')."
487
532
  end
488
533
  require 'sparql/algebra/sxp_extensions'
489
-
534
+
490
535
  to_sxp_bin.to_sxp
491
536
  end
492
537
 
@@ -506,6 +551,24 @@ module SPARQL; module Algebra
506
551
  end
507
552
  alias_method :==, :eql?
508
553
 
554
+ ##
555
+ # Iterate via deapth-first recursive descent over operands, yielding each operator
556
+ # @yield operator
557
+ # @yieldparam [Object] operator
558
+ def descendants(&block)
559
+ operands.each do |operand|
560
+ case operand
561
+ when Operator
562
+ operand.descendants(&block)
563
+ when Array
564
+ operand.each do |op|
565
+ op.descendants(&block) if op.is_a?(Operator)
566
+ block.call(op)
567
+ end
568
+ end
569
+ block.call(operand)
570
+ end
571
+ end
509
572
  protected
510
573
 
511
574
  ##
@@ -1,33 +1,55 @@
1
1
  module SPARQL; module Algebra
2
2
  class Operator
3
- include Evaluatable
4
3
 
5
4
  ##
6
- # The SPARQL numeric `add` operator.
5
+ # The SPARQL UPDATE `add` operator.
6
+ #
7
+ # The ADD operation is a shortcut for inserting all data from an input graph into a destination graph. Data from the input graph is not affected, and initial data from the destination graph, if any, is kept intact.
7
8
  #
8
9
  # @example
9
- # (+ 1 ?x)
10
- # (add 1 ?x)
10
+ # (add default <a>)
11
11
  #
12
- # @see http://www.w3.org/TR/xpath-functions/#func-numeric-add
13
- class Add < Operator::Binary
14
- NAME = [:+, :add]
12
+ # @see http://www.w3.org/TR/sparql11-update/#add
13
+ class Add < Operator
14
+ include SPARQL::Algebra::Update
15
+
16
+ NAME = [:add]
15
17
 
16
18
  ##
17
- # Returns the arithmetic sum of the operands.
19
+ # Executes this upate on the given `writable` graph or repository.
18
20
  #
19
- # @param [RDF::Literal::Numeric] left
20
- # a numeric literal
21
- # @param [RDF::Literal::Numeric] right
22
- # a numeric literal
23
- # @return [RDF::Literal::Numeric]
24
- # @raise [TypeError] if either operand is not a numeric literal
25
- def apply(left, right)
26
- case
27
- when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
28
- left + right
29
- else raise TypeError, "expected two RDF::Literal::Numeric operands, but got #{left.inspect} and #{right.inspect}"
21
+ # @param [RDF::Queryable] queryable
22
+ # the graph or repository to write
23
+ # @param [Hash{Symbol => Object}] options
24
+ # any additional keyword options
25
+ # @option options [Boolean] debug
26
+ # Query execution debugging
27
+ # @return [RDF::Queryable]
28
+ # Returns queryable.
29
+ # @raise [IOError]
30
+ # If `from` does not exist, unless the `silent` operator is present
31
+ # @see http://www.w3.org/TR/sparql11-update/
32
+ def execute(queryable, options = {})
33
+ debug(options) {"Add"}
34
+ silent = operands.first == :silent
35
+ operands.shift if silent
36
+
37
+ src_name, dest_name = operands[-2..-1]
38
+ raise ArgumentError, "add expected two operands, got #{operands.length}" unless operands.length == 2
39
+ raise ArgumentError, "add from must be IRI or :default" unless src_name == :default || src_name.is_a?(RDF::URI)
40
+ raise ArgumentError, "add to must be IRI or :default" unless dest_name == :default || dest_name.is_a?(RDF::URI)
41
+ src = queryable.enum_graph.detect {|g| g.to_s == src_name.to_s}
42
+
43
+ if src.nil?
44
+ raise IOError, "add operation source does not exist" unless silent
45
+ else
46
+ src.each do |statement|
47
+ statement = statement.dup
48
+ statement.context = (dest_name unless dest_name == :default)
49
+ queryable << statement
50
+ end
30
51
  end
52
+ queryable
31
53
  end
32
54
  end # Add
33
55
  end # Operator
@@ -42,13 +42,13 @@ module SPARQL; module Algebra
42
42
  # @raise [TypeError] if the operands could not be coerced to boolean literals
43
43
  def evaluate(bindings, options = {})
44
44
  begin
45
- left = boolean(operand(0).evaluate(bindings, options.merge(:depth => options[:depth].to_i + 1))).true?
45
+ left = boolean(operand(0).evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))).true?
46
46
  rescue TypeError
47
47
  left = nil
48
48
  end
49
49
 
50
50
  begin
51
- right = boolean(operand(1).evaluate(bindings, options.merge(:depth => options[:depth].to_i + 1))).true?
51
+ right = boolean(operand(1).evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))).true?
52
52
  rescue TypeError
53
53
  right = nil
54
54
  end
@@ -25,7 +25,7 @@ module SPARQL; module Algebra
25
25
  # options passed from query
26
26
  # @return [RDF::Term]
27
27
  def evaluate(bindings, options = {})
28
- operand(0).evaluate(bindings, options.merge(:depth => options[:depth].to_i + 1))
28
+ operand(0).evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))
29
29
  end
30
30
  end # Asc
31
31
  end # Operator
@@ -29,7 +29,7 @@ module SPARQL; module Algebra
29
29
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
30
30
  def execute(queryable, options = {})
31
31
  debug(options) {"Ask #{operands.first}"}
32
- res = boolean(!queryable.query(operands.last, options.merge(:depth => options[:depth].to_i + 1)).empty?)
32
+ res = boolean(!queryable.query(operands.last, options.merge(depth: options[:depth].to_i + 1)).empty?)
33
33
  yield res if block_given?
34
34
  res
35
35
  end
@@ -32,7 +32,7 @@ module SPARQL; module Algebra
32
32
  def execute(queryable, options = {}, &block)
33
33
  debug(options) {"Base #{operands.first}"}
34
34
  Operator.base_uri = operands.first
35
- queryable.query(operands.last, options.merge(:depth => options[:depth].to_i + 1), &block)
35
+ queryable.query(operands.last, options.merge(depth: options[:depth].to_i + 1), &block)
36
36
  end
37
37
 
38
38
  ##
@@ -23,7 +23,7 @@ module SPARQL; module Algebra
23
23
  # @yieldreturn [void] ignored
24
24
  # @return [RDF::Query]
25
25
  def self.new(*patterns, &block)
26
- RDF::Query.new(*(patterns + [{:context => false}]), &block)
26
+ RDF::Query.new(*(patterns + [{context: false}]), &block)
27
27
  end
28
28
  end # BGP
29
29
  end # Operator
@@ -41,7 +41,7 @@ module SPARQL; module Algebra
41
41
  # options passed from query
42
42
  # @return [RDF::Term]
43
43
  def evaluate(bindings, options = {})
44
- args = operands.map { |operand| operand.evaluate(bindings, options.merge(:depth => options[:depth].to_i + 1)) }
44
+ args = operands.map { |operand| operand.evaluate(bindings, options.merge(depth: options[:depth].to_i + 1)) }
45
45
  apply(args.first, bindings)
46
46
  end
47
47
 
@@ -0,0 +1,63 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+
4
+ ##
5
+ # The SPARQL UPDATE `clear` operator.
6
+ #
7
+ # The CLEAR operation removes all the triples in the specified graph(s) in the Graph Store.
8
+ #
9
+ # @example
10
+ # (clear silent default)
11
+ #
12
+ # @see http://www.w3.org/TR/sparql11-update/#clear
13
+ class Clear < Operator
14
+ include SPARQL::Algebra::Update
15
+
16
+ NAME = [:clear]
17
+
18
+ ##
19
+ # Executes this upate on the given `writable` graph or repository.
20
+ #
21
+ # @param [RDF::Queryable] queryable
22
+ # the graph or repository to write
23
+ # @param [Hash{Symbol => Object}] options
24
+ # any additional keyword options
25
+ # @option options [Boolean] debug
26
+ # Query execution debugging
27
+ # @return [RDF::Queryable]
28
+ # Returns queryable.
29
+ # @raise [IOError]
30
+ # If `from` does not exist, unless the `silent` operator is present
31
+ # @see http://www.w3.org/TR/sparql11-update/
32
+ def execute(queryable, options = {})
33
+ debug(options) {"Clear"}
34
+ silent = operands.first == :silent
35
+ operands.shift if silent
36
+
37
+ raise ArgumentError, "clear expected operand to be 'default', 'named', 'all', or an IRI" unless operands.length == 1
38
+ case operands.last
39
+ when :default
40
+ queryable.each_graph do |g|
41
+ g.clear! unless g.context
42
+ end
43
+ when :named
44
+ queryable.each_graph do |g|
45
+ g.clear! if g.context
46
+ end
47
+ when :all
48
+ queryable.clear!
49
+ when RDF::URI
50
+ if g = queryable.each_graph.detect {|c| c.context == operands.last}
51
+ g.clear!
52
+ else
53
+ raise IOError, "clear operation graph does not exist" unless silent
54
+ end
55
+ else
56
+ raise ArgumentError, "clear expected operand to be 'default', 'named', 'all', or an IRI"
57
+ end
58
+
59
+ queryable
60
+ end
61
+ end # Clear
62
+ end # Operator
63
+ end; end # SPARQL::Algebra