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
@@ -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