Extension Functions
On this page
SPARQL allows non-standard, custom extension functions to be used within queries. In order to provide an implementation to these extension functions, Comunica allows developers to plug them in via the context.
When querying over SPARQL endpoints, extension functions will be pushed down into the endpoint if the endpoint explicitly mentions these extension functions within the SPARQL Service Description, and will otherwise be executed locally. This means that this pushing down functionality will not work for endpoints without Service Description.
Dictionary-based extension functions
The easiest way to plug in extension functions to Comunica is by using
the extensionFunctions
context entry
in a JavaScript application:
import {DataFactory} from "rdf-data-factory"; const DF = new DataFactory(); const bindingsStream = await myEngine.queryBindings(` PREFIX func: <http://example.org/functions#> SELECT ?caps WHERE { ?s ?p ?o. BIND (func:to-upper-case(?o) AS ?caps) } `, { sources: ['https://www.rubensworks.net/'], extensionFunctions: { 'http://example.org/functions#to-upper-case'(args: RDF.Term[]) { const arg = args[0]; if (arg.termType === 'Literal' && arg.datatype.value === 'http://www.w3.org/2001/XMLSchema#string') { return DF.literal(arg.value.toUpperCase(), arg.datatype); } return arg; }, }, });
Within this extensionFunctions
dictionary, you can provide any number of extension functions.
These functions may even be async
.
Callback-based extension functions
If function names are not known beforehand,
or the dictionary-based format is not usable for whatever reason,
then the callback-based extensionFunctionCreator
entry may be used:
import {DataFactory} from "rdf-data-factory"; const DF = new DataFactory(); const bindingsStream = await myEngine.queryBindings(` PREFIX func: <http://example.org/functions#> SELECT ?caps WHERE { ?s ?p ?o. BIND (func:to-upper-case(?o) AS ?caps) } `, { sources: ['https://www.rubensworks.net/'], extensionFunctionCreator: (funcTerm: RDF.NamedNode) => { if (funcTerm.value === 'http://example.org/functions#to-upper-case') { return (args: RDF.Term[]) => { const arg = args[0]; if (arg.termType === 'Literal' && arg.datatype.value === 'http://www.w3.org/2001/XMLSchema#string') { return DF.literal(arg.value.toUpperCase(), arg.datatype); } return arg; }; } }, });
The extensionFunctionCreator
is invoked upon any occurrence of an extension function,
and is called with the extension function name, wrapped within an RDF/JS named node.
The return type of this function is expected to be a function with the same signature
as the values of the extensionFunction
dictionary, or undefined
.