This document describes the SPINx vocabulary, an extension of the SPIN framework that can be used to define new SPARQL functions based on JavaScript code. This makes it possible to extend SPARQL engines with new functions that execute JavaScript at run-time. The SPINx framework is very light-weight and is easy to implement and use.
1.0.0
This document is an optional part of the SPARQL Inferencing Notation (SPIN) specification.
As of 2017, SPINx has further evolved into SHACL-JS, which provides very similar capabilities. SPINx should no longer be used and will be removed in a future TopBraid version.
While SPARQL is an immensely powerful language, many real-world use cases
require extensions that are not covered by the official standards.
Examples include complex string operations or mathematical computations.
SPARQL provides a built-in extension point, allowing anyone to define custom
functions, identified by a function URI.
The SPIN
framework makes it possible to define and share such functions in
a machine-readable format, fully compliant with the Semantic Web stack.
SPIN includes an RDF vocabulary for defining the arguments and return value
types of a function, as well as other useful information such as comments.
SPIN also has a built-in property (spin:body
) to define how
a SPARQL function is to be executed, based on another SPARQL query.
Those user-defined SPIN functions are a very powerful way of extending SPARQL, but they are still limited by whatever features are natively supported by the executing SPARQL engine. The SPINx framework described in this document makes it possible to define new SPARQL functions that are backed by JavaScript/ECMAScript code. Whenever such SPINx functions are invoked, a SPINx-aware SPARQL engine can look up the function's body and execute it using a JavaScript interpreter.
The following sections introduce the two properties of the SPINx vocabulary. You should already be familiar with user-defined SPIN functions.
The simplest way of defining a JavaScript-based SPIN function is by using
the property spinx:javaScriptCode
.
This property can be used to link a SPIN function (subject) with a JavaScript
snippet (string object).
This is illustrated in the following example (in Turtle notation), which defines a new SPARQL
function distance:squareInline
that takes one argument (?arg1
)
and computes the square of this argument (?arg1 * ?arg1
).
distance:squareInline a spin:Function ; rdfs:label "square inline"^^xsd:string ; rdfs:subClassOf spin:Functions ; spin:constraint [ a spl:Argument ; rdfs:comment "The value to compute the square of"^^xsd:string ; spl:predicate sp:arg1 ; spl:valueType xsd:float ] ; spin:returnType xsd:float ; spinx:javaScriptCode "return arg1 * arg1;"^^xsd:string .
When executed, the function's JavaScript code snippet will be converted into a JavaScript function that has the snippet as its body.
The function's JavaScript code can access the arguments using the pre-defined variables
arg1
, arg2
etc.
The values of those arguments depend on their type:
The return value of a SPINx function will be automatically converted to a RDF node using the following policy:
spin:returnType
is empty, then the function's result will be
converted to a URI resourcespin:returnType
as datatype.
While spinx:javaScriptCode
is suitable for small snippets of simple
JavaScript code, the property spinx:javaScriptFile
provides greater
flexibility to link a SPIN function with larger bodies of JavaScript code.
The subject of the spinx:javaScriptFile
property is a SPIN function,
and the object is the URL of a JavaScript file, encoded as a string.
The following example (in Turtle notation) declares a similar function as above,
but with the JavaScript code stored in a file distance.js
.
Since this is a relative path name, the engine should look up this file in the
same location as the SPIN file (i.e. the distance
namespace).
Alternatively, the file location can also be an absolute URL.
distance:square a spin:Function ; rdfs:comment "Computes the square of a numeric value, backed by a JavaScript implementation." ; rdfs:label "square"^^xsd:string ; rdfs:subClassOf spin:Functions ; spin:constraint [ a spl:Argument ; rdfs:comment "The number to compute the square of."^^xsd:string ; spl:predicate sp:arg1 ; spl:valueType rdfs:Literal ] ; spin:returnType xsd:float ; spinx:javaScriptFile "distance.js"^^xsd:string .
The contents of the file distance.js
is shown below:
function square(x) { return x * x; }
By default, the SPINx engine assumes that the JavaScript file contains a function with the
same name as the local name of the SPIN function (here: distance:square
is mapped
to the JavaScript function square
).
Alternatively, a SPINx function can contain a value for spinx:javaScriptCode
which is executed on top of the file, and may contain any other combination of function calls.
The URL of the SPINx schema is http://spinrdf.org/spinx