rdf 3.0.12 → 3.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHORS +1 -1
- data/README.md +46 -11
- data/VERSION +1 -1
- data/etc/doap.nt +74 -80
- data/lib/rdf.rb +35 -23
- data/lib/rdf/changeset.rb +87 -19
- data/lib/rdf/cli.rb +7 -7
- data/lib/rdf/format.rb +17 -10
- data/lib/rdf/mixin/enumerable.rb +3 -2
- data/lib/rdf/mixin/mutable.rb +5 -15
- data/lib/rdf/mixin/queryable.rb +12 -4
- data/lib/rdf/mixin/writable.rb +9 -14
- data/lib/rdf/model/dataset.rb +1 -1
- data/lib/rdf/model/graph.rb +5 -2
- data/lib/rdf/model/list.rb +5 -5
- data/lib/rdf/model/literal.rb +3 -3
- data/lib/rdf/model/statement.rb +30 -7
- data/lib/rdf/model/uri.rb +44 -23
- data/lib/rdf/nquads.rb +6 -6
- data/lib/rdf/ntriples.rb +6 -4
- data/lib/rdf/ntriples/reader.rb +29 -7
- data/lib/rdf/ntriples/writer.rb +10 -1
- data/lib/rdf/query.rb +27 -35
- data/lib/rdf/query/hash_pattern_normalizer.rb +14 -12
- data/lib/rdf/query/pattern.rb +51 -18
- data/lib/rdf/query/solution.rb +20 -1
- data/lib/rdf/query/solutions.rb +15 -5
- data/lib/rdf/query/variable.rb +17 -5
- data/lib/rdf/reader.rb +76 -25
- data/lib/rdf/repository.rb +32 -18
- data/lib/rdf/transaction.rb +1 -1
- data/lib/rdf/util.rb +6 -5
- data/lib/rdf/util/cache.rb +2 -2
- data/lib/rdf/util/coercions.rb +60 -0
- data/lib/rdf/util/file.rb +20 -10
- data/lib/rdf/util/logger.rb +6 -6
- data/lib/rdf/vocab/owl.rb +401 -86
- data/lib/rdf/vocab/rdfs.rb +81 -18
- data/lib/rdf/vocab/rdfv.rb +147 -1
- data/lib/rdf/vocab/writer.rb +41 -3
- data/lib/rdf/vocab/xsd.rb +203 -2
- data/lib/rdf/vocabulary.rb +108 -14
- data/lib/rdf/writer.rb +32 -10
- metadata +32 -27
data/lib/rdf/model/uri.rb
CHANGED
@@ -141,8 +141,8 @@ module RDF
|
|
141
141
|
#
|
142
142
|
# (see #initialize)
|
143
143
|
# @return [RDF::URI] an immutable, frozen URI object
|
144
|
-
def self.intern(str, *args)
|
145
|
-
(cache[(str = str.to_s).to_sym] ||= self.new(str, *args)).freeze
|
144
|
+
def self.intern(str, *args, **options)
|
145
|
+
(cache[(str = str.to_s).to_sym] ||= self.new(str, *args, **options)).freeze
|
146
146
|
end
|
147
147
|
|
148
148
|
##
|
@@ -225,11 +225,9 @@ module RDF
|
|
225
225
|
@mutex = Mutex.new
|
226
226
|
uri = args.first
|
227
227
|
if uri
|
228
|
-
@value = uri.to_s
|
229
|
-
if @value.encoding != Encoding::UTF_8
|
230
|
-
|
231
|
-
@value.freeze
|
232
|
-
end
|
228
|
+
@value = uri.to_s.dup
|
229
|
+
@value.dup.force_encoding(Encoding::UTF_8) if @value.encoding != Encoding::UTF_8
|
230
|
+
@value.freeze
|
233
231
|
else
|
234
232
|
%w(
|
235
233
|
scheme
|
@@ -402,7 +400,7 @@ module RDF
|
|
402
400
|
# @example Joining two URIs
|
403
401
|
# RDF::URI.new('http://example.org/foo/bar').join('/foo')
|
404
402
|
# #=> RDF::URI('http://example.org/foo')
|
405
|
-
# @see <
|
403
|
+
# @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
|
406
404
|
# @see <http://tools.ietf.org/html/rfc3986#section-5.2>
|
407
405
|
# @see RDF::URI#/
|
408
406
|
# @see RDF::URI#+
|
@@ -431,7 +429,9 @@ module RDF
|
|
431
429
|
joined_parts[:query] = uri.query
|
432
430
|
else
|
433
431
|
# Merge path segments from section 5.2.3
|
434
|
-
|
432
|
+
# Note that if the path includes no segments, the entire path is removed
|
433
|
+
# > return a string consisting of the reference's path component appended to all but the last segment of the base URI's path (i.e., excluding any characters after the right-most "/" in the base URI path, or excluding the entire base URI path if it does not contain any "/" characters).
|
434
|
+
base_path = path.to_s.include?('/') ? path.to_s.sub(/\/[^\/]*$/, '/') : ''
|
435
435
|
joined_parts[:path] = self.class.normalize_path(base_path + uri.path)
|
436
436
|
joined_parts[:query] = uri.query
|
437
437
|
end
|
@@ -439,7 +439,7 @@ module RDF
|
|
439
439
|
end
|
440
440
|
|
441
441
|
# Return joined URI
|
442
|
-
RDF::URI.new(joined_parts)
|
442
|
+
RDF::URI.new(**joined_parts)
|
443
443
|
end
|
444
444
|
|
445
445
|
##
|
@@ -471,7 +471,7 @@ module RDF
|
|
471
471
|
# @see RDF::URI#+
|
472
472
|
# @see RDF::URI#join
|
473
473
|
# @see <http://tools.ietf.org/html/rfc3986#section-5.2>
|
474
|
-
# @see <
|
474
|
+
# @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
|
475
475
|
# @example Building a HTTP URL
|
476
476
|
# RDF::URI.new('http://example.org') / 'jhacker' / 'foaf.ttl'
|
477
477
|
# #=> RDF::URI('http://example.org/jhacker/foaf.ttl')
|
@@ -507,7 +507,7 @@ module RDF
|
|
507
507
|
case fragment.to_s[0,1]
|
508
508
|
when '#'
|
509
509
|
# Base ending with '/', fragment beginning with '#'. The fragment wins, we use '#'.
|
510
|
-
res.path = res.path.to_s.sub
|
510
|
+
res.path = res.path.to_s.sub(/\/*$/, '')
|
511
511
|
# Add fragment
|
512
512
|
res.fragment = fragment.to_s.sub(/^#+/,'')
|
513
513
|
else
|
@@ -572,7 +572,7 @@ module RDF
|
|
572
572
|
self
|
573
573
|
else
|
574
574
|
RDF::URI.new(
|
575
|
-
object.merge(path: '/').
|
575
|
+
**object.merge(path: '/').
|
576
576
|
keep_if {|k, v| [:scheme, :authority, :path].include?(k)})
|
577
577
|
end
|
578
578
|
end
|
@@ -657,7 +657,7 @@ module RDF
|
|
657
657
|
#
|
658
658
|
# @return [RDF::URI]
|
659
659
|
def dup
|
660
|
-
self.class.new(
|
660
|
+
self.class.new(@value, **(@object || {}))
|
661
661
|
end
|
662
662
|
|
663
663
|
##
|
@@ -846,7 +846,7 @@ module RDF
|
|
846
846
|
parts[:user] = (user.dup.force_encoding(Encoding::UTF_8) if user)
|
847
847
|
parts[:password] = (password.dup.force_encoding(Encoding::UTF_8) if password)
|
848
848
|
parts[:host] = (host.dup.force_encoding(Encoding::UTF_8) if host)
|
849
|
-
parts[:port] = (
|
849
|
+
parts[:port] = (URI.decode(port).to_i if port)
|
850
850
|
parts[:path] = (path.to_s.dup.force_encoding(Encoding::UTF_8) unless path.empty?)
|
851
851
|
parts[:query] = (query[1..-1].dup.force_encoding(Encoding::UTF_8) if query)
|
852
852
|
parts[:fragment] = (fragment[1..-1].dup.force_encoding(Encoding::UTF_8) if fragment)
|
@@ -902,7 +902,7 @@ module RDF
|
|
902
902
|
# Normalized version of user
|
903
903
|
# @return [String]
|
904
904
|
def normalized_user
|
905
|
-
|
905
|
+
URI.encode(URI.decode(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if user
|
906
906
|
end
|
907
907
|
|
908
908
|
##
|
@@ -928,7 +928,7 @@ module RDF
|
|
928
928
|
# Normalized version of password
|
929
929
|
# @return [String]
|
930
930
|
def normalized_password
|
931
|
-
|
931
|
+
URI.encode(URI.decode(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if password
|
932
932
|
end
|
933
933
|
|
934
934
|
HOST_FROM_AUTHORITY_RE = /(?:[^@]+@)?([^:]+)(?::.*)?$/.freeze
|
@@ -937,7 +937,7 @@ module RDF
|
|
937
937
|
# @return [String]
|
938
938
|
def host
|
939
939
|
object.fetch(:host) do
|
940
|
-
@object[:host] = ($1 if HOST_FROM_AUTHORITY_RE.match(@object[:authority]))
|
940
|
+
@object[:host] = ($1 if @object[:authority] && HOST_FROM_AUTHORITY_RE.match(@object[:authority]))
|
941
941
|
end
|
942
942
|
end
|
943
943
|
|
@@ -965,7 +965,7 @@ module RDF
|
|
965
965
|
# @return [String]
|
966
966
|
def port
|
967
967
|
object.fetch(:port) do
|
968
|
-
@object[:port] = ($1 if PORT_FROM_AUTHORITY_RE.match(@object[:authority]))
|
968
|
+
@object[:port] = ($1 if @object[:authority] && PORT_FROM_AUTHORITY_RE.match(@object[:authority]))
|
969
969
|
end
|
970
970
|
end
|
971
971
|
|
@@ -1180,8 +1180,8 @@ module RDF
|
|
1180
1180
|
inject(return_type == Hash ? {} : []) do |memo,kv|
|
1181
1181
|
k,v = kv.to_s.split('=', 2)
|
1182
1182
|
next if k.to_s.empty?
|
1183
|
-
k =
|
1184
|
-
v =
|
1183
|
+
k = URI.decode(k)
|
1184
|
+
v = URI.decode(v) if v
|
1185
1185
|
if return_type == Hash
|
1186
1186
|
case memo[k]
|
1187
1187
|
when nil then memo[k] = v
|
@@ -1293,9 +1293,9 @@ module RDF
|
|
1293
1293
|
def normalize_segment(value, expr, downcase = false)
|
1294
1294
|
if value
|
1295
1295
|
value = value.dup.force_encoding(Encoding::UTF_8)
|
1296
|
-
decoded =
|
1296
|
+
decoded = URI.decode(value)
|
1297
1297
|
decoded.downcase! if downcase
|
1298
|
-
|
1298
|
+
URI.encode(decoded, /[^(?:#{expr})]/)
|
1299
1299
|
end
|
1300
1300
|
end
|
1301
1301
|
|
@@ -1314,6 +1314,27 @@ module RDF
|
|
1314
1314
|
""
|
1315
1315
|
end
|
1316
1316
|
end
|
1317
|
+
|
1318
|
+
# URI encode matching characters in value
|
1319
|
+
# From URI gem, as this is now generally deprecated
|
1320
|
+
def self.encode(str, expr)
|
1321
|
+
str.gsub(expr) do
|
1322
|
+
us = $&
|
1323
|
+
tmp = ''
|
1324
|
+
us.each_byte do |uc|
|
1325
|
+
tmp << sprintf('%%%02X', uc)
|
1326
|
+
end
|
1327
|
+
tmp
|
1328
|
+
end.force_encoding(Encoding::US_ASCII)
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
# URI decode escape sequences in value
|
1332
|
+
# From URI gem, as this is now generally deprecated
|
1333
|
+
def self.decode(str)
|
1334
|
+
enc = str.encoding
|
1335
|
+
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
|
1336
|
+
str.gsub(PCT_ENCODED) { [$&[1, 2]].pack('H2').force_encoding(enc) }
|
1337
|
+
end
|
1317
1338
|
end
|
1318
1339
|
|
1319
1340
|
# RDF::IRI is a synonym for RDF::URI
|
data/lib/rdf/nquads.rb
CHANGED
@@ -69,9 +69,9 @@ module RDF
|
|
69
69
|
|
70
70
|
begin
|
71
71
|
unless blank? || read_comment
|
72
|
-
subject = read_uriref || read_node || fail_subject
|
72
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
73
73
|
predicate = read_uriref(intern: true) || fail_predicate
|
74
|
-
object = read_uriref || read_node || read_literal || fail_object
|
74
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
75
75
|
graph_name = read_uriref || read_node
|
76
76
|
if validate? && !read_eos
|
77
77
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
@@ -96,7 +96,7 @@ module RDF
|
|
96
96
|
# @param [RDF::Term] object
|
97
97
|
# @return [void]
|
98
98
|
def write_quad(subject, predicate, object, graph_name)
|
99
|
-
puts format_quad(subject, predicate, object, graph_name,
|
99
|
+
puts format_quad(subject, predicate, object, graph_name, **@options)
|
100
100
|
end
|
101
101
|
|
102
102
|
##
|
@@ -107,7 +107,7 @@ module RDF
|
|
107
107
|
# @return [String]
|
108
108
|
# @since 0.4.0
|
109
109
|
def format_statement(statement, **options)
|
110
|
-
format_quad(*statement.to_quad, options)
|
110
|
+
format_quad(*statement.to_quad, **options)
|
111
111
|
end
|
112
112
|
|
113
113
|
##
|
@@ -120,8 +120,8 @@ module RDF
|
|
120
120
|
# @param [Hash{Symbol => Object}] options = ({})
|
121
121
|
# @return [String]
|
122
122
|
def format_quad(subject, predicate, object, graph_name, **options)
|
123
|
-
s = "%s %s %s " % [subject, predicate, object].map { |value| format_term(value, options) }
|
124
|
-
s += format_term(graph_name, options) + " " if graph_name
|
123
|
+
s = "%s %s %s " % [subject, predicate, object].map { |value| format_term(value, **options) }
|
124
|
+
s += format_term(graph_name, **options) + " " if graph_name
|
125
125
|
s + "."
|
126
126
|
end
|
127
127
|
end # Writer
|
data/lib/rdf/ntriples.rb
CHANGED
@@ -15,15 +15,17 @@ module RDF
|
|
15
15
|
#
|
16
16
|
# <https://rubygems.org/gems/rdf> <http://purl.org/dc/terms/title> "rdf" .
|
17
17
|
#
|
18
|
-
#
|
19
|
-
#
|
18
|
+
# ## RDFStar (RDF*)
|
19
|
+
#
|
20
|
+
# Supports statements as resources using `<<s p o>>`.
|
21
|
+
#
|
22
|
+
# ## Installation
|
20
23
|
#
|
21
24
|
# This is the only RDF serialization format that is directly supported by
|
22
25
|
# RDF.rb. Support for other formats is available in the form of add-on
|
23
26
|
# gems, e.g. 'rdf-xml' or 'rdf-json'.
|
24
27
|
#
|
25
|
-
# Documentation
|
26
|
-
# -------------
|
28
|
+
# ## Documentation
|
27
29
|
#
|
28
30
|
# * {RDF::NTriples::Format}
|
29
31
|
# * {RDF::NTriples::Reader}
|
data/lib/rdf/ntriples/reader.rb
CHANGED
@@ -25,6 +25,10 @@ module RDF::NTriples
|
|
25
25
|
# end
|
26
26
|
# end
|
27
27
|
#
|
28
|
+
# ** RDFStar (RDF*)
|
29
|
+
#
|
30
|
+
# Supports statements as resources using `<<s p o>>`.
|
31
|
+
#
|
28
32
|
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
29
33
|
# @see http://www.w3.org/TR/n-triples/
|
30
34
|
class Reader < RDF::Reader
|
@@ -70,6 +74,10 @@ module RDF::NTriples
|
|
70
74
|
# 22
|
71
75
|
STRING_LITERAL_QUOTE = /"((?:[^\"\\\n\r]|#{ECHAR}|#{UCHAR})*)"/.freeze
|
72
76
|
|
77
|
+
# RDF*
|
78
|
+
ST_START = /^<</.freeze
|
79
|
+
ST_END = /^\s*>>/.freeze
|
80
|
+
|
73
81
|
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
|
74
82
|
COMMENT = /^#\s*(.*)$/.freeze
|
75
83
|
NODEID = /^#{BLANK_NODE_LABEL}/.freeze
|
@@ -96,7 +104,7 @@ module RDF::NTriples
|
|
96
104
|
def self.unserialize(input, **options)
|
97
105
|
case input
|
98
106
|
when nil then nil
|
99
|
-
else self.new(input,
|
107
|
+
else self.new(input, logger: [], **options).read_value
|
100
108
|
end
|
101
109
|
end
|
102
110
|
|
@@ -104,20 +112,20 @@ module RDF::NTriples
|
|
104
112
|
# (see unserialize)
|
105
113
|
# @return [RDF::Resource]
|
106
114
|
def self.parse_subject(input, **options)
|
107
|
-
parse_uri(input, options) || parse_node(input, options)
|
115
|
+
parse_uri(input, **options) || parse_node(input, **options)
|
108
116
|
end
|
109
117
|
|
110
118
|
##
|
111
119
|
# (see unserialize)
|
112
120
|
# @return [RDF::URI]
|
113
|
-
def self.parse_predicate(input,
|
121
|
+
def self.parse_predicate(input, **options)
|
114
122
|
parse_uri(input, intern: true)
|
115
123
|
end
|
116
124
|
|
117
125
|
##
|
118
126
|
# (see unserialize)
|
119
127
|
def self.parse_object(input, **options)
|
120
|
-
parse_uri(input, options) || parse_node(input, options) || parse_literal(input, options)
|
128
|
+
parse_uri(input, **options) || parse_node(input, **options) || parse_literal(input, **options)
|
121
129
|
end
|
122
130
|
|
123
131
|
##
|
@@ -202,7 +210,7 @@ module RDF::NTriples
|
|
202
210
|
begin
|
203
211
|
read_statement
|
204
212
|
rescue RDF::ReaderError
|
205
|
-
value = read_uriref || read_node || read_literal
|
213
|
+
value = read_uriref || read_node || read_literal || read_rdfstar
|
206
214
|
log_recover
|
207
215
|
value
|
208
216
|
end
|
@@ -218,9 +226,9 @@ module RDF::NTriples
|
|
218
226
|
|
219
227
|
begin
|
220
228
|
unless blank? || read_comment
|
221
|
-
subject = read_uriref || read_node || fail_subject
|
229
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
222
230
|
predicate = read_uriref(intern: true) || fail_predicate
|
223
|
-
object = read_uriref || read_node || read_literal || fail_object
|
231
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
224
232
|
|
225
233
|
if validate? && !read_eos
|
226
234
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
@@ -234,6 +242,20 @@ module RDF::NTriples
|
|
234
242
|
end
|
235
243
|
end
|
236
244
|
|
245
|
+
##
|
246
|
+
# @return [RDF::Statement]
|
247
|
+
def read_rdfstar
|
248
|
+
if @options[:rdfstar] && match(ST_START)
|
249
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
250
|
+
predicate = read_uriref(intern: true) || fail_predicate
|
251
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
252
|
+
if !match(ST_END)
|
253
|
+
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
254
|
+
end
|
255
|
+
RDF::Statement.new(subject, predicate, object)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
237
259
|
##
|
238
260
|
# @return [Boolean]
|
239
261
|
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (comment)
|
data/lib/rdf/ntriples/writer.rb
CHANGED
@@ -208,7 +208,7 @@ module RDF::NTriples
|
|
208
208
|
# @param [RDF::Term] object
|
209
209
|
# @return [void]
|
210
210
|
def write_triple(subject, predicate, object)
|
211
|
-
puts format_triple(subject, predicate, object,
|
211
|
+
puts format_triple(subject, predicate, object, **@options)
|
212
212
|
end
|
213
213
|
|
214
214
|
##
|
@@ -221,6 +221,15 @@ module RDF::NTriples
|
|
221
221
|
format_triple(*statement.to_triple, **options)
|
222
222
|
end
|
223
223
|
|
224
|
+
##
|
225
|
+
# Returns the N-Triples representation of an RDF* reified statement.
|
226
|
+
#
|
227
|
+
# @param [RDF::Statement] statement
|
228
|
+
# @param [Hash{Symbol => Object}] options ({})
|
229
|
+
# @return [String]
|
230
|
+
def format_rdfstar(statement, **options)
|
231
|
+
"<<%s %s %s>>" % statement.to_a.map { |value| format_term(value, **options) }
|
232
|
+
end
|
224
233
|
##
|
225
234
|
# Returns the N-Triples representation of a triple.
|
226
235
|
#
|
data/lib/rdf/query.rb
CHANGED
@@ -90,7 +90,7 @@ module RDF
|
|
90
90
|
# the resulting solution sequence
|
91
91
|
# @see RDF::Query#execute
|
92
92
|
def self.execute(queryable, patterns = {}, options = {}, &block)
|
93
|
-
self.new(patterns, options, &block).execute(queryable, options)
|
93
|
+
self.new(patterns, **options, &block).execute(queryable, **options)
|
94
94
|
end
|
95
95
|
|
96
96
|
##
|
@@ -134,6 +134,12 @@ module RDF
|
|
134
134
|
# @return [Hash]
|
135
135
|
attr_reader :options
|
136
136
|
|
137
|
+
##
|
138
|
+
# Scope the query to named graphs matching value
|
139
|
+
#
|
140
|
+
# @return [RDF::Resource, RDF::Query::Variable, false] graph_name
|
141
|
+
attr_accessor :graph_name
|
142
|
+
|
137
143
|
##
|
138
144
|
# Initializes a new basic graph pattern query.
|
139
145
|
#
|
@@ -180,6 +186,7 @@ module RDF
|
|
180
186
|
@options = options.dup
|
181
187
|
@solutions = Query::Solutions(solutions)
|
182
188
|
graph_name = name if graph_name.nil?
|
189
|
+
@graph_name = graph_name
|
183
190
|
|
184
191
|
patterns << @options if patterns.empty?
|
185
192
|
|
@@ -189,8 +196,6 @@ module RDF
|
|
189
196
|
else patterns
|
190
197
|
end
|
191
198
|
|
192
|
-
self.graph_name = graph_name
|
193
|
-
|
194
199
|
if block_given?
|
195
200
|
case block.arity
|
196
201
|
when 1 then block.call(self)
|
@@ -223,7 +228,7 @@ module RDF
|
|
223
228
|
# whether this is an optional pattern
|
224
229
|
# @return [void] self
|
225
230
|
def pattern(pattern, **options)
|
226
|
-
@patterns << Pattern.from(pattern, options)
|
231
|
+
@patterns << Pattern.from(pattern, **options)
|
227
232
|
self
|
228
233
|
end
|
229
234
|
|
@@ -235,7 +240,7 @@ module RDF
|
|
235
240
|
# @return [RDF::Query] a copy of `self`
|
236
241
|
# @since 0.3.0
|
237
242
|
def optimize(**options)
|
238
|
-
self.dup.optimize!(options)
|
243
|
+
self.dup.optimize!(**options)
|
239
244
|
end
|
240
245
|
|
241
246
|
##
|
@@ -284,6 +289,8 @@ module RDF
|
|
284
289
|
# any additional keyword options
|
285
290
|
# @option options [Hash{Symbol => RDF::Term}] bindings
|
286
291
|
# optional variable bindings to use
|
292
|
+
# @option options [Boolean] :optimize
|
293
|
+
# Optimize query before execution.
|
287
294
|
# @option options [RDF::Query::Solutions] solutions
|
288
295
|
# optional initial solutions for chained queries
|
289
296
|
# @yield [solution]
|
@@ -294,9 +301,7 @@ module RDF
|
|
294
301
|
# the resulting solution sequence
|
295
302
|
# @see http://www.holygoat.co.uk/blog/entry/2005-10-25-1
|
296
303
|
# @see http://www.w3.org/TR/sparql11-query/#emptyGroupPattern
|
297
|
-
def execute(queryable, solutions: Solution.new, graph_name: nil, name: nil, **options, &block)
|
298
|
-
options = {bindings: {}}.merge(options)
|
299
|
-
|
304
|
+
def execute(queryable, bindings: {}, solutions: Solution.new, graph_name: nil, name: nil, **options, &block)
|
300
305
|
# Use provided solutions to allow for query chaining
|
301
306
|
# Otherwise, a quick empty solution simplifies the logic below; no special case for
|
302
307
|
# the first pattern
|
@@ -308,17 +313,17 @@ module RDF
|
|
308
313
|
return @solutions
|
309
314
|
end
|
310
315
|
|
316
|
+
self.optimize! if options[:optimize]
|
311
317
|
patterns = @patterns
|
312
318
|
graph_name = name if graph_name.nil?
|
313
|
-
graph_name =
|
314
|
-
options[:graph_name] = graph_name unless graph_name.nil?
|
319
|
+
@graph_name = graph_name unless graph_name.nil?
|
315
320
|
|
316
321
|
# Add graph_name to pattern, if necessary
|
317
|
-
unless graph_name.nil?
|
322
|
+
unless @graph_name.nil?
|
318
323
|
if patterns.empty?
|
319
|
-
patterns = [Pattern.new(nil, nil, nil, graph_name: graph_name)]
|
324
|
+
patterns = [Pattern.new(nil, nil, nil, graph_name: @graph_name)]
|
320
325
|
else
|
321
|
-
apply_graph_name(graph_name)
|
326
|
+
apply_graph_name(@graph_name)
|
322
327
|
end
|
323
328
|
end
|
324
329
|
|
@@ -326,15 +331,15 @@ module RDF
|
|
326
331
|
|
327
332
|
old_solutions, @solutions = @solutions, Query::Solutions()
|
328
333
|
|
329
|
-
|
334
|
+
bindings.each_key do |variable|
|
330
335
|
if pattern.variables.include?(variable)
|
331
336
|
unbound_solutions, old_solutions = old_solutions, Query::Solutions()
|
332
|
-
|
337
|
+
bindings[variable].each do |binding|
|
333
338
|
unbound_solutions.each do |solution|
|
334
339
|
old_solutions << solution.merge(variable => binding)
|
335
340
|
end
|
336
341
|
end
|
337
|
-
|
342
|
+
bindings.delete(variable)
|
338
343
|
end
|
339
344
|
end
|
340
345
|
|
@@ -407,38 +412,26 @@ module RDF
|
|
407
412
|
# Is this query scoped to a named graph?
|
408
413
|
# @return [Boolean]
|
409
414
|
def named?
|
410
|
-
!!
|
415
|
+
!!graph_name
|
411
416
|
end
|
412
417
|
|
413
418
|
# Is this query scoped to the default graph?
|
414
419
|
# @return [Boolean]
|
415
420
|
def default?
|
416
|
-
|
421
|
+
graph_name == false
|
417
422
|
end
|
418
423
|
|
419
424
|
# Is this query unscoped? This indicates that it can return results from
|
420
425
|
# either a named graph or the default graph.
|
421
426
|
# @return [Boolean]
|
422
427
|
def unnamed?
|
423
|
-
|
424
|
-
end
|
425
|
-
|
426
|
-
# Scope the query to named graphs matching value
|
427
|
-
# @param [RDF::IRI, RDF::Query::Variable] value
|
428
|
-
# @return [RDF::IRI, RDF::Query::Variable]
|
429
|
-
def graph_name=(value)
|
430
|
-
options[:graph_name] = value
|
431
|
-
end
|
432
|
-
|
433
|
-
# Scope of this query, if any
|
434
|
-
# @return [RDF::IRI, RDF::Query::Variable]
|
435
|
-
def graph_name
|
436
|
-
options[:graph_name]
|
428
|
+
graph_name.nil?
|
437
429
|
end
|
438
430
|
|
439
431
|
# Apply the graph name specified (or configured) to all patterns that have no graph name
|
440
432
|
# @param [RDF::IRI, RDF::Query::Variable] graph_name (self.graph_name)
|
441
|
-
def apply_graph_name(graph_name =
|
433
|
+
def apply_graph_name(graph_name = nil)
|
434
|
+
graph_name ||= self.graph_name
|
442
435
|
patterns.each {|pattern| pattern.graph_name = graph_name if pattern.graph_name.nil?} unless graph_name.nil?
|
443
436
|
end
|
444
437
|
|
@@ -515,8 +508,7 @@ module RDF
|
|
515
508
|
# @return [RDF::Query]
|
516
509
|
def dup
|
517
510
|
patterns = @patterns.map {|p| p.dup}
|
518
|
-
patterns
|
519
|
-
Query.new(*patterns)
|
511
|
+
Query.new(patterns, graph_name: graph_name, solutions: @solutions.dup, **options)
|
520
512
|
end
|
521
513
|
|
522
514
|
##
|