Skip to content

Commit f15dec5

Browse files
committed
Allow VALUES to be specified using Query#values.
1 parent eb5f8c4 commit f15dec5

File tree

7 files changed

+111
-34
lines changed

7 files changed

+111
-34
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ bundler_args: --without debug
33
script: "bundle exec rspec spec"
44
env:
55
- CI=true
6+
gemfile:
7+
- Gemfile
8+
- Gemfile-pure
69
rvm:
710
- 2.2
811
- 2.3

Gemfile

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ source "https://rubygems.org"
22

33
gemspec
44

5-
gem 'rdf', github: "ruby-rdf/rdf", branch: "develop"
6-
gem 'rdf-aggregate-repo', github: "ruby-rdf/rdf-aggregate-repo", branch: "develop"
7-
gem 'sparql', github: "ruby-rdf/sparql", branch: "develop"
5+
gem 'rdf', git: "https://github.com/ruby-rdf/rdf", branch: "develop"
6+
gem 'rdf-aggregate-repo', git: "https://github.com/ruby-rdf/rdf-aggregate-repo", branch: "develop"
7+
gem 'sparql', git: "https://github.com/ruby-rdf/sparql", branch: "develop"
88
gem "jruby-openssl", platforms: :jruby
9-
gem "nokogiri", '~> 1.6'
9+
gem "nokogiri", '~> 1.8'
1010

1111
group :development, :test do
12-
gem 'ebnf', github: "gkellogg/ebnf", branch: "develop"
13-
gem 'rdf-isomorphic', github: "ruby-rdf/rdf-isomorphic", branch: "develop"
14-
gem 'rdf-spec', github: "ruby-rdf/rdf-spec", branch: "develop"
15-
gem 'rdf-turtle', github: "ruby-rdf/rdf-turtle", branch: "develop"
16-
gem "rdf-xsd", github: "ruby-rdf/rdf-xsd", branch: "develop"
17-
gem 'sxp', github: "dryruby/sxp.rb", branch: "develop"
12+
gem 'ebnf', git: "https://github.com/gkellogg/ebnf", branch: "develop"
13+
gem 'rdf-isomorphic', git: "https://github.com/ruby-rdf/rdf-isomorphic", branch: "develop"
14+
gem 'rdf-spec', git: "https://github.com/ruby-rdf/rdf-spec", branch: "develop"
15+
gem 'rdf-turtle', git: "https://github.com/ruby-rdf/rdf-turtle", branch: "develop"
16+
gem "rdf-xsd", git: "https://github.com/ruby-rdf/rdf-xsd", branch: "develop"
17+
gem 'sxp', git: "https://github.com/dryruby/sxp.rb", branch: "develop"
1818
gem "redcarpet", platform: :ruby
1919
gem 'simplecov', require: false, platform: :mri
2020
gem 'coveralls', require: false, platform: :mri

Gemfile-pure

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ source "https://rubygems.org"
22

33
gemspec
44

5-
gem 'rdf', github: "ruby-rdf/rdf", branch: "develop"
6-
gem 'rdf-aggregate-repo', github: "ruby-rdf/rdf-aggregate-repo", branch: "develop"
7-
gem 'sparql', github: "ruby-rdf/sparql", branch: "develop"
5+
gem 'rdf', git: "https://github.com/ruby-rdf/rdf", branch: "develop"
6+
gem 'rdf-aggregate-repo', git: "https://github.com/ruby-rdf/rdf-aggregate-repo", branch: "develop"
7+
gem 'sparql', git: "https://github.com/ruby-rdf/sparql", branch: "develop"
88
gem "jruby-openssl", platforms: :jruby
9-
#gem "nokogiri", '~> 1.6'
9+
#gem "nokogiri", '~> 1.8'
1010

1111
group :development, :test do
12-
gem 'ebnf', github: "gkellogg/ebnf", branch: "develop"
13-
gem 'rdf-isomorphic', github: "ruby-rdf/rdf-isomorphic", branch: "develop"
14-
gem 'rdf-spec', github: "ruby-rdf/rdf-spec", branch: "develop"
15-
gem 'rdf-turtle', github: "ruby-rdf/rdf-turtle", branch: "develop"
16-
gem "rdf-xsd", github: "ruby-rdf/rdf-xsd", branch: "develop"
17-
gem 'sxp', github: "dryruby/sxp.rb", branch: "develop"
12+
gem 'ebnf', git: "https://github.com/gkellogg/ebnf", branch: "develop"
13+
gem 'rdf-isomorphic', git: "https://github.com/ruby-rdf/rdf-isomorphic", branch: "develop"
14+
gem 'rdf-spec', git: "https://github.com/ruby-rdf/rdf-spec", branch: "develop"
15+
gem 'rdf-turtle', git: "https://github.com/ruby-rdf/rdf-turtle", branch: "develop"
16+
gem "rdf-xsd", git: "https://github.com/ruby-rdf/rdf-xsd", branch: "develop"
17+
gem 'sxp', git: "https://github.com/dryruby/sxp.rb", branch: "develop"
1818
gem "redcarpet", platform: :ruby
1919
gem 'simplecov', require: false, platform: :mri
2020
gem 'coveralls', require: false, platform: :mri

lib/sparql/client/query.rb

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@ class Query < RDF::Query
1717
# @return [Hash{Symbol => Object}]
1818
attr_reader :options
1919

20-
##
21-
# Values returned from previous query.
22-
#
23-
# @return [Array<[key, RDF::Value]>]
24-
attr_reader :values
25-
2620
##
2721
# Creates a boolean `ASK` query.
2822
#
@@ -528,6 +522,71 @@ def minus(*patterns, &block)
528522
self
529523
end
530524

525+
##
526+
# Specify inline data for a query
527+
#
528+
# @overload values
529+
# Values returned from previous query.
530+
#
531+
# @return [Array<Array(key, RDF::Value)>]
532+
#
533+
# @overload values(vars, *data)
534+
# @example single variable with multiple values
535+
# query.select
536+
# .where([:s, RDF::URI('http://purl.org/dc/terms/title'), :title])
537+
# .values(:title, "This title", "Another title")
538+
#
539+
# @example multiple variables with multiple values
540+
# query.select
541+
# .where([:s, RDF::URI('http://purl.org/dc/terms/title'), :title],
542+
# [:s, RDF.type, :type])
543+
# .values([:type, :title],
544+
# [RDF::URI('http://pcdm.org/models#Object'), "This title"],
545+
# [RDF::URI('http://pcdm.org/models#Collection', 'Another title'])
546+
#
547+
# @example multiple variables with UNDEF
548+
# query.select
549+
# .where([:s, RDF::URI('http://purl.org/dc/terms/title'), :title],
550+
# [:s, RDF.type, :type])
551+
# .values([:type, :title],
552+
# [nil "This title"],
553+
# [RDF::URI('http://pcdm.org/models#Collection', nil])
554+
#
555+
# @param [Symbol, Array<Symbol>] vars
556+
# @param [Array<RDF::Term, String, nil>] *data
557+
# @return [Query]
558+
def values(*args)
559+
return @values if args.empty?
560+
vars, *data = *args
561+
vars = Array(vars).map {|var| RDF::Query::Variable.new(var)}
562+
if vars.length == 1
563+
# data may be a in array form or simple form
564+
if data.any? {|d| d.is_a?(Array)} && !data.all? {|d| d.is_a?(Array)}
565+
raise ArgumentError, "values data must all be in array form or all simple"
566+
end
567+
data = data.map {|d| Array(d)}
568+
end
569+
570+
# Each data value must be an array with the same number of entries as vars
571+
unless data.all? {|d| d.is_a?(Array) && d.all? {|dd| dd.is_a?(RDF::Value) || dd.is_a?(String) || dd.nil?}}
572+
raise ArgumentError, "values data must each be an array of terms, strings, or nil"
573+
end
574+
575+
# Turn strings into Literals
576+
data = data.map do |d|
577+
d.map do |nil_literal_or_term|
578+
case nil_literal_or_term
579+
when nil then nil
580+
when String then RDF::Literal(nil_literal_or_term)
581+
when RDF::Value then graph_uri_or_var
582+
else raise ArgumentError
583+
end
584+
end
585+
end
586+
options[:values] = [vars, *data]
587+
self
588+
end
589+
531590
##
532591
# @return expects_statements?
533592
def expects_statements?
@@ -712,6 +771,18 @@ def to_s_ggp
712771
if options[:filters]
713772
buffer += options[:filters].map(&:to_s)
714773
end
774+
if options[:values]
775+
vars = options[:values].first.map {|var| SPARQL::Client.serialize_value(var)}
776+
buffer << "VALUES (#{vars.join(' ')}) {"
777+
options[:values][1..-1].each do |data_block_value|
778+
buffer << '('
779+
buffer << data_block_value.map do |value|
780+
value.nil? ? 'UNDEF' : SPARQL::Client.serialize_value(value)
781+
end.join(' ')
782+
buffer << ')'
783+
end
784+
buffer << '}'
785+
end
715786
if options[:graph]
716787
buffer << '}' # GRAPH
717788
end

lib/sparql/client/repository.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ class Repository < RDF::Repository
1010
##
1111
# @param [URI, #to_s] uri
1212
# Endpoint of this repository
13-
# @param [String, #to_s] title (nil)
1413
# @param [Hash{Symbol => Object}] options passed to RDF::Repository
1514
def initialize(uri: nil, **options, &block)
1615
raise ArgumentError, "uri is a required parameter" unless uri

sparql-client.gemspec

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,14 @@ Gem::Specification.new do |gem|
2929

3030
gem.required_ruby_version = '>= 2.2.2'
3131
gem.requirements = []
32-
#gem.add_runtime_dependency 'rdf', '~> 3.0'
33-
gem.add_runtime_dependency 'rdf', '>= 2.2', '< 4.0'
32+
gem.add_runtime_dependency 'rdf', '~> 3.0'
3433
gem.add_runtime_dependency 'net-http-persistent', '>= 2.9', '< 4'
34+
gem.add_development_dependency 'rdf-spec', '~> 3.0'
3535
#gem.add_development_dependency 'sparql', '~> 3.0'
36-
#gem.add_development_dependency 'rdf-spec', '~> 3.0'
3736
gem.add_development_dependency 'sparql', '>= 2.2', '< 4.0'
38-
gem.add_development_dependency 'rdf-spec', '>= 2.2', '< 4.0'
3937
gem.add_development_dependency 'rspec', '~> 3.7'
4038
gem.add_development_dependency 'rspec-its', '~> 1.2'
41-
gem.add_development_dependency 'webmock', '~> 3.0'
39+
gem.add_development_dependency 'webmock', '~> 3.1'
4240
gem.add_development_dependency 'yard' , '~> 0.9.12'
4341

4442
# Rubinius has it's own dependencies

spec/query_spec.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@
123123
expect(subject.select(:o, :count => { :s => :c }).where([:s, :p, :o]).to_s).to eq "SELECT ?o ( COUNT(?s) AS ?c ) WHERE { ?s ?p ?o . }"
124124
end
125125

126+
it "should support VALUES" do
127+
expect(subject.select(:s).where([:s, :p, :o]).values(:o, "Object").to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o) { ( "Object" ) } }'
128+
expect(subject.select(:s).where([:s, :p, :o]).values(:o, "1", "2").to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o) { ( "1" ) ( "2" ) } }'
129+
expect(subject.select(:s).where([:s, :p, :o]).values([:o, :p], ["Object", "Predicate"]).to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o ?p) { ( "Object" "Predicate" ) } }'
130+
expect(subject.select(:s).where([:s, :p, :o]).values([:o, :p], ["1", "2"], ["3", "4"]).to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o ?p) { ( "1" "2" ) ( "3" "4" ) } }'
131+
expect(subject.select(:s).where([:s, :p, :o]).values([:o, :p], [nil, "2"], ["3", nil]).to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o ?p) { ( UNDEF "2" ) ( "3" UNDEF ) } }'
132+
end
133+
126134
it "should support GROUP BY" do
127135
expect(subject.select(:s).where([:s, :p, :o]).group_by(:s).to_s).to eq "SELECT ?s WHERE { ?s ?p ?o . } GROUP BY ?s"
128136
expect(subject.select(:s).where([:s, :p, :o]).group_by('?s').to_s).to eq "SELECT ?s WHERE { ?s ?p ?o . } GROUP BY ?s"
@@ -239,7 +247,6 @@
239247
end
240248

241249
it "should support block" do
242-
subquery = subject.select.where([:s, :p, :o])
243250
expect(subject.select.where([:s, :p, :o]).union {|q| q.where([:s, :p, :o])}.to_s).to eq "SELECT * WHERE { ?s ?p ?o . } UNION { ?s ?p ?o . }"
244251
end
245252

@@ -264,7 +271,6 @@
264271
end
265272

266273
it "should support block" do
267-
subquery = subject.select.where([:s, :p, :o])
268274
expect(subject.select.where([:s, :p, :o]).minus {|q| q.where([:s, :p, :o])}.to_s).to eq "SELECT * WHERE { ?s ?p ?o . MINUS { ?s ?p ?o . } }"
269275
end
270276

0 commit comments

Comments
 (0)