The SPIN SPARQL Syntax

Version 1.3.0, October 20, 2009

Authors:
Holger Knublauch <holger@topquadrant.com>

Abstract

This document describes the SPIN SPARQL Syntax, an RDF representation of the semantic web query language SPARQL. The SPIN SPARQL Syntax provides an alternative representation of SPARQL queries that goes beyond the textual format. The main benefit of this syntax is that it makes it possible to consistently store SPARQL queries together with the domain model. All resources from the domain model are represented as proper RDF resource references instead of only having them as strings. Having a triple-based SPARQL representation makes it easier to maintain hybrid models in which RDF/OWL definitions are mixed with SPARQL expressions.

Status of This Document

Version 1.3.0

Previous version: Version 1.2.0 (August 11, 2009)

Older version: Version 1.1.0 (June 14, 2009)

This document is part of the SPARQL Inferencing Notation (SPIN) specification.


Table of Contents

1 Overview

The design of the SPIN SPARQL Syntax was motivated by the need to have a machine-readable notation of SPARQL queries so that they can be stored together with other domain models and ontologies in RDF format. The main goal is to enable SPIN compliant software tools to convert SPIN RDF data structures into valid SPARQL query strings, so that they can be processed for various purposes. Editing tools would go the other direction and turn a SPARQL query into an RDF structure.

For example, the SPARQL query

    # must be at least 18 years old
    ASK WHERE {
    	?this my:age ?age .
    	FILTER (?age < 18) .
    }

can be represented by a blank node in the SPIN RDF Syntax in N3 as

    [ a       sp:Ask ;
                rdfs:comment "must be at least 18 years old"^^xsd:string ;
                sp:where ([ sp:object sp:_age ;
                            sp:predicate my:age ;
                            sp:subject spin:_this
                          ] [ a       sp:Filter ;
                            sp:expression
                                    [ sp:arg1 sp:_age ;
                                      sp:arg2 18 ;
                                      a sp:lt
                                    ]
                          ])
              ]

In a typical scenario, each SPARQL query is stored as a (tree) structure of blank nodes. Syntax rules specify which elements can be nested into each other. The top-level blank node of a query is an instance of one of the subclasses of sp:Query, such as sp:Ask. Queries typically have a WHERE clauses, encoded as value of the sp:where property. The elements in the WHERE clause are represented as instances of the subclasses of sp:Element (or plain rdf:Lists for element lists). Some element types such as sp:Filter may point to an Expression. This document introduces the various types of expressions, then the elements and finally the query objects and SPARQL UPDATE language requests.

The URL of the SPIN SPARQL Syntax schema is http://spinrdf.org/sp. It currently covers all standard SPARQL language elements as well as parts of the evolving SPARQL UPDATE language plus several SPARQL extensions that are supported by popular engines such as Jena/ARQ. These extensions are

 

2 Expressions

Expressions are used, among others, as conditions in FILTER elements and in LET assignments. Three kinds of expressions are supported by SPIN: Constants, Variables and Function calls.

2.1 Constants

Constants are simply represented by a URI resource or a literal.

2.2 Variables

Variables are represented by resources that have a string value for the sp:varName property. In many cases, these resources may be untyped blank nodes, but there is also a marker class sp:Variable that can be used to make variables better visible. However, only sp:varName is used to distinguish variables from other types of expressions.

The following example represents a variable called ?x.

    [ sp:varName "x"^^xsd:string
    ]

2.3 Function calls

Function calls are blank nodes that have the function's URI as their rdf:type. The arguments are stored as values of the pre-defined system properties sp:arg1, sp:arg2, etc. All other property values of the function call blank node are ignored (except for sp:varName which would turn it into a variable).

The following example represents the function call ex:getMaximum(42, 43):

    [ a       ex:getMaximum ;
      sp:arg1 42 ;
      sp:arg2 43
    ]

 

3 Elements

SPARQL query elements are the main entities mentioned in WHERE clauses, including triple patterns and FILTER clauses.

3.1 TriplePattern

A blank node that has exactly one value for the properties sp:subject, sp:predicate and sp:object represents a triple pattern. Optionally, the blank node may have the rdf:type sp:TriplePattern.

Example:

    ?this ex:age 42 .

Represented in SPIN Syntax as:

    [ sp:subject spin:_this ;
      sp:predicate ex:age ;
      sp:object 42
    ]

3.2 TriplePath

Triple paths are similar to triple patterns, but have a path expression instead of a predicate. SPIN represents triple paths as blank nodes with a value of sp:path, as well as sp:subject and sp:object. The blank node may also have sp:TriplePath as its rdf:type.

Various types of paths are supported, based on what is currently implemented in the Jena ARQ API:

Example:

    ?this ex:father/ex:age 42 .

Represented in SPIN Syntax as:

    [ a       sp:TriplePath ;
      sp:subject spin:_this ;
      sp:path [ a       sp:SeqPath ;
                sp:path1 ex:father ;
                sp:path2 ex:age
              ] ;
      sp:object 42
    ]

3.3 Filter

Filter elements are stored as blank nodes that have sp:Filter as their rdf:type. The blank node must have exactly one value for the property sp:expression, pointing to an expression that can be evaluated to true or false.

Example:

    FILTER (?age >= 18) .

Represented in SPIN Syntax as:

    [ a       sp:Filter ;
      sp:expression
              [ a       sp:ge ;
                sp:arg1 [ sp:varName "age"^^xsd:string ] ;
                sp:arg2 18
              ]
    ]

3.4 Let

The LET keyword was introduced by ARQ to assign a computed value to a variable in the middle of a pattern. The computed value can then be used in other patterns, CONSTRUCT templates etc.

The SPIN SPARQL Syntax introduces the class sp:Let to represent Let assignments. Instances of this class must be blank nodes with one value for sp:variable to point at the variable on the left side of the assignment. The property sp:expression is used to point to the root of the expression tree that delivers the computed value.

Example:

    LET (?age := 2008 - ?birthYear) .

Represented in SPIN Syntax as:

    [ a       sp:Let ;
      sp:variable [ sp:varName "age"^^xsd:string ] ;
      sp:expression
              [ a       sp:sub ;
                sp:arg1 2008 ;
                sp:arg2 [ sp:varName "birthYear"^^xsd:string  ]
              ]
    ]

3.5 ElementList

Lists of other elements are used in various places in SPARQL, for example as root of the WHERE clause. SPIN represents them as plain rdf:Lists, where each list member must be another element.

3.6 Optional

Optional element blocks are instances of sp:Optional where the property sp:elements is used to point to the list of optional elements (stored as rdf:List).

Example:

    OPTIONAL { ?this ex:firstName ?value }

Represented in SPIN Syntax as:

    [ a       sp:Optional ;
      sp:elements ([ sp:subject spin:_this ;
                     sp:predicate ex:firstName ;
                     sp:object  [ sp:varName "value"^^xsd:string ]
                   ])
    ]

3.7 Union

The UNION operator in SPARQL can be used to specify a graph pattern that matches if one out of several sub-elements matches. SPIN represents UNIONs as blank nodes of type sp:Union, where sp:elements points to an rdf:List of nested element lists (themselves rdf:Lists).

Example:

    {
        ?this ex:age 42
    }
    UNION
    {
        ?this ex:age 43
    }

Represented in SPIN Syntax as:

    [ a       sp:Union ;
      sp:elements ( ([ sp:subject spin:_this ;
                       sp:predicate ex:age ;
                       sp:object 42
                    ]) 
                    ([ sp:subject spin:_this ;
                       sp:predicate ex:age ;
                       sp:object 43
                    ]))
    ]

3.8 NamedGraph

Blank instances of the class sp:NamedGraph represent named graph elements in a query. The property sp:graphNameNode stores the URI resource of the named graph, or a variable. sp:elements links the blank node with an rdf:List containing the elements in the named graph.

Example:

    GRAPH <http://example.org> { 
    	?this ex:firstName ?value 
    }

Represented in SPIN Syntax as:

    [ a       sp:NamedGraph ;
      sp:graphNameNode <http://example.org> ;
      sp:elements ([ sp:subject spin:_this ;
                     sp:predicate ex:firstName ;
                     sp:object  [ sp:varName "value"^^xsd:string ]
                   ])
    ]

 

3.9 SubQuery

Blank instancef of the class sp:SubQuery represent sub-queries that are nested in the body of another query. The property sp:query points to the nested query.

Example:

    SELECT ?y
    WHERE {
        ?class a rdfs:Class .
        {
            SELECT ?y
            WHERE {
                ?class rdfs:label ?y .
            }
        } .
    }

Represented in SPIN Syntax as:

        [ a       sp:Select ;
                sp:resultVariables (_:b2) ;
                sp:where ([ sp:object rdfs:Class ;
                            sp:predicate rdf:type ;
                            sp:subject _:b1
                          ] [ a       sp:SubQuery ;
                            sp:query
                                    [ a       sp:Select ;
                                      sp:resultVariables (_:b2) ;
                                      sp:where ([ sp:object _:b2 ;
                                                  sp:predicate rdfs:label ;
                                                  sp:subject _:b1
                                                ])
                                    ]
                          ])
              ]

 

3.10 NotExists

SPARQL 1.1 will provide keywords for negation. One of the proposals (implemented in Jena's ARQ engine) is to use the NOT EXISTS keyword. In SPIN, NOT EXISTS blocks are represented as instances of sp:NotExists where the property sp:elements is used to point to the list of negative elements (stored as rdf:List).

Note that ARQ also provides an EXISTS keyword, as well as the ability to use NOT EXISTS in FILTER expressions. These cases are not yet supported by the SPIN RDF Syntax.

Example:

    NOT EXISTS { ?this ex:firstName ?value }

Represented in SPIN Syntax as:

    [ a       sp:NotExists ;
      sp:elements ([ sp:subject spin:_this ;
                     sp:predicate ex:firstName ;
                     sp:object  [ sp:varName "value"^^xsd:string ]
                   ])
    ]

3.11 Service

The SERVICE keyword, implemented by ARQ can be used to match a sub-query against a remote SPARQL end point. SPIN RDF Syntax represents such SERVICE calls with instances of sp:Service where the property sp:elements is used to point to the list of optional elements (stored as rdf:List), and the property sp:serviceURI points to the URI of the SPARQL end point.

Example:

    SERVICE <http://dbpedia.org/sparql> { 
        ?this ex:firstName ?value }

Represented in SPIN Syntax as:

    [ a       sp:Service ;
      sp:serviceURI <http://dbpedia.org/sparql>
      sp:elements ([ sp:subject spin:_this ;
                     sp:predicate ex:firstName ;
                     sp:object  [ sp:varName "value"^^xsd:string ]
                   ])
    ]

4 Queries

Queries are the top-level objects in the SPIN metamodel. Queries are instances of the subclasses of sp:Query: sp:Ask, sp:Select, sp:Describe and sp:Construct. Queries might be blank nodes, and in most cases they will be blank nodes that are only linked to the rest of a model via properties such as spin:rule or spin:constraint.

Common to all query types is that they may have a WHERE clause. The WHERE clause is an element list stored as value of the sp:where property on the query instance.

Other common properties are sp:from and sp:fromNamed which can be used to link a query instance with FROM and FROM NAMED URIs, respectively. Queries can have an rdfs:comment to capture a comment string. In the textual notation of SPARQL, those comments would show up in the lines above the query, behind # characters.

Queries may have the textual form in the original SPARQL syntax stored as a string using sp:text. This may contribute to readability and may be useful for tools that cannot parse the full SPIN SPARQL syntax. Note that while the textual notation of SPARQL supports explicit prefix declarations, these are not needed in SPIN. SPIN will instead use the prefixes declared by the RDF model itself.

The following sections provide some details on the various types of queries.

4.1 Ask

The class sp:Ask is used to represent ASK queries.

Example:

    # must be at least 18 years old
    ASK WHERE {
        ?this ex:age ?age .
        FILTER (?age >= 18) .
    }

Represented in SPIN Syntax as:

    [ a       sp:Ask ;
      rdfs:comment "must be at least 18 years old"^^xsd:string ;
      sp:where ([ sp:object _:b1 ;
                  sp:predicate ex:age ;
                  sp:subject spin:_this
                ] [ a       sp:Filter ;
                    sp:expression
                            [ a       sp:ge ;
                              sp:arg1 _:b1 ;
                              sp:arg2 18
                            ]
                ])
    ]

Note that in the above example, the blank node _:b1 points to the variable ?age elsewhere in the model.

4.2 Select

The class sp:Select is used to represent SELECT queries.

If a SELECT query has a DISTINCT keyword, then its value of sp:distinct is set to true. Similarly, the REDUCED keyword is mapped into sp:reduced.

For SELECT queries that do not have the star (*) format, the property sp:resultVariables points to an rdf:List of the variables or aggregations behind the SELECT keyword. The only types of aggregations supported right now are COUNT and SUM. Each COUNT expression is a blank node of type sp:Count which can have a variable as sp:as and an expression in its sp:expression property. Similarly for sp:Sum.

SELECT queries may have solution modifiers. A LIMIT keyword is mapped into an integer value of sp:limit. Similarly, OFFSET is stored with sp:offset.

If an ORDER BY statement is present in a query, then the SPIN query object will have a property sp:orderBy that points to an rdf:List. The members of this list are either expressions, or blank nodes of type sp:Asc or sp:Desc which have the expression stored as value of the sp:expression property.

Example:

    SELECT COUNT(?object)
    WHERE {
    	?this ?arg1 ?object
    }

Represented in SPIN Syntax as:

    [ a       sp:Select ;
      sp:resultVariables ([ a       sp:Count ;
                            sp:expression sp:_object
                          ]) ;
      sp:where ([ sp:object sp:_object ;
                  sp:predicate spin:_arg1 ;
                  sp:subject spin:_this
                ])
    ]

4.3 Describe

The class sp:Describe is used to represent DESCRIBE queries. Comparable to SELECT queries, the property sp:resultNodes is used to link to the list of described variables.

Example:

    DESCRIBE ?value
    WHERE {
    	?this ex:uncle ?value
    }

Represented in SPIN Syntax as:

    [ a       sp:Describe ;
      sp:resultNodes (sp:_value) ;
      sp:where ([ sp:object sp:_value ;
                  sp:predicate ex:uncle ;
                  sp:subject spin:_this
                ])
    ]

4.4 Construct

The class sp:Construct is used to represent CONSTRUCT queries. Beside the usual sp:where clauses, the property sp:templates links to an rdf:List of template triples. Each of these template triples is a blank node with values for sp:subject, sp:predicate and sp:object.

Example:

    # infer grandParent relationship
    CONSTRUCT {
    	?this ex:grandParent ?grandParent .
    }
    WHERE {
        ?parent ex:child ?this .
        ?grandParent ex:child ?parent .
    }

Represented in SPIN Syntax as:

    [ a       sp:Construct ;
      rdfs:comment "infer grandParent relationship"^^xsd:string ;
      sp:templates ([ sp:object sp:_grandParent ;
                      sp:predicate ex:grandParent ;
                      sp:subject spin:_this
                    ]) ;
      sp:where ([ sp:object spin:_this ;
                  sp:predicate ex:child ;
                  sp:subject sp:_parent
                ] 
                [ sp:object sp:_parent ;
                  sp:predicate ex:child ;
                  sp:subject sp:_grandParent
                ])
    ]

 

5 Update Requests

The SPARQL UPDATE language is currently evolving as part of the SPARQL 1.1 working group. However, there is already a de-facto standard syntax emerging, and the SPIN RDF syntax supports it since version 1.3.0.

5.1 Modify

The class sp:Modify is used to represent MODIFY requests.

Example:

    MODIFY GRAPH <urn:example:graph>
    DELETE {
        :Thing rdfs:label ?oldLabel .
    }
    INSERT {
        :Thing rdfs:label "New label" .
    }
    WHERE {
        :Thing rdfs:label ?oldLabel .
    }

Represented in SPIN Syntax as:

    [ a       sp:Modify ;
      sp:graphIRI <urn:example:graph> ;
      sp:deletePattern ([ sp:object _:b1 ;
                          sp:predicate rdfs:label ;
                          sp:subject :Thing
                        ]) ;
      sp:insertPattern ([ sp:object "New label" ;
                          sp:predicate rdfs:label ;
                          sp:subject :Thing
                        ]) ;
      sp:where         ([ sp:object _:b1 ;
                          sp:predicate rdfs:label ;
                          sp:subject :Thing
                        ])
    ]

5.2 Delete

The class sp:Delete is used to represent DELETE FROM requests.

Example:

    DELETE FROM <urn:example:graph> {
        :Thing rdfs:label ?oldLabel .
    }
    WHERE {
        :Thing rdfs:label ?oldLabel .
    }

Represented in SPIN Syntax as:

    [ a       sp:Delete ;
      sp:graphIRI <urn:example:graph> ;
      sp:deletePattern ([ sp:object _:b1 ;
                          sp:predicate rdfs:label ;
                          sp:subject :Thing
                        ]) ;
      sp:where         ([ sp:object _:b1 ;
                          sp:predicate rdfs:label ;
                          sp:subject :Thing
                        ])
    ]

5.3 Insert

The class sp:Insert is used to represent INSERT INTO requests.

Example:

    INSERT INTO <urn:example:graph> {
        :Thing rdfs:label "New Label" .
    }
    WHERE {
        :Thing rdfs:label ?oldLabel .
    }

Represented in SPIN Syntax as:

    [ a       sp:Insert ;
      sp:graphIRI <urn:example:graph> ;
      sp:insertPattern ([ sp:object "New Label"^^xsd:string ;
                          sp:predicate rdfs:label ;
                          sp:subject :Thing
                        ]) ;
      sp:where         ([ sp:object _:b1 ;
                          sp:predicate rdfs:label ;
                          sp:subject :Thing
                        ])
    ]

 

Appendix: Reference

The SPIN SPARQL Syntax schema can be found at http://spinrdf.org/sp.