sparql 1.0.1 → 1.0.2
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.
- data/README.markdown +2 -0
- data/VERSION +1 -1
- data/lib/sparql/algebra.rb +14 -14
- data/lib/sparql/algebra/extensions.rb +7 -0
- data/lib/sparql/algebra/operator.rb +42 -0
- data/lib/sparql/algebra/operator/dataset.rb +144 -10
- data/lib/sparql/algebra/operator/filter.rb +1 -1
- data/lib/sparql/algebra/operator/graph.rb +36 -7
- data/lib/sparql/algebra/operator/union.rb +6 -7
- data/lib/sparql/grammar.rb +0 -89
- metadata +5 -5
data/README.markdown
CHANGED
@@ -54,6 +54,8 @@ passing HTTP Accept headers for various available RDF formats. For best results,
|
|
54
54
|
a full set of RDF formats in the `GET` request. Also, consider overriding `RDF::Util::File.open_file` with
|
55
55
|
an implementation with support for HTTP Get headers (such as `Net::HTTP`).
|
56
56
|
|
57
|
+
Queries using datasets are re-written to use the identified graphs for `FROM` and `FROM NAMED` by filtering the results, allowing the use of a repository that contains many graphs without confusing information.
|
58
|
+
|
57
59
|
### Result formats
|
58
60
|
|
59
61
|
`SPARQL.serialize_results` may be used on it's own, or in conjunction with {Rack::SPARQL} or {Sinatra::SPARQL}
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/lib/sparql/algebra.rb
CHANGED
@@ -147,17 +147,17 @@ module SPARQL
|
|
147
147
|
#
|
148
148
|
# ## Constructing operator expressions using SSE forms
|
149
149
|
#
|
150
|
-
# Expression[:isBlank, RDF::Node(:foobar)].to_sxp #=> "(isBlank _:foobar)"
|
151
|
-
# Expression[:isIRI, RDF::URI('http://rdf.rubyforge.org/')].to_sxp #=> "(isIRI <http://rdf.rubyforge.org/>)"
|
152
|
-
# Expression[:isLiteral, RDF::Literal(3.1415)].to_sxp #=> "(isLiteral 3.1415)"
|
153
|
-
# Expression[:str, [:datatype, RDF::Literal(3.1415)]].to_sxp #=> "(str (datatype 3.1415))"
|
150
|
+
# SPARQL::Algebra::Expression[:isBlank, RDF::Node(:foobar)].to_sxp #=> "(isBlank _:foobar)"
|
151
|
+
# SPARQL::Algebra::Expression[:isIRI, RDF::URI('http://rdf.rubyforge.org/')].to_sxp #=> "(isIRI <http://rdf.rubyforge.org/>)"
|
152
|
+
# SPARQL::Algebra::Expression[:isLiteral, RDF::Literal(3.1415)].to_sxp #=> "(isLiteral 3.1415)"
|
153
|
+
# SPARQL::Algebra::Expression[:str, [:datatype, RDF::Literal(3.1415)]].to_sxp #=> "(str (datatype 3.1415))"
|
154
154
|
#
|
155
155
|
# ## Constructing operator expressions using SSE strings
|
156
156
|
#
|
157
|
-
# Expression.parse('(isBlank _:foobar)')
|
158
|
-
# Expression.parse('(isIRI <http://rdf.rubyforge.org/>)')
|
159
|
-
# Expression.parse('(isLiteral 3.1415)')
|
160
|
-
# Expression.parse('(str (datatype 3.1415))')
|
157
|
+
# SPARQL::Algebra::Expression.parse('(isBlank _:foobar)')
|
158
|
+
# SPARQL::Algebra::Expression.parse('(isIRI <http://rdf.rubyforge.org/>)')
|
159
|
+
# SPARQL::Algebra::Expression.parse('(isLiteral 3.1415)')
|
160
|
+
# SPARQL::Algebra::Expression.parse('(str (datatype 3.1415))')
|
161
161
|
#
|
162
162
|
# ## Evaluating operators standalone
|
163
163
|
#
|
@@ -167,8 +167,8 @@ module SPARQL
|
|
167
167
|
#
|
168
168
|
# ## Optimizing expressions containing constant subexpressions
|
169
169
|
#
|
170
|
-
# Expression.parse('(sameTerm ?var ?var)').optimize #=> RDF::Literal::TRUE
|
171
|
-
# Expression.parse('(* -2 (- (* (+ 1 2) (+ 3 4))))').optimize #=> RDF::Literal(42)
|
170
|
+
# SPARQL::Algebra::Expression.parse('(sameTerm ?var ?var)').optimize #=> RDF::Literal::TRUE
|
171
|
+
# SPARQL::Algebra::Expression.parse('(* -2 (- (* (+ 1 2) (+ 3 4))))').optimize #=> RDF::Literal(42)
|
172
172
|
#
|
173
173
|
# ## Evaluating expressions on a solution sequence
|
174
174
|
#
|
@@ -180,8 +180,8 @@ module SPARQL
|
|
180
180
|
# end
|
181
181
|
#
|
182
182
|
# # Find people who have a name but don't have a known e-mail address:
|
183
|
-
# expression = Expression[:not, [:bound, Variable(:email)]] # ...or just...
|
184
|
-
# expression = Expression.parse('(not (bound ?email))')
|
183
|
+
# expression = SPARQL::Algebra::Expression[:not, [:bound, Variable(:email)]] # ...or just...
|
184
|
+
# expression = SPARQL::Algebra::Expression.parse('(not (bound ?email))')
|
185
185
|
# solutions.filter!(expression)
|
186
186
|
#
|
187
187
|
# @example Optimizations
|
@@ -189,7 +189,7 @@ module SPARQL
|
|
189
189
|
# Some very simple optimizations are currently implemented for `FILTER`
|
190
190
|
# expressions. Use the following to obtain optimized SSE forms:
|
191
191
|
#
|
192
|
-
# Expression.parse(sse).optimize.to_sxp_bin
|
192
|
+
# SPARQL::Algebra::Expression.parse(sse).optimize.to_sxp_bin
|
193
193
|
#
|
194
194
|
# ## Constant comparison folding
|
195
195
|
#
|
@@ -209,7 +209,7 @@ module SPARQL
|
|
209
209
|
# Expressions can optionally be [memoized][memoization], which can speed up
|
210
210
|
# repeatedly executing the expression on a solution sequence:
|
211
211
|
#
|
212
|
-
# Expression.parse(sse, :memoize => true)
|
212
|
+
# SPARQL::Algebra::Expression.parse(sse, :memoize => true)
|
213
213
|
# Operator.new(*operands, :memoize => true)
|
214
214
|
#
|
215
215
|
# Memoization is implemented using RDF.rb's [RDF::Util::Cache][] utility
|
@@ -107,6 +107,13 @@ class RDF::Query
|
|
107
107
|
def ==(other)
|
108
108
|
other.is_a?(RDF::Query) && patterns == other.patterns && context == context
|
109
109
|
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Don't do any more rewriting
|
113
|
+
# @return [SPARQL::Algebra::Expression] `self`
|
114
|
+
def rewrite(&block)
|
115
|
+
self
|
116
|
+
end
|
110
117
|
|
111
118
|
# Transform Query into an Array form of an SSE
|
112
119
|
#
|
@@ -322,6 +322,26 @@ module SPARQL; module Algebra
|
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
325
|
+
##
|
326
|
+
# Rewrite operands by yielding each operand. Recursively descends
|
327
|
+
# through operands implementing this method.
|
328
|
+
#
|
329
|
+
# @yield operand
|
330
|
+
# @yieldparam [] operand
|
331
|
+
# @yieldreturn [SPARQL::Algebra::Expression] the re-written operand
|
332
|
+
# @return [SPARQL::Algebra::Expression] `self`
|
333
|
+
def rewrite(&block)
|
334
|
+
@operands = @operands.map do |op|
|
335
|
+
# Rewrite the operand
|
336
|
+
unless new_op = block.call(op)
|
337
|
+
# Not re-written, rewrite
|
338
|
+
new_op = op.respond_to?(:rewrite) ? op.rewrite(&block) : op
|
339
|
+
end
|
340
|
+
new_op
|
341
|
+
end
|
342
|
+
self
|
343
|
+
end
|
344
|
+
|
325
345
|
##
|
326
346
|
# Returns the SPARQL S-Expression (SSE) representation of this operator.
|
327
347
|
#
|
@@ -362,6 +382,7 @@ module SPARQL; module Algebra
|
|
362
382
|
other.class == self.class && other.operands == self.operands
|
363
383
|
end
|
364
384
|
alias_method :==, :eql?
|
385
|
+
|
365
386
|
protected
|
366
387
|
|
367
388
|
##
|
@@ -401,6 +422,27 @@ module SPARQL; module Algebra
|
|
401
422
|
end
|
402
423
|
end
|
403
424
|
|
425
|
+
##
|
426
|
+
# Transform an array of expressions into a recursive set
|
427
|
+
# of binary operations
|
428
|
+
# e.g.: a || b || c => (|| a (|| b c))
|
429
|
+
# @param [Class] Binary Operator class
|
430
|
+
# @param [Array<SPARQL::Algebra::Expression>] *expressions
|
431
|
+
# @return [SPARQL::Algebra::Expression]
|
432
|
+
def to_binary(klass, *expressions)
|
433
|
+
case expressions.length
|
434
|
+
when 0
|
435
|
+
# Oops!
|
436
|
+
raise "Operator#to_binary requires two or more expressions"
|
437
|
+
when 1
|
438
|
+
expressions.first
|
439
|
+
when 2
|
440
|
+
klass.new(*expressions)
|
441
|
+
else
|
442
|
+
klass.new(expressions.shift, to_binary(klass, *expressions))
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
404
446
|
private
|
405
447
|
|
406
448
|
@@subclasses = [] # @private
|
@@ -4,25 +4,109 @@ rescue LoadError => e
|
|
4
4
|
require 'rdf/ntriples'
|
5
5
|
end
|
6
6
|
|
7
|
+
# FIXME: This version uses named graphs for default graphs, which violates the condition in RDF::Repository#query_pattern, where it specifically does not match variables against the default graph. To work properly, RDF.rb will need to allow some way to specify a set of graphs as being default, and affect the matching within #query_pattern so that variables don't match against this.
|
8
|
+
# Note that a graph may be both default and named, so the context of the query is significant.
|
7
9
|
module SPARQL; module Algebra
|
8
10
|
class Operator
|
9
11
|
##
|
10
12
|
# The SPARQL GraphPattern `dataset` operator.
|
11
13
|
#
|
12
|
-
#
|
14
|
+
# Instantiated with two operands, the first being an array of data source URIs,
|
13
15
|
# either bare, indicating a default dataset, or expressed as an array `\[:named, \<uri\>\]`,
|
14
16
|
# indicating that it represents a named data source.
|
15
17
|
#
|
16
|
-
#
|
18
|
+
# This operator loads from the datasource, unless a graph named by
|
19
|
+
# the datasource URI already exists in the repository.
|
20
|
+
#
|
21
|
+
# The contained BGP queries are then performed against the specified
|
22
|
+
# default and named graphs. Rather than using the actual default
|
23
|
+
# graph of the dataset, queries against the default dataset are
|
24
|
+
# run against named graphs matching a non-distinctive variable
|
25
|
+
# and the results are filtered against those URIs included in
|
26
|
+
# the default dataset.
|
27
|
+
#
|
28
|
+
# Specifically, each BGP which is not part of a graph pattern
|
29
|
+
# is replaced with a union of graph patterns with that BGP repeated
|
30
|
+
# for each graph URI in the default dataset. This requires recursively
|
31
|
+
# updating the operator.
|
32
|
+
#
|
33
|
+
# Each graph pattern containing a variable graph name is replaced
|
34
|
+
# by a filter on that variable such that the variable must match
|
35
|
+
# only those named datasets specified.
|
36
|
+
#
|
37
|
+
# @example Dataset with one default and one named data source
|
17
38
|
#
|
18
39
|
# (prefix ((: <http://example/>))
|
19
40
|
# (dataset (<data-g1.ttl> (named <data-g2.ttl>))
|
41
|
+
# (union
|
42
|
+
# (bgp (triple ?s ?p ?o))
|
43
|
+
# (graph ?g (bgp (triple ?s ?p ?o))))))
|
44
|
+
#
|
45
|
+
# is effectively re-written to the following:
|
46
|
+
#
|
47
|
+
# (prefix ((: <http://example/>))
|
48
|
+
# (union
|
49
|
+
# (graph <data-g1.ttl> (bgp (triple ?s ?p ?o)))
|
50
|
+
# (filter (= ?g <data-g2.ttl>)
|
51
|
+
# (graph ?g (bgp (triple ?s ?p ?o))))))
|
52
|
+
#
|
53
|
+
# If no default or no named graphs are specified, these queries
|
54
|
+
# are eliminated.
|
55
|
+
#
|
56
|
+
# @example Dataset with one default no named data sources
|
57
|
+
#
|
58
|
+
# (prefix ((: <http://example/>))
|
59
|
+
# (dataset (<data-g1.ttl>)
|
60
|
+
# (union
|
61
|
+
# (bgp (triple ?s ?p ?o))
|
62
|
+
# (graph ?g (bgp (triple ?s ?p ?o))))))
|
63
|
+
#
|
64
|
+
# is effectively re-written to the following:
|
65
|
+
#
|
66
|
+
# (prefix ((: <http://example/>))
|
67
|
+
# (union
|
68
|
+
# (graph <data-g1.ttl> (bgp (triple ?s ?p ?o)))
|
69
|
+
# (bgp))
|
70
|
+
#
|
71
|
+
# Multiple default graphs union the information from a graph query
|
72
|
+
# on each default datasource.
|
73
|
+
#
|
74
|
+
# @example Dataset with two default data sources
|
75
|
+
#
|
76
|
+
# (prefix ((: <http://example/>))
|
77
|
+
# (dataset (<data-g1.ttl> <data-g1.ttl)
|
20
78
|
# (bgp (triple ?s ?p ?o))))
|
21
79
|
#
|
80
|
+
# is effectively re-written to the following:
|
81
|
+
#
|
82
|
+
# (prefix ((: <http://example/>))
|
83
|
+
# (union
|
84
|
+
# (graph <data-g1.ttl> (bgp (triple ?s ?p ?o)))
|
85
|
+
# (graph <data-g2.ttl> (bgp (triple ?s ?p ?o)))))
|
86
|
+
#
|
87
|
+
# Multiple named graphs place a filter on all variables used
|
88
|
+
# to identify those named graphs so that they are restricted
|
89
|
+
# to come only from the specified set. Note that this requires
|
90
|
+
# descending through expressions to find graph patterns using
|
91
|
+
# variables and placing a filter on each identified variable.
|
92
|
+
#
|
93
|
+
# @example Dataset with two named data sources
|
94
|
+
#
|
95
|
+
# (prefix ((: <http://example/>))
|
96
|
+
# (dataset ((named <data-g1.ttl>) (named <data-g2.ttl>))
|
97
|
+
# (graph ?g (bgp (triple ?s ?p ?o)))))
|
98
|
+
#
|
99
|
+
# is effectively re-written to the following:
|
100
|
+
#
|
101
|
+
# (prefix ((: <http://example/>))
|
102
|
+
# (filter ((= ?g <data-g1.ttl>) || (= ?g <data-g2.ttl>))
|
103
|
+
# (graph ?g (bgp (triple ?s ?p ?o))))))
|
104
|
+
#
|
105
|
+
# @example Dataset with multiple named graphs
|
22
106
|
# @see http://www.w3.org/TR/rdf-sparql-query/#specifyingDataset
|
23
107
|
class Dataset < Binary
|
24
108
|
include Query
|
25
|
-
|
109
|
+
|
26
110
|
NAME = [:dataset]
|
27
111
|
# Selected accept headers, from those available
|
28
112
|
ACCEPTS = (%w(
|
@@ -52,6 +136,8 @@ module SPARQL; module Algebra
|
|
52
136
|
# @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
|
53
137
|
def execute(queryable, options = {})
|
54
138
|
debug(options) {"Dataset"}
|
139
|
+
default_datasets = []
|
140
|
+
named_datasets = []
|
55
141
|
operand(0).each do |ds|
|
56
142
|
load_opts = {
|
57
143
|
:headers => {"Accept" => ACCEPTS}
|
@@ -69,18 +155,66 @@ module SPARQL; module Algebra
|
|
69
155
|
end
|
70
156
|
uri = self.base_uri ? self.base_uri.join(ds.last) : ds.last
|
71
157
|
uri.lexical = ds.last
|
72
|
-
|
73
|
-
|
158
|
+
debug(options) {"=> named data source #{uri}"}
|
159
|
+
named_datasets << uri
|
74
160
|
else
|
75
|
-
debug(options) {"=> array: join #{self.base_uri.inspect} to #{ds.inspect}"}
|
76
161
|
uri = self.base_uri ? self.base_uri.join(ds) : ds
|
77
|
-
debug(options) {"=>
|
162
|
+
debug(options) {"=> default data source #{uri}"}
|
163
|
+
default_datasets << uri
|
164
|
+
end
|
165
|
+
load_opts[:context] = load_opts[:base_uri] = uri
|
166
|
+
unless queryable.has_context?(uri)
|
167
|
+
debug(options) {"=> load #{uri}"}
|
168
|
+
queryable.load(uri.to_s, load_opts)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
require 'rdf/nquads'
|
172
|
+
debug(options) { queryable.dump(:nquads) }
|
173
|
+
|
174
|
+
# Re-write the operand:
|
175
|
+
operator = self.rewrite do |op|
|
176
|
+
case op
|
177
|
+
when Operator::Graph
|
178
|
+
if named_datasets.empty?
|
179
|
+
# * If there are no named datasets, remove all (graph)
|
180
|
+
# operations.
|
181
|
+
debug(options) {"=> #{op.to_sxp} => (bgp)"}
|
182
|
+
Operator::BGP.new
|
183
|
+
elsif (name = op.operand(0)).is_a?(RDF::Resource)
|
184
|
+
# It must match one of the named_datasets
|
185
|
+
debug(options) {"=> #{op.to_sxp} => (bgp)"}
|
186
|
+
named_datasets.include?(name) ? op : Operator::BGP.new
|
187
|
+
else
|
188
|
+
# Name is a variable, replace op with a filter on that
|
189
|
+
# variable and op
|
190
|
+
filter_expressions = named_datasets.map {|u| Operator::Equal.new(name, u)}
|
191
|
+
debug(options) {"=> #{op.to_sxp} => (filter (...) #{op.to_sxp})"}
|
192
|
+
filt = to_binary(Operator::Or, *filter_expressions)
|
193
|
+
Operator::Filter.new(filt, op)
|
194
|
+
end
|
195
|
+
when RDF::Query # Operator::BGP
|
196
|
+
case default_datasets.length
|
197
|
+
when 0
|
198
|
+
# No Default Datasets, no query to run
|
199
|
+
debug(options) {"=> #{op.to_sxp} => (bgp)"}
|
200
|
+
Operator::BGP.new
|
201
|
+
when 1
|
202
|
+
# A single dataset, write as (graph <dataset> (bgp))
|
203
|
+
debug(options) {"=> #{op.to_sxp} => (graph <#{default_datasets.first}> #{op.to_sxp})"}
|
204
|
+
Operator::Graph.new(default_datasets.first, op)
|
205
|
+
else
|
206
|
+
# Several, rewrite as Union
|
207
|
+
debug(options) {"=> #{op.to_sxp} => (union ...)"}
|
208
|
+
to_binary(Operator::Union, *default_datasets.map {|u| Operator::Graph.new(u, op.dup)})
|
209
|
+
end
|
210
|
+
else
|
211
|
+
nil
|
78
212
|
end
|
79
|
-
load_opts[:base_uri] = uri
|
80
|
-
queryable.load(uri.to_s, load_opts)
|
81
213
|
end
|
214
|
+
executable = operator.operands.last
|
215
|
+
debug(options) {"=> rewritten: #{executable.to_sxp}"}
|
82
216
|
|
83
|
-
@solutions =
|
217
|
+
@solutions = executable.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
|
84
218
|
end
|
85
219
|
|
86
220
|
##
|
@@ -33,7 +33,7 @@ module SPARQL; module Algebra
|
|
33
33
|
# @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
|
34
34
|
# @see http://www.w3.org/TR/rdf-sparql-query/#ebv
|
35
35
|
def execute(queryable, options = {})
|
36
|
-
debug(options) {"Filter #{operands.first}"}
|
36
|
+
debug(options) {"Filter #{operands.first.to_sxp}"}
|
37
37
|
@solutions = operands.last.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
|
38
38
|
debug(options) {"=>(before) #{@solutions.map(&:to_hash).inspect}"}
|
39
39
|
@solutions = @solutions.filter do |solution|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# FIXME: This depends on an update to RDF::Query#execute to be able to pass the context as an option.
|
1
2
|
module SPARQL; module Algebra
|
2
3
|
class Operator
|
3
4
|
##
|
@@ -12,16 +13,44 @@ module SPARQL; module Algebra
|
|
12
13
|
#
|
13
14
|
# @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
|
14
15
|
class Graph < Operator::Binary
|
16
|
+
include Query
|
17
|
+
|
15
18
|
NAME = [:graph]
|
19
|
+
|
16
20
|
##
|
17
|
-
#
|
21
|
+
# Executes this query on the given `queryable` graph or repository.
|
22
|
+
# Applies the given `context` to the query, limiting the scope of the query to the specified `context`, which may be an `RDF::URI` or `RDF::Query::Variable`.
|
18
23
|
#
|
19
|
-
# @param
|
20
|
-
#
|
21
|
-
# @
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
# @param [RDF::Queryable] queryable
|
25
|
+
# the graph or repository to query
|
26
|
+
# @param [Hash{Symbol => Object}] options
|
27
|
+
# any additional keyword options
|
28
|
+
# @return [RDF::Query::Solutions]
|
29
|
+
# the resulting solution sequence
|
30
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
|
31
|
+
def execute(queryable, options = {})
|
32
|
+
debug(options) {"Graph #{operands.first}"}
|
33
|
+
context, query = operands.first, operands.last
|
34
|
+
@solutions = query.execute(queryable, options.merge(:context => context))
|
35
|
+
debug(options) {"=>(after) #{@solutions.map(&:to_hash).inspect}"}
|
36
|
+
@solutions
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Returns an optimized version of this query.
|
41
|
+
#
|
42
|
+
# Return optimized query
|
43
|
+
#
|
44
|
+
# @return [Union, RDF::Query] `self`
|
45
|
+
def optimize
|
46
|
+
operands = operands.map(&:optimize)
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Don't do any more rewriting
|
51
|
+
# @return [SPARQL::Algebra::Expression] `self`
|
52
|
+
def rewrite(&block)
|
53
|
+
self
|
25
54
|
end
|
26
55
|
end # Graph
|
27
56
|
end # Operator
|
@@ -29,11 +29,11 @@ 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) {"Union"}
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
@solutions = RDF::Query::Solutions.new(operands.inject([]) do |memo, op|
|
33
|
+
solns = op.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
|
34
|
+
debug(options) {"=> (op) #{solns.inspect}"}
|
35
|
+
memo + solns
|
36
|
+
end)
|
37
37
|
debug(options) {"=> #{@solutions.inspect}"}
|
38
38
|
@solutions
|
39
39
|
end
|
@@ -41,8 +41,7 @@ module SPARQL; module Algebra
|
|
41
41
|
##
|
42
42
|
# Returns an optimized version of this query.
|
43
43
|
#
|
44
|
-
#
|
45
|
-
# with the unique sum of the query elements
|
44
|
+
# Optimize operands and remove any which are empty.
|
46
45
|
#
|
47
46
|
# @return [Union, RDF::Query] `self`
|
48
47
|
def optimize
|
data/lib/sparql/grammar.rb
CHANGED
@@ -35,12 +35,6 @@ module SPARQL
|
|
35
35
|
#
|
36
36
|
# SELECT * WHERE { ?a ?b ?c }
|
37
37
|
#
|
38
|
-
# SSE:
|
39
|
-
#
|
40
|
-
# RDF::Query.new {
|
41
|
-
# pattern [RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b"), RDF::Query::Variable.new("c")]
|
42
|
-
# }
|
43
|
-
#
|
44
38
|
# SXP:
|
45
39
|
#
|
46
40
|
# (bgp (triple ?a ?b ?c))
|
@@ -49,15 +43,6 @@ module SPARQL
|
|
49
43
|
#
|
50
44
|
# SELECT * FROM <a> WHERE { ?a ?b ?c }
|
51
45
|
#
|
52
|
-
# SSE:
|
53
|
-
#
|
54
|
-
# SPARQL::Algebra::Operator::Dataset.new(
|
55
|
-
# [RDF::URI("a")],
|
56
|
-
# RDF::Query.new {
|
57
|
-
# pattern [RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b"), RDF::Query::Variable.new("c")]
|
58
|
-
# }
|
59
|
-
# )
|
60
|
-
#
|
61
46
|
# SXP:
|
62
47
|
#
|
63
48
|
# (dataset (<a>) (bgp (triple ?a ?b ?c)))
|
@@ -66,15 +51,6 @@ module SPARQL
|
|
66
51
|
#
|
67
52
|
# SELECT * FROM NAMED <a> WHERE { ?a ?b ?c }
|
68
53
|
#
|
69
|
-
# SSE:
|
70
|
-
#
|
71
|
-
# SPARQL::Algebra::Operator::Dataset.new(
|
72
|
-
# [[:named, RDF::URI("a")]],
|
73
|
-
# RDF::Query.new {
|
74
|
-
# pattern [RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b"), RDF::Query::Variable.new("c")]
|
75
|
-
# }
|
76
|
-
# )
|
77
|
-
#
|
78
54
|
# SXP:
|
79
55
|
#
|
80
56
|
# (dataset ((named <a>)) (bgp (triple ?a ?b ?c)))
|
@@ -83,14 +59,6 @@ module SPARQL
|
|
83
59
|
#
|
84
60
|
# SELECT DISTINCT * WHERE {?a ?b ?c}
|
85
61
|
#
|
86
|
-
# SSE:
|
87
|
-
#
|
88
|
-
# SPARQL::Algebra::Operator::Distinct.new(
|
89
|
-
# RDF::Query.new {
|
90
|
-
# pattern [RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b"), RDF::Query::Variable.new("c")]
|
91
|
-
# }
|
92
|
-
# )
|
93
|
-
#
|
94
62
|
# SXP:
|
95
63
|
#
|
96
64
|
# (distinct (bgp (triple ?a ?b ?c)))
|
@@ -99,15 +67,6 @@ module SPARQL
|
|
99
67
|
#
|
100
68
|
# SELECT ?a ?b WHERE {?a ?b ?c}
|
101
69
|
#
|
102
|
-
# SSE:
|
103
|
-
#
|
104
|
-
# SPARQL::Algebra::Operator::Project.new(
|
105
|
-
# [RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b")],
|
106
|
-
# RDF::Query.new {
|
107
|
-
# pattern [RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b"), RDF::Query::Variable.new("c")]
|
108
|
-
# }
|
109
|
-
# )
|
110
|
-
#
|
111
70
|
# SXP:
|
112
71
|
#
|
113
72
|
# (project (?a ?b) (bgp (triple ?a ?b ?c)))
|
@@ -116,18 +75,6 @@ module SPARQL
|
|
116
75
|
#
|
117
76
|
# CONSTRUCT {?a ?b ?c} WHERE {?a ?b ?c FILTER (?a)}
|
118
77
|
#
|
119
|
-
# SSE:
|
120
|
-
#
|
121
|
-
# SPARQL::Algebra::Operator::Construct.new(
|
122
|
-
# [RDF::Query::Pattern.new(RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b"), RDF::Query::Variable.new("c"))],
|
123
|
-
# SPARQL::Algebra::Operator::Filter.new(
|
124
|
-
# RDF::Query::Variable.new("a"),
|
125
|
-
# RDF::Query.new {
|
126
|
-
# pattern [RDF::Query::Variable.new("a"), RDF::Query::Variable.new("b"), RDF::Query::Variable.new("c")]
|
127
|
-
# }
|
128
|
-
# )
|
129
|
-
# )
|
130
|
-
#
|
131
78
|
# SXP:
|
132
79
|
#
|
133
80
|
# (construct ((triple ?a ?b ?c)) (filter ?a (bgp (triple ?a ?b ?c))))
|
@@ -136,17 +83,6 @@ module SPARQL
|
|
136
83
|
#
|
137
84
|
# SELECT * WHERE {<a> <b> <c> OPTIONAL {<d> <e> <f>}}
|
138
85
|
#
|
139
|
-
# SSE:
|
140
|
-
#
|
141
|
-
# SPARQL::Algebra::Operator::LeftJoin.new(
|
142
|
-
# RDF::Query.new {
|
143
|
-
# pattern [RDF::URI("a"), RDF::URI("b"), RDF::URI("c")]
|
144
|
-
# },
|
145
|
-
# RDF::Query.new {
|
146
|
-
# pattern [RDF::URI("d"), RDF::URI("e"), RDF::URI("f")]
|
147
|
-
# }
|
148
|
-
# )
|
149
|
-
#
|
150
86
|
# SXP:
|
151
87
|
#
|
152
88
|
# (leftjoin (bgp (triple <a> <b> <c>)) (bgp (triple <d> <e> <f>)))
|
@@ -155,17 +91,6 @@ module SPARQL
|
|
155
91
|
#
|
156
92
|
# SELECT * WHERE {<a> <b> <c> {<d> <e> <f>}}
|
157
93
|
#
|
158
|
-
# SSE:
|
159
|
-
#
|
160
|
-
# SPARQL::Algebra::Operator::Join.new(
|
161
|
-
# RDF::Query.new {
|
162
|
-
# pattern [RDF::URI("a"), RDF::URI("b"), RDF::URI("c")]
|
163
|
-
# },
|
164
|
-
# RDF::Query.new {
|
165
|
-
# pattern [RDF::URI("d"), RDF::URI("e"), RDF::URI("f")]
|
166
|
-
# }
|
167
|
-
# )
|
168
|
-
#
|
169
94
|
# SXP:
|
170
95
|
#
|
171
96
|
# (join (bgp (triple <a> <b> <c>)) (bgp (triple <d> <e> <f>)))
|
@@ -181,20 +106,6 @@ module SPARQL
|
|
181
106
|
# { GRAPH ?g { ?s ?p ?o } }
|
182
107
|
# }
|
183
108
|
#
|
184
|
-
# SSE:
|
185
|
-
#
|
186
|
-
# SPARQL::Algebra::Operator::Prefix.new(
|
187
|
-
# [[:":", RDF::URI("http://example/")]],
|
188
|
-
# SPARQL::Algebra::Operator::Union.new(
|
189
|
-
# RDF::Query.new {
|
190
|
-
# pattern [RDF::Query::Variable.new("s"), RDF::Query::Variable.new("p"), RDF::Query::Variable.new("o")]
|
191
|
-
# },
|
192
|
-
# RDF::Query.new(:context => RDF::Query::Variable.new("g")) {
|
193
|
-
# pattern [RDF::Query::Variable.new("s"), RDF::Query::Variable.new("p"), RDF::Query::Variable.new("o")]
|
194
|
-
# }
|
195
|
-
# )
|
196
|
-
# )
|
197
|
-
#
|
198
109
|
# SXP:
|
199
110
|
#
|
200
111
|
# (prefix ((: <http://example/>))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sparql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-
|
14
|
+
date: 2013-02-08 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rdf
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 1.0.1
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -28,7 +28,7 @@ dependencies:
|
|
28
28
|
requirements:
|
29
29
|
- - ! '>='
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version:
|
31
|
+
version: 1.0.1
|
32
32
|
- !ruby/object:Gem::Dependency
|
33
33
|
name: builder
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
@@ -386,7 +386,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
386
386
|
version: '0'
|
387
387
|
requirements: []
|
388
388
|
rubyforge_project: sparql
|
389
|
-
rubygems_version: 1.8.
|
389
|
+
rubygems_version: 1.8.25
|
390
390
|
signing_key:
|
391
391
|
specification_version: 3
|
392
392
|
summary: SPARQL library for Ruby.
|