Query Functions
This page discusses implementing your own query functions.
Page Contents
Overview
The Stardog com.complexible.stardog.plan.filter.functions.Function
interface is the extension point for section 17.6 (Extensible Value Testing) of the SPARQL spec.
Function
corresponds to built-in expressions used in FILTER
, BIND
and SELECT
expressions, as well as aggregate operators in a SPARQL query. Examples include &&
and ||
and functions defined in the SPARQL spec like sameTerm
, str
, and now
.
Implementing Custom Functions
The starting point for implementing your own custom function is to extend AbstractFunction
. This class provides much of the basic scaffolding for implementing a new Function
from scratch.
If your new function falls into one of the existing categories, it should implement the appropriate marker interface:
com.complexible.stardog.plan.filter.functions.cast.CastFunction
com.complexible.stardog.plan.filter.functions.datetime.DateTimeFunction
com.complexible.stardog.plan.filter.functions.hash.HashFunction
com.complexible.stardog.plan.filter.functions.numeric.MathFunction
com.complexible.stardog.plan.filter.functions.rdfterm.RDFTermFunction
com.complexible.stardog.plan.filter.functions.string.StringFunction
If not, then it must implement com.complexible.stardog.plan.filter.functions.UserDefinedFunction
. Extending one of these marker interfaces is required for the Function
to be traverseable via the visitor pattern.
A zero-argument constructor must be provided which delegates some initialization to super
, providing first the int
number of required arguments followed by one or more URIs which identify the function. Any these URIs can be used to identify the function in a SPARQL query. The URIs are typed as String
but should be valid URIs.
For functions which take a range of arguments, for example a minimum of 2, but no more than 4 values, a Range can be used as the first parameter passed to super
rather than an int
.
Function
extends from Copyable
, therefore implementations should also provide a “copy constructor” which can be called from the copy
method:
private MyFunc(final MyFunc theFunc) {
super(myFunc);
// make copies of any local data structures
}
@Override
public MyFunc copy() {
return new MyFunc(this);
}
Evaluating the function is handled by Value internalEvaluate(final Value...)
The parameters of this method correspond to the arguments passed into the function; it’s the values of the variables for each solution of the query. Here we can perform whatever actions are required for our function. AbstractFunction
will have already taken care of validating that we’re getting the correct number of arguments to the function, but we still have to validate the input. AbstractFunction
provides some convenience methods to this end, for example assertURI
and assertNumericLiteral
for requiring that inputs are either a valid URI, or a literal with a numeric datatype respectively.
Errors that occur in the evaluation of the function should throw a com.complexible.stardog.plan.filter.ExpressionEvaluationException
; this corresponds to the ValueError
concept defined in the SPARQL specification.
Registering Custom Functions
Create a file called com.complexible.stardog.plan.filter.functions.Function
in the META-INF/services
directory with the name of your custom Function class.
Using Custom Functions
Functions are identified by their URI; you can reference them in a query using their fully-qualified URI, or specify prefixes for the namespaces and utilize only the qname. For this example, if the namespace tag:stardog:api:
is associated with the prefix stardog
and within that namespace we have our function myFunc
we can invoke it from a SPARQL query as: bind(stardog:myFunc(?var) as ?tc)