SPARQL.ex

TravisHex.pm

An implementation of the SPARQL standards for Elixir.

It allows to execute SPARQL queries against RDF.ex data structures. With the separate SPARQL.Client package SPARQL queries can be executed against SPARQL protocol endpoints.

Current state

Other features on the roadmap:

Installation

The SPARQL.ex Hex package can be installed as usual, by adding sparql to your list of dependencies in mix.exs:

def deps do
  [{:sparql, "~> 0.2"}]
end

Usage

Executing queries

Let's say we have an RDF.ex graph like this:

graph = RDF.Turtle.read_string! """
  @prefix foaf:  <http://xmlns.com/foaf/0.1/> .
  
  _:a  foaf:name   "Johnny Lee Outlaw" .
  _:a  foaf:mbox   <mailto:jlow@example.com> .
  _:b  foaf:name   "Peter Goodguy" .
  _:b  foaf:mbox   <mailto:peter@example.org> .
  _:c  foaf:mbox   <mailto:carol@example.org> .
  """

We can execute the following SPARQL query:

query = """
  PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
  SELECT ?name ?mbox
  WHERE
    { ?x foaf:name ?name .
      ?x foaf:mbox ?mbox }
  """

like this:

SPARQL.execute_query(graph, query)

This will return a SPARQL.Query.Result struct which contains the results under the results field as a list of maps with the bindings of the solutions.

%SPARQL.Query.Result{
  results: [
    %{"mbox" => ~I<mailto:peter@example.org>, "name" => ~L"Peter Goodguy"},
    %{"mbox" => ~I<mailto:jlow@example.com>, "name" => ~L"Johnny Lee Outlaw"}
  ],
  variables: ["name", "mbox"]
}

The SPARQL.execute_query/2 function converts a given query string implicitely to a SPARQL.Query struct. If you intend to execute the query multiple times it's better to do this step on your own with the SPARQL.query/1 function and pass the interpreted query directly to SPARQL.execute_query/2, in order to not parse the query on every execution.

query = SPARQL.query """
  PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
  SELECT ?name ?mbox
  WHERE
    { ?x foaf:name ?name .
      ?x foaf:mbox ?mbox }
  """

SPARQL.execute_query(graph, query)

Defining extension functions

The SPARQL query language has a specified way for the introduction of custom extension functions. An extension function for a function with the name http://example.com/fun can be defined in SPARQL.ex like this:

defmodule ExampleFunction do
  use SPARQL.ExtensionFunction, name: "http://example.com/fun"

  def call(distinct, arguments, _, execution) do
    # your implementation
  end
end

The name of the module is arbitrary and has no further meaning. The first argument distinct is a boolean flag telling, if the function was called with the DISTINCT keyword, which is syntactically allowed in custom aggregate function calls only. The arguments argument is the list of already evaluated RDF terms with which the extension function was called in the SPARQL query. The ignored third argument contains the currently evaluated solution and some other internal information and shouldn't be relied upon. Since the arguments are already evaluated against the current solution, this shouldn't be necessary anyway. The execution argument is a map with some global query execution context information. In particular:

Getting help

Contributing

see CONTRIBUTING for details.

License and Copyright

(c) 2018 Marcel Otto. MIT Licensed, see LICENSE for details.