Did you know ... Search Documentation:
Pack sparqlprog -- SPECIFICATION.md


Sparqlprog is a subset of prolog, roughly equivalent to datalog, that can be compiled to SPARQL. Sparqlprog can also be executed natively by a native logic programming engine, allowing for delegation of large database queries to a remote service combined with local programming. See the [README](./README.md) for more information.

Queries and Compound Terms

A query is a boolean combination of `compound terms`. A compound term is composed of a predicate plus zero or more arguments, where each argument can be a term or a variable.

Predicates may be built-in or defined. The core built-in predicate is rdf/3 (the `/3` denotes the predicate has 3 arguments).

The most basic query is a query for all triples:


Variables are denoted by a leading uppercase symbol. In the above example, all arguments are variables to the query succeeds for all triples. It is equivalent to the SPARQL query

SELECT * WHERE {?x ?p ?o}

The following query unifies the variable Cls with all subjects of a triple in which the predicate is rdf:type and the value/object is owl:Class. Note that "Class" is in single quotes to avoid being treated as a variable:


Boolean combinations

Terms can be combined with any combinations of conjunction, disjunction or negation. These are denoted by the symbols ',', ';' and '\+' respectively. Formally these are all predicates (conjunctions and disjunction are binary, negation is unary), but these can be written using infix notation for syntacic convenience.

The ',/2' predicate denotes conjunction:


The ';/2' predicate denotes disjunction:


The '\+/1` predicate denotes negation:


Parentheses can be used to group conbinations


A rule is written Head :- Body, where the head of the rule is a single term and the body is any boolean combination

The following rule defines is_a/2 which is trivially equivalent to an rdf/3 call with the RDFS subclass predicate:

is_a(A,B) :- rdf(A,rdfs:subClassOf,B).

Multiple rules are treated disjunctions. E.g. the following definition of is_a/2 succeeds when the subject is a subclass of the object, or an instance.

is_a(A,B) :- rdf(A,rdfs:subClassOf,B).
is_a(A,B) :- rdf(A,rdf:type,B).

Recursive rules cannot be written in sparqlprog. For example, if you write:

is_a(A,B) :- rdf(A,rdfs:subClassOf,B).
is_a(A,B) :- is_a(A,Z),is_a(Z,B).

This cannot be directly converted to SPARQL. However, in this particular example, a property path can be used - see below.

For examples of rules, see some of the programs in the [ontologies](prolog/sparqlprog/ontologies/) folder


The builtins typically correspond to predicates defined in the swi-prolog semweb package. Additional definitions can optionally be imported.

The core two builtins are:

  • rdf(Subject, Predicate, Object) (triple queries)
  • rdf(Subject, Predicate, Object, Graph) (quad queries)


There are also predicate builtins for a subset of SPARQL functions that return booleans, such as

The complete list is not yet implemented.

Additionally, comparison operators are also supported. We use standard prolog infix operators, e.g.

A @<= B

for string comparisons

A <= B

for numeric comparisons


In addition to predicates, functions can be used in a query. These can be builtins, but functions can also be defined.

bind/2 can be used to explicitly set a value.

  • concat
  • ucase

Predicate paths

Aggregate Queries


Programs and Modules

Execution of sparqlprog queries

A query can be executed using the pl2sparql command, or from any language via an API call to a sparqlprog pengine. See the README for details.

Additionally, queries can be executed from within a prolog program using ??/2.

For example:


Embedding within logic programs

Any sparqlprog program should be executable directly using a prolog engine that defines the rdf/3 predicate, such as swi-prolog.

Additionally, native execution and remote execution can be mixed.