sparql 1.1.5 → 1.1.6

Sign up to get free protection for your applications and to get access to all the features.
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