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.
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')
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
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)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
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.
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
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.