The execution of SPARQL queries can be challenging for a number of reasons
including performance, availability, and reproducibility.
To encourage greater reproducibility, sharability, and performance of these queries, a result caching approach offers a pragmatic solution.
This specification defines SPARQL Query View Materialization Containers (QVMC):
HTTP resources that implement the Linked Data Platform (LDP) Container model to store SPARQL query definitions and their corresponding materialized result sets.
A QVMC is an ldp:BasicContainer whose members include SPARQL query source files
and SPARQL Results documents.
An RDF index resource describes the contained views and how they were generated.
These guidelines enable clients and tools to reliably leverage cached SPARQL queries, their canonical
algebra, provenance, and serialized results, in a way that promotes interoperability and reuse.
This document discusses the canonical view materialization of SPARQL queries and results. This document is primarily intended for the following audiences:
The goals of this specification are to:
queries.ttl — an RDF index that inventories the views in a container and
captures provenance.
Readers are expected to be familiar with the technologies defined in the normative references, in particular RDF 1.1, SPARQL 1.1, and the Linked Data Platform (LDP).
The SPARQL Query Cache (SQC) is a conventional layout for
representing cached SPARQL queries and their results as HTTP resources
inside an ldp:Container. Each cached query is addressed by
a stable, opaque identifier derived from a cache key function over the
query text, dataset/endpoint selection, and selected request headers.
The cache also stores a canonical SPARQL algebra form and a serialized
result set for deterministic reuse.
Key terms are used as defined in the following specifications: Linked Data Platform (LDP), SPARQL 1.1 Query, SPARQL Results JSON and XML.
queries.ttl at the root of a QVMC.RFC 2119 keywords (MUST, SHOULD, MAY) indicate conformance requirements.
The following prefixes are used throughout the document.
PREFIX rdfs: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
PREFIX prov: <http://www.w3.org/ns/prov#> .
PREFIX dc: <http://purl.org/dc/terms/> .
PREFIX sh: <http://www.w3.org/ns/shacl#> .
PREFIX tq: <http://www.w3.org/2001/sw/DataAccess/tests/test-query#> .
PREFIX tm: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> .
PREFIX sd: <http://www.w3.org/ns/sparql-service-description#> .
PREFIX se: <https://purl.expasy.org/sparql-examples/ontology#> .
PREFIX qvmc: <https://vocab.example/qvmc#> .
A SPARQL query execution, from the perspective of the user, consists of four distinct componenets.
A QVMC MUST be an HTTP-accessible ldp:BasicContainer and MUST advertise Link: <http://www.w3.org/ns/ldp#BasicContainer> ; rel="type"
in responses to GET on the container URI.
Servers SHOULD also include ldp:contains statements in RDF representations.
The members of a QVMC are:
queries.ttl (text/turtle)..rq and media type application/sparql-query..srj (application/sparql-results+json) or
.srx (application/sparql-results+xml).Additional non-normative artifacts (e.g., CSV extracts) MAY be present but are out of scope.
{container}/queries.ttl.{hash} token to bind each query entry to its query SPARQL algebra and results files (details below).{container}/{hash}.rq.{container}/{hash}.{srj|srx}.
GET /views/ HTTP/1.1
Accept: text/turtle
HTTP/1.1 200 OK
Link: <http://www.w3.org/ns/ldp#BasicContainer> ; rel="type"
Content-Type: text/turtle; charset=utf-8
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
a ldp:BasicContainer ;
dc:title "SPARQL Query Materialization Container" ;
ldp:contains </views/queries.ttl> ,
</views/hash1.rq> ,
</views/hash1.srj> ,
# ... more members ...
.
The container includes an index file, queries.ttl, which is a Turtle graph that describes each stored SPARQL query entry using terms from SPARQL 1.1, SHACL, and Service Description.
The following classes and properties are used:
tq:QueryForm — a materialized view entry.dct:title, dct:description, dct:modified — human-readable metadata.tq:QuerySelect — the supported SPARQL query operation.sh:SPARQLExecutable - designates that this hash contains a link to the .rq file.tq:query (IRI) — link to the .rq file.sh:select (literal) — the entry's SPARQL query algebra (identical to that in the entry's .rq file).tm:result (IRI) — link to the .srj or .srx file.sd:endpoint (IRI) — link to the RDF list containing the target sources of the query entry (sources must be valid URIs).dct:created (xsd:dateTime) — timestamp of when the query was executed.qvmc:status (literal; values: current | stale | failed) — indicates the current state of the query entry results.prov:wasGeneratedBy — blank node with provenance information about the query entry.
The index resource itself SHOULD be typed as qvmc:Index and ldp:RDFSource and may carry container-level metadata.
Each tq:QueryForm entry MUST include at least tq:query, tm:result, sd:endpoint, and dct:created.
The pair (tq:query, tm:result) MUST be unique within the container.
sd:endpoint MUST be a valid RDF list of one or more URIs.
dct:created MUST be in xsd:dateTime.
qvmc:status MUST be a literal in the range: current | stale | failed.
prov:wasGeneratedBy MUST include a prov:Activity with at least prov:used and prov:modified.
It is recommended that each tq:QueryForm SPARQL query entry is identified by an opaque, 10-character token
(e.g., #aBc1d2Ef3g) composed of integers (0-9) and both lowercase and uppercase letters (a-z, A-Z).
This hash is used as a key to refer to a singular stored SPARQL query entry.
At a minimum, each tq:QueryForm entry MUST be unique within the queries.ttl file.
.rq)
Each SPARQL query entry includes a serialization of the SPARQL algebra for the query, stored in a file named {hash}.rq.
{hash}.application/sparql-query.
PREFIX : <https://example.org/ontology/>
SELECT ?s ?score WHERE { ?s :score ?score } ORDER BY DESC(?score) LIMIT 10
Each SPARQL query entry includes a serialization of the results for the query, stored in a file named {hash}.* (where "*" is the descriptive extension of the file-type respresented).
{hash}.application/sparql-results+json) or SPARQL Results XML (application/sparql-results+xml) serialization formats.queries.ttl
@prefix rdfs: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix qvmc: <https://vocab.example/qvmc#> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix tq: <http://www.w3.org/2001/sw/DataAccess/tests/test-query#> .
@prefix tm: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> .
@prefix sd: <http://www.w3.org/ns/sparql-service-description#> .
@prefix se: <https://purl.expasy.org/sparql-examples/ontology#> .
@base <https://data.example.org/example/> .
<#index> a qvmc:Index ;
dc:title "SPARQL Query Materialization Container Example" ;
dc:modified "2025-09-25T09:00:00Z"^^xsd:dateTime .
<#aBc1d2Ef3g> a tq:QueryForm, tq:QuerySelect, sh:SPARQLExecutable ;
dc:title "Top 10 by score" ;
dc:description "Returns 10 entities with the highest :score." ;
tq:query <aBc1d2Ef3g.rq> ;
tm:result <aBc1d2Ef3g.srj> ;
sh:select "SELECT ?s ?score WHERE { ?s :score ?score } ORDER BY DESC(?score) LIMIT 10" ;
sd:endpoint <#5926e69f-c619-4029-b516-21affc0598e0> ;
dc:created "2025-09-24T16:12:03Z"^^xsd:dateTime ;
qvmc:status "current" ;
prov:wasGeneratedBy [
a prov:Activity ;
prov:used <aBc1d2Ef3g.rq>, <#5926e69f-c619-4029-b516-21affc0598e0> ;
prov:modified "2025-09-24T16:12:03Z"^^xsd:dateTime
] .
<#5926e69f-c619-4029-b516-21affc0598e0> rdfs:first <https://sparql.example.org/sparql/> ;
rdfs:rest rdfs:nil .
The order in which RDF triples occur in an RDF dataset convey no meaning.
Security and Privacy Note: If access controls are implemented, the following operations are permitted only if authorization is successful:
ldp:BasicContainer with GET and POST/PUT access rights on all resources for at least one authorized user.GET and POST/PUT methods to other authenticated users and/or the public.
Implementations MUST update queries.ttl atomically when new members are added, deleted, or modified.
The following describes the requirements for each action:
tq:QueryForm node with a new unique subject IRI <#${name}>.
Both results and query serialization files SHOULD be named <#${name}.rq> and <#${name}.*> respectively after the <#${name}> of the tq:QueryForm node.
Set sd:endpoint to an RDF list of one or more source URIs that the query targets. Set dc:created to the creation timestamp.qvmc:status of the relevant tq:QueryForm node to stale.
IMPORTANT if the results of the query change, users SHOULD create a new query entry instead of modifying the existing one to preserve provenance.
In this case, the pre-existing entry's qvmc:status MUST be set to stale and the triple qvmc:linkedQuery <#${updated-entry-name}> MUST be added.
Whenever a field within an entry is updated, users MUST update prov:wasGeneratedBy with a new timestamp via dc:modified.tq:QueryForm node and all references to its associated files (.rq, .srj, .srx) from queries.ttl. Optionally, remove the files themselves from the container.
PATCH /views/queries.ttl HTTP/1.1
Content-Type: application/sparql-update
DELETE { <#aBc1d2Ef3g> dct:modified ?t ; qvmc:status ?s }
INSERT { <#aBc1d2Ef3g> dct:modified "2025-09-25T10:01:22Z"^^xsd:dateTime ; qvmc:status "current" }
WHERE { OPTIONAL { <#aBc1d2Ef3g> dct:modified ?t ; qvmc:status ?s } }
The index graph MAY include additional metadata such as provenance
(dct:source), execution timing, result counts, or dataset
snapshots. Unknown properties MUST be ignored by consumers.
A QVMC Server conforms to this specification if it exposes a container satisfying the requirements in
Container model, enforces media types in
File formats, and maintains a valid queries.ttl as described in
The index.
A QVMC Client conforms if it manipulates members through LDP operations and creates/patches
queries.ttl entries according to the data model.
queries.ttl updates with results writes to avoid dangling references.If-Match) to prevent lost updates.ldp:contains in RDF representations to help crawlers discover members.