sparql-client 2.1.0 → 2.2.1
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.
- checksums.yaml +4 -4
- data/README.md +15 -16
- data/VERSION +1 -1
- data/lib/sparql/client.rb +29 -8
- data/lib/sparql/client/query.rb +242 -31
- data/lib/sparql/client/repository.rb +26 -1
- data/lib/sparql/client/update.rb +1 -1
- metadata +48 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63643389b5260847e6a5ff81f8ec4e7a8d754adf
|
4
|
+
data.tar.gz: b0ed32a9d7f1fd58efe6de87ab64f2eb0f10a758
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcfec9d172d4bb98f27136bdde32f242780080b05b1fa92390fa69f3c4faea3aad03971dc7d19b22026e228065210b86ccd543d6a749d7fe1d132737480e9459
|
7
|
+
data.tar.gz: b0a1ce446f6930c620b78aee2978cd46b0c9d54f9fec3c08ea00c91f5761eeae083a19f07f00d8a48867505addb370d986d54ad9cb345dcd026826244caed2c3
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#SPARQL Client for RDF.rb
|
1
|
+
# SPARQL Client for RDF.rb
|
2
2
|
|
3
3
|
This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
|
4
4
|
|
@@ -8,7 +8,7 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
|
|
8
8
|
[](http://travis-ci.org/ruby-rdf/sparql-client)
|
9
9
|
[](https://coveralls.io/github/ruby-rdf/sparql-client?branch=master)
|
10
10
|
|
11
|
-
##Features
|
11
|
+
## Features
|
12
12
|
|
13
13
|
* Executes queries against any SPARQL 1.0/1.1-compatible endpoint over HTTP,
|
14
14
|
or against an `RDF::Queryable` instance, using the `SPARQL` gem.
|
@@ -22,7 +22,7 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
|
|
22
22
|
* Supports accessing endpoints as read/write [`RDF::Repository`][RDF::Repository]
|
23
23
|
instances {SPARQL::Client::Repository}.
|
24
24
|
|
25
|
-
##Examples
|
25
|
+
## Examples
|
26
26
|
|
27
27
|
### Querying a remote SPARQL endpoint
|
28
28
|
require 'sparql/client'
|
@@ -73,7 +73,7 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
|
|
73
73
|
data = RDF::Graph.new do |graph|
|
74
74
|
graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
|
75
75
|
end
|
76
|
-
insert_data(data)
|
76
|
+
sparql.insert_data(data)
|
77
77
|
|
78
78
|
### Deleting data from a graph
|
79
79
|
|
@@ -81,16 +81,16 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
|
|
81
81
|
data = RDF::Graph.new do |graph|
|
82
82
|
graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
|
83
83
|
end
|
84
|
-
delete_data(data)
|
84
|
+
sparql.delete_data(data)
|
85
85
|
|
86
|
-
##Documentation
|
86
|
+
## Documentation
|
87
87
|
|
88
88
|
* {SPARQL::Client}
|
89
89
|
* {SPARQL::Client::Query}
|
90
90
|
* {SPARQL::Client::Repository}
|
91
91
|
* {SPARQL::Client::Update}
|
92
92
|
|
93
|
-
##Dependencies
|
93
|
+
## Dependencies
|
94
94
|
|
95
95
|
* [Ruby](http://ruby-lang.org/) (>= 2.2.2)
|
96
96
|
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.0)
|
@@ -98,14 +98,14 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
|
|
98
98
|
* Soft dependency on [SPARQL](http://rubygems.org/gems/sparql) (>= 2.0)
|
99
99
|
* Soft dependency on [Nokogiri](http://rubygems.org/gems/nokogiri) (>= 1.6)
|
100
100
|
|
101
|
-
##Installation
|
101
|
+
## Installation
|
102
102
|
|
103
103
|
The recommended installation method is via [RubyGems](http://rubygems.org/).
|
104
104
|
To install the latest official release of the `SPARQL::Client` gem, do:
|
105
105
|
|
106
106
|
% [sudo] gem install sparql-client
|
107
107
|
|
108
|
-
##Download
|
108
|
+
## Download
|
109
109
|
|
110
110
|
To get a local working copy of the development repository, do:
|
111
111
|
|
@@ -116,17 +116,17 @@ follows:
|
|
116
116
|
|
117
117
|
% wget http://github.com/ruby-rdf/sparql-client/tarball/master
|
118
118
|
|
119
|
-
##Mailing List
|
119
|
+
## Mailing List
|
120
120
|
|
121
121
|
* <http://lists.w3.org/Archives/Public/public-rdf-ruby/>
|
122
122
|
|
123
|
-
##Authors
|
123
|
+
## Authors
|
124
124
|
|
125
125
|
* [Arto Bendiken](http://github.com/bendiken) - <http://ar.to/>
|
126
126
|
* [Ben Lavender](http://github.com/bhuga) - <http://bhuga.net/>
|
127
127
|
* [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
|
128
128
|
|
129
|
-
##Contributors
|
129
|
+
## Contributors
|
130
130
|
|
131
131
|
* [Christoph Badura](http://github.com/bad) - <http://github.com/bad>
|
132
132
|
* [James Hetherington](http://github.com/jamespjh) - <http://twitter.com/jamespjh>
|
@@ -140,7 +140,7 @@ follows:
|
|
140
140
|
* [Thomas Feron](http://github.com/thoferon) - <http://github.com/thoferon>
|
141
141
|
* [Nick Gottlieb](http://github.com/ngottlieb) - <http://www.nicholasgottlieb.com>
|
142
142
|
|
143
|
-
##Contributing
|
143
|
+
## Contributing
|
144
144
|
This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
|
145
145
|
|
146
146
|
* Do your best to adhere to the existing coding conventions and idioms.
|
@@ -155,16 +155,15 @@ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange develo
|
|
155
155
|
of thumb, additions larger than about 15 lines of code), we need an
|
156
156
|
explicit [public domain dedication][PDD] on record from you.
|
157
157
|
|
158
|
-
##Resources
|
158
|
+
## Resources
|
159
159
|
|
160
160
|
* <http://ruby-rdf.github.com/sparql-client/>
|
161
161
|
* <http://github.com/ruby-rdf/sparql-client>
|
162
162
|
* <http://rubygems.org/gems/sparql-client>
|
163
|
-
* <http://rubyforge.org/projects/sparql/>
|
164
163
|
* <http://raa.ruby-lang.org/project/sparql-client/>
|
165
164
|
* <http://www.ohloh.net/p/rdf>
|
166
165
|
|
167
|
-
##License
|
166
|
+
## License
|
168
167
|
|
169
168
|
This is free and unencumbered public domain software. For more information,
|
170
169
|
see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1
|
1
|
+
2.2.1
|
data/lib/sparql/client.rb
CHANGED
@@ -157,7 +157,7 @@ module SPARQL
|
|
157
157
|
# })
|
158
158
|
#
|
159
159
|
# @example Inserting data sourced from a file or URL
|
160
|
-
# data = RDF::Graph.load("
|
160
|
+
# data = RDF::Graph.load("https://raw.githubusercontent.com/ruby-rdf/rdf/develop/etc/doap.nt")
|
161
161
|
# client.insert_data(data)
|
162
162
|
#
|
163
163
|
# @example Inserting data into a named graph
|
@@ -178,7 +178,7 @@ module SPARQL
|
|
178
178
|
# This requires that the endpoint support SPARQL 1.1 Update.
|
179
179
|
#
|
180
180
|
# @example Deleting data sourced from a file or URL
|
181
|
-
# data = RDF::Graph.load("
|
181
|
+
# data = RDF::Graph.load("https://raw.githubusercontent.com/ruby-rdf/rdf/develop/etc/doap.nt")
|
182
182
|
# client.delete_data(data)
|
183
183
|
#
|
184
184
|
# @example Deleting data from a named graph
|
@@ -609,11 +609,15 @@ module SPARQL
|
|
609
609
|
# @private
|
610
610
|
def self.serialize_patterns(patterns, use_vars = false)
|
611
611
|
patterns.map do |pattern|
|
612
|
-
serialized_pattern =
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
612
|
+
serialized_pattern = case pattern
|
613
|
+
when SPARQL::Client::QueryElement then [pattern.to_s]
|
614
|
+
else
|
615
|
+
RDF::Statement.from(pattern).to_triple.each_with_index.map do |v, i|
|
616
|
+
if i == 1
|
617
|
+
SPARQL::Client.serialize_predicate(v)
|
618
|
+
else
|
619
|
+
SPARQL::Client.serialize_value(v, use_vars)
|
620
|
+
end
|
617
621
|
end
|
618
622
|
end
|
619
623
|
serialized_pattern.join(' ') + ' .'
|
@@ -654,7 +658,11 @@ module SPARQL
|
|
654
658
|
value = ENV['https_proxy']
|
655
659
|
proxy_url = URI.parse(value) unless value.nil? || value.empty?
|
656
660
|
end
|
657
|
-
klass = Net::HTTP::Persistent.
|
661
|
+
klass = if Net::HTTP::Persistent::VERSION >= '3.0'
|
662
|
+
Net::HTTP::Persistent.new(name: self.class.to_s, proxy: proxy_url)
|
663
|
+
else
|
664
|
+
Net::HTTP::Persistent.new(self.class.to_s, proxy_url)
|
665
|
+
end
|
658
666
|
klass.keep_alive = @options[:keep_alive] || 120
|
659
667
|
klass.read_timeout = @options[:read_timeout] || 60
|
660
668
|
klass
|
@@ -748,5 +756,18 @@ module SPARQL
|
|
748
756
|
end
|
749
757
|
request
|
750
758
|
end
|
759
|
+
|
760
|
+
# A query element can be used as a component of a query. It may be initialized with a string, which is wrapped in an appropriate container depending on the type of QueryElement. Implements {#to_s} to property serialize when generating a SPARQL query.
|
761
|
+
class QueryElement
|
762
|
+
attr_reader :elements
|
763
|
+
|
764
|
+
def initialize(*args)
|
765
|
+
@elements = args
|
766
|
+
end
|
767
|
+
|
768
|
+
def to_s
|
769
|
+
raise NotImplemented
|
770
|
+
end
|
771
|
+
end
|
751
772
|
end # Client
|
752
773
|
end # SPARQL
|
data/lib/sparql/client/query.rb
CHANGED
@@ -42,6 +42,12 @@ module SPARQL; class Client
|
|
42
42
|
# @example SELECT * WHERE { ?s ?p ?o . }
|
43
43
|
# Query.select.where([:s, :p, :o])
|
44
44
|
#
|
45
|
+
# @example SELECT ?s WHERE {?s ?p ?o .}
|
46
|
+
# Query.select(:s).where([:s, :p, :o])
|
47
|
+
#
|
48
|
+
# @example SELECT COUNT(?uri as ?c) WHERE {?uri a owl:Class}
|
49
|
+
# Query.select(count: {uri: :c}).where([:uri, RDF.type, RDF::OWL.Class])
|
50
|
+
#
|
45
51
|
# @param [Array<Symbol>] variables
|
46
52
|
# @return [Query]
|
47
53
|
#
|
@@ -98,6 +104,10 @@ module SPARQL; class Client
|
|
98
104
|
# @overload self.construct(*variables, options)
|
99
105
|
# @param [Symbol, #to_s] form
|
100
106
|
# @param [Hash{Symbol => Object}] options (see {Client#initialize})
|
107
|
+
# @option options [Hash{Symbol => Symbol}] :count
|
108
|
+
# Contents are symbols relating a variable described within the query,
|
109
|
+
# to the projected variable.
|
110
|
+
#
|
101
111
|
# @yield [query]
|
102
112
|
# @yieldparam [Query]
|
103
113
|
def initialize(form = :ask, options = {}, &block)
|
@@ -121,6 +131,12 @@ module SPARQL; class Client
|
|
121
131
|
# @example SELECT * WHERE { ?s ?p ?o . }
|
122
132
|
# query.select.where([:s, :p, :o])
|
123
133
|
#
|
134
|
+
# @example SELECT ?s WHERE {?s ?p ?o .}
|
135
|
+
# query.select(:s).where([:s, :p, :o])
|
136
|
+
#
|
137
|
+
# @example SELECT COUNT(?uri as ?c) WHERE {?uri a owl:Class}
|
138
|
+
# query.select(count: {uri: :c}).where([:uri, RDF.type, RDF::OWL.Class])
|
139
|
+
#
|
124
140
|
# @param [Array<Symbol>] variables
|
125
141
|
# @return [Query]
|
126
142
|
# @see http://www.w3.org/TR/sparql11-query/#select
|
@@ -172,19 +188,55 @@ module SPARQL; class Client
|
|
172
188
|
# query.select.where([:s, :p, :o])
|
173
189
|
# query.select.whether([:s, :p, :o])
|
174
190
|
#
|
191
|
+
# @example SELECT * WHERE { { SELECT * WHERE { ?s ?p ?o . } } . ?s ?p ?o . }
|
192
|
+
# subquery = query.select.where([:s, :p, :o])
|
193
|
+
# query.select.where([:s, :p, :o], subquery)
|
194
|
+
#
|
195
|
+
# @example SELECT * WHERE { { SELECT * WHERE { ?s ?p ?o . } } . ?s ?p ?o . }
|
196
|
+
# query.select.where([:s, :p, :o]) do |q|
|
197
|
+
# q.select.where([:s, :p, :o])
|
198
|
+
# end
|
199
|
+
#
|
200
|
+
# Block form can be used for chaining calls in addition to creating sub-select queries.
|
201
|
+
#
|
202
|
+
# @example SELECT * WHERE { ?s ?p ?o . } ORDER BY ?o
|
203
|
+
# query.select.where([:s, :p, :o]) do
|
204
|
+
# order(:o)
|
205
|
+
# end
|
206
|
+
#
|
175
207
|
# @param [Array<RDF::Query::Pattern, Array>] patterns_queries
|
176
208
|
# splat of zero or more patterns followed by zero or more queries.
|
209
|
+
# @yield [query]
|
210
|
+
# Yield form with or without argument; without an argument, evaluates within the query.
|
211
|
+
# @yieldparam [SPARQL::Client::Query] query Actually a delegator to query. Methods other than `#select` are evaluated against `self`. For `#select`, a new Query is created, and the result added as a subquery.
|
177
212
|
# @return [Query]
|
178
213
|
# @see http://www.w3.org/TR/sparql11-query/#GraphPattern
|
179
|
-
def where(*patterns_queries)
|
214
|
+
def where(*patterns_queries, &block)
|
180
215
|
subqueries, patterns = patterns_queries.partition {|pq| pq.is_a? SPARQL::Client::Query}
|
181
216
|
@patterns += build_patterns(patterns)
|
182
217
|
@subqueries += subqueries
|
218
|
+
|
219
|
+
if block_given?
|
220
|
+
decorated_query = WhereDecorator.new(self)
|
221
|
+
case block.arity
|
222
|
+
when 1 then block.call(decorated_query)
|
223
|
+
else decorated_query.instance_eval(&block)
|
224
|
+
end
|
225
|
+
end
|
183
226
|
self
|
184
227
|
end
|
185
228
|
|
186
229
|
alias_method :whether, :where
|
187
230
|
|
231
|
+
# @private
|
232
|
+
class WhereDecorator < SimpleDelegator
|
233
|
+
def select(*variables)
|
234
|
+
query = SPARQL::Client::Query.select(*variables)
|
235
|
+
__getobj__.instance_variable_get(:@subqueries) << query
|
236
|
+
query
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
188
240
|
##
|
189
241
|
# @example SELECT * WHERE { ?s ?p ?o . } ORDER BY ?o
|
190
242
|
# query.select.where([:s, :p, :o]).order(:o)
|
@@ -338,10 +390,141 @@ module SPARQL; class Client
|
|
338
390
|
# query.select.where([:s, :p, :o]).
|
339
391
|
# optional([:s, RDF.type, :o], [:s, RDF::Vocab::DC.abstract, :o])
|
340
392
|
#
|
393
|
+
# The block form can be used for adding filters:
|
394
|
+
#
|
395
|
+
# @example ASK WHERE { ?s ?p ?o . OPTIONAL { ?s ?p ?o . FILTER(regex(?s, 'Abiline, Texas'))} }
|
396
|
+
# query.ask.where([:s, :p, :o]).optional([:s, :p, :o]) do
|
397
|
+
# filter("regex(?s, 'Abiline, Texas')")
|
398
|
+
# end
|
399
|
+
#
|
400
|
+
# @param [Array<RDF::Query::Pattern, Array>] patterns
|
401
|
+
# splat of zero or more patterns followed by zero or more queries.
|
402
|
+
# @yield [query]
|
403
|
+
# Yield form with or without argument; without an argument, evaluates within the query.
|
404
|
+
# @yieldparam [SPARQL::Client::Query] query used for creating filters on the optional patterns.
|
341
405
|
# @return [Query]
|
342
406
|
# @see http://www.w3.org/TR/sparql11-query/#optionals
|
343
|
-
def optional(*patterns)
|
407
|
+
def optional(*patterns, &block)
|
344
408
|
(options[:optionals] ||= []) << build_patterns(patterns)
|
409
|
+
|
410
|
+
if block_given?
|
411
|
+
# Steal options[:filters]
|
412
|
+
query_filters = options[:filters]
|
413
|
+
options[:filters] = []
|
414
|
+
case block.arity
|
415
|
+
when 1 then block.call(self)
|
416
|
+
else instance_eval(&block)
|
417
|
+
end
|
418
|
+
options[:optionals].last.concat(options[:filters])
|
419
|
+
options[:filters] = query_filters
|
420
|
+
end
|
421
|
+
|
422
|
+
self
|
423
|
+
end
|
424
|
+
|
425
|
+
##
|
426
|
+
# @example SELECT * WHERE \{ ?book dc:title ?title \} UNION \{ ?book dc11:title ?title \}
|
427
|
+
# query.select.where([:book, RDF::Vocab::DC.title, :title]).
|
428
|
+
# union([:book, RDF::Vocab::DC11.title, :title])
|
429
|
+
#
|
430
|
+
# @example SELECT * WHERE \{ ?book dc:title ?title \} UNION \{ ?book dc11:title ?title . FILTER(langmatches(lang(?title), 'EN'))\}
|
431
|
+
# query1 = SPARQL::Client::Query.select.
|
432
|
+
# where([:book, RDF::Vocab::DC11.title, :title]).
|
433
|
+
# filter("langmatches(?title, 'en')")
|
434
|
+
# query.select.where([:book, RDF::Vocab::DC.title, :title]).union(query1)
|
435
|
+
#
|
436
|
+
# The block form can be used for more complicated queries, using the `select` form (note, use either block or argument forms, not both):
|
437
|
+
#
|
438
|
+
# @example SELECT * WHERE \{ ?book dc:title ?title \} UNION \{ ?book dc11:title ?title . FILTER(langmatches(lang(?title), 'EN'))\}
|
439
|
+
# query1 = SPARQL::Client::Query.select.where([:book, RDF::Vocab::DC11.title, :title]).filter("langmatches(?title, 'en')")
|
440
|
+
# query.select.where([:book, RDF::Vocab::DC.title, :title]).union do |q|
|
441
|
+
# q.select.
|
442
|
+
# where([:book, RDF::Vocab::DC11.title, :title]).
|
443
|
+
# filter("langmatches(?title, 'en')")
|
444
|
+
# end
|
445
|
+
#
|
446
|
+
# @param [Array<RDF::Query::Pattern, Array>] patterns
|
447
|
+
# splat of zero or more patterns followed by zero or more queries.
|
448
|
+
# @yield [query]
|
449
|
+
# Yield form with or without argument; without an argument, evaluates within the query.
|
450
|
+
# @yieldparam [SPARQL::Client::Query] query used for adding select clauses.
|
451
|
+
# @return [Query]
|
452
|
+
# @see http://www.w3.org/TR/sparql11-query/#optionals
|
453
|
+
def union(*patterns, &block)
|
454
|
+
options[:unions] ||= []
|
455
|
+
|
456
|
+
if block_given?
|
457
|
+
raise ArgumentError, "#union requires either arguments or a block, not both." unless patterns.empty?
|
458
|
+
# Evaluate calls in a new query instance
|
459
|
+
query = self.class.select
|
460
|
+
case block.arity
|
461
|
+
when 1 then block.call(query)
|
462
|
+
else query.instance_eval(&block)
|
463
|
+
end
|
464
|
+
options[:unions] << query
|
465
|
+
elsif patterns.all? {|p| p.is_a?(SPARQL::Client::Query)}
|
466
|
+
# With argument form, all must be patterns or queries
|
467
|
+
options[:unions] += patterns
|
468
|
+
elsif patterns.all? {|p| p.is_a?(Array)}
|
469
|
+
# With argument form, all must be patterns, or queries
|
470
|
+
options[:unions] << self.class.select.where(*patterns)
|
471
|
+
else
|
472
|
+
raise ArgumentError, "#union arguments are triple patters or queries, not both."
|
473
|
+
end
|
474
|
+
|
475
|
+
self
|
476
|
+
end
|
477
|
+
|
478
|
+
##
|
479
|
+
# @example SELECT * WHERE \{ ?book dc:title ?title . MINUS \{ ?book dc11:title ?title \} \}
|
480
|
+
# query.select.where([:book, RDF::Vocab::DC.title, :title]).
|
481
|
+
# minus([:book, RDF::Vocab::DC11.title, :title])
|
482
|
+
#
|
483
|
+
# @example SELECT * WHERE \{ ?book dc:title ?title MINUS \{ ?book dc11:title ?title . FILTER(langmatches(lang(?title), 'EN')) \} \}
|
484
|
+
# query1 = SPARQL::Client::Query.select.
|
485
|
+
# where([:book, RDF::Vocab::DC11.title, :title]).
|
486
|
+
# filter("langmatches(?title, 'en')")
|
487
|
+
# query.select.where([:book, RDF::Vocab::DC.title, :title]).minus(query1)
|
488
|
+
#
|
489
|
+
# The block form can be used for more complicated queries, using the `select` form (note, use either block or argument forms, not both):
|
490
|
+
#
|
491
|
+
# @example SELECT * WHERE \{ ?book dc:title ?title MINUS \{ ?book dc11:title ?title . FILTER(langmatches(lang(?title), 'EN'))\} \}
|
492
|
+
# query1 = SPARQL::Client::Query.select.where([:book, RDF::Vocab::DC11.title, :title]).filter("langmatches(?title, 'en')")
|
493
|
+
# query.select.where([:book, RDF::Vocab::DC.title, :title]).minus do |q|
|
494
|
+
# q.select.
|
495
|
+
# where([:book, RDF::Vocab::DC11.title, :title]).
|
496
|
+
# filter("langmatches(?title, 'en')")
|
497
|
+
# end
|
498
|
+
#
|
499
|
+
# @param [Array<RDF::Query::Pattern, Array>] patterns
|
500
|
+
# splat of zero or more patterns followed by zero or more queries.
|
501
|
+
# @yield [query]
|
502
|
+
# Yield form with or without argument; without an argument, evaluates within the query.
|
503
|
+
# @yieldparam [SPARQL::Client::Query] query used for adding select clauses.
|
504
|
+
# @return [Query]
|
505
|
+
# @see http://www.w3.org/TR/sparql11-query/#optionals
|
506
|
+
def minus(*patterns, &block)
|
507
|
+
options[:minuses] ||= []
|
508
|
+
|
509
|
+
if block_given?
|
510
|
+
raise ArgumentError, "#minus requires either arguments or a block, not both." unless patterns.empty?
|
511
|
+
# Evaluate calls in a new query instance
|
512
|
+
query = self.class.select
|
513
|
+
case block.arity
|
514
|
+
when 1 then block.call(query)
|
515
|
+
else query.instance_eval(&block)
|
516
|
+
end
|
517
|
+
options[:minuses] << query
|
518
|
+
elsif patterns.all? {|p| p.is_a?(SPARQL::Client::Query)}
|
519
|
+
# With argument form, all must be patterns or queries
|
520
|
+
options[:minuses] += patterns
|
521
|
+
elsif patterns.all? {|p| p.is_a?(Array)}
|
522
|
+
# With argument form, all must be patterns, or queries
|
523
|
+
options[:minuses] << self.class.select.where(*patterns)
|
524
|
+
else
|
525
|
+
raise ArgumentError, "#minus arguments are triple patters or queries, not both."
|
526
|
+
end
|
527
|
+
|
345
528
|
self
|
346
529
|
end
|
347
530
|
|
@@ -352,15 +535,17 @@ module SPARQL; class Client
|
|
352
535
|
end
|
353
536
|
|
354
537
|
##
|
355
|
-
# @private
|
538
|
+
# @private
|
356
539
|
def build_patterns(patterns)
|
357
540
|
patterns.map {|pattern| RDF::Query::Pattern.from(pattern)}
|
358
541
|
end
|
359
542
|
|
360
543
|
##
|
361
|
-
# @
|
544
|
+
# @example ASK WHERE { ?s ?p ?o . FILTER(regex(?s, 'Abiline, Texas')) }
|
545
|
+
# query.ask.where([:s, :p, :o]).filter("regex(?s, 'Abiline, Texas')")
|
546
|
+
# @return [Query]
|
362
547
|
def filter(string)
|
363
|
-
((options[:filters] ||= []) << string) if string and not string.empty?
|
548
|
+
((options[:filters] ||= []) << Filter.new(string)) if string and not string.empty?
|
364
549
|
self
|
365
550
|
end
|
366
551
|
|
@@ -445,33 +630,11 @@ module SPARQL; class Client
|
|
445
630
|
buffer << "FROM #{SPARQL::Client.serialize_value(options[:from])}" if options[:from]
|
446
631
|
|
447
632
|
unless patterns.empty? && form == :describe
|
448
|
-
buffer
|
449
|
-
|
450
|
-
if options[:graph]
|
451
|
-
buffer << 'GRAPH ' + SPARQL::Client.serialize_value(options[:graph])
|
452
|
-
buffer << '{'
|
453
|
-
end
|
454
|
-
|
455
|
-
@subqueries.each do |sq|
|
456
|
-
buffer << "{ #{sq.to_s} } ."
|
457
|
-
end
|
458
|
-
|
459
|
-
buffer += SPARQL::Client.serialize_patterns(patterns)
|
460
|
-
if options[:optionals]
|
461
|
-
options[:optionals].each do |patterns|
|
462
|
-
buffer << 'OPTIONAL {'
|
463
|
-
buffer += SPARQL::Client.serialize_patterns(patterns)
|
464
|
-
buffer << '}'
|
465
|
-
end
|
466
|
-
end
|
467
|
-
if options[:filters]
|
468
|
-
buffer += options[:filters].map { |filter| "FILTER(#{filter})" }
|
469
|
-
end
|
470
|
-
if options[:graph]
|
471
|
-
buffer << '}' # GRAPH
|
472
|
-
end
|
633
|
+
buffer += self.to_s_ggp.unshift('WHERE')
|
634
|
+
end
|
473
635
|
|
474
|
-
|
636
|
+
options.fetch(:unions, []).each do |query|
|
637
|
+
buffer += query.to_s_ggp.unshift('UNION')
|
475
638
|
end
|
476
639
|
|
477
640
|
if options[:group_by]
|
@@ -524,6 +687,43 @@ module SPARQL; class Client
|
|
524
687
|
buffer.join(' ')
|
525
688
|
end
|
526
689
|
|
690
|
+
# Serialize a Group Graph Pattern
|
691
|
+
# @private
|
692
|
+
def to_s_ggp
|
693
|
+
buffer = ["{"]
|
694
|
+
|
695
|
+
if options[:graph]
|
696
|
+
buffer << 'GRAPH ' + SPARQL::Client.serialize_value(options[:graph])
|
697
|
+
buffer << '{'
|
698
|
+
end
|
699
|
+
|
700
|
+
@subqueries.each do |sq|
|
701
|
+
buffer << "{ #{sq.to_s} } ."
|
702
|
+
end
|
703
|
+
|
704
|
+
buffer += SPARQL::Client.serialize_patterns(patterns)
|
705
|
+
if options[:optionals]
|
706
|
+
options[:optionals].each do |patterns|
|
707
|
+
buffer << 'OPTIONAL {'
|
708
|
+
buffer += SPARQL::Client.serialize_patterns(patterns)
|
709
|
+
buffer << '}'
|
710
|
+
end
|
711
|
+
end
|
712
|
+
if options[:filters]
|
713
|
+
buffer += options[:filters].map(&:to_s)
|
714
|
+
end
|
715
|
+
if options[:graph]
|
716
|
+
buffer << '}' # GRAPH
|
717
|
+
end
|
718
|
+
|
719
|
+
options.fetch(:minuses, []).each do |query|
|
720
|
+
buffer += query.to_s_ggp.unshift('MINUS')
|
721
|
+
end
|
722
|
+
|
723
|
+
buffer << '}'
|
724
|
+
buffer
|
725
|
+
end
|
726
|
+
|
527
727
|
##
|
528
728
|
# Outputs a developer-friendly representation of this query to `stderr`.
|
529
729
|
#
|
@@ -540,5 +740,16 @@ module SPARQL; class Client
|
|
540
740
|
def inspect
|
541
741
|
sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, to_s)
|
542
742
|
end
|
743
|
+
|
744
|
+
# Allow Filters to be
|
745
|
+
class Filter < SPARQL::Client::QueryElement
|
746
|
+
def initialize(*args)
|
747
|
+
super
|
748
|
+
end
|
749
|
+
|
750
|
+
def to_s
|
751
|
+
"FILTER(#{elements.join(' ')})"
|
752
|
+
end
|
753
|
+
end
|
543
754
|
end
|
544
755
|
end; end
|
@@ -38,6 +38,30 @@ module SPARQL; class Client
|
|
38
38
|
client.construct([:s, :p, :o]).where([:s, :p, :o]).each_statement(&block)
|
39
39
|
end
|
40
40
|
|
41
|
+
##
|
42
|
+
# Iterates the given block for each RDF statement.
|
43
|
+
#
|
44
|
+
# If no block was given, returns an enumerator.
|
45
|
+
#
|
46
|
+
# The order in which statements are yielded is undefined.
|
47
|
+
#
|
48
|
+
# @overload each_statement
|
49
|
+
# @yield [statement]
|
50
|
+
# each statement
|
51
|
+
# @yieldparam [RDF::Statement] statement
|
52
|
+
# @yieldreturn [void] ignored
|
53
|
+
# @return [void]
|
54
|
+
#
|
55
|
+
# @overload each_statement
|
56
|
+
# @return [Enumerator<RDF::Statement>]
|
57
|
+
def each_statement(&block)
|
58
|
+
if block_given?
|
59
|
+
# Invoke {#each} in the containing class:
|
60
|
+
each(&block)
|
61
|
+
end
|
62
|
+
enum_statement
|
63
|
+
end
|
64
|
+
|
41
65
|
##
|
42
66
|
# @private
|
43
67
|
# @see RDF::Enumerable#supports?
|
@@ -48,6 +72,7 @@ module SPARQL; class Client
|
|
48
72
|
when :graph_name then false
|
49
73
|
when :inference then false # forward-chaining inference
|
50
74
|
when :validity then false
|
75
|
+
when :literal_equality then true
|
51
76
|
else false
|
52
77
|
end
|
53
78
|
end
|
@@ -151,7 +176,7 @@ module SPARQL; class Client
|
|
151
176
|
# @see RDF::Repository#count?
|
152
177
|
def count
|
153
178
|
begin
|
154
|
-
binding = client.query("SELECT (COUNT(*) AS ?count) WHERE { ?s ?p ?o }").first.
|
179
|
+
binding = client.query("SELECT (COUNT(*) AS ?count) WHERE { ?s ?p ?o }").first.to_h
|
155
180
|
binding[:count].value.to_i rescue 0
|
156
181
|
rescue SPARQL::Client::MalformedQuery => e
|
157
182
|
# SPARQL 1.0 does not include support for aggregate functions:
|
data/lib/sparql/client/update.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sparql-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1
|
4
|
+
version: 2.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arto Bendiken
|
@@ -10,78 +10,102 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2017-12-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rdf
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- - "
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.2'
|
22
|
+
- - "<"
|
20
23
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
24
|
+
version: '4.0'
|
22
25
|
type: :runtime
|
23
26
|
prerelease: false
|
24
27
|
version_requirements: !ruby/object:Gem::Requirement
|
25
28
|
requirements:
|
26
|
-
- - "
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '2.2'
|
32
|
+
- - "<"
|
27
33
|
- !ruby/object:Gem::Version
|
28
|
-
version: '
|
34
|
+
version: '4.0'
|
29
35
|
- !ruby/object:Gem::Dependency
|
30
36
|
name: net-http-persistent
|
31
37
|
requirement: !ruby/object:Gem::Requirement
|
32
38
|
requirements:
|
33
|
-
- - "
|
39
|
+
- - ">="
|
34
40
|
- !ruby/object:Gem::Version
|
35
41
|
version: '2.9'
|
42
|
+
- - "<"
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '4'
|
36
45
|
type: :runtime
|
37
46
|
prerelease: false
|
38
47
|
version_requirements: !ruby/object:Gem::Requirement
|
39
48
|
requirements:
|
40
|
-
- - "
|
49
|
+
- - ">="
|
41
50
|
- !ruby/object:Gem::Version
|
42
51
|
version: '2.9'
|
52
|
+
- - "<"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4'
|
43
55
|
- !ruby/object:Gem::Dependency
|
44
56
|
name: sparql
|
45
57
|
requirement: !ruby/object:Gem::Requirement
|
46
58
|
requirements:
|
47
|
-
- - "
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.2'
|
62
|
+
- - "<"
|
48
63
|
- !ruby/object:Gem::Version
|
49
|
-
version: '
|
64
|
+
version: '4.0'
|
50
65
|
type: :development
|
51
66
|
prerelease: false
|
52
67
|
version_requirements: !ruby/object:Gem::Requirement
|
53
68
|
requirements:
|
54
|
-
- - "
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '2.2'
|
72
|
+
- - "<"
|
55
73
|
- !ruby/object:Gem::Version
|
56
|
-
version: '
|
74
|
+
version: '4.0'
|
57
75
|
- !ruby/object:Gem::Dependency
|
58
76
|
name: rdf-spec
|
59
77
|
requirement: !ruby/object:Gem::Requirement
|
60
78
|
requirements:
|
61
|
-
- - "
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.2'
|
82
|
+
- - "<"
|
62
83
|
- !ruby/object:Gem::Version
|
63
|
-
version: '
|
84
|
+
version: '4.0'
|
64
85
|
type: :development
|
65
86
|
prerelease: false
|
66
87
|
version_requirements: !ruby/object:Gem::Requirement
|
67
88
|
requirements:
|
68
|
-
- - "
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '2.2'
|
92
|
+
- - "<"
|
69
93
|
- !ruby/object:Gem::Version
|
70
|
-
version: '
|
94
|
+
version: '4.0'
|
71
95
|
- !ruby/object:Gem::Dependency
|
72
96
|
name: rspec
|
73
97
|
requirement: !ruby/object:Gem::Requirement
|
74
98
|
requirements:
|
75
99
|
- - "~>"
|
76
100
|
- !ruby/object:Gem::Version
|
77
|
-
version: '3.
|
101
|
+
version: '3.7'
|
78
102
|
type: :development
|
79
103
|
prerelease: false
|
80
104
|
version_requirements: !ruby/object:Gem::Requirement
|
81
105
|
requirements:
|
82
106
|
- - "~>"
|
83
107
|
- !ruby/object:Gem::Version
|
84
|
-
version: '3.
|
108
|
+
version: '3.7'
|
85
109
|
- !ruby/object:Gem::Dependency
|
86
110
|
name: rspec-its
|
87
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,28 +126,28 @@ dependencies:
|
|
102
126
|
requirements:
|
103
127
|
- - "~>"
|
104
128
|
- !ruby/object:Gem::Version
|
105
|
-
version: '
|
129
|
+
version: '3.0'
|
106
130
|
type: :development
|
107
131
|
prerelease: false
|
108
132
|
version_requirements: !ruby/object:Gem::Requirement
|
109
133
|
requirements:
|
110
134
|
- - "~>"
|
111
135
|
- !ruby/object:Gem::Version
|
112
|
-
version: '
|
136
|
+
version: '3.0'
|
113
137
|
- !ruby/object:Gem::Dependency
|
114
138
|
name: yard
|
115
139
|
requirement: !ruby/object:Gem::Requirement
|
116
140
|
requirements:
|
117
141
|
- - "~>"
|
118
142
|
- !ruby/object:Gem::Version
|
119
|
-
version: '0.
|
143
|
+
version: '0.9'
|
120
144
|
type: :development
|
121
145
|
prerelease: false
|
122
146
|
version_requirements: !ruby/object:Gem::Requirement
|
123
147
|
requirements:
|
124
148
|
- - "~>"
|
125
149
|
- !ruby/object:Gem::Version
|
126
|
-
version: '0.
|
150
|
+
version: '0.9'
|
127
151
|
description: |-
|
128
152
|
Executes SPARQL queries and updates against a remote SPARQL 1.0 or 1.1 endpoint,
|
129
153
|
or against a local repository. Generates SPARQL queries using a simple DSL.
|
@@ -163,8 +187,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
187
|
- !ruby/object:Gem::Version
|
164
188
|
version: '0'
|
165
189
|
requirements: []
|
166
|
-
rubyforge_project:
|
167
|
-
rubygems_version: 2.
|
190
|
+
rubyforge_project:
|
191
|
+
rubygems_version: 2.6.14
|
168
192
|
signing_key:
|
169
193
|
specification_version: 4
|
170
194
|
summary: SPARQL client for RDF.rb.
|