diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00b888b8..9b51df46 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - ruby: ['3.0', 3.1, 3.2, ruby-head, jruby] + ruby: ['3.0', 3.1, 3.2, 3.3, ruby-head, jruby] steps: - name: Clone repository uses: actions/checkout@v3 @@ -33,6 +33,6 @@ jobs: run: ruby --version; bundle exec rspec spec || $ALLOW_FAILURES - name: Coveralls GitHub Action uses: coverallsapp/github-action@v2 - if: "matrix.ruby == '3.2'" + if: "matrix.ruby == '3.3'" with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index e5ae4491..e50c882c 100755 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ An implementation of [SPARQL][] for [RDF.rb][]. * Helper method for describing [SPARQL Service Description][SSD] * Helper method for setting up datasets as part of the [SPARQL 1.1 Protocol][]. * Implementation Report: {file:etc/earl.html EARL} -* Compatible with Ruby >= 2.6. +* Compatible with Ruby >= 3.0. * Supports Unicode query strings both on all versions of Ruby. * Provisional support for [SPARQL-star][]. @@ -382,6 +382,10 @@ Find more examples in {SPARQL::Grammar} and {SPARQL::Algebra}. Full documentation available on [Rubydoc.info][SPARQL doc] +## Change Log + +See [Release Notes on GitHub](https://github.com/ruby-rdf/sparql/releases) + ### Principle Classes * {SPARQL} @@ -400,7 +404,7 @@ Full documentation available on [Rubydoc.info][SPARQL doc] * [Ruby](https://ruby-lang.org/) (>= 3.0) * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.3) * [SPARQL::Client](https://rubygems.org/gems/sparql-client) (~> 3.3) -* [SXP](https://rubygems.org/gems/sxp) (~> 1.2) +* [SXP](https://rubygems.org/gems/sxp) (~> 2.0) * [Builder](https://rubygems.org/gems/builder) (~> 3.2) * [JSON](https://rubygems.org/gems/json) (~> 2.6) * Soft dependency on [Linked Data][] (>= 3.3) diff --git a/Rakefile b/Rakefile index f4d0db57..6bc34517 100755 --- a/Rakefile +++ b/Rakefile @@ -31,7 +31,7 @@ namespace :spec do desc "Generate test caches" task :prepare do $:.unshift(File.join(File.dirname(__FILE__), 'spec')) - require 'dawg_helper' + require 'suite_helper' puts "load 1.0 tests" SPARQL::Spec.sparql1_0_tests(true) diff --git a/VERSION b/VERSION index 15a27998..bea438e9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.3.0 +3.3.1 diff --git a/lib/sparql/algebra/operator/concat.rb b/lib/sparql/algebra/operator/concat.rb index 89bda074..c66ef6ff 100644 --- a/lib/sparql/algebra/operator/concat.rb +++ b/lib/sparql/algebra/operator/concat.rb @@ -50,6 +50,11 @@ class Concat < Operator def evaluate(bindings, **options) ops = operands.map {|op| op.evaluate(bindings, **options.merge(depth: options[:depth].to_i + 1))} + # rdf:nil is like empty string + if ops == [RDF.nil] + return RDF::Literal.new("") + end + raise TypeError, "expected all plain literal operands" unless ops.all? {|op| op.literal? && op.plain?} ops.inject do |memo, op| diff --git a/lib/sparql/algebra/operator/sequence.rb b/lib/sparql/algebra/operator/sequence.rb index 342b9992..1e099c69 100644 --- a/lib/sparql/algebra/operator/sequence.rb +++ b/lib/sparql/algebra/operator/sequence.rb @@ -28,7 +28,7 @@ class Sequence < Operator # @yieldparam [RDF::Query::Solution] solution # @yieldreturn [void] ignored # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra - def execute(queryable, **options) + def execute(queryable, **options, &block) debug(options) {"Sequence #{operands.to_sse}"} last = queryable.query(operands.shift, **options.merge(depth: options[:depth].to_i + 1)) diff --git a/lib/sparql/grammar/parser11.rb b/lib/sparql/grammar/parser11.rb index 3b0216e7..67f3cfdd 100644 --- a/lib/sparql/grammar/parser11.rb +++ b/lib/sparql/grammar/parser11.rb @@ -974,6 +974,11 @@ class Parser add_prod_data :row, [:row] else Array(data[:rowdata]).each do |ds| + if ds.length < data[:Var].length + raise Error, "Too few values in a VALUE clause compared to the number of variables" + elsif ds.length > data[:Var].length + raise Error, "Too many values in a VALUE clause compared to the number of variables" + end r = [:row] ds.each_with_index do |d, i| r << [vars[i], d] if d @@ -2325,6 +2330,8 @@ def iri(value) def ns(prefix, suffix) base = prefix(prefix).to_s + suffix = suffix.to_s.gsub(PN_LOCAL_ESC) {|esc| esc[1]} if + suffix.to_s.match?(PN_LOCAL_ESC) suffix = suffix.to_s.sub(/^\#/, "") if base.index("#") debug {"ns(#{prefix.inspect}): base: '#{base}', suffix: '#{suffix}'"} iri(base + suffix.to_s) diff --git a/script/tc b/script/tc index 6252ba09..2da9cbff 100755 --- a/script/tc +++ b/script/tc @@ -103,6 +103,9 @@ def run_tc(tc, **options) info = "Graph variable binding differences" when /tvs02/ info = "Empty vs. Unbound" + when 'Negated Property Set with inverse properties', + 'Negated Property Set with both direct and inverse properties' + info = "new SPARQL tests" end info = "Entailment" if tc.entailment? diff --git a/sparql.gemspec b/sparql.gemspec index cb7bb4b8..a6eb98b9 100755 --- a/sparql.gemspec +++ b/sparql.gemspec @@ -31,13 +31,14 @@ Gem::Specification.new do |gem| gem.requirements = [] gem.add_runtime_dependency 'rdf', '~> 3.3' gem.add_runtime_dependency 'rdf-aggregate-repo', '~> 3.3' - gem.add_runtime_dependency 'ebnf', '~> 2.4' + gem.add_runtime_dependency 'ebnf', '~> 2.5' gem.add_runtime_dependency 'builder', '~> 3.2', '>= 3.2.4' gem.add_runtime_dependency 'logger', '~> 1.5' - gem.add_runtime_dependency 'sxp', '~> 1.3' + gem.add_runtime_dependency 'sxp', '~> 2.0' gem.add_runtime_dependency 'sparql-client', '~> 3.3' gem.add_runtime_dependency 'rdf-xsd', '~> 3.3' + gem.add_development_dependency 'getoptlong', '~> 0.2' gem.add_development_dependency 'sinatra', '~> 3.1' gem.add_development_dependency 'rack', '>= 2.2', '< 4' gem.add_development_dependency 'rack-test', '~> 2.1' diff --git a/spec/.gitignore b/spec/.gitignore index 33c210ab..69c4dd04 100644 --- a/spec/.gitignore +++ b/spec/.gitignore @@ -1,2 +1,2 @@ -/w3c-rdf-star -/w3c-rdf-tests +/rdf-star +/rdf-tests diff --git a/spec/suite_helper.rb b/spec/suite_helper.rb index 94128c6f..8fed50c2 100644 --- a/spec/suite_helper.rb +++ b/spec/suite_helper.rb @@ -10,9 +10,9 @@ module RDF::Util module File REMOTE_PATH = "http://w3c.github.io/rdf-tests/sparql/" - LOCAL_PATH = ::File.expand_path("../w3c-rdf-tests/sparql/", __FILE__) + '/' + LOCAL_PATH = ::File.expand_path("../rdf-tests/sparql/", __FILE__) + '/' REMOTE_PATH_STAR = "https://w3c.github.io/rdf-star/" - LOCAL_PATH_STAR = ::File.expand_path("../w3c-rdf-star/", __FILE__) + '/' + LOCAL_PATH_STAR = ::File.expand_path("../rdf-star/", __FILE__) + '/' REMOTE_PATH_12 = "https://w3c.github.io/sparql-12/" LOCAL_PATH_12 = ::File.expand_path("../w3c-sparql-12/", __FILE__) + '/' REMOTE_PATH_PROTO = "http://kasei.us/2009/09/sparql/data/" @@ -164,6 +164,8 @@ def self.open_file(filename_or_url, **options, &block) else remote_document end + when (filename_or_url.to_s =~ %r{^somescheme}) + raise IOError, "No URL #{filename_or_url}" else original_open_file(filename_or_url, **options, &block) end diff --git a/spec/suite_spec.rb b/spec/suite_spec.rb index c908e106..cb790ed1 100644 --- a/spec/suite_spec.rb +++ b/spec/suite_spec.rb @@ -32,6 +32,8 @@ pending "empty values are the same as missing values" when 'construct_date-02.rq', 'construct_time-01.rq' pending "failed when simplifying whitespace in terminals" + when 'nps_inverse.rq', 'nps_direct_and_inverse.rq' + pending("New SPARQL tests") end skip 'Entailment Regimes' if t.entailment? @@ -185,6 +187,10 @@ when 'compare_time-01.rq', 'adjust_dateTime-01.rq', 'adjust_date-01.rq', 'adjust_time-01.rq' skip "Equivalent form" + when 'nps_inverse.rq', 'nps_direct_and_inverse.rq' + pending("New SPARQL tests") + when 'values04.rq', 'values05.rq', 'values08.rq' + skip("Invalid VALUES Syntax") end t.logger = RDF::Spec.logger t.logger.debug "Source:\n#{t.action.query_string}"