SPARQL.ex
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
Note: The SPARQL.Client supports the full SPARQL 1.1 query language. The missing query language features in the following list are just not yet supported by the query engine executing queries against RDF.ex data structures.
[ ] SPARQL 1.1 Query Language
- [x] Basic Graph Pattern matching
- [x] Group Graph Pattern matching
- [x] Optional Graph Pattern matching via
OPTIONAL
- [x] Alternative Graph Pattern matching via
UNION
- [ ] Pattern matching on Named Graphs via
FROM
andGRAPH
[ ] Solution sequence modification
- [x] Projection with the
SELECT
clause - [x] Assignments to variables in the
SELECT
clause - [x]
DISTINCT
- [x]
REDUCED
- [ ]
ORDER BY
- [ ]
OFFSET
- [ ]
LIMIT
- [x] Projection with the
- [x] Restriction of solutions via
FILTER
- [x] All builtin functions specified in SPARQL 1.0 and 1.1
- [x] Ability to define extension functions
- [x] All XPath constructor functions as specified in the SPARQL 1.1 spec
- [x] Assignments via
BIND
- [ ] Negation via
NOT EXIST
- [ ] Negation via
MINUS
- [ ] Inline Data via
VALUES
- [ ] Aggregates via
GROUP BY
andHAVING
- [ ] Subqueries
- [ ] Property Paths
- [ ]
ASK
query form - [ ]
DESCRIBE
query form - [ ]
CONSTRUCT
query form
- [ ] SPARQL 1.1 Update
- [x] SPARQL Query Results XML Format
- [x] SPARQL 1.1 Query Results JSON Format
- [x] SPARQL 1.1 Query Results CSV and TSV Formats
- [x] SPARQL 1.1 Protocol (currently client-only; in a separate package: sparql_client)
- [ ] SPARQL 1.1 Graph Store HTTP Protocol
- [ ] SPARQL 1.1 Service Description
- [ ] SPARQL 1.1 Federated Query
- [ ] SPARQL 1.1 Entailment Regimes
Other features on the roadmap:
- [ ] parallelization of the query execution
- [ ] query DSL
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 list of results for a single variable can be fetched with the SPARQL.Query.Result.get/2
function.
SPARQL.execute_query(graph, query)
|> SPARQL.Query.Result.get(:mbox)
The SPARQL.execute_query/2
function converts a given query string implicitly 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)
By default the following prefixes are defined before every query:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
You can define further application-wide default prefixes via the default_prefixes
configuration parameter and providing a map of prefixes to IRIs:
config :sparql,
default_prefixes: %{
ex: "http://example.com/ns/"
}
Further query-specific prefixes can be defined with the default_prefixes
option on the SPARQL.query/1
function which also expects a prefixes map. By using the default_prefixes
option with the value none
, the standard application-configured will not be used for a 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:
base
: the base IRItime
: the query execution timebnode_generator
: the name of theRDF.BlankNode.Generator
(see RDF.ex documentation) used to generate unique blank nodes consistently
Getting help
Contributing
see CONTRIBUTING for details.
License and Copyright
(c) 2018 Marcel Otto. MIT Licensed, see LICENSE for details.