ruby-rdf / sparql

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

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

Closed mwkuster closed 11 years ago

mwkuster commented 11 years ago

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)

gkellogg commented 11 years ago

Most likely, this is because your invoking an algebra operator which hasn't yet been implemented. I'll at least see if I can get a better error message out.

mwkuster commented 11 years ago

Which operator would then be the culprit? Seems that you support group_concat?

gkellogg commented 11 years ago

No, group operations aren't supported yet, although concat is. This query uses GROUP. The corrected query is:

PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>

SELECT DISTINCT ?number ?typedoc ?is_corrigendum (GROUP_CONCAT(?lang_code; separator="-") AS ?langs)
WHERE
{
 ?manif cdm:manifestation_official-journal_part_information_number ?number .
 ?manif cdm:manifestation_official-journal_part_typedoc_printer ?typedoc .
 ?manif cdm:manifestation_official-journal_part_is_corrigendum_printer ?is_corrigendum .
 ?manif cdm:manifestation_manifests_expression ?expr .
 ?expr cdm:expression_uses_language ?lang .
 BIND(lcase(replace(str(?lang), ".*/([A-Z]{3})", "$1")) AS ?lang_code)
}
GROUP BY ?number ?typedoc ?is_corrigendum

Which generates the (possibly incorrect) algebra:

(prefix
 ((cdm: <http://publications.europa.eu/ontology/cdm#>))
 (distinct
  (project
   (?number ?typedoc ?is_corrigendum ?langs)
   (extend
    ((?langs (group_concat (separator "-") ?lang_code)))
    (group
     (?number ?typedoc ?is_corrigendum)
     (extend
      ((?lang_code (lcase (replace (str ?lang) ".*/([A-Z]{3})" "$1"))))
      (bgp
       (triple ?manif cdm:manifestation_official-journal_part_information_number ?number)
       (triple ?manif cdm:manifestation_official-journal_part_typedoc_printer ?typedoc)
       (triple ?manif
        cdm:manifestation_official-journal_part_is_corrigendum_printer
        ?is_corrigendum )
       (triple ?manif cdm:manifestation_manifests_expression ?expr)
       (triple ?expr cdm:expression_uses_language ?lang)) )) )) ))

There are some subtleties to aggregating bind variables when doing groups and I need time to focus on. Because the (group) operator isn't implemented, it is rendered as an array such as [:group, [?number ?typedoc ..] ...]. We try to execute this, and it fails. This can be addressed by having Array#execute raise a NotImplemented error, and reference the operator name. I'll do this after I've completed the support for custom functions, which is pretty close.

mwkuster commented 11 years ago

With the help of your excellent explanation I've rewritten the query to an alternative version using a subquery:

PREFIX cdm: http://publications.europa.eu/ontology/cdm#

SELECT DISTINCT ?number ?typedoc ?is_corrigendum ?langs WHERE { ?manif cdm:manifestation_official-journal_part_information_number ?number . ?manif cdm:manifestation_official-journal_part_typedoc_printer ?typedoc . ?manif cdm:manifestation_official-journal_part_is_corrigendum_printer ?is_corrigendum . { SELECT DISTINCT (GROUP_CONCAT(?lang_code; separator="-") AS ?langs) WHERE { ?expr cdm:expression_uses_language ?lang . BIND(lcase(replace(str(?lang), ".*/([A-Z]{3})", "$1")) AS ?lang_code) } } }

Now, it does not produce an error and correctly returns ?number, ?typedoc and ?is_corrigendum, but ?langs is also not bound

mwkuster commented 11 years ago

P. S.: In my case there is an easy workaround to this, i.e. to split this query into two separate ones and use application logic to merge them.

gkellogg commented 11 years ago

Pushed in version 1.0.8.