Janus-QL is Janus's extension for evaluating RDF queries over historical event
logs, live streams, or both. It keeps the SPARQL SELECT/WHERE shape and
adds named-window declarations plus an optional REGISTER RStream wrapper for
live result streams.
This page describes the public, tested query surface. It deliberately does not attempt to reproduce all of SPARQL or RSP-QL.
PREFIX ex: <http://example.org/>
REGISTER RStream ex:output AS
SELECT ?sensor ?value
FROM NAMED WINDOW ex:live ON STREAM ex:stream [RANGE 60000 STEP 30000]
FROM NAMED WINDOW ex:history ON LOG ex:log [START 0 END 86400000]
WHERE {
WINDOW ex:live {
?sensor ex:hasValue ?value .
}
}PREFIXdeclarations are optional, but usually make queries readable.REGISTER RStream <output> ASis used for a query that emits live results.IStreamandDStreamare rejected.- A historical-only
SELECTquery may omitREGISTER. - Each
WINDOW <name> { … }in theWHEREclause must refer to a declared named window.
Use ON LOG with an explicit, non-empty [START … END …] interval:
FROM NAMED WINDOW ex:history ON LOG ex:log [START 1700000000000 END 1700086400000]Janus evaluates this window against the segmented historical event log.
Use ON LOG with OFFSET, RANGE, and STEP:
FROM NAMED WINDOW ex:previousHour ON LOG ex:log [OFFSET 86400000 RANGE 3600000 STEP 30000]At evaluation time T, the window is:
[T - OFFSET, T - OFFSET + RANGE)
OFFSET determines how far before T the historical window starts, and
RANGE determines its duration. The range must not exceed the offset; Janus
rejects a sliding historical window that would extend beyond its evaluation
time.
Use ON STREAM with positive RANGE and STEP values:
FROM NAMED WINDOW ex:live ON STREAM ex:stream [RANGE 60000 STEP 30000]The stream URI identifies the live source; at the HTTP API layer, live execution is MQTT-backed. See the live streaming guide for broker and replay setup.
A query may declare both log and stream windows. The parser lowers historical work to one or more SPARQL executions and keeps live windows in the RSP-QL execution path.
Historical work can also be expressed as a nested SELECT inside the outer
WHERE clause:
PREFIX ex: <http://example.org/>
REGISTER RStream ex:output AS
SELECT ?sensor ?value ?historicalAverage
FROM NAMED WINDOW ex:live ON STREAM ex:stream [RANGE 60000 STEP 30000]
FROM NAMED WINDOW ex:history ON LOG ex:log [START 0 END 86400000]
WHERE {
WINDOW ex:live { ?sensor ex:hasValue ?value . }
{
SELECT ?sensor (AVG(?oldValue) AS ?historicalAverage)
WHERE {
WINDOW ex:history { ?sensor ex:hasValue ?oldValue . }
}
GROUP BY ?sensor
}
FILTER(?value > ?historicalAverage)
}Nested historical materialization is restricted to supported historical shapes. A nested query that is live-only, or mixes live and historical windows inside the same nested subquery, is rejected. Details and limitations are in Nested Historical Subqueries.
Janus validates the Janus-specific surface before execution. In particular, it rejects:
- undeclared
WINDOWnames; START/ENDbounds on a stream window;RANGE/STEPlive bounds on a log window;- zero or invalid window sizes and steps;
IStreamorDStreamregistration; and- unsupported property paths and
SERVICEpatterns.
The parser is not a claim of general SPARQL or RSP-QL equivalence. Use only the syntax exercised by the repository's parser and integration tests.
Janus-QL Core syntax, typed AST construction, validation, and window
normalization are provided by the standalone janusql-parser crate. Janus
lowers that AST into engine windows and execution plans, and owns RSP-QL/
SPARQL generation, materialization, storage, and execution.
DEFINE BASELINE and USING BASELINE remain Janus implementation
compatibility syntax used by benchmark and API paths. They are isolated before
Core parsing and are not portable Janus-QL Core. Their operational constraints
are documented separately in Baselines.