# AllegroGraph 3.3 SPARQL Protocol Client Guide

This document describes AllegroGraph's SPARQL Protocol client. This module allows you to run queries against SPARQL servers (termed "endpoints") via HTTP. AllegroGraph seamlessly translates the protocol responses into native results, so you can query remote triple stores without changing your code.

Exported from the `sparql.client` package is run-sparql-remote. This gives you access to remote SPARQL endpoints (for `SELECT` and `ASK` queries) just as `run-sparql` lets you query local triple stores. Here's an example, querying the DBpedia.org SPARQL endpoint:

    sparql.client(2): (run-sparql-remote "http://wikipedia.org/sparql" "
      PREFIX wikipedia: <http://wikipedia.org/>
      PREFIX foaf: <http://xmlns.com/foaf/0.1/>
      PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
      SELECT ?person {
        ?person wikipedia:birthplace <http://wikipedia.org/resource/Berlin> .
      }
      LIMIT 10" :results-format :alists)
    (((?person . !<http://wikipedia.org/resource/Alexander_Grothendieck>))
     ((?person
       . !<http://wikipedia.org/resource/Frederick_William%2C_Elector_of_Brandenburg>))
     ((?person . !<http://wikipedia.org/resource/Herbert_Marcuse>))
     ((?person . !<http://wikipedia.org/resource/Konrad_Zuse>))
     ((?person . !<http://wikipedia.org/resource/Leni_Riefenstahl>))
     ((?person . !<http://wikipedia.org/resource/Nastassja_Kinski>))
     ((?person
       . !<http://wikipedia.org/resource/Otto_Wilhelm_Hermann_von_Abich>))
     ((?person . !<http://wikipedia.org/resource/Walter_Gropius>))
     ((?person . !<http://wikipedia.org/resource/Erich_H%C3%BCckel>))
     ((?person . !<http://wikipedia.org/resource/Hans_Richter_%28artist%29>)))
    :select
    (?person)

Note that you don't need to have a database open to issue a remote query:

    sparql.client(3): *db*
    nil

All of the SPARQL results formats that are natively supported for local AllegroGraph `ASK` and `SELECT` queries are supported for remote queries, and the values returned by run-sparql-remote are compatible with `run-sparql`. If you don't rely on any extended features, you can seamlessly switch between local and remote queries. You can obtain a list of possible results-formats by calling get-allowed-remote-results-formats.

Because of the similarity between the local and remote query functions, you can easily hide the distinction if the performance difference is of no concern:

    (defun query-wherever (uri &rest args)
      (if uri
        (apply #'sparql.client:run-sparql-remote uri args)
        (apply #'sparql:run-sparql args)))

    (defun get-people (&optional uri)
      "Return a list of people in the store.
       If a URI is provided, the remote store is used instead."
      (let ((q- "
               PREFIX foaf: <http://xmlns.com/foaf/0.1/>
               SELECT ?person {
                 ?person a foaf:Person .
               }"))
        (mapcar #'car
          (query-wherever uri q :results-format :lists))))

## Be aware

There are a few points to bear in mind when using remote queries.

- Remote queries have more overhead than local queries. You must include HTTP request and response times, parsing the response, and applying results formats in your estimates. For illustration, here is the time profile for the query at the start of this document:

      ; cpu time (non-gc) 0 msec user, 0 msec system
      ; cpu time (gc)     0 msec user, 0 msec system
      ; cpu time (total)  0 msec user, 0 msec system
      ; real time  710 msec

— AllegroGraph spends an immeasurably small amount of time making and parsing the request, but it spends about 700ms just waiting for the response to arrive.

- Remote queries raise a wider variety of errors than local queries. For example:

      ;; Try a URL that doesn't exist.
      sparql.client(6): (run-sparql-remote "http://ireallydonotexist.net/sparql" "SELECT * {}" :results-format :count)
      Error: Unknown hostname: "ireallydonotexist.net"
        [condition type: simple-error]

      ;; Try a URL that does exist, but isn't a SPARQL endpoint.
      sparql.client(7): (run-sparql-remote
      "http://example.com"  "SELECT * {}" :results-format :count)
      Error: Invalid MIME type returned for remote query:
             text/html; charset=UTF-8
        [condition type: sparql-remote-incorrect-mime-type-error]

These errors might occur prior to the request, whilst parsing your query for dispatch; during HTTP transport (such as the hostname error above); or whilst parsing the response (as in the MIME type error).

- Remote endpoints might interpret the SPARQL standard differently, support different extensions, or otherwise be incompatible with AllegroGraph. AllegroGraph usually has to parse your query before dispatching it, and it certainly has to parse the response: this means that, in general, remote queries are restricted to standard SPARQL features, and cannot extend the SPARQL XML results format. This restriction does not apply to named extension functions, or legal extensions of `FILTER` semantics.

- AllegroGraph doesn't currently translate from s-expressions into text: use the standard SPARQL text format ("`SELECT ...`") for your queries. Most users will not be affected by this.

- Local queries (in most circumstances) return UPIs: internal representations of values in the triple store. Remote queries have no dependency on a local store, and return `future-parts`: in-memory abstractions of RDF values. You should be careful not to use UPI-specific functions on remote values. Most users will not be affected by this.

## API reference

X run-sparql-remote uri query &rest args &key results-format rdf-format output-stream id
function

Run a SPARQL query against a remote endpoint, locally serializing the results to 'output-stream' in the appropriate format (as with `run-sparql`).

The value of the `uri` argument is provided to net.aserve.client:do-http-request; it can be a string or a `net.uri:uri`.

If `output-stream` is null, and the results format is one that generates textual output, then the serialized output is returned as a string.

Other arguments (such as `:from` and `:from-named`, and arguments to `net.aserve.client:do-http-request`) are passed to `run-sparql-remote-with-results-functions`.

You can use this opportunity to provide `:method :post` to encode large queries in the request body.

If `:function` or `:passthrough-function` are provided, they will be discarded.

You may only make requests that yield legal SPARQL XML or RDF output; the AllegroGraph extended syntax is therefore not available.

At present, the only supported verbs are `SELECT` and `ASK`.

X get-allowed-remote-results-formats &optional verb
function
Returns a list of keyword symbols that are valid when applied as values of `results-format` to a remote query with the given `verb`. if `verb` is not provided, the intersection of `:ask` and `:select` (the two permitted values) is returned.

## Indices

### Full symbol index

- get-allowed-remote-results-formats
- run-sparql-remote