ruby-rdf / sparql

Ruby SPARQL library
http://rubygems.org/gems/sparql
The Unlicense
89 stars 14 forks source link

Missing variables in method `to_sparql` #47

Open danielhz opened 1 year ago

danielhz commented 1 year ago

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) .
}
gkellogg commented 1 year ago

Generating the query form from the algebra is a bit experimental, and it looks like you've encountered a corner-case. There is a problem in the SSE (((?a2 "a3") (?a4 "a4")) should probably be ((?a3 "a3") (?a4 "a4"))), but I don't even get that far, with an argument error being generated along the way, so there is some mismatch in gem versions resulting in different behavior. Regardless, this shouldn't happen.

I can't promise when I'll be able to look at this in any more detail, as I'm pretty swamped with standards work, and this is challenging code to work with.

danielhz commented 1 year ago

Yes, I intended to write (?e3 "a3"). The same issue occurs if join is replaced with leftjoin.

danielhz commented 1 year ago

I tested the following code with JRuby using the Jena library.

require 'jruby/core_ext'
require 'maven_require'

maven_require 'org.apache.jena:jena-core'
maven_require 'org.apache.jena:jena-arq'
maven_require 'org.apache.logging.log4j:log4j-api'
maven_require 'org.apache.logging.log4j:log4j-core'
maven_require 'org.apache.logging.log4j:log4j-slf4j-impl'

java_import 'org.apache.jena.sys.JenaSystem'
java_import 'org.apache.jena.sparql.algebra.Algebra'
java_import 'org.apache.jena.sparql.algebra.OpAsQuery'

JenaSystem.init

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

ops = Algebra.parse(exp)
puts OpAsQuery.as_query(ops).to_s

The output is the following:

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)
          }
        }
        BIND("a3" AS ?a2)
        BIND("a4" AS ?a4)
      }
    UNION
      { ?s6  ?p6  ?o6
        BIND("a9" AS ?a9)
        BIND("a10" AS ?a10)
      }
    BIND("a1" AS ?a1)
    BIND("a2" AS ?a2)
  }