Giter VIP home page Giter VIP logo

sparql's People

Contributors

abrisse avatar artob avatar gkellogg avatar michivi avatar msporny avatar pius avatar seaki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sparql's Issues

SELECT * does not project all in-scope variables

According to https://www.w3.org/TR/sparql11-query/#selectproject, SELECT * selects all of the variables that are in-scope at that point in the query. It excludes variables only used in FILTER, in the right-hand side of MINUS, and takes account of subqueries.

For example:

PREFIX :    <http://example/>

SELECT *
{ 
    :x1 :p ?v .
    OPTIONAL
    {
      :x3 :q ?w .
      OPTIONAL { :x2 :p ?v }
    }
}

has two variables in-scope: ?v and ?w. But if the query result does not bind to ?w, it is omitted from the variable list in the solution. This is because the result set is created from the actual results, which do not include ?w in this case.

To properly solve this, Algebra::Operator should implement an #in_scope_vars method that uses the described logic to find all variables and create a projection.

Random errors when parsing

I'm trying to create a Logstash filter that parses SPARQL queries.

So I'm using sparql v2.2.2 to parse those queries.

I'm testing 3 queries using rspec tests that correctly pass.

Nevertheless, when running Logstash with this filter, I have some random error when parsing (parsed_query = SPARQL::Grammar.parse(sparql_query, {:resolve_iris => TRUE}).

For example, for this one:

SELECT ?subject ?p0 ?p1 ?p2 WHERE {{?subject <http://purl.org/dc/terms/title> ?p0 . VALUES (?subject) { (<http://identifiers.org/ncbigene/6093>) }}UNION{?subject <http://www.w3.org/2000/01/rdf-schema#label> ?p1 . VALUES (?subject) { (<http://identifiers.org/ncbigene/6093>) }}UNION{?subject <http://www.w3.org/2004/02/skos/core#prefLabel> ?p2 . VALUES (?subject) { (<http://identifiers.org/ncbigene/6093>) }}} 

I can have this error

'#<NoMethodError: undefined method `first' for nil:NilClass>' at ["/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:589:in `block in Parser'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:600:in `block in onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `block in eval_with_binding'", "org/jruby/RubyBasicObject.java:1691:in `instance_eval'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `eval_with_binding'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:599:in `onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:402:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:1525:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar.rb:179:in `parse'", "/usr/share/logstash/vendor/local_gems/65c66494/logstash-filter-sparql-0.1.0/lib/logstash/filters/sparql.rb:44:in `filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:145:in `do_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:164:in `block in multi_filter'", "org/jruby/RubyArray.java:1734:in `each'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:161:in `multi_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filter_delegator.rb:48:in `multi_filter'", "(eval):46:in `block in filter_func'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:455:in `filter_batch'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:434:in `worker_loop'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:393:in `block in start_workers'"]

or this one

'#<NoMethodError: undefined method `+' for nil:NilClass>' at ["/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:455:in `add_prod_data'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:125:in `method_missing'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:725:in `block in Parser'", "org/jruby/RubyArray.java:1734:in `each'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:720:in `block in Parser'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:600:in `block in onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `block in eval_with_binding'", "org/jruby/RubyBasicObject.java:1691:in `instance_eval'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `eval_with_binding'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:599:in `onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:402:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:1525:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar.rb:179:in `parse'", "/usr/share/logstash/vendor/local_gems/65c66494/logstash-filter-sparql-0.1.0/lib/logstash/filters/sparql.rb:44:in `filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:145:in `do_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:164:in `block in multi_filter'", "org/jruby/RubyArray.java:1734:in `each'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:161:in `multi_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filter_delegator.rb:48:in `multi_filter'", "(eval):46:in `block in filter_func'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:455:in `filter_batch'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:434:in `worker_loop'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:393:in `block in start_workers'"]

For this query:

PREFIX : <http://rdf.example.com/>
SELECT ?type WHERE { <http://www.metaphacts.com/resource/admin/Templates> a ?type }

I can have the error

'#<TypeError: invalid SPARQL::Algebra::Expression operand: nil>' at ["/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/algebra/expression.rb:118:in `block in new'", "org/jruby/RubyArray.java:2486:in `map'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/algebra/expression.rb:109:in `new'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/algebra/expression.rb:76:in `for'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/algebra.rb:406:in `Expression'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:944:in `block in Parser'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:600:in `block in onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `block in eval_with_binding'", "org/jruby/RubyBasicObject.java:1691:in `instance_eval'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `eval_with_binding'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:599:in `onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:402:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:1525:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar.rb:179:in `parse'", "/usr/share/logstash/vendor/local_gems/65c66494/logstash-filter-sparql-0.1.0/lib/logstash/filters/sparql.rb:44:in `filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:145:in `do_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:164:in `block in multi_filter'", "org/jruby/RubyArray.java:1734:in `each'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:161:in `multi_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filter_delegator.rb:48:in `multi_filter'", "(eval):46:in `block in filter_func'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:455:in `filter_batch'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:434:in `worker_loop'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:393:in `block in start_workers'"]

or

'#<NoMethodError: undefined method `first' for nil:NilClass>' at ["/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:589:in `block in Parser'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:600:in `block in onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `block in eval_with_binding'", "org/jruby/RubyBasicObject.java:1691:in `instance_eval'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `eval_with_binding'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:599:in `onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:402:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:1525:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar.rb:179:in `parse'", "/usr/share/logstash/vendor/local_gems/65c66494/logstash-filter-sparql-0.1.0/lib/logstash/filters/sparql.rb:44:in `filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:145:in `do_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:164:in `block in multi_filter'", "org/jruby/RubyArray.java:1734:in `each'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:161:in `multi_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filter_delegator.rb:48:in `multi_filter'", "(eval):46:in `block in filter_func'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:455:in `filter_batch'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:434:in `worker_loop'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:393:in `block in start_workers'"]

At last, for this one

PREFIX : <http://rdf.example.com/>
SELECT ?isoform ?isoformLabel ?length ?weight ?isoelectricPoint ?canonicalIsoform WHERE {
  <http://identifiers.org/ncbigene/207> <http://rdf.example.com/biomart/encodesProtein> ?uniprot.
  ?entry <http://www.w3.org/2004/02/skos/core#exactMatch> ?uniprot.
  GRAPH ?graph {
    ?entry <http://nextprot.org/rdf#isoform> ?isoform.
    ?isoform <http://nextprot.org/rdf#sequence> ?sequence.
    ?isoform <http://nextprot.org/rdf#canonicalIsoform> ?canonicalIsoform.
    BIND(STRAFTER(STR(?isoform), "http://nextprot.org/rdf/isoform/") AS ?isoformLabel)
    ?sequence <http://nextprot.org/rdf#length> ?length.
    ?sequence <http://nextprot.org/rdf#molecularWeight> ?weight.
    ?sequence <http://nextprot.org/rdf#isoelectricPoint> ?isoelectricPoint.
  }
  FILTER(?graph = <http://rdf.example.com/nextprot>)
}

I can have this error

'#<NoMethodError: undefined method `<<' for nil:NilClass>' at ["/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:446:in `add_prod_datum'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:125:in `method_missing'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:146:in `block in Parser'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:636:in `block in onTerminal'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `block in eval_with_binding'", "org/jruby/RubyBasicObject.java:1691:in `instance_eval'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `eval_with_binding'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:635:in `onTerminal'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:309:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:1525:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar.rb:179:in `parse'", "/usr/share/logstash/vendor/local_gems/65c66494/logstash-filter-sparql-0.1.0/lib/logstash/filters/sparql.rb:44:in `filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:145:in `do_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:164:in `block in multi_filter'", "org/jruby/RubyArray.java:1734:in `each'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:161:in `multi_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filter_delegator.rb:48:in `multi_filter'", "(eval):46:in `block in filter_func'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:455:in `filter_batch'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:434:in `worker_loop'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:393:in `block in start_workers'"]

or this one

'#<NoMethodError: undefined method `first' for nil:NilClass>' at ["/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:622:in `block in Parser'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:600:in `block in onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `block in eval_with_binding'", "org/jruby/RubyBasicObject.java:1691:in `instance_eval'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:118:in `eval_with_binding'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:599:in `onFinish'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/ebnf-1.1.2/lib/ebnf/ll1/parser.rb:402:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:1525:in `parse'", "/usr/share/logstash/vendor/bundle/jruby/2.3.0/gems/sparql-2.2.2/lib/sparql/grammar.rb:179:in `parse'", "/usr/share/logstash/vendor/local_gems/65c66494/logstash-filter-sparql-0.1.0/lib/logstash/filters/sparql.rb:44:in `filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:145:in `do_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:164:in `block in multi_filter'", "org/jruby/RubyArray.java:1734:in `each'", "/usr/share/logstash/logstash-core/lib/logstash/filters/base.rb:161:in `multi_filter'", "/usr/share/logstash/logstash-core/lib/logstash/filter_delegator.rb:48:in `multi_filter'", "(eval):46:in `block in filter_func'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:455:in `filter_batch'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:434:in `worker_loop'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:393:in `block in start_workers'"]

Do you know if SPARQL::Grammar.parse(sparql_query, {:resolve_iris => TRUE}) depends on some various environment settings on runtime or is those error can be explained differently?

I asked to the Elasticsearch community the same issue and specify how to reproduce this (Docker and docker-compose are needed):

git clone https://github.com/anthony-o/docker-elk_logstash-filter-sparql.git
cd docker-elk_logstash-filter-sparql
docker-compose up -d

Then connect to http://localhost:5602, create the index pattern * and go to the "Discover" tab. If none of the events contain the field exception, restart the ELK stack with ocker-compose down --volumes && docker-compose build && docker-compose up -d

PropertyPath's [ ] is missing.

I test 2216ee3

I run this code to parse sparql which include Property Path.
I think [ ] is missing

require_relative "lib/sparql"
require 'digest/md5'

# SPARQL
endpoint = "https://integbio.jp/togosite/sparql"
rq = <<'SPARQL'.chop
PREFIX p14: <http://ddbj.nig.ac.jp/ontologies/taxonomy/>
PREFIX up: <http://purl.uniprot.org/core/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?taxonomy ?node_43 ?gene ?node_37 ?structured_name ?node_27 ?journal_citation ?catalytic_activity_annotation ?function ?node_0
WHERE {
  ?node_0 rdfs:seeAlso ?taxonomy .
  ?node_0 rdfs:seeAlso/rdfs:seeAlso [
     up:recommendedName ?structured_name ;
     up:mnemonic ?node_27 ;
     up:encodedBy ?gene ;
     up:citation ?journal_citation ;
     up:annotation ?catalytic_activity_annotation ;
     up:annotation ?function
    ] .
  ?gene rdf:type up:Gene .
  ?gene up:orfName ?node_37 .
  ?taxonomy p14:genbankCommonName ?node_43 .
}
LIMIT 100
SPARQL

# # convert
parsedobject = SPARQL.parse(rq)
rqfromparsedobject = parsedobject.to_sparql()

puts "#{rqfromparsedobject}"

Original query is

PREFIX p14: <http://ddbj.nig.ac.jp/ontologies/taxonomy/>
PREFIX up: <http://purl.uniprot.org/core/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?taxonomy ?node_43 ?gene ?node_37 ?structured_name ?node_27 ?journal_citation ?catalytic_activity_annotation ?function ?node_0
WHERE {
  ?node_0 rdfs:seeAlso ?taxonomy .
  ?node_0 rdfs:seeAlso/rdfs:seeAlso [
     up:recommendedName ?structured_name ;
     up:mnemonic ?node_27 ;
     up:encodedBy ?gene ;
     up:citation ?journal_citation ;
     up:annotation ?catalytic_activity_annotation ;
     up:annotation ?function
    ] .
  ?gene rdf:type up:Gene .
  ?gene up:orfName ?node_37 .
  ?taxonomy p14:genbankCommonName ?node_43 .
}
LIMIT 100

parse and to_sparql

PREFIX p14: <http://ddbj.nig.ac.jp/ontologies/taxonomy/>
PREFIX up: <http://purl.uniprot.org/core/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?taxonomy ?node_43 ?gene ?node_37 ?structured_name ?node_27 ?journal_citation ?catalytic_activity_annotation ?function ?node_0
WHERE {
{
?node_0 rdfs:seeAlso ?taxonomy . 

{
{
?node_0 (rdfs:seeAlso/rdfs:seeAlso) _:_nd0 .
{
?gene rdf:type up:Gene . 
?gene up:orfName ?node_37 . 
?taxonomy p14:genbankCommonName ?node_43 . 

}
}
}
}
}
LIMIT 100

I think following parts are missing

[
     up:recommendedName ?structured_name ;
     up:mnemonic ?node_27 ;
     up:encodedBy ?gene ;
     up:citation ?journal_citation ;
     up:annotation ?catalytic_activity_annotation ;
     up:annotation ?function
    ] .

JSON output not emitting 'typed-literal' for boolean values

SPARQL::Client expects boolean literals to have the type set to 'typed-literal' rather than just 'literal'. If you run the example below you will see that the JSON data has the type set to 'literal' and when this is parsed by SPARQL::Client.parse_json_bindings it becomes a RDF::Literal rather than a RDF::Literal::Boolean.

require 'rdf'
require 'sparql'
require 'json'
require 'pp'
require 'sparql/client'


class TestRepo < ::RDF::Repository

  def query(pattern, &block)
    statements = []
    statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/1'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/has_name'),
        :object    => RDF::Literal.new(true))

    statements.each(&block)
  end
end


query = %q(
PREFIX a: <http://localhost/attribute_types/>
  SELECT ?entity ?has_name
  WHERE {
    ?entity a:has_name ?has_name .
  }
)

rep = TestRepo.new(:base_url => 'http://localhost')
sse = SPARQL.parse(query)


solutions = sse.execute(rep)
pp JSON.parse(solutions.to_json)
puts SPARQL::Client.parse_json_bindings(solutions.to_json).inspect

sparql construct blanknodes

Hello,

When I try to run the following sparql construct:

  CONSTRUCT {
       :s :p1 _:b1 .                                                                                                                                                                                                                                                                                              
      _:b1 :p2 :o1 .
 }
 WHERE {
  }

I receive:

"<s> <p1> _:g2199868280 ."
"_:g2199867760 <p2> <o1> ."

There the blank nodes are not the same blank notes as one would expect.
I think this is a bug. If I run the same query inside an sesame repository i receive:

:s  :p1 _:node1692
_:node1692  :p2 :o1

JSON binding

Hi,
Congratulation on the library, it's amazingly useful.

I'm not sure if this is the right place to report my issue, since it concerns the JSON ouput. Specifically, the bindings of the requested variables in the JSON.

Here's the example:

server.rb

require 'sinatra'
require 'sinatra/sparql'
require 'linkeddata'

dataset = RDF::Graph.new do |graph|
  graph << [RDF::Node.new, RDF::DC.title, "Hello, world!"]
  graph << [RDF::Node.new, RDF::DC.title, "Foo bar"]
end

get '/sparql' do
  SPARQL.execute( request[:query], dataset )
end

$ ruby server.rb

Now when I query it,

curl http://localhost:4567/sparql --data-urlencode "query=SELECT ?x ?y ?z WHERE { ?x ?y ?z } LIMIT 10"  -G

I get:

{"head":
          {"vars":["x","y","z"]},
          "results":{
                      "bindings": [
                              {"x":{"type":"bnode","value":"g26035760"}},
                              {"y":{"type":"uri","value":"http://purl.org/dc/terms/title"}},
                              {"z":{"type":"literal","value":"Hello, world!"}},
                              {"x":{"type":"bnode","value":"g26106100"}},
                              {"y":{"type":"uri","value":"http://purl.org/dc/terms/title"}},
                              {"z":{"type":"literal","value":"Foo bar"}}]}}

So this results in 6 different solutions with each one bound variable, instead of 2 solutions with 3 bound variables.

There is no problem when requesting sparql-results+xml.

Executing a SPARQL 1.1 construct query gives Argument error

Executing a SPARQL 1.1 construct query gives a SPARQL::MalformedQuery: ArgumentError: wrong number of arguments exception

Query: https://github.com/mwkuster/eli-budabe/blob/master/sparql/eli_md.rq
Sample data for the query: https://github.com/mwkuster/eli-budabe/tree/master/samples

The query executes correctly against ARQ and validates using http://www.sparql.org/query-validator.html

irb(main):011:0> g2 = SPARQL.execute(query, e.repo)
SPARQL::MalformedQuery: ArgumentError: wrong number of arguments (5 for 3) at line 53, production = :BuiltInCall
ArgumentError: wrong number of arguments (2 for 3) at line 53, production = :BuiltInCall
ArgumentError: wrong number of arguments (0 for 1) at line 53, production = :BuiltInCall
ArgumentError: wrong number of arguments (0 for 1) at line 53, production = :BuiltInCall
NoMethodError: undefined method unshift' for nil:NilClass at line 53, production = :Bind from /opt/local/lib/ruby1.9/gems/1.9.1/gems/sparql-1.0.7/lib/sparql.rb:87:inrescue in execute'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/sparql-1.0.7/lib/sparql.rb:66:in execute' from (irb):11 from /opt/local/bin/irb1.9:12:in

'

Invalid SPARQL parsing

Ruby version : 2.4.4p296
Gem version: 3.0.1

require 'sparql'

query = %(
  CONSTRUCT {
      ?uri <http://prop3> ?anotherURI .
  }
  WHERE
  {
      ?uri a ?type ;
        <http://prop1> / <http://prop2> ?anotherURI
  }
)

SPARQL.parse(query)

Current behaviour:

Produce

(construct 
  ((triple ?uri <http://prop3> ?anotherURI)) 
  (bgp (triple ?uri a ?type) (triple ?uri a ?anotherURI))
)

Expected behaviour:

Should produce instead

(construct
  ((triple ?uri <http://prop3> ?anotherURI)) 
  (join
   (bgp (triple ?uri a ?type)) 
   (path ?uri (seq <http://prop1> <http://prop2>) ?anotherURI)
  )
)

Regex error with ruby 3.2

Unfortunately there is some issue with using the sparql library on ruby 3.2, I have experienced the bug using your library in jekyll-rdf resp. the jod theme.

The issue can be reproduced with the following image (docker or podman):

FROM ruby:3.2-slim # ruby:3.2 and ruby:3.2-alpine give the same result
RUN gem install sparql
RUN echo "require 'sparql'" > bug.rb
RUN echo "sparql = SPARQL::Client.new(RDF::Graph.new << [:hello, RDF::RDFS.label, 'Hello, world!'])" >> bug.rb
RUN echo "sparql.query('SELECT ?s { ?s ?p ?o }')" >> bug.rb
CMD ruby bug.rb

or just running this code under ruby 3.2 I guess:

require 'sparql'
sparql = SPARQL::Client.new(RDF::Graph.new << [:hello, RDF::RDFS.label, 'Hello, world!'])
sparql.query('SELECT ?s { ?s ?p ?o }')

Complete output:

docker run sparql-bug
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:9: warning: already initialized constant SPARQL::Grammar::Terminals::U_CHARS1
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:9: warning: previous definition of U_CHARS1 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:15: warning: already initialized constant SPARQL::Grammar::Terminals::U_CHARS2
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:15: warning: previous definition of U_CHARS2 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:16: warning: already initialized constant SPARQL::Grammar::Terminals::IRI_RANGE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:16: warning: previous definition of IRI_RANGE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:19: warning: already initialized constant SPARQL::Grammar::Terminals::UCHAR
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:19: warning: previous definition of UCHAR was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:21: warning: already initialized constant SPARQL::Grammar::Terminals::PERCENT
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:21: warning: previous definition of PERCENT was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:23: warning: already initialized constant SPARQL::Grammar::Terminals::PN_LOCAL_ESC
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:23: warning: previous definition of PN_LOCAL_ESC was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:25: warning: already initialized constant SPARQL::Grammar::Terminals::PLX
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:25: warning: previous definition of PLX was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:27: warning: already initialized constant SPARQL::Grammar::Terminals::PN_CHARS_BASE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:27: warning: previous definition of PN_CHARS_BASE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:29: warning: already initialized constant SPARQL::Grammar::Terminals::PN_CHARS_U
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:29: warning: previous definition of PN_CHARS_U was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:31: warning: already initialized constant SPARQL::Grammar::Terminals::VARNAME
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:31: warning: previous definition of VARNAME was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:34: warning: already initialized constant SPARQL::Grammar::Terminals::PN_CHARS
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:34: warning: previous definition of PN_CHARS was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:35: warning: already initialized constant SPARQL::Grammar::Terminals::PN_LOCAL_BODY
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:35: warning: previous definition of PN_LOCAL_BODY was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:36: warning: already initialized constant SPARQL::Grammar::Terminals::PN_CHARS_BODY
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:36: warning: previous definition of PN_CHARS_BODY was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:38: warning: already initialized constant SPARQL::Grammar::Terminals::PN_PREFIX
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:38: warning: previous definition of PN_PREFIX was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:40: warning: already initialized constant SPARQL::Grammar::Terminals::PN_LOCAL
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:40: warning: previous definition of PN_LOCAL was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:42: warning: already initialized constant SPARQL::Grammar::Terminals::EXPONENT
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:42: warning: previous definition of EXPONENT was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:44: warning: already initialized constant SPARQL::Grammar::Terminals::ECHAR
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:44: warning: previous definition of ECHAR was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:46: warning: already initialized constant SPARQL::Grammar::Terminals::IRIREF
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:46: warning: previous definition of IRIREF was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:48: warning: already initialized constant SPARQL::Grammar::Terminals::PNAME_NS
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:48: warning: previous definition of PNAME_NS was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:50: warning: already initialized constant SPARQL::Grammar::Terminals::PNAME_LN
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:50: warning: previous definition of PNAME_LN was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:52: warning: already initialized constant SPARQL::Grammar::Terminals::BLANK_NODE_LABEL
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:52: warning: previous definition of BLANK_NODE_LABEL was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:54: warning: already initialized constant SPARQL::Grammar::Terminals::VAR1
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:54: warning: previous definition of VAR1 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:56: warning: already initialized constant SPARQL::Grammar::Terminals::VAR2
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:56: warning: previous definition of VAR2 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:58: warning: already initialized constant SPARQL::Grammar::Terminals::LANGTAG
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:58: warning: previous definition of LANGTAG was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:60: warning: already initialized constant SPARQL::Grammar::Terminals::INTEGER
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:60: warning: previous definition of INTEGER was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:62: warning: already initialized constant SPARQL::Grammar::Terminals::DECIMAL
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:62: warning: previous definition of DECIMAL was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:64: warning: already initialized constant SPARQL::Grammar::Terminals::DOUBLE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:64: warning: previous definition of DOUBLE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:66: warning: already initialized constant SPARQL::Grammar::Terminals::INTEGER_POSITIVE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:66: warning: previous definition of INTEGER_POSITIVE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:68: warning: already initialized constant SPARQL::Grammar::Terminals::DECIMAL_POSITIVE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:68: warning: previous definition of DECIMAL_POSITIVE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:70: warning: already initialized constant SPARQL::Grammar::Terminals::DOUBLE_POSITIVE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:70: warning: previous definition of DOUBLE_POSITIVE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:72: warning: already initialized constant SPARQL::Grammar::Terminals::INTEGER_NEGATIVE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:72: warning: previous definition of INTEGER_NEGATIVE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:74: warning: already initialized constant SPARQL::Grammar::Terminals::DECIMAL_NEGATIVE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:74: warning: previous definition of DECIMAL_NEGATIVE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:76: warning: already initialized constant SPARQL::Grammar::Terminals::DOUBLE_NEGATIVE
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:76: warning: previous definition of DOUBLE_NEGATIVE was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:78: warning: already initialized constant SPARQL::Grammar::Terminals::STRING_LITERAL1
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:78: warning: previous definition of STRING_LITERAL1 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:80: warning: already initialized constant SPARQL::Grammar::Terminals::STRING_LITERAL2
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:80: warning: previous definition of STRING_LITERAL2 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:82: warning: already initialized constant SPARQL::Grammar::Terminals::STRING_LITERAL_LONG1
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:82: warning: previous definition of STRING_LITERAL_LONG1 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:84: warning: already initialized constant SPARQL::Grammar::Terminals::STRING_LITERAL_LONG2
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:84: warning: previous definition of STRING_LITERAL_LONG2 was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:87: warning: already initialized constant SPARQL::Grammar::Terminals::WS
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:87: warning: previous definition of WS was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:89: warning: already initialized constant SPARQL::Grammar::Terminals::NIL
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:89: warning: previous definition of NIL was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:91: warning: already initialized constant SPARQL::Grammar::Terminals::ANON
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:91: warning: previous definition of ANON was here
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:94:in `<module:Terminals>': end pattern with unmatched parenthesis: /ABS|ADD|ADJUST|ALL|ASC|ASK|AS|AVG|BASE|BINDINGS|BIND (RegexpError)
                 |BNODE|BOUND|BY|CEIL|CLEAR|COALESCE|CONCAT
                 |CONSTRUCT|CONTAINS|COPY|COUNT|CREATE|DATATYPE|DAY
                 |DEFAULT|DELETE(?m-ix:(?:\s|(?:#[^\n\r]*))+)DATA|DELETE(?m-ix:(?:\s|(?:#[^\n\r]*))+)WHERE|DELETE
                 |DESCRIBE|DESC|DISTINCT|DROP|ENCODE_FOR_URI|EXISTS
                 |FILTER|FLOOR|FROM|GRAPH|GROUP_CONCAT|GROUP|HAVING
                 |HOURS|IF|INSERT(?m-ix:(?:\s|(?:#[^\n\r]*))+)DATA|INSERT|INTO|IN|IRI
                 |LANGMATCHES|LANGTAG|LANG|LCASE|LIMIT|LOAD
                 |MAX|MD5|MINUS|MINUTES|MIN|MONTH|MOVE
                 |NAMED|NOT|NOW|OFFSET|OPTIONAL
                 |ORDER|PREFIX|RAND|REDUCED|REGEX|REPLACE|ROUND|SAMPLE|SECONDS
                 |SELECT|SEPARATOR|SERVICE
                 |SHA1|SHA224|SHA256|SHA384|SHA512|SILENT
                 |STRAFTER|STRBEFORE|STRDT|STRENDS|STRLANG|STRLEN|STRSTARTS|STRUUID|SUBSTR|STR|SUM
                 |TIMEZONE|TO|TZ|UCASE|UNDEF|UNION|URI|USING|UUID|VALUES
                 |WHERE|WITH|YEAR
                 |isBLANK|isIRI|isURI|isLITERAL|isNUMERIC|sameTerm
                 |isTRIPLE|TRIPLE|SUBJECT|PREDICATE|OBJECT
                 |true
                 |false
                 |<<|>>
                 |\{\||\|\}
                 |&&|!=|!|<=|>=|\^\^|\|\||[\(\),.;\[\]\{\}\+\-=<>\?\^\|\*\/a]
              /mix
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:4:in `<module:Grammar>'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:3:in `<top (required)>'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/parser11.rb:13:in `<class:Parser>'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/parser11.rb:11:in `<module:Grammar>'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/parser11.rb:5:in `<top (required)>'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql.rb:95:in `rescue in execute'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql.rb:76:in `execute'
	from /usr/local/bundle/gems/sparql-client-3.2.1/lib/sparql/client.rb:332:in `query'
	from bug.rb:3:in `<main>'
/usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:94:in `<module:Terminals>': end pattern with unmatched parenthesis: /ABS|ADD|ADJUST|ALL|ASC|ASK|AS|AVG|BASE|BINDINGS|BIND (RegexpError)
                 |BNODE|BOUND|BY|CEIL|CLEAR|COALESCE|CONCAT
                 |CONSTRUCT|CONTAINS|COPY|COUNT|CREATE|DATATYPE|DAY
                 |DEFAULT|DELETE(?m-ix:(?:\s|(?:#[^\n\r]*))+)DATA|DELETE(?m-ix:(?:\s|(?:#[^\n\r]*))+)WHERE|DELETE
                 |DESCRIBE|DESC|DISTINCT|DROP|ENCODE_FOR_URI|EXISTS
                 |FILTER|FLOOR|FROM|GRAPH|GROUP_CONCAT|GROUP|HAVING
                 |HOURS|IF|INSERT(?m-ix:(?:\s|(?:#[^\n\r]*))+)DATA|INSERT|INTO|IN|IRI
                 |LANGMATCHES|LANGTAG|LANG|LCASE|LIMIT|LOAD
                 |MAX|MD5|MINUS|MINUTES|MIN|MONTH|MOVE
                 |NAMED|NOT|NOW|OFFSET|OPTIONAL
                 |ORDER|PREFIX|RAND|REDUCED|REGEX|REPLACE|ROUND|SAMPLE|SECONDS
                 |SELECT|SEPARATOR|SERVICE
                 |SHA1|SHA224|SHA256|SHA384|SHA512|SILENT
                 |STRAFTER|STRBEFORE|STRDT|STRENDS|STRLANG|STRLEN|STRSTARTS|STRUUID|SUBSTR|STR|SUM
                 |TIMEZONE|TO|TZ|UCASE|UNDEF|UNION|URI|USING|UUID|VALUES
                 |WHERE|WITH|YEAR
                 |isBLANK|isIRI|isURI|isLITERAL|isNUMERIC|sameTerm
                 |isTRIPLE|TRIPLE|SUBJECT|PREDICATE|OBJECT
                 |true
                 |false
                 |<<|>>
                 |\{\||\|\}
                 |&&|!=|!|<=|>=|\^\^|\|\||[\(\),.;\[\]\{\}\+\-=<>\?\^\|\*\/a]
              /mix
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:4:in `<module:Grammar>'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/terminals11.rb:3:in `<top (required)>'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/parser11.rb:13:in `<class:Parser>'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/parser11.rb:11:in `<module:Grammar>'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql/grammar/parser11.rb:5:in `<top (required)>'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from <internal:/usr/local/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql.rb:36:in `parse'
	from /usr/local/bundle/gems/sparql-3.2.4/lib/sparql.rb:77:in `execute'
	from /usr/local/bundle/gems/sparql-client-3.2.1/lib/sparql/client.rb:332:in `query'
	from bug.rb:3:in `<main>'

Reverse SSE serializer

As discussed in the email thread, which has been discussed elsewhere, it would be useful to be able to turn a SPARQL S-Expression (SSE) back into the SPARQL Grammar. A motivating use case is a query rewriter, which parses SPARQL to SSE (actually, the object representation based on SPARQL Algebra class instances) for easier manipulation, getting back to the SPARQL Grammar. For example:

query = SPARQL.parse 'SELECT ?s WHERE { ?s ?p ?o }'
sxp = query.to_sxp_bin
sxp2 = rewriting(exp) # Using custom query rewriter
grammar = sxp2.to_sparql # the hypothetical method for producing SPARQL

Jena has a mechanism for doing this here.

Only the first ORDER operand value is taken into account

Hello,

I believe the current implementation of the ORDER operator only takes into account the first ordering command.

I've made a small script to try and reveal the issue:

require 'rdf'
require 'sparql'

query = "select *
where
{
  values ?a { 3 1 2 }
  values ?b { 5 3 4 }
}
order by desc(?a) asc(?b)"

sse = SPARQL::Grammar.parse(query);
puts "
  Query:
    #{query}

  SXP:
    #{sse.to_sxp}

  Expected:
    a: 3, b: 3
    a: 3, b: 4
    a: 3, b: 5
    a: 2, b: 3
    a: 2, b: 4
    a: 2, b: 5
    a: 1, b: 3
    a: 1, b: 4
    a: 1, b: 5

  Actual:
"
repo = RDF::Repository.new
sse.execute(repo) { |solution| puts "    a: #{solution.a}, b: #{solution.b}" }

When executing this script, I get this:

  Query:
    select *
where
{
  values ?a { 3 1 2 }
  values ?b { 5 3 4 }
}
order by desc(?a) asc(?b)

  SXP:
    (order ((desc ?a) (asc ?b)) (join (table (vars ?a) (row (?a 3)) (row (?a 1)) (row (?a 2))) (table (vars ?b) (row (?b 5)) (row (?b 3)) (row (?b 4)))))

  Expected:
    a: 3, b: 3
    a: 3, b: 4
    a: 3, b: 5
    a: 2, b: 3
    a: 2, b: 4
    a: 2, b: 5
    a: 1, b: 3
    a: 1, b: 4
    a: 1, b: 5

  Actual:
    a: 3, b: 5
    a: 3, b: 3
    a: 3, b: 4
    a: 2, b: 3
    a: 2, b: 5
    a: 2, b: 4
    a: 1, b: 4
    a: 1, b: 5
    a: 1, b: 3

The actual values show that the ASC(?b) order seems to be ignored.

Looking at the code in lib/sparql/algebra/operator/order.rb, I believe the error is at the lines 37-54:

          operand(0).inject(false) do |memo, op|
            debug(options) {"(order) #{op.inspect}"}
            memo ||= begin
              # CODE
              comp == 0 ? false : comp
            end
           end || 0  # They compare equivalently if there are no matches

Shouldn't it be:

          operand(0).inject(0) do |memo, op|
            debug(options) {"(order) #{op.inspect}"}
            memo = begin
              # CODE
              comp
            end
          end if memo == 0

Does the false value have a specific meaning for comp? (it is used as the initial value and the value used in case of equality in the block, but overwritten by the || operator)

Wrong permissions in gem files

Hello,

The latest versions of the gem (3.2.1 and 3.2.2 at least, from my testing) suffer from weird file permission issues on some operator files.

Steps to reproduce

  1. Create a folder sparql-bug and move inside it.
mkdir sparql-bug && cd $_
  1. Create a minimalistic Dockerfile as such. (Running from a Docker container makes it easy to run with different UID, which triggers the bug.)
FROM ruby:2.6-alpine

RUN apk add --no-cache build-base && \
    gem install sparql -v '= 3.2.2'

ENTRYPOINT ["/usr/local/bundle/bin/sparql"]
  1. Build the image
docker build . -t sparql-bug:xxx
  1. Create a sample SPARQL query file
echo "SELECT * WHERE { ?s ?p ?o }" > query.sparql
  1. Run the Docker image and see that the command works.
docker run --rm -ti -v $PWD:/data:ro sparql-bug:xxx parse /data/query.sparql
  1. Run the same command with a -u flag to run as a different user.
docker run --rm -ti -u $(id -u) -v $PWD:/data:ro sparql-bug:xxx parse /data/query.sparql

Expected behavior

The command outputs the same result as the previous one.

Observed behaivor

The command fails with the following error.

/usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `require': cannot load such file -- sparql/algebra/operator/triple (LoadError)
        from /usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `rescue in require'
        from /usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:34:in `require'
        from /usr/local/bundle/gems/sparql-3.2.2/lib/sparql/algebra/expression.rb:146:in `new'
        from /usr/local/bundle/gems/sparql-3.2.2/lib/sparql/algebra/expression.rb:86:in `for'
        from /usr/local/bundle/gems/sparql-3.2.2/lib/sparql/grammar/parser11.rb:827:in `block in <class:Parser>'
        from /usr/local/bundle/gems/ebnf-2.3.1/lib/ebnf/ll1/parser.rb:640:in `block in onFinish'
        from /usr/local/bundle/gems/ebnf-2.3.1/lib/ebnf/ll1/parser.rb:158:in `block in eval_with_binding'
        from /usr/local/bundle/gems/ebnf-2.3.1/lib/ebnf/ll1/parser.rb:158:in `instance_eval'
        from /usr/local/bundle/gems/ebnf-2.3.1/lib/ebnf/ll1/parser.rb:158:in `eval_with_binding'
        from /usr/local/bundle/gems/ebnf-2.3.1/lib/ebnf/ll1/parser.rb:639:in `onFinish'
        from /usr/local/bundle/gems/ebnf-2.3.1/lib/ebnf/ll1/parser.rb:442:in `parse'
        from /usr/local/bundle/gems/sparql-3.2.2/lib/sparql/grammar/parser11.rb:2115:in `parse'
        from /usr/local/bundle/gems/sparql-3.2.2/lib/sparql/grammar.rb:255:in `parse'
        from /usr/local/bundle/gems/sparql-3.2.2/bin/sparql:45:in `run'
        from /usr/local/bundle/gems/sparql-3.2.2/bin/sparql:136:in `<top (required)>'
        from /usr/local/bundle/bin/sparql:23:in `load'
        from /usr/local/bundle/bin/sparql:23:in `<main>'

Additional notes

The require of sparql/algebra/operator/triple fails because, in the second command, we are a different user than root.

Use the following command to look up the permissions of these files.

docker run --rm -ti --entrypoint /bin/sh sparql-bug:xxx -c 'ls -l /usr/local/bundle/gems/sparql-3.2.*/lib/sparql/algebra/operator'
total 608
-rw-r--r--    1 root     root          1460 May  5 08:59 abs.rb
-rw-r--r--    1 root     root          2597 May  5 08:59 add.rb
[...]
-rw-r--r--    1 root     root          1761 May  5 08:59 timezone.rb
-rw-------    1 root     root          1673 May  5 08:59 triple.rb
-rw-r--r--    1 root     root          1512 May  5 08:59 tz.rb
[...]

We can see that almost every file here has a 644 permission value (-rw-r--r--), except for triple.rb that has 600 permissions (-rw-------). These permissions mean that the file is not readable for any user other than root, which, in turn, prevents Ruby from loading the file.

Workaround

It is possible to circumvent this issue by manually fixing the permissions in the Dockerfile with chmod.

FROM ruby:2.6-alpine

RUN apk add --no-cache build-base && \
    gem install sparql -v '= 3.2.2'

# This fixes the missing permissions
RUN chmod -R a+r /usr/local/bundle/gems/sparql-*/lib

ENTRYPOINT ["/usr/local/bundle/bin/sparql"]

Build and release workflow?

The most interesting part in this bug is that everything is okay on the GitHub repository itself, but the problem gets triggered when downloading the gem from rubygems.org.

@gkellogg: I see that the GitHub actions of this repository do not mention anything about building and releasing the gem. Do you perform these operations manually from your workstation? If that is the case, maybe the erroneous permissions come from your local setup, like a unusual umask value, for instance?

[critical] UNION operator not properly evaluated (max. 3 alternations possible)

When a SPARQL query contains multiple basic graph patterns which are alternated using the UNION operator, only the first three BGPs are matched. This limitation is (when I interpret it correctly) not dictated by the SPARQL 1.x language specification and should thus be considered as a bug.

Code to reproduce: https://gist.github.com/peta/5424335

When I feed the triple corpus from this testcase into Jena and run the same SPARQL query against it (using the Fuseki frontend for both tasks), I get back exactly the expected output.

Implement basic AST-walking operators

Quite often, one needs to process or transform the result of SPARQL.parse() in some way, which typically involves locating a child node of a particular kind. Here follows a simple proposal for methods to aid in this:

module SPARQL::Algebra
  class Operator
    ##
    # @param  [Class] sought_class
    # @return [Operator]
    def find_node_by_class(sought_class)
      return self if sought_class === self
      self.operands.find do |operand|
        operand.find_node_by_class(sought_class)
      end
    end

    ##
    # @param  [Symbol] sought_name
    # @return [Operator]
    def find_node_by_name(sought_name)
      return self if [self.class.const_get(:NAME)].flatten.include?(sought_name)
      self.operands.find do |operand|
        operand.find_node_by_name(sought_name)
      end
    end

    ##
    # @param  [Symbol, Class] sought_child
    # @return [Operator]
    def find_node(sought_child)
      case sought_child
        when Symbol then self.find_node_by_name(sought_child)
        when Class  then self.find_node_by_class(sought_child)
        else raise ArgumentError, "expected Symbol or Class, but got #{sought_child.inspect}"
      end
    end
  end
end # SPARQL::Algebra

I've opened this as a ticket, instead of directly committing it, in order to check with @gkellogg regarding naming and/or duplication of functionality with whatever facilities may already exist to do this:

ast = SPARQL.parse("SELECT * WHERE {?s ?p ?o FILTER(?o >= 123)}")
ast.find_node(SPARQL::Algebra::Operator::GreaterThanOrEqual)
ast.find_node(:>=)

CC: @helios

BIND disappers when it used with VALUES

Hello

I use rdf/sparql 3.2.0

I want to use to_sparql .

The problem is when I use to_sparql,
BIND is diappeared, when it is used with VALUES.

When I test some code in sparql source code document.
BIND works fine .

For example this query

https://togodx.integbio.jp/sparqlist/gene_biotype_ensembl

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
  ?enst obo:SO_transcribed_from ?ensg .
  ?ensg a ?parent ;
        obo:RO_0002162 taxon:9606 ;
        faldo:location ?ensg_location ;
        dc:identifier ?child ;
        rdfs:label ?child_label .
  FILTER(CONTAINS(STR(?parent), "terms/ensembl/"))
  BIND(STRBEFORE(STRAFTER(STR(?ensg_location), "GRCh38/"), ":") AS ?chromosome)
  VALUES ?chromosome {
      "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
      "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22"
      "X" "Y" "MT"
  }
}

I just parsed above SPARQL and use to_sparql
The result is here
BIND is disappear.

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
SELECT DISTINCT ?parent ?child ?child_label
WHERE {
?enst obo:SO_transcribed_from ?ensg .
?ensg a ?parent .
?ensg obo:RO_0002162 taxon:9606 .
?ensg faldo:location ?ensg_location .
?ensg dc:identifier ?child .
?ensg rdfs:label ?child_label .
VALUES (?chromosome) {
("1")
("2")
("3")
("4")
("5")
("6")
("7")
("8")
("9")
("10")
("11")
("12")
("13")
("14")
("15")
("16")
("17")
("18")
("19")
("20")
("21")
("22")
("X")
("Y")
("MT")
}

FILTER contains(str(?parent), "terms/ensembl/") .
}

I tested original query without VALUES
SPARQL query is following.

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
  ?enst obo:SO_transcribed_from ?ensg .
  ?ensg a ?parent ;
        obo:RO_0002162 taxon:9606 ;
        faldo:location ?ensg_location ;
        dc:identifier ?child ;
        rdfs:label ?child_label .
  FILTER(CONTAINS(STR(?parent), "terms/ensembl/"))
  BIND(STRBEFORE(STRAFTER(STR(?ensg_location), "GRCh38/"), ":") AS ?chromosome)
}

And parsed result is here.
BIND is not disappear.

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
SELECT DISTINCT ?parent ?child ?child_label
WHERE {
?enst obo:SO_transcribed_from ?ensg .
?ensg a ?parent .
?ensg obo:RO_0002162 taxon:9606 .
?ensg faldo:location ?ensg_location .
?ensg dc:identifier ?child .
?ensg rdfs:label ?child_label .
BIND (STRBEFORE(STRAFTER(str(?ensg_location), "GRCh38/"), ":") AS ?chromosome) .
FILTER contains(str(?parent), "terms/ensembl/") .
}

BIND disappear Source Code is here

require "sparql"

# SPARQL
endpoint = "https://integbio.jp/togosite/sparql"
rq = <<'SPARQL'.chop
PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
  ?enst obo:SO_transcribed_from ?ensg .
  ?ensg a ?parent ;
        obo:RO_0002162 taxon:9606 ;
        faldo:location ?ensg_location ;
        dc:identifier ?child ;
        rdfs:label ?child_label .
  FILTER(CONTAINS(STR(?parent), "terms/ensembl/"))
  BIND(STRBEFORE(STRAFTER(STR(?ensg_location), "GRCh38/"), ":") AS ?chromosome)
  VALUES ?chromosome {
      "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
      "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22"
      "X" "Y" "MT"
  }
}
SPARQL

puts "original SPARQL query has VALUES:\n#{rq}"

# # convert
parsedobject = SPARQL.parse(rq)
rqfromparsedobject = parsedobject.to_sparql()

puts "BIND disappear SPARQL converted from parsedobject:\n#{rqfromparsedobject}"

Remove VALUES, BIND is not disappear source code is

require "sparql"

# SPARQL
endpoint = "https://integbio.jp/togosite/sparql"
rq = <<'SPARQL'.chop
PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
  ?enst obo:SO_transcribed_from ?ensg .
  ?ensg a ?parent ;
        obo:RO_0002162 taxon:9606 ;
        faldo:location ?ensg_location ;
        dc:identifier ?child ;
        rdfs:label ?child_label .
  FILTER(CONTAINS(STR(?parent), "terms/ensembl/"))
  BIND(STRBEFORE(STRAFTER(STR(?ensg_location), "GRCh38/"), ":") AS ?chromosome)
  VALUES ?chromosome {
      "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
      "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22"
      "X" "Y" "MT"
  }
}
SPARQL

puts "original SPARQL query has VALUES:\n#{rq}"

# # convert
parsedobject = SPARQL.parse(rq)
rqfromparsedobject = parsedobject.to_sparql()

puts "BIND is not disappear SPARQL converted from parsedobject:\n#{rqfromparsedobject}"

multiple aggregates return wrong value

When I execute a query with two aggregates the bound values are taken from the first.

If in the example MIN is replaced by SAMPLE in all places you get the same result.

require 'sparql'
require 'rdf/turtle'

data = %(
PREFIX ex: <http://example.org/>

ex:e1 ex:a 1 ;
      ex:b 10 .

ex:e2 ex:a 1 ;
      ex:b 20 .

ex:e3 ex:a 2 ;
      ex:b 20 .
)

query_string = %(
PREFIX ex: <http://example.org/>

SELECT ?ev (MIN(?a) as ?a_min) (MIN(?b) as ?b_min)
WHERE {
  ?ev ex:a ?a ;
      ex:b ?b .
}
GROUP BY ?ev
)

queryable = RDF::Graph.new do |graph|
  RDF::Turtle::Reader.new(data) {|reader| graph << reader}
end

query = SPARQL.parse(query_string)
queryable.query(query) do |result|
  puts result.inspect
end

the result is:

$ ruby mwe.rb 
#<RDF::Query::Solution:0x7d0({:ev=>#<RDF::URI:0x64 URI:http://example.org/e1>, :a_min=>#<RDF::Literal::Integer:0x7e4("1"^^<http://www.w3.org/2001/XMLSchema#integer>)>, :b_min=>#<RDF::Literal::Integer:0x7e4("1"^^<http://www.w3.org/2001/XMLSchema#integer>)>})>
#<RDF::Query::Solution:0x80c({:ev=>#<RDF::URI:0x4b0 URI:http://example.org/e2>, :a_min=>#<RDF::Literal::Integer:0x820("1"^^<http://www.w3.org/2001/XMLSchema#integer>)>, :b_min=>#<RDF::Literal::Integer:0x820("1"^^<http://www.w3.org/2001/XMLSchema#integer>)>})>
#<RDF::Query::Solution:0x834({:ev=>#<RDF::URI:0x4c4 URI:http://example.org/e3>, :a_min=>#<RDF::Literal::Integer:0x848("2"^^<http://www.w3.org/2001/XMLSchema#integer>)>, :b_min=>#<RDF::Literal::Integer:0x848("2"^^<http://www.w3.org/2001/XMLSchema#integer>)>})>

Update query keywords are case-sensitive

According to https://www.w3.org/TR/sparql11-query/#sparqlGrammar (note 1), SPARQL keywords are treated as case insensitive. This appears to be true for RDF Ruby's SPARQL queries, but not for SPARQL updates.

Test case:

require "minitest/autorun"
require "sparql"

class CaseInsensitiviyInKeywordsTest < Minitest::Test
  NS = "http://foo.bar/".freeze

  def test_select_with_lower_case
    parsed = SPARQL.parse("select * {?s ?p ?o}", update: false)
    refute_nil parsed
  end

  def test_select_with_upper_case
    parsed = SPARQL.parse("SELECT * {?s ?p ?o}", update: false)
    refute_nil parsed
  end

  def test_update_with_lower_case
    parsed = SPARQL.parse("insert data {<#{NS}a> <#{NS}b> <#{NS}b>}", update: true)
    refute_nil parsed
  end

  def test_update_with_upper_case
    parsed = SPARQL.parse("INSERT DATA {<#{NS}a> <#{NS}b> <#{NS}b>}", update: true)
    refute_nil parsed
  end
end

Expected: four tests pass. Currently with RDF::Sparql 2.0, test_update_with_lower_case throws a parse exception:

Error:
CaseInsensitiviyInKeywordsTest#test_update_with_lower_case:
EBNF::LL1::Parser::Error: ERROR [line: 1] Expected one of [:_eps, "BASE", "PREFIX", "LOAD", 
"CLEAR", "DROP", "ADD", "MOVE", "COPY", "CREATE", "INSERT DATA", "DELETE DATA", "DELETE
  WHERE", "WITH", "INSERT", "DELETE"] (found "insert data"), production = :UpdateUnit
  test/models/case_insensitivity_in_keywords_test.rb:18:in `test_update_with_lower_case'

OPTIONAL not behaving as expected

I am running the following sample SPARQL query with an OPTIONAL block and it appears that the bindings in the outer query are not being passed through to the inner query. The solution that ultimately is returned is correct (/people/1), but by not passing binding ?entity to the optional pattern retrieving results from say a SQL backend becomes costly because there is no restriction to a particular context. Would it be possible to include the bindings in queries to optional patterns?

require 'rdf'
require 'sparql'



class TestRepo


  def query(pattern, &block)
    puts "received pattern #{pattern.inspect}"

    statements = []
    if pattern[:predicate].is_a?(RDF::URI) and pattern[:predicate].path == '/attribute_types/first_name'
      statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/1'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/first_name'),
        :object    => RDF::Literal.new('joe'))
    elsif pattern[:predicate].is_a?(RDF::URI) and pattern[:predicate].path == '/attribute_types/last_name'
      statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/1'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/last_name'),
        :object    => RDF::Literal.new('smith'))
    elsif pattern[:predicate].is_a?(RDF::URI) and pattern[:predicate].path == '/attribute_types/middle_name'

      statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/2'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/middle_name'),
        :object    => RDF::Literal.new('blah'))

      statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/1'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/middle_name'),
        :object    => RDF::Literal.new('blah'))

    end

    statements.each(&block)
  end
end


query = %q(
PREFIX a: <http://localhost/attribute_types/>
  SELECT ?entity
  WHERE {
    ?entity a:first_name 'joe' .
    ?entity a:last_name 'smith' .
    OPTIONAL {
      ?entity a:middle_name 'blah'
    }
  }
)

rep = TestRepo.new(:base_url => 'http://localhost')
sse = SPARQL.parse(query)


solutions = sse.execute(rep)

solutions.each_solution do |s|
  puts s.to_hash
end

OPTIONAL with to_json throws exception can't convert nil into Hash

Running the following code results in the following error:

sparql-0.3.1/lib/sparql/results.rb:21:in `merge': can't convert nil into Hash (TypeError)

The json loop does this:

variable_names.inject({}) do |memo, n|
  memo.merge case s = solution[n]

I think if that was changed to this the error would be prevented:

variable_names.inject({}) do |memo, n|
       memo.merge case s = solution[n]
       when ...
       else
       {}
       end
require 'rdf'
require 'sparql'



class TestRepo < ::RDF::Repository


  def query(pattern, &block)
    statements = []
    if pattern[:predicate].is_a?(RDF::URI) and pattern[:predicate].path == '/attribute_types/first_name'
      statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/1'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/first_name'),
        :object    => RDF::Literal.new('joe'))
      statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/2'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/first_name'),
        :object    => RDF::Literal.new('joe'))
    elsif pattern[:predicate].is_a?(RDF::URI) and pattern[:predicate].path == '/attribute_types/middle_name'

      statements << RDF::Statement.new(
        :subject   => RDF::URI.new('http://localhost/people/2'),
        :predicate => RDF::URI.new('http://localhost/attribute_types/middle_name'),
        :object    => RDF::Literal.new('blah'))


    end

    statements.each(&block)
  end
end


query = %q(
PREFIX a: <http://localhost/attribute_types/>
  SELECT ?entity ?middle_name
  WHERE {
    ?entity a:first_name 'joe' .
    OPTIONAL {
      ?entity a:middle_name ?middle_name
    }
  }
)

rep = TestRepo.new(:base_url => 'http://localhost')
sse = SPARQL.parse(query)


solutions = sse.execute(rep)

solutions.each_solution do |s|
  puts s.to_hash.inspect
end

puts solutions.to_json # throws exception

SPARQL Grammar parsing regression on 1.1.7

A bug was introduced in sparql 1.1.7. See the script below:

require 'sparql'

query = <<-eos
  PREFIX ext:<http://ext.com/1.0#>

  CONSTRUCT {
      ?x ?prop ?obj .
      ?obj rdf:type ext:Subject .
    }
    WHERE {
      ?x rdf:type ext:Subject ;
        ?prop ?obj .
    }
eos

SPARQL::Grammar.parse(query).to_sxp

1.1.6 - OK

(prefix ((ext: <http://ext.com/1.0#>)) (construct ((triple ?x ?prop ?obj) (triple ?obj rdf:type ext:Subject)) (bgp (triple ?x rdf:type ext:Subject) (triple ?x ?prop ?obj))))

1.1.7 - KO

(prefix ((ext: <http://ext.com/1.0#>)) (construct ((triple ?x ?prop ?obj) (triple ?obj rdf:type ext:Subject)) (bgp (triple ?x rdf:type ext:Subject) (triple ?x <type[#<RDF::Query::Variable:0x1fa12b0(?prop)>]> ?obj))))

Missing variables in method `to_sparql`

I tested the following code with sparql 3.2.5:

require 'sparql'

exp = <<-EOS
(extend ((?a1 "a1") (?a2 "a2"))
	(union
	 (extend
	  ((?a2 "a3") (?a4 "a4"))
	  (join (extend
		 ((?a5 "a5") (?a6 "a6"))
		 (bgp (triple ?s1 ?p1 ?o1) (triple ?s2 ?p2 ?o2) (triple ?s3 ?p3 ?o3)))
		(extend
		 ((?a7 "a7") (?a8 "a8"))
		 (bgp (triple ?s4 ?p4 ?o4) (triple ?s5 ?p5 ?o5)))))
	 (extend ((?a9 "a9") (?a10 "a10")) (bgp (triple ?s6 ?p6 ?o6)))))
EOS

puts SPARQL::Algebra.parse(exp).to_sparql

I expect a query where the variables ?a3 and ?a4. However, in the output listed below, variables ?a3 and ?a4 do not appear.

SELECT *
WHERE {
{
{
{?s1 ?p1 ?o1 . 
?s2 ?p2 ?o2 . 
?s3 ?p3 ?o3 . 

BIND ("a5" AS ?a5) .
BIND ("a6" AS ?a6) .}
{
{?s4 ?p4 ?o4 . 
?s5 ?p5 ?o5 . 

BIND ("a7" AS ?a7) .
BIND ("a8" AS ?a8) .}
}
}
} UNION {
{?s6 ?p6 ?o6 . 

BIND ("a1" AS ?a1) .
BIND ("a2" AS ?a2) .
BIND ("a9" AS ?a9) .
BIND ("a10" AS ?a10) .}
}
BIND ("a1" AS ?a1) .
BIND ("a2" AS ?a2) .
}

FILTER with !bound duplicates

Hello,

with @jindrichmynarz we were trying to use following sparql query

PREFIX ex: <http://example.com/>

CONSTRUCT {
  [] ex:label "Should appear once" .
}
WHERE {
  OPTIONAL {
    ?s ?p ex:not-bound .
  }
  FILTER (!bound(?s))
}

on

@prefix ex: <http://example.com/> .

[] a ex:bound .
[] a ex:somethingElse .

and it returns two results

[ <http://example.com/label> "Should appear once"] .

[ <http://example.com/label> "Should appear once"] .

We think there should be some deduplication of results and should appear only once.

Here is gist for issue replication https://gist.github.com/vhyza/a00d415a70db429b8860

SELECT and FROM position

Hello , to_sparql is really awesome ๐Ÿ‘
For out project wanted it.

I use rdf/sparql 3.2.0.

I parse following SPARQL Query

PREFIX obo: <http://purl.obolibrary.org/obo/>

SELECT DISTINCT ?enst
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {

  ?enst obo:SO_transcribed_from ?ensg .
}
LIMIT 10

and I use to_sparql()

The problem is FROM is appear before SELECT .

I run follwing code

require "sparql"

# SPARQL
endpoint = "https://integbio.jp/togosite/sparql"
rq = <<'SPARQL'.chop
PREFIX obo: <http://purl.obolibrary.org/obo/>

SELECT DISTINCT ?enst
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {

  ?enst obo:SO_transcribed_from ?ensg .
}
LIMIT 10
SPARQL

puts "original SPARQL:\n#{rq}"

# # convert
parsedobject = SPARQL.parse(rq)


rqfromparsedobject = parsedobject.to_sparql()

puts "\n\nSPARQL converted from parsedobject:\n#{rqfromparsedobject}"

Output is here:

original SPARQL:
PREFIX obo: <http://purl.obolibrary.org/obo/>

SELECT DISTINCT ?enst
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {

  ?enst obo:SO_transcribed_from ?ensg .
}
LIMIT 10


SPARQL converted from parsedobject:
PREFIX obo: <http://purl.obolibrary.org/obo/>
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
SELECT DISTINCT ?enst
WHERE {
?enst obo:SO_transcribed_from ?ensg .
}
LIMIT 10

VAULES position looks wrong

Hello

I use rdf/sparql .

When I use to_sparql() , VAULES position looks wrong .

3.2.1 (release version)
VAULES position looks wrong.

3.2.1 (git 2216ee3)
VAULES position looks wrong.

3.2.0 (exactly git 2b484da)
VALUES poistion looks fine ๐Ÿ‘

I test with this SPARQL

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
  ?enst obo:SO_transcribed_from ?ensg .
  ?ensg a ?parent ;
        obo:RO_0002162 taxon:9606 ;
        faldo:location ?ensg_location ;
        dc:identifier ?child ;
        rdfs:label ?child_label .
  FILTER(CONTAINS(STR(?parent), "terms/ensembl/"))
  BIND(STRBEFORE(STRAFTER(STR(?ensg_location), "GRCh38/"), ":") AS ?chromosome)
  VALUES ?chromosome {
      "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
      "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22"
      "X" "Y" "MT"
  }
}

I test with this code.

require "sparql"

# SPARQL
endpoint = "https://integbio.jp/togosite/sparql"
rq = <<'SPARQL'.chop
PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
  ?enst obo:SO_transcribed_from ?ensg .
  ?ensg a ?parent ;
        obo:RO_0002162 taxon:9606 ;
        faldo:location ?ensg_location ;
        dc:identifier ?child ;
        rdfs:label ?child_label .
  FILTER(CONTAINS(STR(?parent), "terms/ensembl/"))
  BIND(STRBEFORE(STRAFTER(STR(?ensg_location), "GRCh38/"), ":") AS ?chromosome)
  VALUES ?chromosome {
      "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
      "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22"
      "X" "Y" "MT"
  }
}
SPARQL

# # convert
parsedobject = SPARQL.parse(rq)
rqfromparsedobject = parsedobject.to_sparql()

puts "#{rqfromparsedobject}"

3.2.1 looks wrong version output like hits.
WHERE clause is closed before VALUES.
The difference release 3.2.1 and 3.2.1 git 2216ee3 (current latest)
is , very small spaces and blank line.

relase 3.2.1

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
{
{?enst obo:SO\_transcribed\_from ?ensg. 
?ensg a ?parent. 
?ensg obo:RO\_0002162 taxon:9606. 
?ensg faldo:location ?ensg_location. 
?ensg dc:identifier ?child. 
?ensg rdfs:label ?child_label
BIND (STRBEFORE(STRAFTER(str(?ensg_location), "GRCh38/"), ":") AS ?chromosome) .}
FILTER (contains(str(?parent), "terms/ensembl/")) .
}
}
VALUES (?chromosome) {
("1")
("2")
("3")
("4")
("5")
("6")
("7")
("8")
("9")
("10")
("11")
("12")
("13")
("14")
("15")
("16")
("17")
("18")
("19")
("20")
("21")
("22")
("X")
("Y")
("MT")
}

git 2216ee3 (current latest)

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
{
{?enst obo:SO\_transcribed\_from ?ensg . 
?ensg a ?parent . 
?ensg obo:RO\_0002162 taxon:9606 . 
?ensg faldo:location ?ensg_location . 
?ensg dc:identifier ?child . 
?ensg rdfs:label ?child_label . 

BIND (STRBEFORE(STRAFTER(str(?ensg_location), "GRCh38/"), ":") AS ?chromosome) .}
FILTER (contains(str(?parent), "terms/ensembl/")) .
}
}
VALUES (?chromosome) {
("1")
("2")
("3")
("4")
("5")
("6")
("7")
("8")
("9")
("10")
("11")
("12")
("13")
("14")
("15")
("16")
("17")
("18")
("19")
("20")
("21")
("22")
("X")
("Y")
("MT")
}

3.2.0 fine version output looks like this.
WHERE clause is closed include VALUES.

PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX taxon: <http://identifiers.org/taxonomy/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX faldo: <http://biohackathon.org/resource/faldo#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT DISTINCT ?parent ?child ?child_label
FROM <http://rdf.integbio.jp/dataset/togosite/ensembl>
WHERE {
{
{?enst obo:SO\_transcribed\_from ?ensg .
?ensg a ?parent .
?ensg obo:RO\_0002162 taxon:9606 .
?ensg faldo:location ?ensg_location .
?ensg dc:identifier ?child .
?ensg rdfs:label ?child_label .
BIND (STRBEFORE(STRAFTER(str(?ensg_location), "GRCh38/"), ":") AS ?chromosome) .}
FILTER (contains(str(?parent), "terms/ensembl/")) .
VALUES (?chromosome) {
("1")
("2")
("3")
("4")
("5")
("6")
("7")
("8")
("9")
("10")
("11")
("12")
("13")
("14")
("15")
("16")
("17")
("18")
("19")
("20")
("21")
("22")
("X")
("Y")
("MT")
}

}
}

Parser fails on empty `values` group

Hi,

Considering the following valid SPARQL query:

require 'sparql'

query = SPARQL.parse(<<~QUERY)
  SELECT * WHERE {
      ?s ?p ?o
      VALUES ?s { } # Notice the empty values list
  }
QUERY

The parser fails with the following error.

NoMethodError: undefined method `each' for nil:NilClass
	from /home/richard/dev/.bundle/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:706:in `block in <class:Parser>'
	from /home/richard/dev/.bundle/gems/ebnf-1.1.1/lib/ebnf/ll1/parser.rb:600:in `block in onFinish'
	from /home/richard/dev/.bundle/gems/ebnf-1.1.1/lib/ebnf/ll1/parser.rb:118:in `block in eval_with_binding'
	from /home/richard/dev/.bundle/gems/ebnf-1.1.1/lib/ebnf/ll1/parser.rb:118:in `instance_eval'
	from /home/richard/dev/.bundle/gems/ebnf-1.1.1/lib/ebnf/ll1/parser.rb:118:in `eval_with_binding'
	from /home/richard/dev/.bundle/gems/ebnf-1.1.1/lib/ebnf/ll1/parser.rb:599:in `onFinish'
	from /home/richard/dev/.bundle/gems/ebnf-1.1.1/lib/ebnf/ll1/parser.rb:402:in `parse'
	from /home/richard/dev/.bundle/gems/sparql-2.2.2/lib/sparql/grammar/parser11.rb:1525:in `parse'
	from /home/richard/dev/.bundle/gems/sparql-2.2.2/lib/sparql.rb:32:in `parse'

This is caused by the values list being empty, as you can see given the following counter-example:

require 'sparql'

query = SPARQL.parse(<<~QUERY)
  SELECT * WHERE {
      ?s ?p ?o
      VALUES ?s { <http://www.example.com> }
  }
QUERY
=> #<SPARQL::Algebra::Operator::Join:0x12f0b38(((bgp (triple ?s ?p ?o)) (table (vars ?s) (row (?s <http://www.example.com>)))) )>

uninitialized constant Logger

Hello,

I get the following error when I launch the sparql command:

Traceback (most recent call last):
        2: from /usr/local/bin/sparql:23:in `<main>'
        1: from /usr/local/bin/sparql:23:in `load'
/var/lib/gems/2.7.0/gems/sparql-3.1.7/bin/sparql:123:in `<top (required)>': uninitialized constant Logger (NameError)

A missing dependency in the gemspec?

NoMethodError: undefined method `execute' for #<Array:0x007fb6e33c3380>

The following program snippet produces the following stack trace:
NoMethodError: undefined method execute' for #<Array:0x007fb6e33c3380> from /opt/local/lib/ruby1.9/gems/1.9.1/gems/sparql-1.0.7/lib/sparql/algebra/operator/extend.rb:35:inexecute'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/sparql-1.0.7/lib/sparql/algebra/operator/project.rb:30:in execute' from /opt/local/lib/ruby1.9/gems/1.9.1/gems/sparql-1.0.7/lib/sparql/algebra/operator/distinct.rb:32:inexecute'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/sparql-1.0.7/lib/sparql/algebra/operator/prefix.rb:30:in execute' from /opt/local/lib/ruby1.9/gems/1.9.1/gems/sparql-1.0.7/lib/sparql.rb:85:inexecute'
from (irb):12
from /opt/local/bin/irb1.9:12:in `

'

Again, the query validates against http://www.sparql.org/validate/query and produces the following output with ARQ:

?number: "2010/24 (EU)"^^http://www.w3.org/2001/XMLSchema#string
?typedoc "DIR"^^http://www.w3.org/2001/XMLSchema#string
?is_corrigendum "O"^^http://www.w3.org/2001/XMLSchema#string
?langs "fra-eng"


require 'rdf'
require 'rdf/turtle'
rep = RDF::Repository.new
rep.load("https://raw.github.com/mwkuster/eli-budabe/master/sparql/source.ttl")
query = "PREFIX cdm: http://publications.europa.eu/ontology/cdm#\n\nSELECT DISTINCT ?number ?typedoc ?is_corrigendum (GROUP_CONCAT(?lang_code; separator="-") AS ?langs)\nWHERE\n{\n ?manif cdm:manifestation_official-journal_part_information_number ?number .\n ?manif cdm:manifestation_official-journal_part_typedoc_printer ?typedoc .\n ?manif cdm:manifestation_official-journal_part_is_corrigendum_printer ?is_corrigendum .\n ?manif cdm:manifestation_manifests_expression ?expr .\n ?expr cdm:expression_uses_language ?lang .\n BIND(lcase(replace(str(?lang), ".*/([A-Z]{3})", "$1")) AS ?lang_code)\n}\nGROUP BY ?number ?typedoc ?is_corrigendum\n"
require 'sparql'
s = SPARQL.execute(query, rep)

Exception while parsing a query with path expression

Hello, I'm having a bad luck parsing a query with path expression. The query works just fine in Protege 5.1.0.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>

SELECT ?class (group_concat(DISTINCT ?item;separator=",") as ?keys) WHERE {
  ?class rdf:type owl:Class .
  ?class owl:hasKey ?key .
  ?key rdf:rest*/rdf:first ?item .
}
GROUP BY ?class ?key

STDERR output: https://gist.github.com/b36694c3a1577944acbecad4262deef9
bundle output: https://gist.github.com/anonymous/d83b285d1e77b830f0b0436ef19d400e
Ruby version: ruby 2.2.6p396 (2016-11-15 revision 56800) [x86_64-linux]

Property path operator * unbinds variable

Hallo, after encountering a bug in my main project I decided to set up the following test code:

require 'linkeddata'
require 'sparql'
require 'pp'

graph = RDF::Graph.load(File.join(File.dirname("__FILE__"),"_rdf_data/simpsons.ttl"))
sparql = SPARQL::Client.new(graph)

query = "SELECT ?r ?f WHERE{
  <http://www.ifi.uio.no/INF3580/simpson-collection#Collection> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest>* ?r.
  ?r <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> ?f
}"
pp sparql.query(query)

and the knowledge base:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix simc: <http://www.ifi.uio.no/INF3580/simpson-collection#> .
@prefix sim: <http://www.ifi.uio.no/INF3580/simpsons#>.

simc:Collection a rdf:List.
simc:Collection rdf:first sim:Homer.
simc:Collection rdf:rest simc:c1.
simc:c1 rdf:first sim:Marge.
simc:c1 rdf:rest simc:c2.
simc:c2 rdf:first sim:Bart.
simc:c2 rdf:rest simc:c3.
simc:c3 rdf:first sim:Maggie.
simc:c3 rdf:rest simc:c4.
simc:c4 rdf:first sim:Lisa.
simc:c4 rdf:rest rdf:nil.

The output I get from this is:
[#RDF::Query::Solution:0x1621e38({:r=#<RDF::URI:0x169f220 URI:http://www.ifi.uio.no/INF3580/simpson-collection#Collection>})>,
#RDF::Query::Solution:0x161ea94({:r=#<RDF::URI:0x10b1e94 URI:http://www.ifi.uio.no/INF3580/simpson-collection#c1>})>,
#RDF::Query::Solution:0x161c3fc({:r=#<RDF::URI:0x108f830 URI:http://www.ifi.uio.no/INF3580/simpson-collection#c2>})>,
#RDF::Query::Solution:0x161abec({:r=#<RDF::URI:0x1087874 URI:http://www.ifi.uio.no/INF3580/simpson-collection#c3>})>,
#RDF::Query::Solution:0x16193a0({:r=#<RDF::URI:0x1077e88 URI:http://www.ifi.uio.no/INF3580/simpson-collection#c4>})>,
#RDF::Query::Solution:0x1617d5c({:r=#<RDF::URI:0x105d128 URI:http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>})>]

However, variable ?f is nowhere to be found and the last solution should not be in the answer set. I also tried the same query on a virtuoso server and got the desired results:

r f
http://www.ifi.uio.no/INF3580/simpson-collection#c3 http://www.ifi.uio.no/INF3580/simpsons#Maggie
http://www.ifi.uio.no/INF3580/simpson-collection#Collection http://www.ifi.uio.no/INF3580/simpsons#Homer
http://www.ifi.uio.no/INF3580/simpson-collection#c1 http://www.ifi.uio.no/INF3580/simpsons#Marge
http://www.ifi.uio.no/INF3580/simpson-collection#c2 http://www.ifi.uio.no/INF3580/simpsons#Bart
http://www.ifi.uio.no/INF3580/simpson-collection#c4 http://www.ifi.uio.no/INF3580/simpsons#Lisa

Did I missed something that would bind ?f ?.

SPARQL parsing drops the property paths when after a PROJECT

When a property path follows a PROJECT operator, it seems dropped during the parsing:

sparql = %{
PREFIX ns:<http://ns.com>
CONSTRUCT {
   ?item ns:link ?target
}
WHERE {
  ?item ?link ?wrapper .
  {
    SELECT DISTINCT ?wrapper
    WHERE {
     ?item ?p ?wrapper .
    }
  }
  ?item ns:slot / ns:item ?target .
}
}

SPARQL.parse(sparql)

returns:

#<SPARQL::Algebra::Operator::Prefix:0x25a452c(( ((ns: <http://ns.com>)) 
(construct ((triple ?item ns:link ?target)) (join (bgp (triple ?item ?link ?wrapper))
(distinct (project (?wrapper) (bgp (triple ?item ?p ?wrapper))))) )) )>

Redefining Array#dup breaks lots of other things

After a half-day of debugging, I realized that your redefinition of Array#dup, introduced in 84f36c2, causes all kinds of things to go haywire in a Rails application. (I was inexplicably no longer able to log in.)

I'm not even a conscious user of your gem, pulling it in via rdf-n3, but could you perhaps roll back that change? I suspect my case isn't the only weird interaction it will produce.

(EDIT: Just to be clear, I've confirmed that all the weird behavior I saw was a result of sparql 3.1.1, and could be fixed by commenting out that one function.)

sparql server fails

Hi, I use sparql 3.1.2 on ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19].
When trying to launch sparql server rdfdata.nt, I got the following error.

Traceback (most recent call last):
	12: from /usr/local/lib/ruby/gems/2.7.0/bin/sparql:23:in `<main>'
	11: from /usr/local/lib/ruby/gems/2.7.0/bin/sparql:23:in `load'
	10: from /usr/local/lib/ruby/gems/2.7.0/gems/sparql-3.1.2/bin/sparql:162:in `<top (required)>'
	 9: from /usr/local/lib/ruby/gems/2.7.0/gems/sparql-3.1.2/bin/sparql:56:in `server'
	 8: from /usr/local/Cellar/ruby/2.7.2/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
	 7: from /usr/local/Cellar/ruby/2.7.2/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:72:in `require'
	 6: from /usr/local/lib/ruby/gems/2.7.0/gems/sparql-3.1.2/lib/sinatra/sparql.rb:111:in `<top (required)>'
	 5: from /usr/local/lib/ruby/gems/2.7.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:2008:in `register'
	 4: from /usr/local/lib/ruby/gems/2.7.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1947:in `register'
	 3: from /usr/local/lib/ruby/gems/2.7.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1453:in `register'
	 2: from /usr/local/lib/ruby/gems/2.7.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1453:in `each'
	 1: from /usr/local/lib/ruby/gems/2.7.0/gems/sinatra-2.1.0/lib/sinatra/base.rb:1455:in `block in register'
/usr/local/lib/ruby/gems/2.7.0/gems/sparql-3.1.2/lib/sinatra/sparql.rb:106:in `registered': uninitialized constant LinkedData (NameError)

Is there any way of fixing this issue?

Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.