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
@@ -47,7 +47,7 @@ module SPARQL; module Algebra
47
47
  def evaluate(bindings, options = {})
48
48
  operands.each do |op|
49
49
  begin
50
- return op.evaluate(bindings, options.merge(:depth => options[:depth].to_i + 1))
50
+ return op.evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))
51
51
  rescue
52
52
  end
53
53
  end
@@ -31,16 +31,16 @@ module SPARQL; module Algebra
31
31
  # @return [RDF::Term]
32
32
  # @raise [TypeError] if any operand is not a literal
33
33
  def evaluate(bindings, options = {})
34
- ops = operands.map {|op| op.evaluate(bindings, options.merge(:depth => options[:depth].to_i + 1))}
34
+ ops = operands.map {|op| op.evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))}
35
35
 
36
36
  raise TypeError, "expected all plain literal operands" unless ops.all? {|op| op.literal? && op.plain?}
37
37
 
38
38
  ops.inject do |memo, op|
39
39
  case
40
40
  when memo.datatype == RDF::XSD.string && op.datatype == RDF::XSD.string
41
- RDF::Literal.new("#{memo}#{op}", :datatype => RDF::XSD.string)
41
+ RDF::Literal.new("#{memo}#{op}", datatype: RDF::XSD.string)
42
42
  when memo.has_language? && memo.language == op.language
43
- RDF::Literal.new("#{memo}#{op}", :language => memo.language)
43
+ RDF::Literal.new("#{memo}#{op}", language: memo.language)
44
44
  else
45
45
  RDF::Literal.new("#{memo}#{op}")
46
46
  end
@@ -42,7 +42,7 @@ module SPARQL; module Algebra
42
42
  patterns = operands.first
43
43
  query = operands.last
44
44
 
45
- queryable.query(query, options.merge(:depth => options[:depth].to_i + 1)).each do |solution|
45
+ queryable.query(query, options.merge(depth: options[:depth].to_i + 1)).each do |solution|
46
46
  debug(options) {"(construct apply) #{solution.inspect} to BGP"}
47
47
 
48
48
  # Create a mapping from BNodes within the pattern list to newly constructed BNodes
@@ -71,7 +71,7 @@ module SPARQL; module Algebra
71
71
  end
72
72
  end
73
73
 
74
- debug(options) {"=>\n#{graph.dump(:ttl, :standard_prefixes => true)}"}
74
+ debug(options) {"=>\n#{graph.dump(:ttl, standard_prefixes: true)}"}
75
75
  graph.each(&block) if block_given?
76
76
  graph
77
77
  end
@@ -0,0 +1,64 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+
4
+ ##
5
+ # The SPARQL UPDATE `copy` operator.
6
+ #
7
+ # The COPY operation is a shortcut for inserting all data from an input graph into a destination graph. Data from the input graph is not affected, but data from the destination graph, if any, is removed before insertion.
8
+ #
9
+ # @example
10
+ # (copy silent <iri> to default)
11
+ #
12
+ # @see hhttp://www.w3.org/TR/sparql11-update/#copy
13
+ class Copy < Operator
14
+ include SPARQL::Algebra::Update
15
+
16
+ NAME = [:copy]
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) {"Copy"}
34
+ silent = operands.first == :silent
35
+ operands.shift if silent
36
+
37
+ src_name, dest_name = operands[-2..-1]
38
+ raise ArgumentError, "copy expected two operands, got #{operands.length}" unless operands.length == 2
39
+ raise ArgumentError, "copy from must be IRI or :default" unless src_name == :default || src_name.is_a?(RDF::URI)
40
+ raise ArgumentError, "copy 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, "copy operation source does not exist" unless silent
45
+ elsif dest_name == src_name
46
+ # No operation
47
+ else
48
+ dest = queryable.enum_graph.detect {|g| g.to_s == dest_name.to_s}
49
+
50
+ # Clear destination first
51
+ dest.clear! if dest
52
+
53
+ # Copy statements using destination context
54
+ src.each do |statement|
55
+ statement = statement.dup
56
+ statement.context = (dest_name unless dest_name == :default)
57
+ queryable << statement
58
+ end
59
+ end
60
+ queryable
61
+ end
62
+ end # Copy
63
+ end # Operator
64
+ end; end # SPARQL::Algebra
@@ -0,0 +1,49 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+
4
+ ##
5
+ # The SPARQL UPDATE `create` operator.
6
+ #
7
+ # This operation creates a graph in the Graph Store
8
+ #
9
+ # This is a no-op for RDF.rb implementations, unless the graph exists
10
+ #
11
+ # @example
12
+ # (create silent <graph>)
13
+ #
14
+ # @see http://www.w3.org/TR/sparql11-update/#create
15
+ class Create < Operator
16
+ include SPARQL::Algebra::Update
17
+
18
+ NAME = [:create]
19
+
20
+ ##
21
+ # Executes this upate on the given `writable` graph or repository.
22
+ #
23
+ # @param [RDF::Queryable] queryable
24
+ # the graph or repository to write
25
+ # @param [Hash{Symbol => Object}] options
26
+ # any additional keyword options
27
+ # @option options [Boolean] debug
28
+ # Query execution debugging
29
+ # @return [RDF::Queryable]
30
+ # Returns queryable.
31
+ # @raise [IOError]
32
+ # If `from` does not exist, unless the `silent` operator is present
33
+ # @see http://www.w3.org/TR/sparql11-update/
34
+ def execute(queryable, options = {})
35
+ debug(options) {"Create"}
36
+ silent = operands.first == :silent
37
+ operands.shift if silent
38
+
39
+ iri = operands.first
40
+ #require 'byebug'; byebug
41
+ raise ArgumentError, "clear expected a single IRI" if operands.length != 1 || !iri.is_a?(RDF::URI)
42
+ if queryable.has_context?(iri)
43
+ raise IOError, "create operation graph #{iri.to_ntriples} exists" unless silent
44
+ end
45
+ queryable
46
+ end
47
+ end # Create
48
+ end # Operator
49
+ end; end # SPARQL::Algebra
@@ -106,19 +106,7 @@ module SPARQL; module Algebra
106
106
  class Dataset < Binary
107
107
  include Query
108
108
 
109
- NAME = [:dataset]
110
- # Selected accept headers, from those available
111
- ACCEPTS = (%w(
112
- application/turtle
113
- text/turtle;q=0.9
114
- application/rdf+xml;q=0.8
115
- application/n-triples;q=0.4
116
- text/plain;q=0.1
117
- ).
118
- select do |content_type|
119
- # Add other content types
120
- RDF::Format.content_types.include?(content_type.split(';').first)
121
- end << ' */*;q=0.2').join(', ').freeze
109
+ NAME = :dataset
122
110
 
123
111
  ##
124
112
  # Executes this query on the given `queryable` graph or repository.
@@ -142,31 +130,18 @@ module SPARQL; module Algebra
142
130
  debug(options) {"Dataset"}
143
131
  default_datasets = []
144
132
  named_datasets = []
145
- operand(0).each do |ds|
146
- load_opts = {
147
- :headers => {"Accept" => ACCEPTS}
148
- }
149
- load_opts[:debug] = options.fetch(:debug, nil)
150
- case ds
133
+ operand(0).each do |uri|
134
+ case uri
151
135
  when Array
152
136
  # Format is (named <uri>), only need the URI part
153
- uri = if self.base_uri
154
- u = self.base_uri.join(ds.last)
155
- u.lexical = "<#{ds.last}>" unless u.to_s == ds.last.to_s
156
- u
157
- else
158
- ds.last
159
- end
160
- uri = self.base_uri ? self.base_uri.join(ds.last) : ds.last
161
- uri.lexical = ds.last
137
+ uri = uri.last
162
138
  debug(options) {"=> named data source #{uri}"}
163
139
  named_datasets << uri
164
140
  else
165
- uri = self.base_uri ? self.base_uri.join(ds) : ds
166
141
  debug(options) {"=> default data source #{uri}"}
167
142
  default_datasets << uri
168
143
  end
169
- load_opts[:context] = load_opts[:base_uri] = uri
144
+ load_opts = {debug: options.fetch(:debug, nil), context: uri, base_uri: uri}
170
145
  unless queryable.has_context?(uri)
171
146
  debug(options) {"=> load #{uri}"}
172
147
  queryable.load(uri.to_s, load_opts)
@@ -181,7 +156,7 @@ module SPARQL; module Algebra
181
156
  aggregate = RDF::AggregateRepo.new(queryable)
182
157
  named_datasets.each {|name| aggregate.named(name) if queryable.has_context?(name)}
183
158
  aggregate.default(*default_datasets.select {|name| queryable.has_context?(name)})
184
- aggregate.query(operands.last, options.merge(:depth => options[:depth].to_i + 1), &base)
159
+ aggregate.query(operands.last, options.merge(depth: options[:depth].to_i + 1), &base)
185
160
  end
186
161
 
187
162
  ##
@@ -0,0 +1,55 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+
4
+ ##
5
+ # The SPARQL UPDATE `delete` operator.
6
+ #
7
+ # The DELETE operation is a form of the DELETE/INSERT operation having no INSERT section
8
+ #
9
+ # @example
10
+ # (delete ((triple ?s ?p ?o))))
11
+ #
12
+ # @see http://www.w3.org/TR/sparql11-update/#delete
13
+ class Delete < Operator::Unary
14
+ include SPARQL::Algebra::Update
15
+
16
+ NAME = [:delete]
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 [RDF::Query::Solution] solution
24
+ # Solution to map to patterns for this operation
25
+ # @param [Hash{Symbol => Object}] options
26
+ # any additional keyword options
27
+ # @option options [Boolean] debug
28
+ # Query execution debugging
29
+ # @return [RDF::Queryable]
30
+ # Returns queryable.
31
+ # @raise [IOError]
32
+ # If `from` does not exist, unless the `silent` operator is present
33
+ # @see http://www.w3.org/TR/sparql11-update/
34
+ def execute(queryable, solution, options = {})
35
+ debug(options) {"Delete: #{solution} against #{operands.to_sse}"}
36
+ # Operands are an array of patterns and Queries (when named).
37
+ # Create a new query made up all patterns
38
+ patterns = operand.inject([]) do |memo, op|
39
+ if op.respond_to?(:statements)
40
+ memo += op.statements.to_a
41
+ else
42
+ memo << op
43
+ end
44
+ memo
45
+ end
46
+ patterns.each do |pattern|
47
+ pattern = pattern.dup.bind(solution)
48
+ debug(options) {"Delete statement #{statement.to_sse}"}
49
+ queryable.delete(RDF::Statement.from(pattern)) if pattern.bound? || pattern.constant?
50
+ end
51
+ queryable
52
+ end
53
+ end # Delete
54
+ end # Operator
55
+ end; end # SPARQL::Algebra
@@ -0,0 +1,41 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+
4
+ ##
5
+ # The SPARQL UPDATE `deleteData` operator.
6
+ #
7
+ # The DELETE DATA operation removes some triples, given inline in the request, if the respective graphs in the Graph Store contain those
8
+ #
9
+ # @example
10
+ # (deleteData ((triple :a foaf:knows :c)))
11
+ #
12
+ # @see http://www.w3.org/TR/sparql11-update/#deleteData
13
+ class DeleteData < Operator::Unary
14
+ include SPARQL::Algebra::Update
15
+
16
+ NAME = [:deleteData]
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
+ operand.each do |op|
34
+ debug(options) {"DeleteData #{op.to_sxp}"}
35
+ queryable.delete(op)
36
+ end
37
+ queryable
38
+ end
39
+ end # DeleteData
40
+ end # Operator
41
+ end; end # SPARQL::Algebra
@@ -0,0 +1,57 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+
4
+ ##
5
+ # The SPARQL UPDATE `deleteWhere` operator.
6
+ #
7
+ # The DELETE WHERE operation is a shortcut form for the DELETE/INSERT operation where bindings matched by the WHERE clause are used to define the triples in a graph that will be deleted.
8
+ #
9
+ # @example
10
+ # (deleteWhere ((triple :a foaf:knows ?b))
11
+ #
12
+ # @see http://www.w3.org/TR/sparql11-update/#deleteWhere
13
+ class DeleteWhere < Operator::Unary
14
+ include SPARQL::Algebra::Update
15
+
16
+ NAME = [:deleteWhere]
17
+
18
+ ##
19
+ # Query the operand, and delete all statements created by binding each solution to the patterns
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
+ # Operands are an array of patterns and Queries (when named).
34
+ # Create a new query made up all patterns
35
+ patterns = operand.inject([]) do |memo, op|
36
+ if op.respond_to?(:statements)
37
+ memo += op.statements.to_a
38
+ else
39
+ memo << op
40
+ end
41
+ memo
42
+ end
43
+ query = RDF::Query.new(*patterns)
44
+ debug(options) {"DeleteWhere query #{query.to_sse}"}
45
+ query.execute(queryable, options.merge(depth: options[:depth].to_i + 1)) do |solution|
46
+ debug(options) {"DeleteWhere solution #{solution.to_sse}"}
47
+ query.each_statement do |pattern|
48
+ pattern = pattern.dup.bind(solution)
49
+ debug(options) {"DeleteWhere statement #{statement.to_sse}"}
50
+ queryable.delete(RDF::Statement.from(pattern)) if pattern.bound? || pattern.constant?
51
+ end
52
+ end
53
+ queryable
54
+ end
55
+ end # DeleteWhere
56
+ end # Operator
57
+ end; end # SPARQL::Algebra
@@ -32,7 +32,7 @@ module SPARQL; module Algebra
32
32
  # the resulting solution sequence
33
33
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
34
34
  def execute(queryable, options = {}, &block)
35
- @solutions = queryable.query(operands.last, options.merge(:depth => options[:depth].to_i + 1)).distinct
35
+ @solutions = queryable.query(operands.last, options.merge(depth: options[:depth].to_i + 1)).distinct
36
36
  @solutions.each(&block) if block_given?
37
37
  @solutions
38
38
  end
@@ -0,0 +1,66 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+
4
+ ##
5
+ # The SPARQL UPDATE `drop` operator.
6
+ #
7
+ # The DROP operation removes the specified graph(s) from the Graph Store
8
+ #
9
+ # Equivalent to `clear` in this implementation
10
+ #
11
+ # @example
12
+ # (drop default)
13
+ #
14
+ # @see http://www.w3.org/TR/sparql11-update/#drop
15
+ class Drop < Operator
16
+ include SPARQL::Algebra::Update
17
+
18
+ NAME = [:drop]
19
+
20
+ ##
21
+ # Executes this upate on the given `writable` graph or repository.
22
+ #
23
+ # @param [RDF::Queryable] queryable
24
+ # the graph or repository to write
25
+ # @param [Hash{Symbol => Object}] options
26
+ # any additional keyword options
27
+ # @option options [Boolean] debug
28
+ # Query execution debugging
29
+ # @return [RDF::Queryable]
30
+ # Returns queryable.
31
+ # @raise [IOError]
32
+ # If `from` does not exist, unless the `silent` operator is present
33
+ # @see http://www.w3.org/TR/sparql11-update/
34
+ def execute(queryable, options = {})
35
+ debug(options) {"Drop"}
36
+ silent = operands.first == :silent
37
+ silent = operands.first == :silent
38
+ operands.shift if silent
39
+
40
+ raise ArgumentError, "drop expected operand to be 'default', 'named', 'all', or an IRI" unless operands.length == 1
41
+ case operands.last
42
+ when :default
43
+ queryable.each_graph do |g|
44
+ g.clear! unless g.context
45
+ end
46
+ when :named
47
+ queryable.each_graph do |g|
48
+ g.clear! if g.context
49
+ end
50
+ when :all
51
+ queryable.clear!
52
+ when RDF::URI
53
+ if g = queryable.each_graph.detect {|c| c.context == operands.last}
54
+ g.clear!
55
+ else
56
+ raise IOError, "drop operation graph does not exist" unless silent
57
+ end
58
+ else
59
+ raise ArgumentError, "drop expected operand to be 'default', 'named', 'all', or an IRI"
60
+ end
61
+
62
+ queryable
63
+ end
64
+ end # Drop
65
+ end # Operator
66
+ end; end # SPARQL::Algebra