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

Specification

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:

rdf(S,P,O)

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:

rdf(Cls,rdf:type,owl:'Class')

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:

rdf(Cls,rdf:type,owl:'Class'),rdf(Cls,rdfs:subClassOf,Super)

The ';/2' predicate denotes disjunction:

rdf(Obj,rdf:type,owl:'ObjectProperty');rdf(Obj,rdf:type,owl:'DataProperty')

The '\+/1` predicate denotes negation:

...

Parentheses can be used to group conbinations

Rules

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

Builtins

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)

Additionally:

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

Functions

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

Namespaces

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:

TODO

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.