Querying SPARQL endpoints using GNU Guile
Recently I attempted to load all GNU Guix packages into a triplet store. For this we need to find or create an ontology that describes software in a compatible way with GNU Guix.
The easy part was transforming the package information into SPARQL queries, which can be done using the following snippet:
(use-modules (gnu packages)
(guix packages)
(ice-9 vlist))
(define (packages->sparql)
"Display available packages."
(format #t "INSERT DATA~%{~% GRAPH <http://sparql.guixsd.org/packages>~% {~%")
(let ((packages (fold-packages
(lambda (p r) (vhash-cons (package-full-name p) p r))
vlist-null)))
(vlist-for-each
(lambda (pair)
(let* ((package (cdr pair))
(full-name (package-full-name package))
(version (package-version package))
(name (package-name package))
(home-page (package-home-page package)))
(format #t " <#~a> <#name> ~s .~%" full-name name)
(format #t " <#~a> <#version> ~s .~%" full-name version)
(when home-page
(format #t " <#~a> <#home-page> ~s .~%" full-name home-page))))
packages))
(format #t " }~%}~%"))
(define guix-packages (with-output-to-string packages->sparql))
At this point, we have the SPARQL query, but we don't have the GNU Guile interface to submit it to a SPARQL endpoint. Ideally, we want the following function:
(sparql-query guix-packages)
This turns out to be rather easy to implement with GNU Guile's (web client)
module. The initial implementation looks like so:
(define* (sparql-query query
#:key
(host "localhost")
(port 8890)
(type "text/csv"))
(http-post (format #f "http://~a:~a/sparql" host port)
#:body query
#:streaming? #t
#:headers `((user-agent . "GNU Guile")
(content-type . (application/sparql-update))
(accept . ((,(string->symbol type)))))))
After using SPARQL and triple-stores more, I created a Guile module called
guile-sparql
, which can be viewed on Github,
or installed with GNU Guix:
$ guix package -i guile-sparql