ljos / sparql-mode

A SPARQL mode for emacs
GNU General Public License v3.0
62 stars 23 forks source link

Enable RDF result formats; default format should vary with query form #77

Open VladimirAlexiev opened 6 months ago

VladimirAlexiev commented 6 months ago
(defcustom sparql-default-format "text/csv"
  "The default format of the returned results."
  :group 'sparql
  :type '(choice
          (const :tag "Comma separated values" "text/csv")
          (const :tag "Tab separated values" "text/tab-separated-values")
          (const :tag "JSON" "application/sparql-results+json")
          (const :tag "SPARQL XML" "application/sparql-results+xml")
          (string :tag "Custom")))

(defvar org-babel-default-header-args:sparql
  `((:url . ,sparql-default-base-url)
    (:format . ,sparql-default-format))

This is all nice and good for SELECT and ASK queries.

However, CONSTRUCT and DESCRIBE queries return RDF formats not the above tabular formats. See this spec: https://www.w3.org/TR/sparql12-protocol/#query-success. I don't know if there's an authoritative list, so I posted https://github.com/w3c/rdf-concepts/issues/83 and you can see a list of 9 there.

@johanwk's new version https://github.com/johanwk/elot/blob/main/elot-defs.org#execute-sparql-using-robot checks for ttl vs csv depending on query form: but sparql-mode should support the various formats.

(if (string-match-p "\\(turtle\\|ttl\\)" format) 'ttl 'csv)))

In addition, the default format should not be fixed to "text/csv" but should vary with the query form. It's not so easy to find it in a SPARQL query without parsing it.

Look at this twisted test.rq: the first keyword CONSTRUCT is a false positive, and select is hidden at the end of a line:

# CONSTRUCT {is not the form of this query}                        
PREFIX owl: <http://www.w3.org/2002/07/owl#>                       
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> select  * {   
    values ?t {owl:Class owl:DatatypeProperty owl:ObjectProperty}  
        ?x a ?t                                                    
    filter(not exists {?x rdfs:isDefinedBy ?y})                    
}                                                                  

The regex will fail miserably, but qparse outputs the query in a normal form, where SELECT is easy to detect:

# qparse --query test.rq
PREFIX  owl:  <http://www.w3.org/2002/07/owl#>
PREFIX  rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT  *
WHERE
  { VALUES ?t { owl:Class owl:DatatypeProperty owl:ObjectProperty }
    ?x  a  ?t
    FILTER NOT EXISTS { ?x  rdfs:isDefinedBy  ?y }
  }